diff options
Diffstat (limited to 'spec')
230 files changed, 3264 insertions, 1665 deletions
diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb index 3bc49023357..d8c96501f5c 100644 --- a/spec/controllers/admin/spam_logs_controller_spec.rb +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -27,7 +27,7 @@ describe Admin::SpamLogsController do expect(response).to have_gitlab_http_status(200) end - it 'removes user and his spam logs when removing the user' do + it 'removes user and his spam logs when removing the user', :sidekiq_might_not_need_inline do delete :destroy, params: { id: first_spam.id, remove_user: true } expect(flash[:notice]).to eq "User #{user.username} was successfully removed." diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index afe21c8b34a..50ba7418d2c 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -35,7 +35,7 @@ describe Admin::UsersController do end end - describe 'DELETE #user with projects' do + describe 'DELETE #user with projects', :sidekiq_might_not_need_inline do let(:project) { create(:project, namespace: user.namespace) } let!(:issue) { create(:issue, author: user) } diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index ed91b5973b8..94afe741057 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -96,30 +96,14 @@ describe ApplicationController do request.path = '/-/peek' end - # TODO: - # remove line below once `privacy_policy_update_callout` - # feature flag is removed and `gon` reverts back to - # to not setting any variables. - if Gitlab.ee? - it_behaves_like 'setting gon variables' - else - it_behaves_like 'not setting gon variables' - end + it_behaves_like 'not setting gon variables' end end context 'with json format' do let(:format) { :json } - # TODO: - # remove line below once `privacy_policy_update_callout` - # feature flag is removed and `gon` reverts back to - # to not setting any variables. - if Gitlab.ee? - it_behaves_like 'setting gon variables' - else - it_behaves_like 'not setting gon variables' - end + it_behaves_like 'not setting gon variables' end end @@ -852,7 +836,7 @@ describe ApplicationController do let(:experiment_enabled) { true } before do - stub_experiment(signup_flow: experiment_enabled) + stub_experiment_for_user(signup_flow: experiment_enabled) end context 'experiment enabled and user with required role' do diff --git a/spec/controllers/concerns/lfs_request_spec.rb b/spec/controllers/concerns/lfs_request_spec.rb index cb8c0b8f71c..823b9a50434 100644 --- a/spec/controllers/concerns/lfs_request_spec.rb +++ b/spec/controllers/concerns/lfs_request_spec.rb @@ -16,13 +16,17 @@ describe LfsRequest do end def project - @project ||= Project.find(params[:id]) + @project ||= Project.find_by(id: params[:id]) end def download_request? true end + def upload_request? + false + end + def ci? false end @@ -49,4 +53,41 @@ describe LfsRequest do expect(assigns(:storage_project)).to eq(project) end end + + context 'user is authenticated without access to lfs' do + before do + allow(controller).to receive(:authenticate_user) + allow(controller).to receive(:authentication_result) do + Gitlab::Auth::Result.new + end + end + + context 'with access to the project' do + it 'returns 403' do + get :show, params: { id: project.id } + + expect(response.status).to eq(403) + end + end + + context 'without access to the project' do + context 'project does not exist' do + it 'returns 404' do + get :show, params: { id: 'does not exist' } + + expect(response.status).to eq(404) + end + end + + context 'project is private' do + let(:project) { create(:project, :private) } + + it 'returns 404' do + get :show, params: { id: project.id } + + expect(response.status).to eq(404) + end + end + end + end end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 3c39a6468e5..2ed2b319298 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -45,7 +45,7 @@ describe GroupsController do it { is_expected.to render_template('groups/show') } - it 'assigns events for all the projects in the group' do + it 'assigns events for all the projects in the group', :sidekiq_might_not_need_inline do subject expect(assigns(:events)).to contain_exactly(event) end @@ -125,7 +125,7 @@ describe GroupsController do end context 'as json' do - it 'includes events from all projects in group and subgroups' do + it 'includes events from all projects in group and subgroups', :sidekiq_might_not_need_inline do 2.times do project = create(:project, group: group) create(:event, project: project) @@ -255,7 +255,7 @@ describe GroupsController do end end - describe 'GET #issues' do + describe 'GET #issues', :sidekiq_might_not_need_inline do let(:issue_1) { create(:issue, project: project, title: 'foo') } let(:issue_2) { create(:issue, project: project, title: 'bar') } @@ -304,7 +304,7 @@ describe GroupsController do end end - describe 'GET #merge_requests' do + describe 'GET #merge_requests', :sidekiq_might_not_need_inline do let(:merge_request_1) { create(:merge_request, source_project: project) } let(:merge_request_2) { create(:merge_request, :simple, source_project: project) } diff --git a/spec/controllers/import/phabricator_controller_spec.rb b/spec/controllers/import/phabricator_controller_spec.rb index 85085a8e996..a127e3cda3a 100644 --- a/spec/controllers/import/phabricator_controller_spec.rb +++ b/spec/controllers/import/phabricator_controller_spec.rb @@ -52,7 +52,7 @@ describe Import::PhabricatorController do namespace_id: current_user.namespace_id } end - it 'creates a project to import' do + it 'creates a project to import', :sidekiq_might_not_need_inline do expect_next_instance_of(Gitlab::PhabricatorImport::Importer) do |importer| expect(importer).to receive(:execute) end diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 086ec9dfbcf..78599935910 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -320,7 +320,7 @@ describe Projects::BlobController do default_params[:project_id] = forked_project end - it 'redirects to blob' do + it 'redirects to blob', :sidekiq_might_not_need_inline do put :update, params: default_params expect(response).to redirect_to(project_blob_path(forked_project, 'master/CHANGELOG')) @@ -328,7 +328,7 @@ describe Projects::BlobController do end context 'when editing on the original repository' do - it "redirects to forked project new merge request" do + it "redirects to forked project new merge request", :sidekiq_might_not_need_inline do default_params[:branch_name] = "fork-test-1" default_params[:create_merge_request] = 1 diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index c9558abab33..4c2b58551bf 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -1252,7 +1252,7 @@ describe Projects::IssuesController do stub_feature_flags(create_confidential_merge_request: true) end - it 'creates a new merge request' do + it 'creates a new merge request', :sidekiq_might_not_need_inline do expect { create_merge_request }.to change(target_project.merge_requests, :count).by(1) end end diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 90ccb884927..349d73f13ca 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -154,7 +154,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do .and_return(merge_request) end - it 'does not serialize builds in exposed stages' do + it 'does not serialize builds in exposed stages', :sidekiq_might_not_need_inline do get_show_json json_response.dig('pipeline', 'details', 'stages').tap do |stages| @@ -183,7 +183,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do context 'job is cancelable' do let(:job) { create(:ci_build, :running, pipeline: pipeline) } - it 'cancel_path is present with correct redirect' do + it 'cancel_path is present with correct redirect', :sidekiq_might_not_need_inline do expect(response).to have_gitlab_http_status(:ok) expect(response).to match_response_schema('job/job_details') expect(json_response['cancel_path']).to include(CGI.escape(json_response['build_path'])) @@ -193,7 +193,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do context 'with web terminal' do let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) } - it 'exposes the terminal path' do + it 'exposes the terminal path', :sidekiq_might_not_need_inline do expect(response).to have_gitlab_http_status(:ok) expect(response).to match_response_schema('job/job_details') expect(json_response['terminal_path']).to match(%r{/terminal}) @@ -268,7 +268,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do project.add_maintainer(user) # Need to be a maintianer to view cluster.path end - it 'exposes the deployment information' do + it 'exposes the deployment information', :sidekiq_might_not_need_inline do get_show_json expect(response).to have_gitlab_http_status(:ok) @@ -292,7 +292,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do sign_in(user) end - it 'user can edit runner' do + it 'user can edit runner', :sidekiq_might_not_need_inline do get_show_json expect(response).to have_gitlab_http_status(:ok) @@ -312,7 +312,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do sign_in(user) end - it 'user can not edit runner' do + it 'user can not edit runner', :sidekiq_might_not_need_inline do get_show_json expect(response).to have_gitlab_http_status(:ok) @@ -331,7 +331,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do sign_in(user) end - it 'user can not edit runner' do + it 'user can not edit runner', :sidekiq_might_not_need_inline do get_show_json expect(response).to have_gitlab_http_status(:ok) @@ -412,7 +412,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do context 'when job has trace' do let(:job) { create(:ci_build, :running, :trace_live, pipeline: pipeline) } - it "has_trace is true" do + it "has_trace is true", :sidekiq_might_not_need_inline do get_show_json expect(response).to match_response_schema('job/job_details') @@ -458,7 +458,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do create(:ci_pipeline_variable, pipeline: pipeline, key: :TRIGGER_KEY_1, value: 'TRIGGER_VALUE_1') end - context 'user is a maintainer' do + context 'user is a maintainer', :sidekiq_might_not_need_inline do before do project.add_maintainer(user) diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 74834e86467..9c9c12d22f1 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -431,7 +431,7 @@ describe Projects::MergeRequestsController do context 'when a squash commit message is passed' do let(:message) { 'My custom squash commit message' } - it 'passes the same message to SquashService' do + it 'passes the same message to SquashService', :sidekiq_might_not_need_inline do params = { squash: '1', squash_commit_message: message } expect_next_instance_of(MergeRequests::SquashService, project, user, params.merge(merge_request: merge_request)) do |squash_service| @@ -724,7 +724,7 @@ describe Projects::MergeRequestsController do context 'with private builds' do context 'for the target project member' do - it 'does not respond with serialized pipelines' do + it 'does not respond with serialized pipelines', :sidekiq_might_not_need_inline do expect(json_response['pipelines']).to be_empty expect(json_response['count']['all']).to eq(0) expect(response).to include_pagination_headers @@ -734,7 +734,7 @@ describe Projects::MergeRequestsController do context 'for the source project member' do let(:user) { fork_user } - it 'responds with serialized pipelines' do + it 'responds with serialized pipelines', :sidekiq_might_not_need_inline do expect(json_response['pipelines']).to be_present expect(json_response['count']['all']).to eq(1) expect(response).to include_pagination_headers @@ -750,7 +750,7 @@ describe Projects::MergeRequestsController do end context 'for the target project member' do - it 'does not respond with serialized pipelines' do + it 'does not respond with serialized pipelines', :sidekiq_might_not_need_inline do expect(json_response['pipelines']).to be_present expect(json_response['count']['all']).to eq(1) expect(response).to include_pagination_headers @@ -760,7 +760,7 @@ describe Projects::MergeRequestsController do context 'for the source project member' do let(:user) { fork_user } - it 'responds with serialized pipelines' do + it 'responds with serialized pipelines', :sidekiq_might_not_need_inline do expect(json_response['pipelines']).to be_present expect(json_response['count']['all']).to eq(1) expect(response).to include_pagination_headers @@ -1203,13 +1203,13 @@ describe Projects::MergeRequestsController do create(:merge_request, source_project: forked, target_project: project, target_branch: 'master', head_pipeline: pipeline) end - it 'links to the environment on that project' do + it 'links to the environment on that project', :sidekiq_might_not_need_inline do get_ci_environments_status expect(json_response.first['url']).to match /#{forked.full_path}/ end - context "when environment_target is 'merge_commit'" do + context "when environment_target is 'merge_commit'", :sidekiq_might_not_need_inline do it 'returns nothing' do get_ci_environments_status(environment_target: 'merge_commit') @@ -1240,13 +1240,13 @@ describe Projects::MergeRequestsController do # we're trying to reduce the overall number of queries for this method. # set a hard limit for now. https://gitlab.com/gitlab-org/gitlab-foss/issues/52287 - it 'keeps queries in check' do + it 'keeps queries in check', :sidekiq_might_not_need_inline do control_count = ActiveRecord::QueryRecorder.new { get_ci_environments_status }.count expect(control_count).to be <= 137 end - it 'has no N+1 SQL issues for environments', :request_store, retry: 0 do + it 'has no N+1 SQL issues for environments', :request_store, :sidekiq_might_not_need_inline, retry: 0 do # First run to insert test data from lets, which does take up some 30 queries get_ci_environments_status @@ -1464,7 +1464,7 @@ describe Projects::MergeRequestsController do sign_in(fork_owner) end - it 'returns 200' do + it 'returns 200', :sidekiq_might_not_need_inline do expect_rebase_worker_for(fork_owner) post_rebase diff --git a/spec/controllers/projects/mirrors_controller_spec.rb b/spec/controllers/projects/mirrors_controller_spec.rb index fb3dd75460a..e14686970a1 100644 --- a/spec/controllers/projects/mirrors_controller_spec.rb +++ b/spec/controllers/projects/mirrors_controller_spec.rb @@ -51,10 +51,6 @@ describe Projects::MirrorsController do sign_in(project.owner) end - around do |example| - Sidekiq::Testing.fake! { example.run } - end - context 'With valid URL for a push' do let(:remote_mirror_attributes) do { "0" => { "enabled" => "0", url: 'https://updated.example.com' } } diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index 3ab191c0032..e9d285aa0b0 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -518,7 +518,7 @@ describe Projects::NotesController do project.id && Project.maximum(:id).succ end - it 'returns a 404' do + it 'returns a 404', :sidekiq_might_not_need_inline do create! expect(response).to have_gitlab_http_status(404) end @@ -527,13 +527,13 @@ describe Projects::NotesController do context 'when the user has no access to the fork' do let(:fork_visibility) { Gitlab::VisibilityLevel::PRIVATE } - it 'returns a 404' do + it 'returns a 404', :sidekiq_might_not_need_inline do create! expect(response).to have_gitlab_http_status(404) end end - context 'when the user has access to the fork' do + context 'when the user has access to the fork', :sidekiq_might_not_need_inline do let!(:discussion) { forked_project.notes.find_discussion(existing_comment.discussion_id) } let(:fork_visibility) { Gitlab::VisibilityLevel::PUBLIC } diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index e3ad36f8d24..9d3753ef2ab 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -93,7 +93,7 @@ describe Projects::PipelinesController do end context 'when performing gitaly calls', :request_store do - it 'limits the Gitaly requests' do + it 'limits the Gitaly requests', :sidekiq_might_not_need_inline do # Isolate from test preparation (Repository#exists? is also cached in RequestStore) RequestStore.end! RequestStore.clear! @@ -571,7 +571,7 @@ describe Projects::PipelinesController do format: :json end - it 'cancels a pipeline without returning any content' do + it 'cancels a pipeline without returning any content', :sidekiq_might_not_need_inline do expect(response).to have_gitlab_http_status(:no_content) expect(pipeline.reload).to be_canceled end diff --git a/spec/controllers/projects/wiki_directories_controller_spec.rb b/spec/controllers/projects/wiki_directories_controller_spec.rb new file mode 100644 index 00000000000..b09e1bc2ca4 --- /dev/null +++ b/spec/controllers/projects/wiki_directories_controller_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::WikiDirectoriesController do + set(:project) { create(:project, :public, :repository) } + + let(:user) { project.owner } + let(:project_wiki) { ProjectWiki.new(project, user) } + let(:wiki) { project_wiki.wiki } + let(:dir_slug) { 'the-directory' } + let(:dir_contents) { [create(:wiki_page)] } + let(:the_dir) { WikiDirectory.new(dir_slug, dir_contents) } + + before do + allow(controller).to receive(:find_dir).and_return(the_dir) + + sign_in(user) + end + + describe 'GET #show' do + let(:show_params) do + { + namespace_id: project.namespace, + project_id: project, + id: dir_slug + } + end + + before do + get :show, params: show_params + end + + context 'the directory is empty' do + let(:the_dir) { nil } + + it { is_expected.to render_template('empty') } + end + + context 'the directory does exist' do + it { is_expected.to render_template('show') } + + it 'sets the wiki_dir attribute' do + expect(assigns(:wiki_dir)).to eq(the_dir) + end + + it 'assigns the wiki pages' do + expect(assigns(:wiki_pages)).to eq(dir_contents) + end + end + end +end diff --git a/spec/controllers/projects/wiki_pages_controller_spec.rb b/spec/controllers/projects/wiki_pages_controller_spec.rb new file mode 100644 index 00000000000..01a84fbbf20 --- /dev/null +++ b/spec/controllers/projects/wiki_pages_controller_spec.rb @@ -0,0 +1,399 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::WikiPagesController do + set(:project) { create(:project, :public, :repository) } + let(:user) { project.owner } + let(:project_wiki) { ProjectWiki.new(project, user) } + let(:wiki) { project_wiki.wiki } + let(:wiki_title) { 'page-title-test' } + let(:parent_ids) { { namespace_id: project.namespace.path, project_id: project.name } } + let(:redirect_destination) { Rails.application.routes.recognize_path(response.redirect_url) } + + before do + create_page(wiki_title, 'hello world') + + sign_in(user) + end + + after do + destroy_page(wiki_title) + end + + def helper + Helper.instance + end + + class Helper + include Singleton + include ActionView::Helpers::UrlHelper + end + + describe 'GET #new' do + subject { get :new, params: parent_ids } + + it 'redirects to #show and appends a `random_title` param' do + subject + + expect(response).to have_http_status(302) + + expect(redirect_destination) + .to include(parent_ids.merge(controller: 'projects/wiki_pages', action: 'show')) + + expect(response.redirect_url).to match(/\?random_title=true\Z/) + end + end + + describe 'GET #show' do + render_views + let(:requested_wiki_page) { wiki_title } + let(:random_title) { nil } + + subject do + get :show, params: { + namespace_id: project.namespace, + project_id: project, + id: requested_wiki_page, + random_title: random_title + } + end + + context 'when the wiki repo cannot be created' do + before do + allow(controller).to receive(:load_wiki) { raise ProjectWiki::CouldNotCreateWikiError } + end + + it 'redirects to the project path' do + headers = { 'Location' => a_string_ending_with(Gitlab::Routing.url_helpers.project_path(project)) } + + subject + + expect(response).to be_redirect + expect(response.header.to_hash).to include(headers) + end + end + + context 'when the page exists' do + it 'limits the retrieved pages for the sidebar' do + expect(controller).to receive(:load_wiki).and_return(project_wiki) + + # Sidebar entries + expect(project_wiki).to receive(:list_pages).with(limit: 15).and_call_original + + subject + + expect(response).to have_http_status(:ok) + expect(response.body).to include(wiki_title) + end + + context 'when page content encoding is invalid' do + it 'sets flash error' do + allow(controller).to receive(:valid_encoding?).and_return(false) + + subject + + expect(response).to have_http_status(:ok) + expect(flash[:notice]).to eq 'The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.' + end + end + end + + context 'when the page does not exist' do + let(:requested_wiki_page) { 'this-page-does-not-yet-exist' } + + context 'the current user can create wiki pages' do + it { is_expected.to render_template('edit') } + + it 'makes a call to see if the wiki is empty' do + expect(controller).to receive(:load_wiki).and_return(project_wiki) + expect(project_wiki).to receive(:list_pages).once.with(limit: anything).and_call_original + expect(project_wiki).to receive(:list_pages).with(limit: 1).and_call_original + subject + end + + describe 'assigned title' do + shared_examples :wiki_page_with_correct_title do + it 'assigns the correct title' do + subject + + expect(assigns(:page)).to have_attributes(title: assigned_title) + end + end + + context 'random_title is absent' do + let(:random_title) { nil } + + it_behaves_like :wiki_page_with_correct_title do + let(:assigned_title) { WikiPage.unhyphenize(requested_wiki_page) } + end + end + + context 'random_title is present' do + let(:random_title) { true } + + it_behaves_like :wiki_page_with_correct_title do + let(:assigned_title) { be_empty } + end + end + end + end + + context 'the current user cannot create wiki pages' do + before do + forbid_controller_ability! :create_wiki + end + it { is_expected.to render_template('missing_page') } + end + end + + context 'when page is a file' do + include WikiHelpers + + let(:path) { upload_file_to_wiki(project, user, file_name) } + + before do + get :show, params: { namespace_id: project.namespace, project_id: project, id: path } + end + + context 'when file is an image' do + let(:file_name) { 'dk.png' } + + it 'delivers the image' do + expect(response.headers['Content-Disposition']).to match(/^inline/) + expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" + end + + context 'when file is a svg' do + let(:file_name) { 'unsanitized.svg' } + + it 'delivers the image' do + expect(response.headers['Content-Disposition']).to match(/^inline/) + expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" + end + end + end + + context 'when file is a pdf' do + let(:file_name) { 'git-cheat-sheet.pdf' } + + it 'sets the content type to sets the content response headers' do + expect(response.headers['Content-Disposition']).to match(/^inline/) + expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" + end + end + end + end + + describe 'POST #preview_markdown' do + let(:page_id) { 'page/path' } + let(:markdown_text) { '*Markdown* text' } + let(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: wiki_title }) } + let(:processed_md) { json_response.fetch('body') } + + let(:preview_params) do + { namespace_id: project.namespace, project_id: project, id: wiki_page.slug, text: markdown_text } + end + + before do + post :preview_markdown, params: preview_params + end + + it 'renders json in a correct format' do + expect(response).to have_http_status(:ok) + expect(json_response).to include('body' => String, 'references' => Hash) + end + + describe 'double brackets within backticks' do + let(:markdown_text) do + <<-HEREDOC + `[[do_not_linkify]]` + ``` + [[also_do_not_linkify]] + ``` + HEREDOC + end + + it "does not linkify double brackets inside code blocks as expected" do + expect(processed_md).to include('[[do_not_linkify]]', '[[also_do_not_linkify]]') + end + end + + describe 'link re-writing' do + let(:links) do + [ + { text: 'regular link', path: 'regular' }, + { text: 'relative link 1', path: '../relative' }, + { text: 'relative link 2', path: './relative' }, + { text: 'relative link 3', path: './e/f/relative' }, + { text: 'spaced link', path: 'title with spaces' } + ] + end + + shared_examples :wiki_link_rewriter do + let(:markdown_text) { links.map { |text:, path:| "[#{text}](#{path})" }.join("\n") } + let(:expected_links) do + links.zip(paths).map do |(link, path)| + helper.link_to(link[:text], "#{project_wiki.wiki_page_path}/#{path}") + end + end + + it 'processes the links correctly' do + expect(processed_md).to include(*expected_links) + end + end + + context 'the current page has spaces in its title' do + let(:wiki_title) { 'page a/page b/page c/page d' } + it_behaves_like :wiki_link_rewriter do + let(:paths) do + ['regular', + 'page-a/page-b/relative', + 'page-a/page-b/page-c/relative', + 'page-a/page-b/page-c/e/f/relative', + 'title%20with%20spaces'] + end + end + end + + context 'the current page has an unproblematic title' do + let(:wiki_title) { 'a/b/c/d' } + it_behaves_like :wiki_link_rewriter do + let(:paths) do + ['regular', 'a/b/relative', 'a/b/c/relative', 'a/b/c/e/f/relative', 'title%20with%20spaces'] + end + end + end + + context "when there are hyphens in the page name" do + let(:wiki_title) { 'page-a/page-b/page-c/page-d' } + it_behaves_like :wiki_link_rewriter do + let(:paths) do + ['regular', + 'page-a/page-b/relative', + 'page-a/page-b/page-c/relative', + 'page-a/page-b/page-c/e/f/relative', + 'title%20with%20spaces'] + end + end + end + end + end + + describe 'GET #edit' do + subject { get(:edit, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }) } + + context 'when page content encoding is invalid' do + it 'redirects to show' do + allow(controller).to receive(:valid_encoding?).and_return(false) + + subject + + expect(response).to redirect_to(project_wiki_path(project, project_wiki.list_pages.first)) + end + end + + context 'when page content encoding is valid' do + render_views + + it 'shows the edit page' do + subject + + expect(response).to have_http_status(:ok) + expect(response.body).to include('Edit Page') + end + end + end + + describe 'PATCH #update' do + let(:new_title) { 'New title' } + let(:new_content) { 'New content' } + subject do + patch(:update, + params: { + namespace_id: project.namespace, + project_id: project, + id: wiki_title, + wiki_page: { title: new_title, content: new_content } + }) + end + + context 'when page content encoding is invalid' do + it 'redirects to show' do + allow(controller).to receive(:valid_encoding?).and_return(false) + + subject + expect(response).to redirect_to(project_wiki_path(project, project_wiki.list_pages.first)) + end + end + + context 'when page content encoding is valid' do + render_views + + it 'updates the page' do + subject + + wiki_page = project_wiki.list_pages(load_content: true).first + + expect(wiki_page.title).to eq new_title + expect(wiki_page.content).to eq new_content + end + end + end + + describe 'GET #history' do + before do + allow(controller) + .to receive(:can?) + .with(any_args) + .and_call_original + + # The :create_wiki permission is irrelevant to reading history. + expect(controller) + .not_to receive(:can?) + .with(anything, :create_wiki, any_args) + + allow(controller) + .to receive(:can?) + .with(anything, :read_wiki, any_args) + .and_return(allow_read_wiki) + end + + shared_examples 'fetching history' do |expected_status| + before do + get :history, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } + end + + it "returns status #{expected_status}" do + expect(response).to have_http_status(expected_status) + end + end + + it_behaves_like 'fetching history', :ok do + let(:allow_read_wiki) { true } + + it 'assigns @page_versions' do + expect(assigns(:page_versions)).to be_present + end + end + + it_behaves_like 'fetching history', :not_found do + let(:allow_read_wiki) { false } + end + end + + private + + def create_page(name, content) + wiki.write_page(name, :markdown, content, commit_details(name)) + end + + def commit_details(name) + Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "created page #{name}") + end + + def destroy_page(title, dir = '') + page = wiki.page(title: title, dir: dir) + project_wiki.delete_page(page, "test commit") + end +end diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb index f46da908218..7fbefa5787b 100644 --- a/spec/controllers/projects/wikis_controller_spec.rb +++ b/spec/controllers/projects/wikis_controller_spec.rb @@ -4,10 +4,10 @@ require 'spec_helper' describe Projects::WikisController do let_it_be(:project) { create(:project, :public, :repository) } - let(:user) { project.owner } - let(:project_wiki) { ProjectWiki.new(project, user) } - let(:wiki) { project_wiki.wiki } - let(:wiki_title) { 'page title test' } + let_it_be(:user) { project.owner } + let_it_be(:project_wiki) { ProjectWiki.new(project, user) } + let_it_be(:wiki) { project_wiki.wiki } + let_it_be(:wiki_title) { 'page title test' } before do create_page(wiki_title, 'hello world') @@ -19,231 +19,86 @@ describe Projects::WikisController do destroy_page(wiki_title) end - describe 'GET #new' do - subject { get :new, params: { namespace_id: project.namespace, project_id: project } } - - it 'redirects to #show and appends a `random_title` param' do - subject - - expect(response).to have_http_status(302) - expect(Rails.application.routes.recognize_path(response.redirect_url)).to include( - controller: 'projects/wikis', - action: 'show' - ) - expect(response.redirect_url).to match(/\?random_title=true\Z/) + describe 'GET #pages' do + subject do + get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }.merge(extra_params) end - end - describe 'GET #pages' do - subject { get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } } + let(:extra_params) { {} } it 'does not load the pages content' do expect(controller).to receive(:load_wiki).and_return(project_wiki) - expect(project_wiki).to receive(:list_pages).twice.and_call_original subject end - end - - describe 'GET #history' do - before do - allow(controller) - .to receive(:can?) - .with(any_args) - .and_call_original - # The :create_wiki permission is irrelevant to reading history. - expect(controller) - .not_to receive(:can?) - .with(anything, :create_wiki, any_args) - - allow(controller) - .to receive(:can?) - .with(anything, :read_wiki, any_args) - .and_return(allow_read_wiki) - end - - shared_examples 'fetching history' do |expected_status| - before do - get :history, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } - end - - it "returns status #{expected_status}" do - expect(response).to have_http_status(expected_status) + describe 'illegal params' do + shared_examples :a_bad_request do + it do + expect { subject }.to raise_error(ActionController::BadRequest) + end end - end - it_behaves_like 'fetching history', :ok do - let(:allow_read_wiki) { true } + describe ':sort' do + let(:extra_params) { { sort: 'wibble' } } - it 'assigns @page_versions' do - expect(assigns(:page_versions)).to be_present + it_behaves_like :a_bad_request end - end - it_behaves_like 'fetching history', :not_found do - let(:allow_read_wiki) { false } - end - end - - describe 'GET #show' do - render_views - - let(:random_title) { nil } - - subject { get :show, params: { namespace_id: project.namespace, project_id: project, id: id, random_title: random_title } } - - context 'when page exists' do - let(:id) { wiki_title } + describe ':direction' do + let(:extra_params) { { direction: 'wibble' } } - it 'limits the retrieved pages for the sidebar' do - expect(controller).to receive(:load_wiki).and_return(project_wiki) - expect(project_wiki).to receive(:list_pages).with(limit: 15).and_call_original - - subject - - expect(response).to have_http_status(:ok) - expect(assigns(:page).title).to eq(wiki_title) + it_behaves_like :a_bad_request end - context 'when page content encoding is invalid' do - it 'sets flash error' do - allow(controller).to receive(:valid_encoding?).and_return(false) - - subject + describe ':show_children' do + let(:extra_params) { { show_children: 'wibble' } } - expect(response).to have_http_status(:ok) - expect(flash[:notice]).to eq('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.') - end + it_behaves_like :a_bad_request end end - context 'when the page does not exist' do - let(:id) { 'does not exist' } - - before do - subject - end - - it 'builds a new wiki page with the id as the title' do - expect(assigns(:page).title).to eq(id) - end + shared_examples 'sorting-and-nesting' do |sort_key, default_nesting| + context "the user is sorting by #{sort_key}" do + let(:extra_params) { sort_params.merge(nesting_params) } + let(:sort_params) { { sort: sort_key } } + let(:nesting_params) { {} } - context 'when a random_title param is present' do - let(:random_title) { true } - - it 'builds a new wiki page with no title' do - expect(assigns(:page).title).to be_empty + before do + subject end - end - end - context 'when page is a file' do - include WikiHelpers - - let(:id) { upload_file_to_wiki(project, user, file_name) } - - before do - subject - end - - context 'when file is an image' do - let(:file_name) { 'dk.png' } + it "sets nesting to #{default_nesting} by default" do + expect(assigns :nesting).to eq default_nesting + end - it 'delivers the image' do - expect(response.headers['Content-Disposition']).to match(/^inline/) - expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" + it 'hides children if the default requires it' do + expect(assigns :show_children).to be(default_nesting != ProjectWiki::NESTING_CLOSED) end - context 'when file is a svg' do - let(:file_name) { 'unsanitized.svg' } + ProjectWiki::NESTINGS.each do |nesting| + context "the user explicitly passes show_children = #{nesting}" do + let(:nesting_params) { { show_children: nesting } } - it 'delivers the image' do - expect(response.headers['Content-Disposition']).to match(/^inline/) - expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" + it 'sets nesting to the provided value' do + expect(assigns :nesting).to eq nesting + end end end - end - context 'when file is a pdf' do - let(:file_name) { 'git-cheat-sheet.pdf' } + context 'the user wants children hidden' do + let(:nesting_params) { { show_children: 'hidden' } } - it 'sets the content type to sets the content response headers' do - expect(response.headers['Content-Disposition']).to match(/^inline/) - expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true" + it 'hides children' do + expect(assigns :show_children).to be false + end end end end - end - - describe 'POST #preview_markdown' do - it 'renders json in a correct format' do - post :preview_markdown, params: { namespace_id: project.namespace, project_id: project, id: 'page/path', text: '*Markdown* text' } - - expect(json_response.keys).to match_array(%w(body references)) - end - end - - describe 'GET #edit' do - subject { get(:edit, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }) } - - context 'when page content encoding is invalid' do - it 'redirects to show' do - allow(controller).to receive(:valid_encoding?).and_return(false) - - subject - - expect(response).to redirect_to(project_wiki_path(project, project_wiki.list_pages.first)) - end - end - context 'when page content encoding is valid' do - render_views - - it 'shows the edit page' do - subject - - expect(response).to have_http_status(:ok) - expect(response.body).to include('Edit Page') - end - end - end - - describe 'PATCH #update' do - let(:new_title) { 'New title' } - let(:new_content) { 'New content' } - subject do - patch(:update, - params: { - namespace_id: project.namespace, - project_id: project, - id: wiki_title, - wiki: { title: new_title, content: new_content } - }) - end - - context 'when page content encoding is invalid' do - it 'redirects to show' do - allow(controller).to receive(:valid_encoding?).and_return(false) - - subject - expect(response).to redirect_to(project_wiki_path(project, project_wiki.list_pages.first)) - end - end - - context 'when page content encoding is valid' do - render_views - - it 'updates the page' do - subject - - wiki_page = project_wiki.list_pages(load_content: true).first - - expect(wiki_page.title).to eq new_title - expect(wiki_page.content).to eq new_content - end - end + include_examples 'sorting-and-nesting', ProjectWiki::CREATED_AT_ORDER, ProjectWiki::NESTING_FLAT + include_examples 'sorting-and-nesting', ProjectWiki::TITLE_ORDER, ProjectWiki::NESTING_CLOSED end def create_page(name, content) diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index ea7dd78329a..321f5ecdbc9 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -653,7 +653,7 @@ describe ProjectsController do describe "#destroy" do let(:admin) { create(:admin) } - it "redirects to the dashboard" do + it "redirects to the dashboard", :sidekiq_might_not_need_inline do controller.instance_variable_set(:@project, project) sign_in(admin) @@ -674,7 +674,7 @@ describe ProjectsController do target_project: project) end - it "closes all related merge requests" do + it "closes all related merge requests", :sidekiq_might_not_need_inline do project.merge_requests << merge_request sign_in(admin) diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index ebeed94c274..8f147f949d0 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -9,6 +9,49 @@ describe RegistrationsController do stub_feature_flags(invisible_captcha: false) end + describe '#new' do + subject { get :new } + + context 'with the experimental signup flow enabled and the user is part of the experimental group' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: true) + end + + it 'tracks the event with the right parameters' do + expect(Gitlab::Tracking).to receive(:event).with( + 'Growth::Acquisition::Experiment::SignUpFlow', + 'start', + label: anything, + property: 'experimental_group' + ) + subject + end + + it 'renders new template and sets the resource variable' do + expect(subject).to render_template(:new) + expect(assigns(:resource)).to be_a(User) + end + end + + context 'with the experimental signup flow enabled and the user is part of the control group' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: false) + end + + it 'does not track the event' do + expect(Gitlab::Tracking).not_to receive(:event) + subject + end + + it 'renders new template and sets the resource variable' do + subject + expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane')) + end + end + end + describe '#create' do let(:base_user_params) { { name: 'new_user', username: 'new_username', email: 'new@user.com', password: 'Any_password' } } let(:user_params) { { user: base_user_params } } @@ -217,6 +260,37 @@ describe RegistrationsController do end end + describe 'tracking data' do + context 'with the experimental signup flow enabled and the user is part of the control group' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: false) + end + + it 'tracks the event with the right parameters' do + expect(Gitlab::Tracking).to receive(:event).with( + 'Growth::Acquisition::Experiment::SignUpFlow', + 'end', + label: anything, + property: 'control_group' + ) + post :create, params: user_params + end + end + + context 'with the experimental signup flow enabled and the user is part of the experimental group' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: true) + end + + it 'does not track the event' do + expect(Gitlab::Tracking).not_to receive(:event) + post :create, params: user_params + end + end + end + it "logs a 'User Created' message" do stub_feature_flags(registrations_recaptcha: false) @@ -304,4 +378,22 @@ describe RegistrationsController do end end end + + describe '#update_role' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: true) + sign_in(create(:user)) + end + + it 'tracks the event with the right parameters' do + expect(Gitlab::Tracking).to receive(:event).with( + 'Growth::Acquisition::Experiment::SignUpFlow', + 'end', + label: anything, + property: 'experimental_group' + ) + patch :update_role, params: { user: { name: 'New name', role: 'software_developer' } } + end + end end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 2108cf1c8ae..53847e30a5c 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -34,6 +34,39 @@ describe SessionsController do end end end + + describe 'tracking data' do + context 'when the user is part of the experimental group' do + before do + stub_experiment_for_user(signup_flow: true) + end + + it 'doesn\'t pass tracking parameters to the frontend' do + get(:new) + expect(Gon.tracking_data).to be_nil + end + end + + context 'with the experimental signup flow enabled and the user is part of the control group' do + before do + stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: false) + allow_any_instance_of(described_class).to receive(:experimentation_subject_id).and_return('uuid') + end + + it 'passes the right tracking parameters to the frontend' do + get(:new) + expect(Gon.tracking_data).to eq( + { + category: 'Growth::Acquisition::Experiment::SignUpFlow', + action: 'start', + label: 'uuid', + property: 'control_group' + } + ) + end + end + end end describe '#create' do diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 9477eeb18d4..2608f717f1c 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -234,10 +234,7 @@ FactoryBot.define do trait :broken_repo do after(:create) do |project| - raise "Failed to create repository!" unless project.create_repository - - project.gitlab_shell.rm_directory(project.repository_storage, - File.join("#{project.disk_path}.git", 'refs')) + TestEnv.rm_storage_dir(project.repository_storage, "#{project.disk_path}.git/refs") end end diff --git a/spec/factories/wiki_pages.rb b/spec/factories/wiki_pages.rb index 761ba58edb2..3ac8fe4ae43 100644 --- a/spec/factories/wiki_pages.rb +++ b/spec/factories/wiki_pages.rb @@ -18,12 +18,12 @@ FactoryBot.define do association :wiki, factory: :project_wiki, strategy: :build initialize_with { new(wiki, page, true) } - before(:create) do |page, evaluator| - page.attributes = evaluator.attrs + before(:create) do |wiki_page, evaluator| + wiki_page.attributes = evaluator.attrs.with_indifferent_access end - to_create do |page| - page.create + to_create do |wiki_page| + wiki_page.create end end end diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index 235b6d0fd40..bac5c9f568e 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -134,11 +134,9 @@ describe 'Contributions Calendar', :js do shared_examples 'a day with activity' do |contribution_count:| include_context 'visit user page' - it 'displays calendar activity square color for 1 contribution' do + it 'displays calendar activity square for 1 contribution', :sidekiq_might_not_need_inline do expect(find('#js-overview')).to have_selector(get_cell_color_selector(contribution_count), count: 1) - end - it 'displays calendar activity square on the correct date' do today = Date.today.strftime(date_format) expect(find('#js-overview')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1) end @@ -154,7 +152,7 @@ describe 'Contributions Calendar', :js do describe 'issue title is shown on activity page' do include_context 'visit user page' - it 'displays calendar activity log' do + it 'displays calendar activity log', :sidekiq_might_not_need_inline do expect(find('#js-overview .overview-content-list .event-target-title')).to have_content issue_title end end @@ -186,11 +184,11 @@ describe 'Contributions Calendar', :js do end include_context 'visit user page' - it 'displays calendar activity squares for both days' do + it 'displays calendar activity squares for both days', :sidekiq_might_not_need_inline do expect(find('#js-overview')).to have_selector(get_cell_color_selector(1), count: 2) end - it 'displays calendar activity square for yesterday' do + it 'displays calendar activity square for yesterday', :sidekiq_might_not_need_inline do yesterday = Date.yesterday.strftime(date_format) expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, yesterday), count: 1) end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 96d8da845cb..94bcabd3ca4 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -102,7 +102,7 @@ describe 'Commits' do end describe 'Cancel all builds' do - it 'cancels commit', :js do + it 'cancels commit', :js, :sidekiq_might_not_need_inline do visit pipeline_path(pipeline) click_on 'Cancel running' expect(page).to have_content 'canceled' @@ -110,7 +110,7 @@ describe 'Commits' do end describe 'Cancel build' do - it 'cancels build', :js do + it 'cancels build', :js, :sidekiq_might_not_need_inline do visit pipeline_path(pipeline) find('.js-btn-cancel-pipeline').click expect(page).to have_content 'canceled' diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb index 03a2402a2d6..28b68e699e8 100644 --- a/spec/features/container_registry_spec.rb +++ b/spec/features/container_registry_spec.rb @@ -42,7 +42,7 @@ describe 'Container Registry', :js do expect(page).to have_content('my/image') end - it 'user removes entire container repository' do + it 'user removes entire container repository', :sidekiq_might_not_need_inline do visit_container_registry expect_any_instance_of(ContainerRepository).to receive(:delete_tags!).and_return(true) diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 07f0864fb3b..3f46772c4b0 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -56,7 +56,7 @@ describe 'Cycle Analytics', :js do expect(deploys_counter).to have_content('1') end - it 'shows data on each stage' do + it 'shows data on each stage', :sidekiq_might_not_need_inline do expect_issue_to_be_present click_stage('Plan') diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index ca994c95df8..4fd241dedd1 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -189,7 +189,7 @@ describe 'Group' do expect(page).to have_selector '#confirm_name_input:focus' end - it 'removes group' do + it 'removes group', :sidekiq_might_not_need_inline do expect { remove_with_confirm('Remove group', group.path) }.to change {Group.count}.by(-1) expect(group.members.all.count).to be_zero expect(page).to have_content "scheduled for deletion" diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb index e9471257544..89bf69dea7d 100644 --- a/spec/features/import/manifest_import_spec.rb +++ b/spec/features/import/manifest_import_spec.rb @@ -24,7 +24,7 @@ describe 'Import multiple repositories by uploading a manifest file', :js do expect(page).to have_content('https://android-review.googlesource.com/platform/build/blueprint') end - it 'imports successfully imports a project' do + it 'imports successfully imports a project', :sidekiq_might_not_need_inline do visit new_import_manifest_path attach_file('manifest', Rails.root.join('spec/fixtures/aosp_manifest.xml')) diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb index f3b534bca49..efd84cf67b0 100644 --- a/spec/features/issuables/markdown_references/internal_references_spec.rb +++ b/spec/features/issuables/markdown_references/internal_references_spec.rb @@ -64,7 +64,7 @@ describe "Internal references", :js do visit(project_issue_path(public_project, public_project_issue)) end - it "shows references" do + it "shows references", :sidekiq_might_not_need_inline do page.within("#merge-requests .merge-requests-title") do expect(page).to have_content("Related merge requests") expect(page).to have_css(".mr-count-badge") @@ -133,7 +133,7 @@ describe "Internal references", :js do visit(project_merge_request_path(public_project, public_project_merge_request)) end - it "shows references" do + it "shows references", :sidekiq_might_not_need_inline do expect(page).to have_content("mentioned in merge request #{private_project_merge_request.to_reference(public_project)}") .and have_content(private_project_user.name) end diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb index 8085918f533..596a374ec6d 100644 --- a/spec/features/issuables/markdown_references/jira_spec.rb +++ b/spec/features/issuables/markdown_references/jira_spec.rb @@ -46,7 +46,7 @@ describe "Jira", :js do end end - it "creates a note on the referenced issues" do + it "creates a note on the referenced issues", :sidekiq_might_not_need_inline do click_button("Comment") wait_for_requests diff --git a/spec/features/issues/notes_on_issues_spec.rb b/spec/features/issues/notes_on_issues_spec.rb index 5247baa58a1..74eb699c7ef 100644 --- a/spec/features/issues/notes_on_issues_spec.rb +++ b/spec/features/issues/notes_on_issues_spec.rb @@ -23,7 +23,7 @@ describe 'Create notes on issues', :js do submit_comment(note_text) end - it 'creates a note with reference and cross references the issue' do + it 'creates a note with reference and cross references the issue', :sidekiq_might_not_need_inline do page.within('div#notes li.note div.note-text') do expect(page).to have_content(note_text) expect(page.find('a')).to have_content(mention.to_reference) 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 be31c45b373..8322a6afa04 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 @@ -67,7 +67,7 @@ describe 'User creates branch and merge request on issue page', :js do end context 'when branch name is auto-generated' do - it 'creates a merge request' do + it 'creates a merge request', :sidekiq_might_not_need_inline do perform_enqueued_jobs do select_dropdown_option('create-mr') @@ -96,7 +96,7 @@ describe 'User creates branch and merge request on issue page', :js do context 'when branch name is custom' do let(:branch_name) { 'custom-branch-name' } - it 'creates a merge request' do + it 'creates a merge request', :sidekiq_might_not_need_inline do perform_enqueued_jobs do select_dropdown_option('create-mr', branch_name) diff --git a/spec/features/issues/user_creates_confidential_merge_request_spec.rb b/spec/features/issues/user_creates_confidential_merge_request_spec.rb index 24089bdeb81..838c0a6349c 100644 --- a/spec/features/issues/user_creates_confidential_merge_request_spec.rb +++ b/spec/features/issues/user_creates_confidential_merge_request_spec.rb @@ -42,7 +42,7 @@ describe 'User creates confidential merge request on issue page', :js do visit_confidential_issue end - it 'create merge request in fork' do + it 'create merge request in fork', :sidekiq_might_not_need_inline do click_button 'Create confidential merge request' page.within '.create-confidential-merge-request-dropdown-menu' do diff --git a/spec/features/markdown/metrics_spec.rb b/spec/features/markdown/metrics_spec.rb index 4de67cfcdbe..580826f4a29 100644 --- a/spec/features/markdown/metrics_spec.rb +++ b/spec/features/markdown/metrics_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching do +describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching, :sidekiq_might_not_need_inline do include PrometheusHelpers let(:user) { create(:user) } diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb index 030638cba71..fa53682b024 100644 --- a/spec/features/merge_request/maintainer_edits_fork_spec.rb +++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe 'a maintainer edits files on a source-branch of an MR from a fork', :js do +describe 'a maintainer edits files on a source-branch of an MR from a fork', :js, :sidekiq_might_not_need_inline do include ProjectForksHelper let(:user) { create(:user, username: 'the-maintainer') } let(:target_project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb index 4d305d43351..5e1ff232b80 100644 --- a/spec/features/merge_request/user_accepts_merge_request_spec.rb +++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe 'User accepts a merge request', :js do +describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inline do let(:merge_request) { create(:merge_request, :with_diffs, :simple, source_project: project) } let(:project) { create(:project, :public, :repository) } let(:user) { create(:user) } diff --git a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb index be403abcc4d..0ecd32565d0 100644 --- a/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb +++ b/spec/features/merge_request/user_allows_commits_from_memebers_who_can_merge_spec.rb @@ -23,7 +23,7 @@ describe 'create a merge request, allowing commits from members who can merge to sign_in(user) end - it 'allows setting possible' do + it 'allows setting possible', :sidekiq_might_not_need_inline do visit_new_merge_request check 'Allow commits from members who can merge to the target branch' @@ -35,7 +35,7 @@ describe 'create a merge request, allowing commits from members who can merge to expect(page).to have_content('Allows commits from members who can merge to the target branch') end - it 'shows a message when one of the projects is private' do + it 'shows a message when one of the projects is private', :sidekiq_might_not_need_inline do source_project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) visit_new_merge_request @@ -43,7 +43,7 @@ describe 'create a merge request, allowing commits from members who can merge to expect(page).to have_content('Not available for private projects') end - it 'shows a message when the source branch is protected' do + it 'shows a message when the source branch is protected', :sidekiq_might_not_need_inline do create(:protected_branch, project: source_project, name: 'fix') visit_new_merge_request diff --git a/spec/features/merge_request/user_creates_merge_request_spec.rb b/spec/features/merge_request/user_creates_merge_request_spec.rb index f92791cc810..afb792c2ab9 100644 --- a/spec/features/merge_request/user_creates_merge_request_spec.rb +++ b/spec/features/merge_request/user_creates_merge_request_spec.rb @@ -36,7 +36,7 @@ describe "User creates a merge request", :js do context "to a forked project" do let(:forked_project) { fork_project(project, user, namespace: user.namespace, repository: true) } - it "creates a merge request" do + it "creates a merge request", :sidekiq_might_not_need_inline do visit(project_new_merge_request_path(forked_project)) expect(page).to have_content("Source branch").and have_content("Target branch") diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb index da15a4bda4b..32e40740a61 100644 --- a/spec/features/merge_request/user_merges_merge_request_spec.rb +++ b/spec/features/merge_request/user_merges_merge_request_spec.rb @@ -10,7 +10,7 @@ describe "User merges a merge request", :js do end shared_examples "fast forward merge a merge request" do - it "merges a merge request" do + it "merges a merge request", :sidekiq_might_not_need_inline do expect(page).to have_content("Fast-forward merge without a merge commit").and have_button("Merge") page.within(".mr-state-widget") do diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index ffc12ffdbaf..e40276f74e4 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -142,7 +142,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do refresh end - it 'merges merge request' do + it 'merges merge request', :sidekiq_might_not_need_inline do expect(page).to have_content 'The changes were merged' expect(merge_request.reload).to be_merged end diff --git a/spec/features/merge_request/user_reverts_merge_request_spec.rb b/spec/features/merge_request/user_reverts_merge_request_spec.rb index 71270b13c14..906ff1d61b2 100644 --- a/spec/features/merge_request/user_reverts_merge_request_spec.rb +++ b/spec/features/merge_request/user_reverts_merge_request_spec.rb @@ -20,7 +20,7 @@ describe 'User reverts a merge request', :js do visit(merge_request_path(merge_request)) end - it 'reverts a merge request' do + it 'reverts a merge request', :sidekiq_might_not_need_inline do find("a[href='#modal-revert-commit']").click page.within('#modal-revert-commit') do @@ -33,7 +33,7 @@ describe 'User reverts a merge request', :js do wait_for_requests end - it 'does not revert a merge request that was previously reverted' do + it 'does not revert a merge request that was previously reverted', :sidekiq_might_not_need_inline do find("a[href='#modal-revert-commit']").click page.within('#modal-revert-commit') do @@ -51,7 +51,7 @@ describe 'User reverts a merge request', :js do expect(page).to have_content('Sorry, we cannot revert this merge request automatically.') end - it 'reverts a merge request in a new merge request' do + it 'reverts a merge request in a new merge request', :sidekiq_might_not_need_inline do find("a[href='#modal-revert-commit']").click page.within('#modal-revert-commit') do diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb index 8eeed7b0843..d9783f3388c 100644 --- a/spec/features/merge_request/user_sees_diff_spec.rb +++ b/spec/features/merge_request/user_sees_diff_spec.rb @@ -62,7 +62,7 @@ describe 'Merge request > User sees diff', :js do end context 'as author' do - it 'shows direct edit link' do + it 'shows direct edit link', :sidekiq_might_not_need_inline do sign_in(author_user) visit diffs_project_merge_request_path(project, merge_request) @@ -72,7 +72,7 @@ describe 'Merge request > User sees diff', :js do end context 'as user who needs to fork' do - it 'shows fork/cancel confirmation' do + it 'shows fork/cancel confirmation', :sidekiq_might_not_need_inline do sign_in(user) visit diffs_project_merge_request_path(project, merge_request) diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb index dd5662d83f2..abf159949db 100644 --- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb @@ -67,13 +67,13 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end end - it 'sees the latest detached merge request pipeline as the head pipeline' do + it 'sees the latest detached merge request pipeline as the head pipeline', :sidekiq_might_not_need_inline do page.within('.ci-widget-content') do expect(page).to have_content("##{detached_merge_request_pipeline.id}") end end - context 'when a user updated a merge request in the parent project' do + context 'when a user updated a merge request in the parent project', :sidekiq_might_not_need_inline do let!(:push_pipeline_2) do Ci::CreatePipelineService.new(project, user, ref: 'feature') .execute(:push) @@ -133,7 +133,7 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end end - context 'when a user merges a merge request in the parent project' do + context 'when a user merges a merge request in the parent project', :sidekiq_might_not_need_inline do before do click_button 'Merge when pipeline succeeds' @@ -196,7 +196,7 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end end - it 'sees the latest branch pipeline as the head pipeline' do + it 'sees the latest branch pipeline as the head pipeline', :sidekiq_might_not_need_inline do page.within('.ci-widget-content') do expect(page).to have_content("##{push_pipeline.id}") end @@ -204,7 +204,7 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end end - context 'when a user created a merge request from a forked project to the parent project' do + context 'when a user created a merge request from a forked project to the parent project', :sidekiq_might_not_need_inline do let(:merge_request) do create(:merge_request, source_project: forked_project, diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 9fadd46ed44..7c2c7ae4386 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -76,7 +76,7 @@ describe 'Merge request > User sees merge widget', :js do expect(find('.accept-merge-request')['disabled']).not_to be(true) end - it 'allows me to merge, see cherry-pick modal and load branches list' do + it 'allows me to merge, see cherry-pick modal and load branches list', :sidekiq_might_not_need_inline do wait_for_requests click_button 'Merge' @@ -191,7 +191,7 @@ describe 'Merge request > User sees merge widget', :js do end shared_examples 'pipeline widget' do - it 'shows head pipeline information' do + it 'shows head pipeline information', :sidekiq_might_not_need_inline do within '.ci-widget-content' do expect(page).to have_content("Detached merge request pipeline ##{pipeline.id} pending for #{pipeline.short_sha}") end @@ -230,7 +230,7 @@ describe 'Merge request > User sees merge widget', :js do end shared_examples 'pipeline widget' do - it 'shows head pipeline information' do + it 'shows head pipeline information', :sidekiq_might_not_need_inline do within '.ci-widget-content' do expect(page).to have_content("Merged result pipeline ##{pipeline.id} pending for #{pipeline.short_sha}") end @@ -371,7 +371,7 @@ describe 'Merge request > User sees merge widget', :js do visit project_merge_request_path(project, merge_request) end - it 'updates the MR widget' do + it 'updates the MR widget', :sidekiq_might_not_need_inline do click_button 'Merge' page.within('.mr-widget-body') do @@ -417,7 +417,7 @@ describe 'Merge request > User sees merge widget', :js do visit project_merge_request_path(project, merge_request) end - it 'user cannot remove source branch' do + it 'user cannot remove source branch', :sidekiq_might_not_need_inline do expect(page).not_to have_field('remove-source-branch-input') expect(page).to have_content('Deletes source branch') end diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb index 0391794649c..9c9e0dacb87 100644 --- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb @@ -21,7 +21,7 @@ describe 'Merge request > User sees notes from forked project', :js do sign_in(user) end - it 'user can reply to the comment' do + it 'user can reply to the comment', :sidekiq_might_not_need_inline do visit project_merge_request_path(project, merge_request) expect(page).to have_content('A commit comment') diff --git a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb index 3e15a9c136b..d258b98f4a9 100644 --- a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb @@ -28,7 +28,7 @@ describe 'Merge request > User sees pipelines from forked project', :js do visit project_merge_request_path(target_project, merge_request) end - it 'user visits a pipelines page' do + it 'user visits a pipelines page', :sidekiq_might_not_need_inline do page.within('.merge-request-tabs') { click_link 'Pipelines' } page.within('.ci-table') do diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb index 7a8b938486a..f3d8f2b42f8 100644 --- a/spec/features/merge_request/user_sees_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_spec.rb @@ -124,7 +124,7 @@ describe 'Merge request > User sees pipelines', :js do threads.each { |thr| thr.join } end - it 'user sees pipeline in merge request widget' do + it 'user sees pipeline in merge request widget', :sidekiq_might_not_need_inline do visit project_merge_request_path(project, @merge_request) expect(page.find(".ci-widget")).to have_content(TestEnv::BRANCH_SHA['feature']) diff --git a/spec/features/merge_requests/user_squashes_merge_request_spec.rb b/spec/features/merge_requests/user_squashes_merge_request_spec.rb index 4fc8c71e47e..a018c86fa9a 100644 --- a/spec/features/merge_requests/user_squashes_merge_request_spec.rb +++ b/spec/features/merge_requests/user_squashes_merge_request_spec.rb @@ -10,7 +10,7 @@ describe 'User squashes a merge request', :js do let!(:original_head) { project.repository.commit('master') } shared_examples 'squash' do - it 'squashes the commits into a single commit, and adds a merge commit' do + it 'squashes the commits into a single commit, and adds a merge commit', :sidekiq_might_not_need_inline do expect(page).to have_content('Merged') latest_master_commits = project.repository.commits_between(original_head.sha, 'master').map(&:raw) @@ -31,7 +31,7 @@ describe 'User squashes a merge request', :js do end shared_examples 'no squash' do - it 'accepts the merge request without squashing' do + it 'accepts the merge request without squashing', :sidekiq_might_not_need_inline do expect(page).to have_content('Merged') expect(project.repository).to be_merged_to_root_ref(source_branch) end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index e80a3cd32cc..0147963c0a3 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -22,7 +22,7 @@ describe 'Profile account page', :js do expect(User.exists?(user.id)).to be_truthy end - it 'deletes user', :js do + it 'deletes user', :js, :sidekiq_might_not_need_inline do click_button 'Delete account' fill_in 'password', with: '12345678' diff --git a/spec/features/projects/badges/pipeline_badge_spec.rb b/spec/features/projects/badges/pipeline_badge_spec.rb index f2c57d702a5..af936c80886 100644 --- a/spec/features/projects/badges/pipeline_badge_spec.rb +++ b/spec/features/projects/badges/pipeline_badge_spec.rb @@ -22,7 +22,7 @@ describe 'Pipeline Badge' do let!(:job) { create(:ci_build, pipeline: pipeline) } context 'when the pipeline was successful' do - it 'displays so on the badge' do + it 'displays so on the badge', :sidekiq_might_not_need_inline do job.success visit pipeline_project_badges_path(project, ref: ref, format: :svg) @@ -33,7 +33,7 @@ describe 'Pipeline Badge' do end context 'when the pipeline failed' do - it 'shows displays so on the badge' do + it 'shows displays so on the badge', :sidekiq_might_not_need_inline do job.drop visit pipeline_project_badges_path(project, ref: ref, format: :svg) @@ -52,7 +52,7 @@ describe 'Pipeline Badge' do allow(job).to receive(:prerequisites).and_return([double]) end - it 'displays the preparing badge' do + it 'displays the preparing badge', :sidekiq_might_not_need_inline do job.enqueue visit pipeline_project_badges_path(project, ref: ref, format: :svg) @@ -63,7 +63,7 @@ describe 'Pipeline Badge' do end context 'when the pipeline is running' do - it 'shows displays so on the badge' do + it 'shows displays so on the badge', :sidekiq_might_not_need_inline do create(:ci_build, pipeline: pipeline, name: 'second build', status_event: 'run') visit pipeline_project_badges_path(project, ref: ref, format: :svg) diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index 3b32d213754..e02a4579095 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -60,6 +60,13 @@ describe 'Editing file blob', :js do expect(page).to have_content 'NextFeature' end + it 'renders a URL in the content of file as a link' do + project.repository.create_file(user, 'file.yml', '# go to https://gitlab.com', message: 'testing', branch_name: branch) + visit project_edit_blob_path(project, tree_join(branch, 'file.yml')) + + expect(page).to have_selector('.ace_content .ace_line a') + end + context 'from blob file path' do before do visit project_blob_path(project, tree_join(branch, file_path)) diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index 9ec61743a11..8b7fef84dd7 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' describe 'Edit Project Settings' do + set(:project) { create(:project, :public, :repository) } + let(:member) { create(:user) } - let!(:project) { create(:project, :public, :repository) } let!(:issue) { create(:issue, project: project) } let(:non_member) { create(:user) } @@ -81,85 +82,88 @@ describe 'Edit Project Settings' do end describe 'project features visibility pages' do - let(:pipeline) { create(:ci_empty_pipeline, project: project) } - let(:job) { create(:ci_build, pipeline: pipeline) } - - let(:tools) do - { - builds: project_job_path(project, job), - issues: project_issues_path(project), - wiki: project_wiki_path(project, :home), - snippets: project_snippets_path(project), - merge_requests: project_merge_requests_path(project) - } + set(:pipeline) { create(:ci_empty_pipeline, project: project) } + set(:job) { create(:ci_build, pipeline: pipeline) } + + where(:method_name, :build_url) do + [ + [:builds, -> { project_job_path(project, job) }], + [:issues, -> { project_issues_path(project) }], + [:wiki, -> { project_wiki_path(project, :home) }], + [:snippets, -> { project_snippets_path(project) }], + [:merge_requests, -> { project_merge_requests_path(project) }] + ] end - context 'normal user' do - before do - sign_in(member) - end + with_them do + let(:url) { build_url.call } + let(:attr_name) { "#{method_name}_access_level" } + + context 'normal user' do + before do + project.team.truncate + sign_in(member) + end + + it 'renders 200 if tool is enabled' do + project.project_feature.update_attribute(attr_name, ProjectFeature::ENABLED) - it 'renders 200 if tool is enabled' do - tools.each do |method_name, url| - project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::ENABLED) visit url + expect(page.status_code).to eq(200) end - end - it 'renders 404 if feature is disabled' do - tools.each do |method_name, url| - project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::DISABLED) + it 'renders 404 if feature is disabled' do + project.project_feature.update_attribute(attr_name, ProjectFeature::DISABLED) + visit url + expect(page.status_code).to eq(404) end - end - it 'renders 404 if feature is enabled only for team members' do - project.team.truncate + it 'renders 404 if feature is enabled only for team members' do + project.project_feature.update_attribute(attr_name, ProjectFeature::PRIVATE) - tools.each do |method_name, url| - project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE) visit url + expect(page.status_code).to eq(404) end - end - it 'renders 200 if user is member of group' do - group = create(:group) - project.group = group - project.save + it 'renders 200 if user is member of group' do + group = create(:group) + project.group = group + project.save - group.add_owner(member) + group.add_owner(member) + + project.project_feature.update_attribute(attr_name, ProjectFeature::PRIVATE) - tools.each do |method_name, url| - project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE) visit url + expect(page.status_code).to eq(200) end end - end - context 'admin user' do - before do - non_member.update_attribute(:admin, true) - sign_in(non_member) - end + context 'admin user' do + before do + non_member.update_attribute(:admin, true) + project.team.truncate + sign_in(non_member) + end - it 'renders 404 if feature is disabled' do - tools.each do |method_name, url| + it 'renders 404 if feature is disabled' do project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::DISABLED) + visit url + expect(page.status_code).to eq(404) end - end - it 'renders 200 if feature is enabled only for team members' do - project.team.truncate - - tools.each do |method_name, url| + it 'renders 200 if feature is enabled only for team members' do project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE) + visit url + expect(page.status_code).to eq(200) end end diff --git a/spec/features/projects/files/user_creates_directory_spec.rb b/spec/features/projects/files/user_creates_directory_spec.rb index 19d95c87c6c..f828ee63cd7 100644 --- a/spec/features/projects/files/user_creates_directory_spec.rb +++ b/spec/features/projects/files/user_creates_directory_spec.rb @@ -71,7 +71,7 @@ describe 'Projects > Files > User creates a directory', :js do visit(project2_tree_path_root_ref) end - it 'creates a directory in a forked project' do + it 'creates a directory in a forked project', :sidekiq_might_not_need_inline do find('.add-to-tree').click click_link('New directory') diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb index 74c037641cd..23663aeaef0 100644 --- a/spec/features/projects/files/user_creates_files_spec.rb +++ b/spec/features/projects/files/user_creates_files_spec.rb @@ -42,7 +42,7 @@ describe 'Projects > Files > User creates files' do visit(project2_tree_path_root_ref) end - it 'opens new file page on a forked project' do + it 'opens new file page on a forked project', :sidekiq_might_not_need_inline do find('.add-to-tree').click click_link('New file') @@ -159,7 +159,7 @@ describe 'Projects > Files > User creates files' do end end - context 'when an user does not have write access' do + context 'when an user does not have write access', :sidekiq_might_not_need_inline do before do project2.add_reporter(user) visit(project2_tree_path_root_ref) diff --git a/spec/features/projects/files/user_deletes_files_spec.rb b/spec/features/projects/files/user_deletes_files_spec.rb index fd4783cfb6b..570813ce085 100644 --- a/spec/features/projects/files/user_deletes_files_spec.rb +++ b/spec/features/projects/files/user_deletes_files_spec.rb @@ -47,7 +47,7 @@ describe 'Projects > Files > User deletes files', :js do wait_for_requests end - it 'deletes the file in a forked project', :js do + it 'deletes the file in a forked project', :js, :sidekiq_might_not_need_inline do click_link('.gitignore') expect(page).to have_content('.gitignore') diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb index 56430721ed6..c0312f5bb62 100644 --- a/spec/features/projects/files/user_edits_files_spec.rb +++ b/spec/features/projects/files/user_edits_files_spec.rb @@ -136,7 +136,7 @@ describe 'Projects > Files > User edits files', :js do ) end - it 'inserts a content of a file in a forked project' do + it 'inserts a content of a file in a forked project', :sidekiq_might_not_need_inline do click_link('.gitignore') click_button('Edit') @@ -154,7 +154,7 @@ describe 'Projects > Files > User edits files', :js do expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca') end - it 'opens the Web IDE in a forked project' do + it 'opens the Web IDE in a forked project', :sidekiq_might_not_need_inline do click_link('.gitignore') click_button('Web IDE') @@ -168,7 +168,7 @@ describe 'Projects > Files > User edits files', :js do expect(page).to have_css('.ide .multi-file-tab', text: '.gitignore') end - it 'commits an edited file in a forked project' do + it 'commits an edited file in a forked project', :sidekiq_might_not_need_inline do click_link('.gitignore') find('.js-edit-blob').click @@ -199,7 +199,7 @@ describe 'Projects > Files > User edits files', :js do wait_for_requests end - it 'links to the forked project for editing' do + it 'links to the forked project for editing', :sidekiq_might_not_need_inline do click_link('.gitignore') find('.js-edit-blob').click diff --git a/spec/features/projects/files/user_replaces_files_spec.rb b/spec/features/projects/files/user_replaces_files_spec.rb index d50bc0a7d18..bdef40690a2 100644 --- a/spec/features/projects/files/user_replaces_files_spec.rb +++ b/spec/features/projects/files/user_replaces_files_spec.rb @@ -55,7 +55,7 @@ describe 'Projects > Files > User replaces files', :js do wait_for_requests end - it 'replaces an existed file with a new one in a forked project' do + it 'replaces an existed file with a new one in a forked project', :sidekiq_might_not_need_inline do click_link('.gitignore') expect(page).to have_content('.gitignore') diff --git a/spec/features/projects/files/user_uploads_files_spec.rb b/spec/features/projects/files/user_uploads_files_spec.rb index 74b5d7c5041..284f891731c 100644 --- a/spec/features/projects/files/user_uploads_files_spec.rb +++ b/spec/features/projects/files/user_uploads_files_spec.rb @@ -76,7 +76,7 @@ describe 'Projects > Files > User uploads files' do visit(project2_tree_path_root_ref) end - it 'uploads and commit a new file to a forked project', :js do + it 'uploads and commit a new file to a forked project', :js, :sidekiq_might_not_need_inline do find('.add-to-tree').click click_link('Upload file') diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb index 6792a6e2af0..0f97032eefa 100644 --- a/spec/features/projects/fork_spec.rb +++ b/spec/features/projects/fork_spec.rb @@ -27,7 +27,7 @@ describe 'Project fork' do expect(page).to have_css('a.disabled', text: 'Fork') end - it 'forks the project' do + it 'forks the project', :sidekiq_might_not_need_inline do visit project_path(project) click_link 'Fork' @@ -174,7 +174,7 @@ describe 'Project fork' do expect(page).to have_css('.fork-thumbnail.disabled') end - it 'links to the fork if the project was already forked within that namespace' do + it 'links to the fork if the project was already forked within that namespace', :sidekiq_might_not_need_inline do forked_project = fork_project(project, user, namespace: group, repository: true) visit new_project_fork_path(project) diff --git a/spec/features/projects/forks/fork_list_spec.rb b/spec/features/projects/forks/fork_list_spec.rb index 2dbe3d90bad..3b63d9a4c2d 100644 --- a/spec/features/projects/forks/fork_list_spec.rb +++ b/spec/features/projects/forks/fork_list_spec.rb @@ -15,7 +15,7 @@ describe 'listing forks of a project' do sign_in(user) end - it 'shows the forked project in the list with commit as description' do + it 'shows the forked project in the list with commit as description', :sidekiq_might_not_need_inline do visit project_forks_path(source) page.within('li.project-row') do diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 7618a2bdea3..b3ed550f45e 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -38,7 +38,7 @@ describe 'Import/Export - project export integration test', :js do sign_in(user) end - it 'exports a project successfully' do + it 'exports a project successfully', :sidekiq_might_not_need_inline do visit edit_project_path(project) expect(page).to have_content('Export project') diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 6f96da60a31..904c5390415 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -27,7 +27,7 @@ describe 'Import/Export - project import integration test', :js do let(:project_path) { 'test-project-name' + randomHex } context 'prefilled the path' do - it 'user imports an exported project successfully' do + it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do visit new_project_path fill_in :project_name, with: project_name, visible: true @@ -53,7 +53,7 @@ describe 'Import/Export - project import integration test', :js do end context 'path is not prefilled' do - it 'user imports an exported project successfully' do + it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do visit new_project_path click_import_project_tab click_link 'GitLab export' diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index f5d5bc7f5b9..c9568dbb7ce 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -166,7 +166,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do let(:source_project) { fork_project(project, user, repository: true) } let(:target_project) { project } - it 'shows merge request iid and source branch' do + it 'shows merge request iid and source branch', :sidekiq_might_not_need_inline do visit project_job_path(source_project, job) within '.js-pipeline-info' do @@ -214,7 +214,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do let(:source_project) { fork_project(project, user, repository: true) } let(:target_project) { project } - it 'shows merge request iid and source branch' do + it 'shows merge request iid and source branch', :sidekiq_might_not_need_inline do visit project_job_path(source_project, job) within '.js-pipeline-info' do diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 66807eb1c17..94fac9a2eb5 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -128,7 +128,7 @@ describe 'Pipeline', :js do end end - it 'cancels the running build and shows retry button' do + it 'cancels the running build and shows retry button', :sidekiq_might_not_need_inline do find('#ci-badge-deploy .ci-action-icon-container').click page.within('#ci-badge-deploy') do @@ -146,7 +146,7 @@ describe 'Pipeline', :js do end end - it 'cancels the preparing build and shows retry button' do + it 'cancels the preparing build and shows retry button', :sidekiq_might_not_need_inline do find('#ci-badge-deploy .ci-action-icon-container').click page.within('#ci-badge-deploy') do @@ -186,7 +186,7 @@ describe 'Pipeline', :js do end end - it 'unschedules the delayed job and shows play button as a manual job' do + it 'unschedules the delayed job and shows play button as a manual job', :sidekiq_might_not_need_inline do find('#ci-badge-delayed-job .ci-action-icon-container').click page.within('#ci-badge-delayed-job') do @@ -305,7 +305,9 @@ describe 'Pipeline', :js do find('.js-retry-button').click end - it { expect(page).not_to have_content('Retry') } + it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do + expect(page).not_to have_content('Retry') + end end end @@ -321,7 +323,9 @@ describe 'Pipeline', :js do click_on 'Cancel running' end - it { expect(page).not_to have_content('Cancel running') } + it 'does not show a "Cancel running" button', :sidekiq_might_not_need_inline do + expect(page).not_to have_content('Cancel running') + end end end @@ -400,7 +404,7 @@ describe 'Pipeline', :js do visit project_pipeline_path(source_project, pipeline) end - it 'shows the pipeline information' do + it 'shows the pipeline information', :sidekiq_might_not_need_inline do within '.pipeline-info' do expect(page).to have_content("#{pipeline.statuses.count} jobs " \ "for !#{merge_request.iid} " \ @@ -473,7 +477,7 @@ describe 'Pipeline', :js do visit project_pipeline_path(source_project, pipeline) end - it 'shows the pipeline information' do + it 'shows the pipeline information', :sidekiq_might_not_need_inline do within '.pipeline-info' do expect(page).to have_content("#{pipeline.statuses.count} jobs " \ "for !#{merge_request.iid} " \ @@ -651,7 +655,9 @@ describe 'Pipeline', :js do find('.js-retry-button').click end - it { expect(page).not_to have_content('Retry') } + it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do + expect(page).not_to have_content('Retry') + end end end @@ -663,7 +669,9 @@ describe 'Pipeline', :js do click_on 'Cancel running' end - it { expect(page).not_to have_content('Cancel running') } + it 'does not show a "Cancel running" button', :sidekiq_might_not_need_inline do + expect(page).not_to have_content('Cancel running') + end end end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 4fb72eb8737..a9a127da56f 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -133,14 +133,14 @@ describe 'Pipelines', :js do wait_for_requests end - it 'indicated that pipelines was canceled' do + it 'indicated that pipelines was canceled', :sidekiq_might_not_need_inline do expect(page).not_to have_selector('.js-pipelines-cancel-button') expect(page).to have_selector('.ci-canceled') end end end - context 'when pipeline is retryable' do + context 'when pipeline is retryable', :sidekiq_might_not_need_inline do let!(:build) do create(:ci_build, pipeline: pipeline, stage: 'test') @@ -185,33 +185,29 @@ describe 'Pipelines', :js do visit project_pipelines_path(source_project) end - shared_examples_for 'showing detached merge request pipeline information' do - it 'shows detached tag for the pipeline' do + shared_examples_for 'detached merge request pipeline' do + it 'shows pipeline information without pipeline ref', :sidekiq_might_not_need_inline do within '.pipeline-tags' do expect(page).to have_content('detached') end - end - it 'shows the link of the merge request' do within '.branch-commit' do expect(page).to have_link(merge_request.iid, href: project_merge_request_path(project, merge_request)) end - end - it 'does not show the ref of the pipeline' do within '.branch-commit' do expect(page).not_to have_link(pipeline.ref) end end end - it_behaves_like 'showing detached merge request pipeline information' + it_behaves_like 'detached merge request pipeline' context 'when source project is a forked project' do let(:source_project) { fork_project(project, user, repository: true) } - it_behaves_like 'showing detached merge request pipeline information' + it_behaves_like 'detached merge request pipeline' end end @@ -233,20 +229,16 @@ describe 'Pipelines', :js do end shared_examples_for 'Correct merge request pipeline information' do - it 'does not show detached tag for the pipeline' do + it 'does not show detached tag for the pipeline, and shows the link of the merge request, and does not show the ref of the pipeline', :sidekiq_might_not_need_inline do within '.pipeline-tags' do expect(page).not_to have_content('detached') end - end - it 'shows the link of the merge request' do within '.branch-commit' do expect(page).to have_link(merge_request.iid, href: project_merge_request_path(project, merge_request)) end - end - it 'does not show the ref of the pipeline' do within '.branch-commit' do expect(page).not_to have_link(pipeline.ref) end @@ -429,7 +421,7 @@ describe 'Pipelines', :js do find('.js-modal-primary-action').click end - it 'indicates that pipeline was canceled' do + it 'indicates that pipeline was canceled', :sidekiq_might_not_need_inline do expect(page).not_to have_selector('.js-pipelines-cancel-button') expect(page).to have_selector('.ci-canceled') end @@ -452,7 +444,7 @@ describe 'Pipelines', :js do expect(page).not_to have_selector('.js-pipelines-retry-button') end - it 'has failed pipeline' do + it 'has failed pipeline', :sidekiq_might_not_need_inline do expect(page).to have_selector('.ci-failed') end end diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb index 9f09c5c4501..c0089e3c28c 100644 --- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb @@ -107,4 +107,27 @@ describe 'Projects > Settings > User manages merge request settings' do expect(project.printing_merge_request_link_enabled).to be(false) end end + + describe 'Checkbox to remove source branch after merge', :js do + it 'is initially checked' do + checkbox = find_field('project_remove_source_branch_after_merge') + expect(checkbox).to be_checked + end + + it 'when unchecked sets :remove_source_branch_after_merge to false' do + uncheck('project_remove_source_branch_after_merge') + within('.merge-request-settings-form') do + find('.qa-save-merge-request-changes') + click_on('Save changes') + end + + find('.flash-notice') + checkbox = find_field('project_remove_source_branch_after_merge') + + expect(checkbox).not_to be_checked + + project.reload + expect(project.remove_source_branch_after_merge).to be(false) + end + end end diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb index 5c6b04a7141..a56b3e4955a 100644 --- a/spec/features/projects/wiki/markdown_preview_spec.rb +++ b/spec/features/projects/wiki/markdown_preview_spec.rb @@ -4,164 +4,54 @@ require 'spec_helper' describe 'Projects > Wiki > User previews markdown changes', :js do set(:user) { create(:user) } - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) } - let(:wiki_content) do - <<-HEREDOC -[regular link](regular) -[relative link 1](../relative) -[relative link 2](./relative) -[relative link 3](./e/f/relative) -[spaced link](title with spaces) - HEREDOC - end + set(:project) { create(:project, :wiki_repo, namespace: user.namespace) } + let(:project_wiki) { ProjectWiki.new(project, user) } before do project.add_maintainer(user) - sign_in(user) + init_home! end - context "while creating a new wiki page" do - context "when there are no spaces or hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a/b/c/d', content: wiki_content) - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are spaces in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a page/b page/c page/d page', content: wiki_content) - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a-page/b-page/c-page/d-page', content: wiki_content) - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") - end - end + def init_home! + create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) end - context "while editing a wiki page" do - context "when there are no spaces or hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a/b/c/d') - click_link 'Edit' - - fill_in :wiki_content, with: wiki_content - click_on "Preview" - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are spaces in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a page/b page/c page/d page') - click_link 'Edit' - - fill_in :wiki_content, with: wiki_content - click_on "Preview" - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") - end - end - - context "when there are hyphens in the page name" do - it "rewrites relative links as expected" do - create_wiki_page('a-page/b-page/c-page/d-page') - click_link 'Edit' - - fill_in :wiki_content, with: wiki_content - click_on "Preview" - - expect(page).to have_content("regular link") - - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>") - expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>") - end + def fill_in_content! + page.within '.wiki-form' do + fill_in :wiki_page_content, with: wiki_content end + end - context 'when rendering the preview' do - it 'renders content with CommonMark' do - create_wiki_page('a-page/b-page/c-page/common-mark') - click_link 'Edit' - - fill_in :wiki_content, with: "1. one\n - sublist\n" - click_on "Preview" - - # the above generates two separate lists (not embedded) in CommonMark - expect(page).to have_content("sublist") - expect(page).not_to have_xpath("//ol//li//ul") - end + def show_preview! + page.within '.wiki-form' do + click_on 'Preview' end end - it "does not linkify double brackets inside code blocks as expected" do - wiki_content = <<-HEREDOC - `[[do_not_linkify]]` - ``` - [[also_do_not_linkify]] - ``` - HEREDOC - - create_wiki_page('linkify_test', wiki_content) + context 'when writing a new page' do + let(:new_wiki_path) { 'a/b/c/d' } + let(:wiki_content) { 'Some [awesome wiki](content)' } - expect(page).to have_content("do_not_linkify") + it 'can show a preview of markdown content' do + visit project_wiki_pages_new_path(project, id: new_wiki_path) + fill_in_content! + show_preview! - expect(page.html).to include('[[do_not_linkify]]') - expect(page.html).to include('[[also_do_not_linkify]]') + expect(page).to have_link('awesome wiki') + end end - private - - def create_wiki_page(path, content = 'content') - visit project_wiki_path(project, wiki_page) + context 'when editing an existing page' do + let(:wiki_content) { 'Some [bemusing](content)' } + let(:wiki_page) { create(:wiki_page, wiki: project_wiki) } - click_link 'New page' + it 'can show a preview of markdown content, when writing' do + visit project_wiki_edit_path(project, wiki_page) + fill_in_content! + show_preview! - fill_in :wiki_title, with: path - fill_in :wiki_content, with: content - - click_button 'Create page' + expect(page).to have_link('bemusing') + end end end diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb index 56d0518015d..6b651ccb67a 100644 --- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb @@ -3,9 +3,15 @@ require "spec_helper" describe "User creates wiki page" do - let(:user) { create(:user) } - let(:wiki) { ProjectWiki.new(project, user) } + include CapybaraHelpers + include WikiHelpers + + set(:user) { create(:user) } + let(:project) { create(:project) } + let(:wiki) { ProjectWiki.new(project, user) } + let(:new_page) { WikiPage.new(wiki) } + let(:message_field) { form_field_name(new_page, :message) } before do project.add_maintainer(user) @@ -13,38 +19,78 @@ describe "User creates wiki page" do sign_in(user) end + def start_writing(page_path) + click_link("New page") + fill_in(:wiki_page_title, with: page_path) + end + + def create_page(attrs = {}) + page.within(".wiki-form") do + attrs.each do |k, v| + fill_in("wiki_page_#{k}".to_sym, with: v) + end + end + click_on("Create page") + end + + shared_examples 'updates commit message' do + describe 'commit message', :js do + it "has `Create home` as a commit message" do + wait_for_requests + + expect(page).to have_field(message_field, with: "Create home") + end + end + end + context "when wiki is empty" do before do visit(project_wikis_path(project)) click_link "Create your first page" + find('.wiki-form') end context "in a user namespace" do let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } + let(:wiki_page_content) { '' } it "shows validation error message" do - page.within(".wiki-form") do - fill_in(:wiki_content, with: "") + create_page - click_on("Create page") - end - - expect(page).to have_content("The form contains the following error:").and have_content("Content can't be blank") - - page.within(".wiki-form") do - fill_in(:wiki_content, with: "[link test](test)") + expect(page) + .to have_content("The form contains the following error:") + .and have_content("Content can't be blank") + .and have_css('.wiki-form') + .and have_css('.qa-create-page-button') + end - click_on("Create page") - end + it 'offers to create pages that do not yet exist' do + create_page(content: "[link test](test)") - expect(page).to have_content("Home").and have_content("link test") + expect(page) + .to have_content("Home") + .and have_content("link test") click_link("link test") expect(page).to have_content("Create New Page") end + it "has a link to the parent directory in the pages sidebar" do + wiki_full_path = "one/two/three-test" + create_page(title: wiki_full_path, content: 'wiki content') + + wiki_page = wiki.find_page(wiki_full_path) + expect(wiki_page).to be_present + dir = wiki.find_dir(wiki_page.directory) + expect(dir).to be_present + + expect(current_path).to include(wiki_full_path) + + expect(page).to have_link(dir.slug, href: project_wiki_dir_path(project, dir)) + end + it "shows non-escaped link in the pages list", :quarantine do fill_in(:wiki_title, with: "one/two/three-test") @@ -58,19 +104,17 @@ describe "User creates wiki page" do expect(page).to have_xpath("//a[@href='/#{project.full_path}/wikis/one/two/three-test']") end - it "has `Create home` as a commit message", :js do - wait_for_requests - - expect(page).to have_field("wiki[message]", with: "Create home") - end + it_behaves_like 'updates commit message' it "creates a page from the home page" do - fill_in(:wiki_content, with: "[test](test)\n[GitLab API doc](api)\n[Rake tasks](raketasks)\n# Wiki header\n") - fill_in(:wiki_message, with: "Adding links to wiki") + page_content = <<~WIKI_CONTENT + [test](test) + [GitLab API doc](api) + [Rake tasks](raketasks) + # Wiki header + WIKI_CONTENT - page.within(".wiki-form") do - click_button("Create page") - end + create_page(content: page_content, message: "Adding links to wiki") expect(current_path).to eq(project_wiki_path(project, "home")) expect(page).to have_content("test GitLab API doc Rake tasks Wiki header") @@ -111,7 +155,7 @@ describe "User creates wiki page" do end end - it "creates ASCII wiki with LaTeX blocks", :js do + it "creates ASCIIdoc wiki with LaTeX blocks", :js do stub_application_setting(plantuml_url: "http://localhost", plantuml_enabled: true) ascii_content = <<~MD @@ -132,37 +176,25 @@ describe "User creates wiki page" do stem:[2+2] is 4 MD - find("#wiki_format option[value=asciidoc]").select_option - - fill_in(:wiki_content, with: ascii_content) + find("#wiki_page_format option[value=asciidoc]").select_option - page.within(".wiki-form") do - click_button("Create page") - end + create_page(content: ascii_content) page.within ".md" do expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4") end end - it_behaves_like 'wiki file attachments', :quarantine + it_behaves_like 'wiki file attachments' end - context "in a group namespace", :js do + context "in a group namespace" do let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } - it "has `Create home` as a commit message" do - wait_for_requests - - expect(page).to have_field("wiki[message]", with: "Create home") - end - - it "creates a page from the home page", :quarantine do - page.within(".wiki-form") do - fill_in(:wiki_content, with: "My awesome wiki!") + it_behaves_like 'updates commit message' - click_button("Create page") - end + it "creates a page from the home page" do + create_page(content: "My awesome wiki!") expect(page).to have_content("Home") .and have_content("Last edited by #{user.name}") @@ -178,76 +210,37 @@ describe "User creates wiki page" do visit(project_wikis_path(project)) end - context "in a user namespace" do - let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - - context "via the `new wiki page` page" do - it "creates a page with a single word" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "foo") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create foo") - - click_button("Create page") - - expect(page).to have_content("foo") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - - it "creates a page with spaces in the name" do - click_link("New page") + shared_examples 'creates page by slug' do |slug, unslug| + it "creates #{slug}" do + start_writing(slug) - page.within(".wiki-form") do - fill_in(:wiki_title, with: "Spaces in the name") - fill_in(:wiki_content, with: "My awesome wiki!") - end + # Commit message field should have correct value. + expect(page).to have_field(message_field, with: "Create #{unslug}") - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create Spaces in the name") + create_page(content: "My awesome wiki!") - click_button("Create page") - - expect(page).to have_content("Spaces in the name") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end - - it "creates a page with hyphens in the name" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "hyphens-in-the-name") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create hyphens in the name") - - page.within(".wiki-form") do - fill_in(:wiki_content, with: "My awesome wiki!") + expect(page).to have_content(unslug) + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") + end + end - click_button("Create page") - end + context "in a user namespace" do + let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } - expect(page).to have_content("hyphens in the name") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end + context "via the `new wiki page` page" do + include_examples 'creates page by slug', 'foo', 'foo' + include_examples 'creates page by slug', 'Spaces in the name', 'Spaces in the name' + include_examples 'creates page by slug', 'Hyphens-in-the-name', 'Hyphens in the name' end it "shows the emoji autocompletion dropdown" do - click_link("New page") + start_writing('text-autocomplete') page.within(".wiki-form") do - find("#wiki_content").native.send_keys("") + find("#wiki_page_content").native.send_keys("") - fill_in(:wiki_content, with: ":") + fill_in(:wiki_page_content, with: ":") end expect(page).to have_selector(".atwho-view") @@ -258,23 +251,9 @@ describe "User creates wiki page" do let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) } context "via the `new wiki page` page" do - it "creates a page" do - click_link("New page") - - page.within(".wiki-form") do - fill_in(:wiki_title, with: "foo") - fill_in(:wiki_content, with: "My awesome wiki!") - end - - # Commit message field should have correct value. - expect(page).to have_field("wiki[message]", with: "Create foo") - - click_button("Create page") - - expect(page).to have_content("foo") - .and have_content("Last edited by #{user.name}") - .and have_content("My awesome wiki!") - end + include_examples 'creates page by slug', 'foo', 'foo' + include_examples 'creates page by slug', 'Spaces in the name', 'Spaces in the name' + include_examples 'creates page by slug', 'Hyphens-in-the-name', 'Hyphens in the name' end end end diff --git a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb index 38e5e292064..9b9d3100bf5 100644 --- a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb @@ -6,6 +6,7 @@ describe 'User deletes wiki page', :js do let(:user) { create(:user) } let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:wiki_page) { create(:wiki_page, wiki: project.wiki) } + let(:project_wiki) { ProjectWiki.new(project, user) } before do sign_in(user) @@ -18,5 +19,6 @@ describe 'User deletes wiki page', :js do find('.modal-footer .btn-danger').click expect(page).to have_content('Page was successfully deleted') + expect(project_wiki.find_page(wiki_page.slug)).to be nil end end diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb index 3f3711f9eb8..5ab44e83f73 100644 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb @@ -10,6 +10,13 @@ describe 'User updates wiki page' do sign_in(user) end + def create_page(attrs = {}) + page.within('.wiki-form') do + attrs.each { |k, v| fill_in("wiki_page_#{k}".to_sym, with: v) } + click_on('Create page') + end + end + context 'when wiki is empty' do before do visit(project_wikis_path(project)) @@ -28,12 +35,7 @@ describe 'User updates wiki page' do end it 'updates a page that has a path', :js do - fill_in(:wiki_title, with: 'one/two/three-test') - - page.within '.wiki-form' do - fill_in(:wiki_content, with: 'wiki content') - click_on('Create page') - end + create_page(title: 'one/two/three-test', content: 'wiki content') expect(current_path).to include('one/two/three-test') expect(find('.wiki-pages')).to have_content('three') @@ -72,9 +74,9 @@ describe 'User updates wiki page' do it 'updates a page', :js do # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Update home') + expect(page).to have_field('wiki_page[message]', with: 'Update home') - fill_in(:wiki_content, with: 'My awesome wiki!') + fill_in(:wiki_page_content, with: 'My awesome wiki!') click_button('Save changes') expect(page).to have_content('Home') @@ -83,31 +85,31 @@ describe 'User updates wiki page' do end it 'updates the commit message as the title is changed', :js do - fill_in(:wiki_title, with: 'Wiki title') + fill_in(:wiki_page_title, with: 'Wiki title') - expect(page).to have_field('wiki[message]', with: 'Update Wiki title') + expect(page).to have_field('wiki_page[message]', with: 'Update Wiki title') end it 'does not allow XSS', :js do - fill_in(:wiki_title, with: '<script>') + fill_in(:wiki_page_title, with: '<script>') - expect(page).to have_field('wiki[message]', with: 'Update <script>') + expect(page).to have_field('wiki_page[message]', with: 'Update <script>') end it 'shows a validation error message' do - fill_in(:wiki_content, with: '') + fill_in(:wiki_page_content, with: '') click_button('Save changes') expect(page).to have_selector('.wiki-form') expect(page).to have_content('Edit Page') expect(page).to have_content('The form contains the following error:') expect(page).to have_content("Content can't be blank") - expect(find('textarea#wiki_content').value).to eq('') + expect(find('textarea#wiki_page_content').value).to eq('') end it 'shows the emoji autocompletion dropdown', :js do - find('#wiki_content').native.send_keys('') - fill_in(:wiki_content, with: ':') + find('#wiki_page_content').native.send_keys('') + fill_in(:wiki_page_content, with: ':') expect(page).to have_selector('.atwho-view') end @@ -143,9 +145,9 @@ describe 'User updates wiki page' do it 'updates a page', :js do # Commit message field should have correct value. - expect(page).to have_field('wiki[message]', with: 'Update home') + expect(page).to have_field('wiki_page[message]', with: 'Update home') - fill_in(:wiki_content, with: 'My awesome wiki!') + fill_in(:wiki_page_content, with: 'My awesome wiki!') click_button('Save changes') @@ -169,50 +171,43 @@ describe 'User updates wiki page' do visit(project_wiki_edit_path(project, wiki_page)) end - it 'moves the page to the root folder' do - fill_in(:wiki_title, with: "/#{page_name}") + def edit_title!(title) + fill_in(:wiki_page_title, with: title) click_button('Save changes') + end + + it 'moves the page to the root folder' do + edit_title!("/#{page_name}") expect(current_path).to eq(project_wiki_path(project, page_name)) end it 'moves the page to other dir' do - new_page_dir = "foo1/bar1/#{page_name}" - - fill_in(:wiki_title, with: new_page_dir) - - click_button('Save changes') + new_page_path = "baz/quux/#{page_name}" + edit_title!(new_page_path) - expect(current_path).to eq(project_wiki_path(project, new_page_dir)) + expect(current_path).to eq(project_wiki_path(project, new_page_path)) end it 'remains in the same place if title has not changed' do original_path = project_wiki_path(project, wiki_page) - - fill_in(:wiki_title, with: page_name) - - click_button('Save changes') + edit_title!(page_name) expect(current_path).to eq(original_path) end it 'can be moved to a different dir with a different name' do - new_page_dir = "foo1/bar1/new_page_name" - - fill_in(:wiki_title, with: new_page_dir) + new_page_path = "quux/baz/new_page_name" + edit_title!(new_page_path) - click_button('Save changes') - - expect(current_path).to eq(project_wiki_path(project, new_page_dir)) + expect(current_path).to eq(project_wiki_path(project, new_page_path)) end it 'can be renamed and moved to the root folder' do new_name = 'new_page_name' - fill_in(:wiki_title, with: "/#{new_name}") - - click_button('Save changes') + edit_title!("/#{new_name}") expect(current_path).to eq(project_wiki_path(project, new_name)) end @@ -220,9 +215,7 @@ describe 'User updates wiki page' do it 'squishes the title before creating the page' do new_page_dir = " foo1 / bar1 / #{page_name} " - fill_in(:wiki_title, with: new_page_dir) - - click_button('Save changes') + edit_title!(new_page_dir) expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}")) end diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb index 77e725e7f11..af8f86106d9 100644 --- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb @@ -8,10 +8,11 @@ describe 'User views a wiki page' do let(:user) { create(:user) } let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } let(:path) { 'image.png' } + let(:wiki_content) { "Look at this [image](#{path})\n\n ![alt text](#{path})" } let(:wiki_page) do create(:wiki_page, wiki: project.wiki, - attrs: { title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})" }) + attrs: { title: 'home', content: wiki_content }) end before do @@ -19,17 +20,18 @@ describe 'User views a wiki page' do sign_in(user) end + def create_page(attrs = {}) + page.within('.wiki-form') do + attrs.each { |k, v| fill_in("wiki_page_#{k}".to_sym, with: v) } + click_on('Create page') + end + end + context 'when wiki is empty' do before do visit(project_wikis_path(project)) click_link "Create your first page" - - fill_in(:wiki_title, with: 'one/two/three-test') - - page.within('.wiki-form') do - fill_in(:wiki_content, with: 'wiki content') - click_on('Create page') - end + create_page(title: 'one/two/three-test', content: 'wiki content') end it 'shows the history of a page that has a path', :js do @@ -83,24 +85,27 @@ describe 'User views a wiki page' do context 'shows a file stored in a page' do let(:path) { upload_file_to_wiki(project, user, 'dk.png') } + let(:image_path) { project_wiki_path(project, path) } it do - expect(page).to have_xpath("//img[@data-src='#{project.wiki.wiki_base_path}/#{path}']") - expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}") + expect(page).to have_xpath("//img[@data-src='#{image_path}']") + expect(page).to have_link('image', href: "#{image_path}") click_on('image') - expect(current_path).to match("wikis/#{path}") + expect(current_path).to match(path) expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved end end it 'shows the creation page if file does not exist' do - expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}") + href = project_wiki_path(project, path) + + expect(page).to have_link('image', href: href) click_on('image') - expect(current_path).to match("wikis/#{path}") + expect(current_path).to match(href) expect(page).to have_content('Create New Page') end end diff --git a/spec/features/projects/wiki/user_views_wiki_pages_spec.rb b/spec/features/projects/wiki/user_views_wiki_pages_spec.rb index 6740df1d4ed..adb59c891c6 100644 --- a/spec/features/projects/wiki/user_views_wiki_pages_spec.rb +++ b/spec/features/projects/wiki/user_views_wiki_pages_spec.rb @@ -7,6 +7,7 @@ describe 'User views wiki pages' do let(:user) { create(:user) } let(:project) { create(:project, :wiki_repo, namespace: user.namespace) } + let(:project_wiki) { ProjectWiki.new(project, user) } let!(:wiki_page1) do create(:wiki_page, wiki: project.wiki, attrs: { title: '3 home', content: '3' }) @@ -17,73 +18,182 @@ describe 'User views wiki pages' do let!(:wiki_page3) do create(:wiki_page, wiki: project.wiki, attrs: { title: '2 home', content: '2' }) end + let!(:wiki_page4) do + create(:wiki_page, wiki: project.wiki, attrs: { title: 'sub-folder/0', content: 'a' }) + end + let!(:wiki_page5) do + create(:wiki_page, wiki: project.wiki, attrs: { title: 'sub-folder/b', content: 'b' }) + end + + let(:page_link_selector) { 'a' } let(:pages) do - page.find('.wiki-pages-list').all('li').map { |li| li.find('a') } + page.all(".wiki-pages-list li #{page_link_selector}") end + let(:wikis_allow_change_nesting) { false } before do + stub_feature_flags(wikis_allow_change_nesting: wikis_allow_change_nesting) project.add_maintainer(user) sign_in(user) visit(project_wikis_pages_path(project)) end + def sort_desc! + page.within('.wiki-sort-dropdown') do + page.find('.qa-reverse-sort').click + end + end + + def sort_by_created_at! + page.within('.wiki-sort-dropdown') do + click_button('Title') + click_link('Created date') + end + end + + shared_examples 'correctly_sorted_pages' do + it 'has pages displayed in correct order' do + displayed_texts = pages.map(&:text) + expect(displayed_texts).to eq expected_sequence.map(&:title) + end + end + context 'ordered by title' do - let(:pages_ordered_by_title) { [wiki_page2, wiki_page3, wiki_page1] } + let(:sub_folder) { project_wiki.find_dir('sub-folder') } - context 'asc' do - it 'pages are displayed in direct order' do - pages.each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_title[index].title) + context 'default display settings' do + context 'asc' do + let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, sub_folder] } + + it_behaves_like 'correctly_sorted_pages' + end + + context 'desc' do + before do + sort_desc! end + + let(:expected_sequence) { [sub_folder, wiki_page1, wiki_page3, wiki_page2] } + + it_behaves_like 'correctly_sorted_pages' end end - context 'desc' do - before do - page.within('.wiki-sort-dropdown') do - page.find('.rspec-reverse-sort').click + context 'changing nesting is disabled' do + let(:wikis_allow_change_nesting) { false } + + it 'does not display a nesting controller' do + expect(page).not_to have_css('.wiki-nesting-dropdown') + end + end + + context 'changing nesting is enabled' do + let(:wikis_allow_change_nesting) { true } + + it 'displays a nesting controller' do + expect(page).to have_css('.wiki-nesting-dropdown') + end + + context 'tree' do + before do + page.within('.wiki-nesting-dropdown') do + click_link 'Show folder contents' + end + end + + context 'asc' do + let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, sub_folder, wiki_page4, wiki_page5] } + + it_behaves_like 'correctly_sorted_pages' + end + + context 'desc' do + before do + sort_desc! + end + + let(:expected_sequence) { [sub_folder, wiki_page5, wiki_page4, wiki_page1, wiki_page3, wiki_page2] } + + it_behaves_like 'correctly_sorted_pages' end end - it 'pages are displayed in reversed order' do - pages.reverse_each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_title[index].title) + context 'nested' do + before do + page.within('.wiki-nesting-dropdown') do + click_link 'Hide folder contents' + end + end + + context 'asc' do + let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, sub_folder] } + + it_behaves_like 'correctly_sorted_pages' + end + + context 'desc' do + before do + sort_desc! + end + + let(:expected_sequence) { [sub_folder, wiki_page1, wiki_page3, wiki_page2] } + + it_behaves_like 'correctly_sorted_pages' + end + end + + context 'flat' do + before do + page.within('.wiki-nesting-dropdown') do + click_link 'Show files separately' + end + end + + let(:page_link_selector) { 'a.wiki-page-title' } + + context 'asc' do + let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, wiki_page4, wiki_page5] } + + it_behaves_like 'correctly_sorted_pages' + end + + context 'desc' do + before do + sort_desc! + end + + let(:expected_sequence) { [wiki_page5, wiki_page4, wiki_page1, wiki_page3, wiki_page2] } + + it_behaves_like 'correctly_sorted_pages' end end end end context 'ordered by created_at' do - let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3] } + let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3, wiki_page4, wiki_page5] } before do - page.within('.wiki-sort-dropdown') do - click_button('Title') - click_link('Created date') - end + sort_by_created_at! end + let(:page_link_selector) { 'a.wiki-page-title' } + context 'asc' do - it 'pages are displayed in direct order' do - pages.each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_created_at[index].title) - end - end + let(:expected_sequence) { [wiki_page1, wiki_page2, wiki_page3, wiki_page4, wiki_page5] } + + it_behaves_like 'correctly_sorted_pages' end context 'desc' do before do - page.within('.wiki-sort-dropdown') do - page.find('.rspec-reverse-sort').click - end + sort_desc! end - it 'pages are displayed in reversed order' do - pages.reverse_each.with_index do |page_title, index| - expect(page_title.text).to eq(pages_ordered_by_created_at[index].title) - end - end + let(:expected_sequence) { [wiki_page5, wiki_page4, wiki_page3, wiki_page2, wiki_page1] } + + it_behaves_like 'correctly_sorted_pages' end end end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 67ae26d8d1e..df71a4f3f70 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -190,7 +190,7 @@ describe 'Project' do sign_in user end - it 'shows a link to the source project when it is available' do + it 'shows a link to the source project when it is available', :sidekiq_might_not_need_inline do visit project_path(forked_project) expect(page).to have_content('Forked from') @@ -206,7 +206,7 @@ describe 'Project' do expect(page).not_to have_content('Forked from') end - it 'shows the name of the deleted project when the source was deleted' do + it 'shows the name of the deleted project when the source was deleted', :sidekiq_might_not_need_inline do forked_project Projects::DestroyService.new(base_project, base_project.owner).execute @@ -218,7 +218,7 @@ describe 'Project' do context 'a fork of a fork' do let(:fork_of_fork) { fork_project(forked_project, user, repository: true) } - it 'links to the base project if the source project is removed' do + it 'links to the base project if the source project is removed', :sidekiq_might_not_need_inline do fork_of_fork Projects::DestroyService.new(forked_project, user).execute @@ -263,7 +263,7 @@ describe 'Project' do expect(page).to have_selector '#confirm_name_input:focus' end - it 'removes a project' do + it 'removes a project', :sidekiq_might_not_need_inline do expect { remove_with_confirm('Remove project', project.path) }.to change { Project.count }.by(-1) expect(page).to have_content "Project '#{project.full_name}' is in the process of being deleted." expect(Project.all.count).to be_zero diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb index 2615e8400a4..9e2634657a0 100644 --- a/spec/features/signed_commits_spec.rb +++ b/spec/features/signed_commits_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' describe 'GPG signed commits' do let(:project) { create(:project, :public, :repository) } - it 'changes from unverified to verified when the user changes his email to match the gpg key' do + it 'changes from unverified to verified when the user changes his email to match the gpg key', :sidekiq_might_not_need_inline do ref = GpgHelpers::SIGNED_AND_AUTHORED_SHA user = create(:user, email: 'unrelated.user@example.org') @@ -30,7 +30,7 @@ describe 'GPG signed commits' do expect(page).to have_button 'Verified' end - it 'changes from unverified to verified when the user adds the missing gpg key' do + it 'changes from unverified to verified when the user adds the missing gpg key', :sidekiq_might_not_need_inline do ref = GpgHelpers::SIGNED_AND_AUTHORED_SHA user = create(:user, email: GpgHelpers::User1.emails.first) diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index 2f8b715289c..cf30776786b 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe 'Unsubscribe links' do +describe 'Unsubscribe links', :sidekiq_might_not_need_inline do include Warden::Test::Helpers let(:recipient) { create(:user) } diff --git a/spec/features/user_sees_revert_modal_spec.rb b/spec/features/user_sees_revert_modal_spec.rb index 24b4f8dd4aa..c0cffe885de 100644 --- a/spec/features/user_sees_revert_modal_spec.rb +++ b/spec/features/user_sees_revert_modal_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe 'Merge request > User sees revert modal', :js do +describe 'Merge request > User sees revert modal', :js, :sidekiq_might_not_need_inline do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index 562d6fcab1b..8a82d3f3bd0 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -413,6 +413,7 @@ end describe 'With original flow' do before do stub_experiment(signup_flow: false) + stub_experiment_for_user(signup_flow: false) end it_behaves_like 'Signup' @@ -421,6 +422,7 @@ end describe 'With experimental flow' do before do stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: true) end it_behaves_like 'Signup' diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index c27ce263bf0..6c10a617279 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -163,6 +163,20 @@ describe IssuesFinder do end end + context 'filtering by nonexistent author ID and issue term using CTE for search' do + let(:params) do + { + author_id: 'does-not-exist', + search: 'git', + attempt_group_search_optimizations: true + } + end + + it 'returns no results' do + expect(issues).to be_empty + end + end + context 'filtering by milestone' do let(:params) { { milestone_title: milestone.title } } diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index a396284f1e9..bc85a622119 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -23,6 +23,18 @@ describe MergeRequestsFinder do expect(merge_requests).to contain_exactly(merge_request1) end + it 'filters by nonexistent author ID and MR term using CTE for search' do + params = { + author_id: 'does-not-exist', + search: 'git', + attempt_group_search_optimizations: true + } + + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to be_empty + end + it 'filters by projects' do params = { projects: [project2.id, project3.id] } diff --git a/spec/fixtures/api/schemas/public_api/v4/blobs.json b/spec/fixtures/api/schemas/public_api/v4/blobs.json index a812815838f..5dcefb42367 100644 --- a/spec/fixtures/api/schemas/public_api/v4/blobs.json +++ b/spec/fixtures/api/schemas/public_api/v4/blobs.json @@ -5,6 +5,7 @@ "properties" : { "basename": { "type": "string" }, "data": { "type": "string" }, + "path": { "type": ["string"] }, "filename": { "type": ["string"] }, "id": { "type": ["string", "null"] }, "project_id": { "type": "integer" }, @@ -12,7 +13,7 @@ "startline": { "type": "integer" } }, "required": [ - "basename", "data", "filename", "id", "ref", "startline", "project_id" + "basename", "data", "path", "filename", "id", "ref", "startline", "project_id" ], "additionalProperties": false } diff --git a/spec/frontend/fixtures/static/environments_logs.html b/spec/frontend/fixtures/static/environments_logs.html index ccf9c364154..4e242b77d1f 100644 --- a/spec/frontend/fixtures/static/environments_logs.html +++ b/spec/frontend/fixtures/static/environments_logs.html @@ -2,8 +2,7 @@ class="js-kubernetes-logs" data-current-environment-name="production" data-environments-path="/root/my-project/environments.json" - data-logs-page="/root/my-project/environments/1/logs" - data-logs-path="/root/my-project/environments/1/logs.json" + data-logs-endpoint="/root/my-project/environments/1/logs.json" > <div class="build-page-pod-logs"> <div class="build-trace-container prepend-top-default"> diff --git a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap index 08173f4f0c4..706c26403c0 100644 --- a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap +++ b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap @@ -62,19 +62,23 @@ exports[`Repository last commit component renders commit widget 1`] = ` > <!----> - <gllink-stub - class="js-commit-pipeline" - data-original-title="Commit: failed" - href="https://test.com/pipeline" - title="" + <div + class="ci-status-link" > - <ciicon-stub - aria-label="Commit: failed" - cssclasses="" - size="24" - status="[object Object]" - /> - </gllink-stub> + <gllink-stub + class="js-commit-pipeline" + data-original-title="Commit: failed" + href="https://test.com/pipeline" + title="" + > + <ciicon-stub + aria-label="Commit: failed" + cssclasses="" + size="24" + status="[object Object]" + /> + </gllink-stub> + </div> <div class="commit-sha-group d-flex" @@ -165,19 +169,23 @@ exports[`Repository last commit component renders the signature HTML as returned </button> </div> - <gllink-stub - class="js-commit-pipeline" - data-original-title="Commit: failed" - href="https://test.com/pipeline" - title="" + <div + class="ci-status-link" > - <ciicon-stub - aria-label="Commit: failed" - cssclasses="" - size="24" - status="[object Object]" - /> - </gllink-stub> + <gllink-stub + class="js-commit-pipeline" + data-original-title="Commit: failed" + href="https://test.com/pipeline" + title="" + > + <ciicon-stub + aria-label="Commit: failed" + cssclasses="" + size="24" + status="[object Object]" + /> + </gllink-stub> + </div> <div class="commit-sha-group d-flex" diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js index 964f8b8787e..d9cc7104139 100644 --- a/spec/frontend/tracking_spec.js +++ b/spec/frontend/tracking_spec.js @@ -11,6 +11,7 @@ describe('Tracking', () => { namespace: '_namespace_', hostname: 'app.gitfoo.com', cookieDomain: '.gitfoo.com', + userId: null, }; snowplowSpy = jest.spyOn(window, 'snowplow'); }); @@ -34,6 +35,7 @@ describe('Tracking', () => { contexts: { webPage: true }, formTracking: false, linkClickTracking: false, + userId: null, }); }); @@ -41,15 +43,18 @@ describe('Tracking', () => { initUserTracking(); expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30); expect(snowplowSpy).toHaveBeenCalledWith('trackPageView'); + expect(snowplowSpy).not.toHaveBeenCalledWith('setUserId'); expect(snowplowSpy).not.toHaveBeenCalledWith('enableFormTracking'); expect(snowplowSpy).not.toHaveBeenCalledWith('enableLinkClickTracking'); window.snowplowOptions = Object.assign({}, window.snowplowOptions, { formTracking: true, linkClickTracking: true, + userId: '1', }); initUserTracking(); + expect(snowplowSpy).toHaveBeenCalledWith('setUserId', '1'); expect(snowplowSpy).toHaveBeenCalledWith('enableFormTracking'); expect(snowplowSpy).toHaveBeenCalledWith('enableLinkClickTracking'); }); diff --git a/spec/frontend/wikis_spec.js b/spec/frontend/wikis_spec.js index b2475488d97..a2b68bf866e 100644 --- a/spec/frontend/wikis_spec.js +++ b/spec/frontend/wikis_spec.js @@ -3,27 +3,27 @@ import { setHTMLFixture } from './helpers/fixtures'; describe('Wikis', () => { describe('setting the commit message when the title changes', () => { - const editFormHtmlFixture = args => `<form class="wiki-form ${ - args.newPage ? 'js-new-wiki-page' : '' - }"> - <input type="text" id="wiki_title" value="My title" /> - <input type="text" id="wiki_message" /> - </form>`; - let wikis; let titleInput; let messageInput; + const CREATE = true; + const UPDATE = false; - describe('when the wiki page is being created', () => { - const formHtmlFixture = editFormHtmlFixture({ newPage: true }); + const editFormHtmlFixture = newPage => + `<form class="wiki-form ${newPage ? 'js-new-wiki-page' : ''}"> + <input type="text" id="wiki_page_title" value="My title" /> + <input type="text" id="wiki_page_message" /> + </form>`; - beforeEach(() => { - setHTMLFixture(formHtmlFixture); + const init = newPage => { + setHTMLFixture(editFormHtmlFixture(newPage)); + titleInput = document.getElementById('wiki_page_title'); + messageInput = document.getElementById('wiki_page_message'); + wikis = new Wikis(); + }; - titleInput = document.getElementById('wiki_title'); - messageInput = document.getElementById('wiki_message'); - wikis = new Wikis(); - }); + describe('when the wiki page is being created', () => { + beforeEach(() => init(CREATE)); it('binds an event listener to the title input', () => { wikis.handleWikiTitleChange = jest.fn(); @@ -51,15 +51,7 @@ describe('Wikis', () => { }); describe('when the wiki page is being updated', () => { - const formHtmlFixture = editFormHtmlFixture({ newPage: false }); - - beforeEach(() => { - setHTMLFixture(formHtmlFixture); - - titleInput = document.getElementById('wiki_title'); - messageInput = document.getElementById('wiki_message'); - wikis = new Wikis(); - }); + beforeEach(() => init(UPDATE)); it('sets the commit message when title changes, prefixing with "Update"', () => { titleInput.value = 'My title'; diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index cfd0f8ec7a7..f837fb9f77f 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -23,6 +23,7 @@ describe GitlabSchema.types['Project'] do only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled namespace group statistics repository merge_requests merge_request issues issue pipelines + removeSourceBranchAfterMerge ] is_expected.to have_graphql_fields(*expected_fields) diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb index bcc2bd71da1..4310e4bd22c 100644 --- a/spec/helpers/wiki_helper_spec.rb +++ b/spec/helpers/wiki_helper_spec.rb @@ -23,8 +23,13 @@ describe WikiHelper do describe '#wiki_sort_controls' do let(:project) { create(:project) } - let(:wiki_link) { helper.wiki_sort_controls(project, sort, direction) } - let(:classes) { "btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" } + let(:classes) { described_class::WIKI_SORT_CSS_CLASSES } + + subject(:wiki_link) do + helper.wiki_sort_controls(sort: sort, direction: direction) do |opts| + project_wikis_pages_path(project, opts) + end + end def expected_link(sort, direction, icon_class) path = "/#{project.full_path}/wikis/pages?direction=#{direction}&sort=#{sort}" @@ -62,6 +67,18 @@ describe WikiHelper do end end + describe '#wiki_show_children_icon' do + ProjectWiki::NESTINGS.each do |nesting| + context "When the nesting parameter is `#{nesting}`" do + let(:element) { helper.wiki_show_children_icon(nesting) } + + it 'produces something that contains an SVG' do + expect(element).to match(/svg/) + end + end + end + end + describe '#wiki_sort_title' do it 'returns a title corresponding to a key' do expect(helper.wiki_sort_title('created_at')).to eq('Created date') diff --git a/spec/javascripts/blob/viewer/index_spec.js b/spec/javascripts/blob/viewer/index_spec.js index 06c06613887..bbc59632f3c 100644 --- a/spec/javascripts/blob/viewer/index_spec.js +++ b/spec/javascripts/blob/viewer/index_spec.js @@ -11,6 +11,13 @@ describe('Blob viewer', () => { preloadFixtures('snippets/show.html'); + const asyncClick = () => + new Promise(resolve => { + document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click(); + + setTimeout(resolve); + }); + beforeEach(() => { mock = new MockAdapter(axios); @@ -66,19 +73,12 @@ describe('Blob viewer', () => { }); it('doesnt reload file if already loaded', done => { - const asyncClick = () => - new Promise(resolve => { - document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click(); - - setTimeout(resolve); - }); - asyncClick() .then(() => asyncClick()) .then(() => { - expect( - document.querySelector('.blob-viewer[data-type="simple"]').getAttribute('data-loaded'), - ).toBe('true'); + expect(document.querySelector('.blob-viewer[data-type="simple"]').dataset.loaded).toBe( + 'true', + ); done(); }) @@ -100,9 +100,7 @@ describe('Blob viewer', () => { }); it('has tooltip when disabled', () => { - expect(copyButton.getAttribute('data-original-title')).toBe( - 'Switch to the source to copy the file contents', - ); + expect(copyButton.dataset.title).toBe('Switch to the source to copy the file contents'); }); it('is blurred when clicked and disabled', () => { @@ -136,7 +134,7 @@ describe('Blob viewer', () => { document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click(); setTimeout(() => { - expect(copyButton.getAttribute('data-original-title')).toBe('Copy file contents'); + expect(copyButton.dataset.title).toBe('Copy file contents'); done(); }); @@ -177,4 +175,27 @@ describe('Blob viewer', () => { expect(axios.get.calls.count()).toBe(1); }); }); + + describe('a URL inside the blob content', () => { + beforeEach(() => { + mock.onGet('http://test.host/snippets/1.json?viewer=simple').reply(200, { + html: + '<div class="js-blob-content"><pre class="code"><code><span class="line" lang="yaml"><span class="c1">To install gitlab-shell you also need a Go compiler version 1.8 or newer. https://golang.org/dl/</span></span></code></pre></div>', + }); + }); + + it('is rendered as a link in simple view', done => { + asyncClick() + .then(() => { + expect(document.querySelector('.blob-viewer[data-type="simple"]').innerHTML).toContain( + '<a href="https://golang.org/dl/">https://golang.org/dl/</a>', + ); + done(); + }) + .catch(() => { + fail(); + done(); + }); + }); + }); }); diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js index dd58f234394..4d782e5bd0e 100644 --- a/spec/javascripts/jobs/components/job_log_spec.js +++ b/spec/javascripts/jobs/components/job_log_spec.js @@ -10,7 +10,7 @@ describe('Job Log', () => { let vm; const trace = - '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section js-section-header section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>'; + '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="append-right-8" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>'; beforeEach(() => { store = createStore(); diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js index c5022d3e93d..3d40e94d219 100644 --- a/spec/javascripts/jobs/mock_data.js +++ b/spec/javascripts/jobs/mock_data.js @@ -1189,18 +1189,3 @@ export const jobsInStage = { path: '/gitlab-org/gitlab-shell/pipelines/27#build', dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build', }; - -export const logWithCollapsibleSections = { - append: false, - complete: true, - html: - '<div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer" data-timestamp="1559571405" data-section="after-script" role="button"></div><span class="term-fg-l-green term-bold section js-section-header js-s-after-script">Running after script...</span><span class="section js-section-header js-s-after-script"><br /></span><span class="section s_after-script line"></span><span class="section js-s-after-script"></span><span class="term-fg-l-green term-bold section js-s-after-script">$ date</span><span class="section js-s-after-script"><br /></span><span class="section s_after-script line"></span><span class="section js-s-after-script">Mon Jun 3 14:16:46 UTC 2019<br /></span><span class="section s_after-script line"></span><span class="section js-s-after-script"></span><div class="section-end" data-section="after-script"></div><div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer"data-timestamp="1559571408" data-section="archive-cache" role="button" ></div><span class="term-fg-l-green term-bold section js-section-header js-s-archive-cache">Not uploading cache debian-stretch-ruby-2.6.3-node-10.x-3 due to policy</span><span class="section js-section-header js-s-archive-cache"><br /></span><span class="section s_archive-cache line"></span><span class="section js-s-archive-cache"></span><div class="section-end" data-section="archive-cache"></div><div class="js-section-start fa fa-caret-down append-right-8 cursor-pointer" data-timestamp="1559571409" data-section="upload-artifacts-on-success" role="button"></div><span class="term-fg-l-green term-bold section js-section-header js-s-upload-artifacts-on-success">Uploading artifacts...</span><span class="section js-section-header js-s-upload-artifacts-on-success"><br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">coverage/: found 5 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">knapsack/: found 4 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">rspec_flaky/: found 4 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">rspec_profiling/: found 1 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success"></span><span class="term-fg-yellow section js-s-upload-artifacts-on-success">WARNING: tmp/capybara/: no matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">Uploading artifacts to coordinator... ok </span><span class="section js-s-upload-artifacts-on-success"> id</span><span class="section js-s-upload-artifacts-on-success">=224162288 responseStatus</span><span class="section js-s-upload-artifacts-on-success">=201 Created token</span><span class="section js-s-upload-artifacts-on-success">=bBmyXJNW<br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success"></span><span class="term-fg-l-green term-bold section js-s-upload-artifacts-on-success">Uploading artifacts...</span><span class="section js-s-upload-artifacts-on-success"><br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">junit_rspec.xml: found 1 matching files </span><span class="section js-s-upload-artifacts-on-success"> <br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success">Uploading artifacts to coordinator... ok </span><span class="section js-s-upload-artifacts-on-success"> id</span><span class="section js-s-upload-artifacts-on-success">=224162288 responseStatus</span><span class="section js-s-upload-artifacts-on-success">=201 Created token</span><span class="section js-s-upload-artifacts-on-success">=bBmyXJNW<br /></span><span class="section s_upload-artifacts-on-success line"></span><span class="section js-s-upload-artifacts-on-success"></span><div class="section-end" data-section="upload-artifacts-on-success"></div><span class="term-fg-l-green term-bold">Job succeeded<br /><span class="term-fg-l-green term-bold"></span></span>', - id: 1385, - offset: 0, - size: 78815, - state: - 'eyJvZmZzZXQiOjc4ODE1LCJuX29wZW5fdGFncyI6MCwiZmdfY29sb3IiOm51bGwsImJnX2NvbG9yIjpudWxsLCJzdHlsZV9tYXNrIjowLCJzZWN0aW9ucyI6W10sImxpbmVub19pbl9zZWN0aW9uIjoxMX0=', - status: 'success', - total: 78815, - truncated: false, -}; diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb index bf827fb3914..5f120f258cd 100644 --- a/spec/lib/backup/repository_spec.rb +++ b/spec/lib/backup/repository_spec.rb @@ -70,7 +70,7 @@ describe Backup::Repository do end context 'restoring object pools' do - it 'schedules restoring of the pool' do + it 'schedules restoring of the pool', :sidekiq_might_not_need_inline do pool_repository = create(:pool_repository, :failed) pool_repository.delete_object_pool diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb index 4587bd85939..7a83dc3ec1d 100644 --- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb +++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb @@ -11,6 +11,10 @@ describe Banzai::Filter::WikiLinkFilter do let(:wiki) { ProjectWiki.new(project, user) } let(:repository_upload_folder) { Wikis::CreateAttachmentService::ATTACHMENT_PATH } + def upload_href(file_name) + ::File.join(wiki.wiki_page_path, repository_upload_folder, file_name) + end + it "doesn't rewrite absolute links" do filtered_link = filter("<a href='http://example.com:8000/'>Link</a>", project_wiki: wiki).children[0] @@ -28,12 +32,12 @@ describe Banzai::Filter::WikiLinkFilter do it 'rewrites links' do filtered_link = filter("<a href='#{repository_upload_folder}/a.test'>Link</a>", project_wiki: wiki).children[0] - expect(filtered_link.attribute('href').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.test") + expect(filtered_link.attribute('href').value).to eq(upload_href "a.test") end end context 'with "img" html tag' do - let(:path) { "#{wiki.wiki_base_path}/#{repository_upload_folder}/a.jpg" } + let(:path) { upload_href "a.jpg" } context 'inside an "a" html tag' do it 'rewrites links' do @@ -57,7 +61,7 @@ describe Banzai::Filter::WikiLinkFilter do it 'rewrites links' do filtered_link = filter("<video src='#{repository_upload_folder}/a.mp4'></video>", project_wiki: wiki).children[0] - expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.mp4") + expect(filtered_link.attribute('src').value).to eq(upload_href "a.mp4") end end @@ -65,7 +69,8 @@ describe Banzai::Filter::WikiLinkFilter do it 'rewrites links' do filtered_link = filter("<audio src='#{repository_upload_folder}/a.wav'></audio>", project_wiki: wiki).children[0] - expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.wav") + # expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.wav") + expect(filtered_link.attribute('src').value).to eq(upload_href "a.wav") end end end diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 26f2b0b0acf..7f60106cdca 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -3,6 +3,12 @@ require 'spec_helper' describe Banzai::Pipeline::WikiPipeline do + let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") } + let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) } + let_it_be(:project_wiki) { ProjectWiki.new(project, double(:user)) } + let_it_be(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) } + let(:prefix) { project_wiki.wiki_page_path } + describe 'TableOfContents' do it 'replaces the tag with the TableOfContentsFilter result' do markdown = <<-MD.strip_heredoc @@ -54,132 +60,138 @@ describe Banzai::Pipeline::WikiPipeline do end describe "Links" do - let(:namespace) { create(:namespace, name: "wiki_link_ns") } - let(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) } - let(:project_wiki) { ProjectWiki.new(project, double(:user)) } - let(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) } - - { "when GitLab is hosted at a root URL" => '/', - "when GitLab is hosted at a relative URL" => '/nested/relative/gitlab' }.each do |test_name, relative_url_root| - context test_name do + shared_examples 'a correct link rewrite' do + it 'rewrites links correctly' do + output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + + expect(output).to include("href=\"#{page_href}\"") + end + end + + shared_examples 'link examples' do |test_name| + let(:page_href) { "#{prefix}/#{expected_page_path}" } + + context "when GitLab is hosted at a #{test_name} URL" do before do allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return(relative_url_root) end describe "linking to pages within the wiki" do - context "when creating hierarchical links to the current directory" do - it "rewrites non-file links to be at the scope of the current directory" do - markdown = "[Page](./page)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + let(:markdown) { "[Page](#{nesting}page#{extension})" } - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page\"") + context "when creating hierarchical links to the current directory" do + let(:nesting) { './' } + context 'non file links' do + let(:extension) { '' } + let(:expected_page_path) { 'nested/twice/page' } + it_behaves_like 'a correct link rewrite' end - it "rewrites file links to be at the scope of the current directory" do - markdown = "[Link to Page](./page.md)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"") + context 'file-like links' do + let(:extension) { '.md' } + let(:expected_page_path) { 'nested/twice/page.md' } + it_behaves_like 'a correct link rewrite' end end context "when creating hierarchical links to the parent directory" do - it "rewrites non-file links to be at the scope of the parent directory" do - markdown = "[Link to Page](../page)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page\"") + let(:nesting) { '../' } + context "non file links" do + let(:extension) { '' } + let(:expected_page_path) { 'nested/page' } + it_behaves_like 'a correct link rewrite' end - it "rewrites file links to be at the scope of the parent directory" do - markdown = "[Link to Page](../page.md)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page.md\"") + context "file-like links" do + let(:extension) { '.md' } + let(:expected_page_path) { 'nested/page.md' } + it_behaves_like 'a correct link rewrite' end end context "when creating hierarchical links to a sub-directory" do - it "rewrites non-file links to be at the scope of the sub-directory" do - markdown = "[Link to Page](./subdirectory/page)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + let(:nesting) { './subdirectory/' } - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page\"") + context "non file links" do + let(:extension) { '' } + let(:expected_page_path) { 'nested/twice/subdirectory/page' } + it_behaves_like 'a correct link rewrite' end - it "rewrites file links to be at the scope of the sub-directory" do - markdown = "[Link to Page](./subdirectory/page.md)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page.md\"") + context 'file-like links' do + let(:extension) { '.md' } + let(:expected_page_path) { 'nested/twice/subdirectory/page.md' } + it_behaves_like 'a correct link rewrite' end end describe "when creating non-hierarchical links" do - it 'rewrites non-file links to be at the scope of the wiki root' do - markdown = "[Link to Page](page)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + let(:nesting) { '' } - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") + context 'non-file links' do + let(:extension) { '' } + let(:expected_page_path) { 'page' } + it_behaves_like 'a correct link rewrite' end - it 'rewrites non-file links (with spaces) to be at the scope of the wiki root' do - markdown = "[Link to Page](page slug)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page%20slug\"") + context 'non-file links (with spaces)' do + let(:extension) { ' slug' } + let(:expected_page_path) { 'page%20slug' } + it_behaves_like 'a correct link rewrite' end - it "rewrites file links to be at the scope of the current directory" do - markdown = "[Link to Page](page.md)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"") + context "file links" do + let(:extension) { '.md' } + let(:expected_page_path) { 'nested/twice/page.md' } + it_behaves_like 'a correct link rewrite' end - it 'rewrites links with anchor' do - markdown = '[Link to Header](start-page#title)' - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start-page#title\"") + context 'links with anchor' do + let(:extension) { '#title' } + let(:expected_page_path) { 'page#title' } + it_behaves_like 'a correct link rewrite' end - it 'rewrites links (with spaces) with anchor' do - markdown = '[Link to Header](start page#title)' - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start%20page#title\"") + context 'links (with spaces) with anchor' do + let(:extension) { ' two#title' } + let(:expected_page_path) { 'page%20two#title' } + it_behaves_like 'a correct link rewrite' end end describe "when creating root links" do - it 'rewrites non-file links to be at the scope of the wiki root' do - markdown = "[Link to Page](/page)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + let(:nesting) { '/' } - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"") + context 'non-file links' do + let(:extension) { '' } + let(:expected_page_path) { 'page' } + it_behaves_like 'a correct link rewrite' end - it 'rewrites file links to be at the scope of the wiki root' do - markdown = "[Link to Page](/page.md)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page.md\"") + context 'file links' do + let(:extension) { '.md' } + let(:expected_page_path) { 'page.md' } + it_behaves_like 'a correct link rewrite' end end end describe "linking to pages outside the wiki (absolute)" do - it "doesn't rewrite links" do - markdown = "[Link to Page](http://example.com/page)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - - expect(output).to include('href="http://example.com/page"') - end + let(:markdown) { "[Link to Page](http://example.com/page)" } + let(:page_href) { 'http://example.com/page' } + it_behaves_like 'a correct link rewrite' end end end + include_examples 'link examples', :root do + let(:relative_url_root) { '/' } + end + + include_examples 'link examples', :relative do + let(:relative_url_root) { '/nested/relative/gitlab' } + end + describe "checking slug validity when assembling links" do context "with a valid slug" do let(:valid_slug) { "http://example.com" } @@ -261,37 +273,54 @@ describe Banzai::Pipeline::WikiPipeline do end describe 'videos and audio' do - let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") } - let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) } - let_it_be(:project_wiki) { ProjectWiki.new(project, double(:user)) } - let_it_be(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) } + def src(file_name) + "#{prefix}/nested/twice/#{file_name}" + end - it 'generates video html structure' do - markdown = "![video_file](video_file_name.mp4)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + shared_examples 'correct video rewrite' do + let(:markdown) { "![video_file](#{file_name})" } + let(:video_fragment) { "<video src=\"#{prefix}/#{expected_file_path}\"" } + let(:options) do + { + project: project, + project_wiki: project_wiki, + page_slug: page.slug + } + end + + it 'generates video html structure' do + output = described_class.to_html(markdown, options) - expect(output).to include('<video src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/video_file_name.mp4"') + expect(output).to include(video_fragment) + end end - it 'rewrites and replaces video links names with white spaces to %20' do - markdown = "![video file](video file name.mp4)" - output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) + context 'underscores' do + let(:file_name) { 'video_file_name.mp4' } + let(:expected_file_path) { 'nested/twice/video_file_name.mp4' } + it_behaves_like 'correct video rewrite' + end - expect(output).to include('<video src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/video%20file%20name.mp4"') + context 'spaces' do + let(:file_name) { 'video file name.mp4' } + let(:expected_file_path) { 'nested/twice/video%20file%20name.mp4' } + it_behaves_like 'correct video rewrite' end it 'generates audio html structure' do markdown = "![audio_file](audio_file_name.wav)" + safe_name = "audio_file_name.wav" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/audio_file_name.wav"') + expect(output).to include(%Q'<audio src="#{src(safe_name)}"') end it 'rewrites and replaces audio links names with white spaces to %20' do markdown = "![audio file](audio file name.wav)" + safe_name = "audio%20file%20name.wav" output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug) - expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/audio%20file%20name.wav"') + expect(output).to include(%Q'<audio src="#{src(safe_name)}"') end end end diff --git a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb index c1eaf1d3433..f2de73d5aea 100644 --- a/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb +++ b/spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb @@ -91,15 +91,26 @@ describe Gitlab::BackgroundMigration::LegacyUploadMover do end end - context 'when no model found for the upload' do + context 'when no note found for the upload' do before do - legacy_upload.model = nil + legacy_upload.model_id = nil + legacy_upload.model_type = 'Note' expect_error_log end it_behaves_like 'legacy upload deletion' end + context 'when upload does not belong to a note' do + before do + legacy_upload.model = create(:appearance) + end + + it 'does not remove the upload' do + expect { described_class.new(legacy_upload).execute }.not_to change { Upload.count } + end + end + context 'when the upload move fails' do before do expect(FileUploader).to receive(:copy_to).and_raise('failed') diff --git a/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb b/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb index cabca3dbef9..85187d039c1 100644 --- a/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb +++ b/spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb @@ -35,6 +35,8 @@ describe Gitlab::BackgroundMigration::LegacyUploadsMigrator do let!(:legacy_upload_no_file) { create_upload(note2, false) } let!(:legacy_upload_legacy_project) { create_upload(note_legacy) } + let!(:appearance) { create(:appearance, :with_logo) } + let(:start_id) { 1 } let(:end_id) { 10000 } @@ -52,12 +54,18 @@ describe Gitlab::BackgroundMigration::LegacyUploadsMigrator do expect(File.exist?(legacy_upload_legacy_project.absolute_path)).to be_falsey end - it 'removes all AttachmentUploader records' do - expect { subject }.to change { Upload.where(uploader: 'AttachmentUploader').count }.from(3).to(0) + it 'removes all Note AttachmentUploader records' do + expect { subject }.to change { Upload.where(uploader: 'AttachmentUploader').count }.from(4).to(1) end it 'creates new uploads for successfully migrated records' do expect { subject }.to change { Upload.where(uploader: 'FileUploader').count }.from(0).to(2) end + + it 'does not remove appearance uploads' do + subject + + expect(appearance.logo.file).to exist + end end # rubocop: enable RSpec/FactoriesInMigrationSpecs diff --git a/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb b/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb index f877e8cc1b8..399db4ac259 100644 --- a/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb +++ b/spec/lib/gitlab/background_migration/schedule_calculate_wiki_sizes_spec.rb @@ -33,7 +33,7 @@ describe ScheduleCalculateWikiSizes, :migration, :sidekiq do end end - it 'calculates missing wiki sizes' do + it 'calculates missing wiki sizes', :sidekiq_might_not_need_inline do expect(project_statistics.find_by(id: 2).wiki_size).to be_nil expect(project_statistics.find_by(id: 3).wiki_size).to be_nil diff --git a/spec/lib/gitlab/badge/pipeline/status_spec.rb b/spec/lib/gitlab/badge/pipeline/status_spec.rb index 684c6829879..ab8d1f0ec5b 100644 --- a/spec/lib/gitlab/badge/pipeline/status_spec.rb +++ b/spec/lib/gitlab/badge/pipeline/status_spec.rb @@ -26,7 +26,7 @@ describe Gitlab::Badge::Pipeline::Status do end end - context 'pipeline exists' do + context 'pipeline exists', :sidekiq_might_not_need_inline do let!(:pipeline) { create_pipeline(project, sha, branch) } context 'pipeline success' do diff --git a/spec/lib/gitlab/bare_repository_import/importer_spec.rb b/spec/lib/gitlab/bare_repository_import/importer_spec.rb index 2fb9f1a0a08..ddb1d3cea21 100644 --- a/spec/lib/gitlab/bare_repository_import/importer_spec.rb +++ b/spec/lib/gitlab/bare_repository_import/importer_spec.rb @@ -90,7 +90,7 @@ describe Gitlab::BareRepositoryImport::Importer, :seed_helper do hook_path = File.join(repo_path, 'hooks') expect(gitlab_shell.repository_exists?(project.repository_storage, repo_path)).to be(true) - expect(gitlab_shell.exists?(project.repository_storage, hook_path)).to be(true) + expect(TestEnv.storage_dir_exists?(project.repository_storage, hook_path)).to be(true) end context 'hashed storage enabled' do diff --git a/spec/lib/gitlab/checks/lfs_integrity_spec.rb b/spec/lib/gitlab/checks/lfs_integrity_spec.rb index 88e8f5d74d1..505f117034e 100644 --- a/spec/lib/gitlab/checks/lfs_integrity_spec.rb +++ b/spec/lib/gitlab/checks/lfs_integrity_spec.rb @@ -58,7 +58,7 @@ describe Gitlab::Checks::LfsIntegrity do end end - context 'for forked project' do + context 'for forked project', :sidekiq_might_not_need_inline do let(:parent_project) { create(:project, :repository) } let(:project) { fork_project(parent_project, nil, repository: true) } diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb index c8afcbd053d..ee789995bc2 100644 --- a/spec/lib/gitlab/ci/ansi2html_spec.rb +++ b/spec/lib/gitlab/ci/ansi2html_spec.rb @@ -209,7 +209,7 @@ describe Gitlab::Ci::Ansi2html do let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K"} let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K"} let(:section_start_html) do - '<div class="js-section-start section-start fa fa-caret-down pr-2 cursor-pointer"' \ + '<div class="section-start"' \ " data-timestamp=\"#{section_start_time.to_i}\" data-section=\"#{class_name(section_name)}\"" \ ' role="button"></div>' end @@ -233,8 +233,8 @@ describe Gitlab::Ci::Ansi2html do it 'prints light red' do text = "#{section_start}\e[91mHello\e[0m\nLine 1\nLine 2\nLine 3\n#{section_end}" - header = %{<span class="term-fg-l-red section js-section-header section-header cursor-pointer js-s-#{class_name(section_name)}">Hello</span>} - line_break = %{<span class="section js-section-header section-header cursor-pointer js-s-#{class_name(section_name)}"><br/></span>} + header = %{<span class="term-fg-l-red section section-header js-s-#{class_name(section_name)}">Hello</span>} + line_break = %{<span class="section section-header js-s-#{class_name(section_name)}"><br/></span>} output_line = %{<span class="section line js-s-#{class_name(section_name)}">Line 1<br/>Line 2<br/>Line 3<br/></span>} html = "#{section_start_html}#{header}#{line_break}#{output_line}#{section_end_html}" diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index a163de07967..9eee7e89062 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -129,7 +129,7 @@ describe 'cycle analytics events' do end end - describe '#test_events' do + describe '#test_events', :sidekiq_might_not_need_inline do let(:stage) { :test } let(:merge_request) { MergeRequest.first } @@ -234,7 +234,7 @@ describe 'cycle analytics events' do end end - describe '#staging_events' do + describe '#staging_events', :sidekiq_might_not_need_inline do let(:stage) { :staging } let(:merge_request) { MergeRequest.first } @@ -306,7 +306,7 @@ describe 'cycle analytics events' do end end - describe '#production_events' do + describe '#production_events', :sidekiq_might_not_need_inline do let(:stage) { :production } let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } diff --git a/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb b/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb index e568ea633db..d4ab9bc225b 100644 --- a/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/usage_data_spec.rb @@ -71,7 +71,7 @@ describe Gitlab::CycleAnalytics::UsageData do } end - it 'returns the aggregated usage data of every selected project' do + it 'returns the aggregated usage data of every selected project', :sidekiq_might_not_need_inline do result = subject.to_json expect(result).to have_key(:avg_cycle_analytics) diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb index 2e5fd16d370..725c23e913c 100644 --- a/spec/lib/gitlab/experimentation_spec.rb +++ b/spec/lib/gitlab/experimentation_spec.rb @@ -2,81 +2,204 @@ require 'spec_helper' -describe Gitlab::Experimentation::ControllerConcern, type: :controller do - controller(ApplicationController) do - include Gitlab::Experimentation::ControllerConcern +describe Gitlab::Experimentation do + before do + stub_const('Gitlab::Experimentation::EXPERIMENTS', { + test_experiment: { + feature_toggle: feature_toggle, + environment: environment, + enabled_ratio: enabled_ratio, + tracking_category: 'Team' + } + }) - def index - head :ok - end + stub_feature_flags(feature_toggle => true) end - describe '#set_experimentation_subject_id_cookie' do - before do - get :index + let(:feature_toggle) { :test_experiment_toggle } + let(:environment) { Rails.env.test? } + let(:enabled_ratio) { 0.1 } + + describe Gitlab::Experimentation::ControllerConcern, type: :controller do + controller(ApplicationController) do + include Gitlab::Experimentation::ControllerConcern + + def index + head :ok + end end - context 'cookie is present' do + describe '#set_experimentation_subject_id_cookie' do before do - cookies[:experimentation_subject_id] = 'test' + get :index end - it 'does not change the cookie' do - expect(cookies[:experimentation_subject_id]).to eq 'test' + context 'cookie is present' do + before do + cookies[:experimentation_subject_id] = 'test' + end + + it 'does not change the cookie' do + expect(cookies[:experimentation_subject_id]).to eq 'test' + end end - end - context 'cookie is not present' do - it 'sets a permanent signed cookie' do - expect(cookies.permanent.signed[:experimentation_subject_id]).to be_present + context 'cookie is not present' do + it 'sets a permanent signed cookie' do + expect(cookies.permanent.signed[:experimentation_subject_id]).to be_present + end end end - end - describe '#experiment_enabled?' do - context 'cookie is not present' do - it 'calls Gitlab::Experimentation.enabled? with the name of the experiment and an experimentation_subject_index of nil' do - expect(Gitlab::Experimentation).to receive(:enabled?).with(:test_experiment, nil) - controller.experiment_enabled?(:test_experiment) + describe '#experiment_enabled?' do + context 'cookie is not present' do + it 'calls Gitlab::Experimentation.enabled_for_user? with the name of the experiment and an experimentation_subject_index of nil' do + expect(Gitlab::Experimentation).to receive(:enabled_for_user?).with(:test_experiment, nil) # rubocop:disable RSpec/DescribedClass + controller.experiment_enabled?(:test_experiment) + end + end + + context 'cookie is present' do + before do + cookies.permanent.signed[:experimentation_subject_id] = 'abcd-1234' + get :index + end + + it 'calls Gitlab::Experimentation.enabled_for_user? with the name of the experiment and an experimentation_subject_index of the modulo 100 of the hex value of the uuid' do + # 'abcd1234'.hex % 100 = 76 + expect(Gitlab::Experimentation).to receive(:enabled_for_user?).with(:test_experiment, 76) # rubocop:disable RSpec/DescribedClass + controller.experiment_enabled?(:test_experiment) + end + end + + describe 'URL parameter to force enable experiment' do + context 'is not present' do + it 'returns false' do + get :index, params: { force_experiment: :test_experiment2 } + + expect(controller.experiment_enabled?(:test_experiment)).to be_falsey + end + end + + context 'is present' do + it 'returns true' do + get :index, params: { force_experiment: :test_experiment } + + expect(controller.experiment_enabled?(:test_experiment)).to be_truthy + end + end end end - context 'cookie is present' do - before do - cookies.permanent.signed[:experimentation_subject_id] = 'abcd-1234' - get :index + describe '#track_experiment_event' do + context 'when the experiment is enabled' do + before do + stub_experiment(test_experiment: true) + end + + context 'the user is part of the experimental group' do + before do + stub_experiment_for_user(test_experiment: true) + end + + it 'tracks the event with the right parameters' do + expect(Gitlab::Tracking).to receive(:event).with( + 'Team', + 'start', + label: nil, + property: 'experimental_group' + ) + controller.track_experiment_event(:test_experiment, 'start') + end + end + + context 'the user is part of the control group' do + before do + stub_experiment_for_user(test_experiment: false) + end + + it 'tracks the event with the right parameters' do + expect(Gitlab::Tracking).to receive(:event).with( + 'Team', + 'start', + label: nil, + property: 'control_group' + ) + controller.track_experiment_event(:test_experiment, 'start') + end + end end - it 'calls Gitlab::Experimentation.enabled? with the name of the experiment and an experimentation_subject_index of the modulo 100 of the hex value of the uuid' do - # 'abcd1234'.hex % 100 = 76 - expect(Gitlab::Experimentation).to receive(:enabled?).with(:test_experiment, 76) - controller.experiment_enabled?(:test_experiment) + context 'when the experiment is disabled' do + before do + stub_experiment(test_experiment: false) + end + + it 'does not track the event' do + expect(Gitlab::Tracking).not_to receive(:event) + controller.track_experiment_event(:test_experiment, 'start') + end end end - end -end -describe Gitlab::Experimentation do - before do - stub_const('Gitlab::Experimentation::EXPERIMENTS', { - test_experiment: { - feature_toggle: feature_toggle, - environment: environment, - enabled_ratio: enabled_ratio - } - }) + describe '#frontend_experimentation_tracking_data' do + context 'when the experiment is enabled' do + before do + stub_experiment(test_experiment: true) + end - stub_feature_flags(feature_toggle => true) - end + context 'the user is part of the experimental group' do + before do + stub_experiment_for_user(test_experiment: true) + end + + it 'pushes the right parameters to gon' do + controller.frontend_experimentation_tracking_data(:test_experiment, 'start') + expect(Gon.tracking_data).to eq( + { + category: 'Team', + action: 'start', + label: nil, + property: 'experimental_group' + } + ) + end + end - let(:feature_toggle) { :test_experiment_toggle } - let(:environment) { Rails.env.test? } - let(:enabled_ratio) { 0.1 } + context 'the user is part of the control group' do + before do + allow_any_instance_of(described_class).to receive(:experiment_enabled?).with(:test_experiment).and_return(false) + end + + it 'pushes the right parameters to gon' do + controller.frontend_experimentation_tracking_data(:test_experiment, 'start') + expect(Gon.tracking_data).to eq( + { + category: 'Team', + action: 'start', + label: nil, + property: 'control_group' + } + ) + end + end + end - describe '.enabled?' do - subject { described_class.enabled?(:test_experiment, experimentation_subject_index) } + context 'when the experiment is disabled' do + before do + stub_experiment(test_experiment: false) + end - let(:experimentation_subject_index) { 9 } + it 'does not push data to gon' do + expect(Gon.method_defined?(:tracking_data)).to be_falsey + controller.track_experiment_event(:test_experiment, 'start') + end + end + end + end + + describe '.enabled?' do + subject { described_class.enabled?(:test_experiment) } context 'feature toggle is enabled, we are on the right environment and we are selected' do it { is_expected.to be_truthy } @@ -84,7 +207,7 @@ describe Gitlab::Experimentation do describe 'experiment is not defined' do it 'returns false' do - expect(described_class.enabled?(:missing_experiment, experimentation_subject_index)).to be_falsey + expect(described_class.enabled?(:missing_experiment)).to be_falsey end end @@ -127,30 +250,52 @@ describe Gitlab::Experimentation do it { is_expected.to be_falsey } end end + end - describe 'enabled ratio' do - context 'enabled ratio is not set' do - let(:enabled_ratio) { nil } + describe '.enabled_for_user?' do + subject { described_class.enabled_for_user?(:test_experiment, experimentation_subject_index) } - it { is_expected.to be_falsey } + let(:experimentation_subject_index) { 9 } + + context 'experiment is disabled' do + before do + allow(described_class).to receive(:enabled?).and_return(false) end - context 'experimentation_subject_index is not set' do - let(:experimentation_subject_index) { nil } + it { is_expected.to be_falsey } + end - it { is_expected.to be_falsey } + context 'experiment is enabled' do + before do + allow(described_class).to receive(:enabled?).and_return(true) end - context 'experimentation_subject_index is an empty string' do - let(:experimentation_subject_index) { '' } + it { is_expected.to be_truthy } + + context 'enabled ratio is not set' do + let(:enabled_ratio) { nil } it { is_expected.to be_falsey } end - context 'experimentation_subject_index outside enabled ratio' do - let(:experimentation_subject_index) { 11 } + describe 'experimentation_subject_index' do + context 'experimentation_subject_index is not set' do + let(:experimentation_subject_index) { nil } - it { is_expected.to be_falsey } + it { is_expected.to be_falsey } + end + + context 'experimentation_subject_index is an empty string' do + let(:experimentation_subject_index) { '' } + + it { is_expected.to be_falsey } + end + + context 'experimentation_subject_index outside enabled ratio' do + let(:experimentation_subject_index) { 11 } + + it { is_expected.to be_falsey } + end end end end diff --git a/spec/lib/gitlab/file_finder_spec.rb b/spec/lib/gitlab/file_finder_spec.rb index b49c5817131..a3ba7388f36 100644 --- a/spec/lib/gitlab/file_finder_spec.rb +++ b/spec/lib/gitlab/file_finder_spec.rb @@ -6,11 +6,11 @@ describe Gitlab::FileFinder do subject { described_class.new(project, project.default_branch) } it_behaves_like 'file finder' do - let(:expected_file_by_name) { 'files/images/wm.svg' } + let(:expected_file_by_path) { 'files/images/wm.svg' } let(:expected_file_by_content) { 'CHANGELOG' } end - it 'filters by name' do + it 'filters by filename' do results = subject.find('files filename:wm.svg') expect(results.count).to eq(1) diff --git a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb index 1dfca0b056c..da307754243 100644 --- a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb +++ b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb @@ -43,7 +43,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do verification_status: 'verified' end - it 'assigns the gpg key to the signature when the missing gpg key is added' do + it 'assigns the gpg key to the signature when the missing gpg key is added', :sidekiq_might_not_need_inline do # InvalidGpgSignatureUpdater is called by the after_create hook gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key, @@ -86,7 +86,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do verification_status: 'unknown_key' end - it 'updates the signature to being valid when the missing gpg key is added' do + it 'updates the signature to being valid when the missing gpg key is added', :sidekiq_might_not_need_inline do # InvalidGpgSignatureUpdater is called by the after_create hook gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key, @@ -133,7 +133,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do verification_status: 'unknown_key' end - it 'updates the signature to being valid when the user updates the email address' do + it 'updates the signature to being valid when the user updates the email address', :sidekiq_might_not_need_inline do gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key, user: user @@ -152,7 +152,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do ) end - it 'keeps the signature at being invalid when the changed email address is still unrelated' do + it 'keeps the signature at being invalid when the changed email address is still unrelated', :sidekiq_might_not_need_inline do gpg_key = create :gpg_key, key: GpgHelpers::User1.public_key, user: user @@ -192,7 +192,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do verification_status: 'unknown_key' end - it 'updates the signature to being valid when the missing gpg key is added' do + it 'updates the signature to being valid when the missing gpg key is added', :sidekiq_might_not_need_inline do # InvalidGpgSignatureUpdater is called by the after_create hook gpg_key = create(:gpg_key, key: GpgHelpers::User3.public_key, user: user) subkey = gpg_key.subkeys.last diff --git a/spec/lib/gitlab/hashed_storage/migrator_spec.rb b/spec/lib/gitlab/hashed_storage/migrator_spec.rb index 8e253b51597..ce7f2c4530d 100644 --- a/spec/lib/gitlab/hashed_storage/migrator_spec.rb +++ b/spec/lib/gitlab/hashed_storage/migrator_spec.rb @@ -42,7 +42,7 @@ describe Gitlab::HashedStorage::Migrator, :sidekiq, :redis do subject.bulk_migrate(start: ids.min, finish: ids.max) end - it 'has all projects migrated and set as writable' do + it 'has all projects migrated and set as writable', :sidekiq_might_not_need_inline do perform_enqueued_jobs do subject.bulk_migrate(start: ids.min, finish: ids.max) end @@ -79,7 +79,7 @@ describe Gitlab::HashedStorage::Migrator, :sidekiq, :redis do subject.bulk_rollback(start: ids.min, finish: ids.max) end - it 'has all projects rolledback and set as writable' do + it 'has all projects rolledback and set as writable', :sidekiq_might_not_need_inline do perform_enqueued_jobs do subject.bulk_rollback(start: ids.min, finish: ids.max) end @@ -108,7 +108,7 @@ describe Gitlab::HashedStorage::Migrator, :sidekiq, :redis do expect { subject.migrate(project) }.not_to raise_error end - it 'migrates project storage' do + it 'migrates project storage', :sidekiq_might_not_need_inline do perform_enqueued_jobs do subject.migrate(project) end @@ -154,7 +154,7 @@ describe Gitlab::HashedStorage::Migrator, :sidekiq, :redis do expect { subject.rollback(project) }.not_to raise_error end - it 'rolls-back project storage' do + it 'rolls-back project storage', :sidekiq_might_not_need_inline do perform_enqueued_jobs do subject.rollback(project) end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 4fd61383c6b..2e3bc4606b9 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -421,6 +421,7 @@ project: - pages_metadatum - alerts_service - grafana_integration +- remove_source_branch_after_merge award_emoji: - awardable - user diff --git a/spec/lib/gitlab/import_export/fork_spec.rb b/spec/lib/gitlab/import_export/fork_spec.rb index 71fd5a51c3b..5752fd8fa0d 100644 --- a/spec/lib/gitlab/import_export/fork_spec.rb +++ b/spec/lib/gitlab/import_export/fork_spec.rb @@ -47,7 +47,7 @@ describe 'forked project import' do end end - it 'can access the MR' do + it 'can access the MR', :sidekiq_might_not_need_inline do project.merge_requests.first.fetch_ref! expect(project.repository.ref_exists?('refs/merge-requests/1/head')).to be_truthy diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 16f4115fc6e..ede8eb4b2bd 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -512,6 +512,7 @@ Project: - request_access_enabled - has_external_wiki - only_allow_merge_if_all_discussions_are_resolved +- remove_source_branch_after_merge - auto_cancel_pending_pipelines - printing_merge_request_link_enabled - resolve_outdated_diff_discussions diff --git a/spec/lib/gitlab/phabricator_import/project_creator_spec.rb b/spec/lib/gitlab/phabricator_import/project_creator_spec.rb index e9455b866ac..fd17284eea2 100644 --- a/spec/lib/gitlab/phabricator_import/project_creator_spec.rb +++ b/spec/lib/gitlab/phabricator_import/project_creator_spec.rb @@ -11,7 +11,7 @@ describe Gitlab::PhabricatorImport::ProjectCreator do subject(:creator) { described_class.new(user, params) } describe '#execute' do - it 'creates a project correctly and schedule an import' do + it 'creates a project correctly and schedule an import', :sidekiq_might_not_need_inline do expect_next_instance_of(Gitlab::PhabricatorImport::Importer) do |importer| expect(importer).to receive(:execute) end diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index d6e50c672e6..99078f19361 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -79,20 +79,20 @@ describe Gitlab::ProjectSearchResults do end it 'finds by name' do - expect(results.map(&:filename)).to include(expected_file_by_name) + expect(results.map(&:path)).to include(expected_file_by_path) end - it "loads all blobs for filename matches in single batch" do + it "loads all blobs for path matches in single batch" do expect(Gitlab::Git::Blob).to receive(:batch).once.and_call_original expected = project.repository.search_files_by_name(query, 'master') - expect(results.map(&:filename)).to include(*expected) + expect(results.map(&:path)).to include(*expected) end it 'finds by content' do - blob = results.select { |result| result.filename == expected_file_by_content }.flatten.last + blob = results.select { |result| result.path == expected_file_by_content }.flatten.last - expect(blob.filename).to eq(expected_file_by_content) + expect(blob.path).to eq(expected_file_by_content) end end @@ -146,7 +146,7 @@ describe Gitlab::ProjectSearchResults do let(:blob_type) { 'blobs' } let(:disabled_project) { create(:project, :public, :repository, :repository_disabled) } let(:private_project) { create(:project, :public, :repository, :repository_private) } - let(:expected_file_by_name) { 'files/images/wm.svg' } + let(:expected_file_by_path) { 'files/images/wm.svg' } let(:expected_file_by_content) { 'CHANGELOG' } end @@ -169,7 +169,7 @@ describe Gitlab::ProjectSearchResults do let(:blob_type) { 'wiki_blobs' } let(:disabled_project) { create(:project, :public, :wiki_repo, :wiki_disabled) } let(:private_project) { create(:project, :public, :wiki_repo, :wiki_private) } - let(:expected_file_by_name) { 'Files/Title.md' } + let(:expected_file_by_path) { 'Files/Title.md' } let(:expected_file_by_content) { 'CHANGELOG.md' } end diff --git a/spec/lib/gitlab/search/found_blob_spec.rb b/spec/lib/gitlab/search/found_blob_spec.rb index a575f6e2f11..07842faa638 100644 --- a/spec/lib/gitlab/search/found_blob_spec.rb +++ b/spec/lib/gitlab/search/found_blob_spec.rb @@ -15,7 +15,6 @@ describe Gitlab::Search::FoundBlob do is_expected.to be_an described_class expect(subject.id).to be_nil expect(subject.path).to eq('CHANGELOG') - expect(subject.filename).to eq('CHANGELOG') expect(subject.basename).to eq('CHANGELOG') expect(subject.ref).to eq('master') expect(subject.startline).to eq(188) @@ -25,12 +24,12 @@ describe Gitlab::Search::FoundBlob do it 'does not parse content if not needed' do expect(subject).not_to receive(:parse_search_result) expect(subject.project_id).to eq(project.id) - expect(subject.binary_filename).to eq('CHANGELOG') + expect(subject.binary_path).to eq('CHANGELOG') end it 'parses content only once when needed' do expect(subject).to receive(:parse_search_result).once.and_call_original - expect(subject.filename).to eq('CHANGELOG') + expect(subject.path).to eq('CHANGELOG') expect(subject.startline).to eq(188) end @@ -38,7 +37,7 @@ describe Gitlab::Search::FoundBlob do let(:search_result) { "master:testdata/project::function1.yaml\x001\x00---\n" } it 'returns a valid FoundBlob' do - expect(subject.filename).to eq('testdata/project::function1.yaml') + expect(subject.path).to eq('testdata/project::function1.yaml') expect(subject.basename).to eq('testdata/project::function1') expect(subject.ref).to eq('master') expect(subject.startline).to eq(1) @@ -50,7 +49,7 @@ describe Gitlab::Search::FoundBlob do let(:search_result) { "master:testdata/foo.txt\x001\x00blah:9:blah" } it 'returns a valid FoundBlob' do - expect(subject.filename).to eq('testdata/foo.txt') + expect(subject.path).to eq('testdata/foo.txt') expect(subject.basename).to eq('testdata/foo') expect(subject.ref).to eq('master') expect(subject.startline).to eq(1) @@ -62,7 +61,7 @@ describe Gitlab::Search::FoundBlob do let(:search_result) { "master:testdata/foo.txt\x001\x00blah\x001\x00foo" } it 'returns a valid FoundBlob' do - expect(subject.filename).to eq('testdata/foo.txt') + expect(subject.path).to eq('testdata/foo.txt') expect(subject.basename).to eq('testdata/foo') expect(subject.ref).to eq('master') expect(subject.startline).to eq(1) @@ -74,7 +73,7 @@ describe Gitlab::Search::FoundBlob do let(:results) { project.repository.search_files_by_content('Role models', 'master') } it 'returns a valid FoundBlob that ends with an empty line' do - expect(subject.filename).to eq('files/markdown/ruby-style-guide.md') + expect(subject.path).to eq('files/markdown/ruby-style-guide.md') expect(subject.basename).to eq('files/markdown/ruby-style-guide') expect(subject.ref).to eq('master') expect(subject.startline).to eq(1) @@ -87,7 +86,7 @@ describe Gitlab::Search::FoundBlob do let(:results) { project.repository.search_files_by_content('файл', 'master') } it 'returns results as UTF-8' do - expect(subject.filename).to eq('encoding/russian.rb') + expect(subject.path).to eq('encoding/russian.rb') expect(subject.basename).to eq('encoding/russian') expect(subject.ref).to eq('master') expect(subject.startline).to eq(1) @@ -99,7 +98,7 @@ describe Gitlab::Search::FoundBlob do let(:results) { project.repository.search_files_by_content('webhook', 'master') } it 'returns results as UTF-8' do - expect(subject.filename).to eq('encoding/テスト.txt') + expect(subject.path).to eq('encoding/テスト.txt') expect(subject.basename).to eq('encoding/テスト') expect(subject.ref).to eq('master') expect(subject.startline).to eq(3) @@ -111,7 +110,7 @@ describe Gitlab::Search::FoundBlob do let(:search_result) { (+"master:encoding/iso8859.txt\x001\x00\xC4\xFC\nmaster:encoding/iso8859.txt\x002\x00\nmaster:encoding/iso8859.txt\x003\x00foo\n").force_encoding(Encoding::ASCII_8BIT) } it 'returns results as UTF-8' do - expect(subject.filename).to eq('encoding/iso8859.txt') + expect(subject.path).to eq('encoding/iso8859.txt') expect(subject.basename).to eq('encoding/iso8859') expect(subject.ref).to eq('master') expect(subject.startline).to eq(1) @@ -124,7 +123,6 @@ describe Gitlab::Search::FoundBlob do let(:search_result) { "master:CONTRIBUTE.md\x005\x00- [Contribute to GitLab](#contribute-to-gitlab)\n" } it { expect(subject.path).to eq('CONTRIBUTE.md') } - it { expect(subject.filename).to eq('CONTRIBUTE.md') } it { expect(subject.basename).to eq('CONTRIBUTE') } end @@ -132,7 +130,6 @@ describe Gitlab::Search::FoundBlob do let(:search_result) { "master:a/b/c.md\x005\x00a b c\n" } it { expect(subject.path).to eq('a/b/c.md') } - it { expect(subject.filename).to eq('a/b/c.md') } it { expect(subject.basename).to eq('a/b/c') } end end @@ -141,7 +138,7 @@ describe Gitlab::Search::FoundBlob do context 'when file is under directory' do let(:path) { 'a/b/c.md' } - subject { described_class.new(blob_filename: path, project: project, ref: 'master') } + subject { described_class.new(blob_path: path, project: project, ref: 'master') } before do allow(Gitlab::Git::Blob).to receive(:batch).and_return([ @@ -150,7 +147,6 @@ describe Gitlab::Search::FoundBlob do end it { expect(subject.path).to eq('a/b/c.md') } - it { expect(subject.filename).to eq('a/b/c.md') } it { expect(subject.basename).to eq('a/b/c') } context 'when filename has multiple extensions' do diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb index a17e9a31212..79ad1c0b43f 100644 --- a/spec/lib/gitlab/shell_spec.rb +++ b/spec/lib/gitlab/shell_spec.rb @@ -310,18 +310,18 @@ describe Gitlab::Shell do let(:disk_path) { "#{project.disk_path}.git" } it 'returns true when the command succeeds' do - expect(gitlab_shell.exists?(project.repository_storage, disk_path)).to be(true) + expect(TestEnv.storage_dir_exists?(project.repository_storage, disk_path)).to be(true) expect(gitlab_shell.remove_repository(project.repository_storage, project.disk_path)).to be(true) - expect(gitlab_shell.exists?(project.repository_storage, disk_path)).to be(false) + expect(TestEnv.storage_dir_exists?(project.repository_storage, disk_path)).to be(false) end it 'keeps the namespace directory' do gitlab_shell.remove_repository(project.repository_storage, project.disk_path) - expect(gitlab_shell.exists?(project.repository_storage, disk_path)).to be(false) - expect(gitlab_shell.exists?(project.repository_storage, project.disk_path.gsub(project.name, ''))).to be(true) + expect(TestEnv.storage_dir_exists?(project.repository_storage, disk_path)).to be(false) + expect(TestEnv.storage_dir_exists?(project.repository_storage, project.disk_path.gsub(project.name, ''))).to be(true) end end @@ -332,18 +332,18 @@ describe Gitlab::Shell do old_path = project2.disk_path new_path = "project/new_path" - expect(gitlab_shell.exists?(project2.repository_storage, "#{old_path}.git")).to be(true) - expect(gitlab_shell.exists?(project2.repository_storage, "#{new_path}.git")).to be(false) + expect(TestEnv.storage_dir_exists?(project2.repository_storage, "#{old_path}.git")).to be(true) + expect(TestEnv.storage_dir_exists?(project2.repository_storage, "#{new_path}.git")).to be(false) expect(gitlab_shell.mv_repository(project2.repository_storage, old_path, new_path)).to be_truthy - expect(gitlab_shell.exists?(project2.repository_storage, "#{old_path}.git")).to be(false) - expect(gitlab_shell.exists?(project2.repository_storage, "#{new_path}.git")).to be(true) + expect(TestEnv.storage_dir_exists?(project2.repository_storage, "#{old_path}.git")).to be(false) + expect(TestEnv.storage_dir_exists?(project2.repository_storage, "#{new_path}.git")).to be(true) end it 'returns false when the command fails' do expect(gitlab_shell.mv_repository(project2.repository_storage, project2.disk_path, '')).to be_falsy - expect(gitlab_shell.exists?(project2.repository_storage, "#{project2.disk_path}.git")).to be(true) + expect(TestEnv.storage_dir_exists?(project2.repository_storage, "#{project2.disk_path}.git")).to be(true) end end @@ -403,56 +403,32 @@ describe Gitlab::Shell do it 'creates a namespace' do subject.add_namespace(storage, "mepmep") - expect(subject.exists?(storage, "mepmep")).to be(true) + expect(TestEnv.storage_dir_exists?(storage, "mepmep")).to be(true) end end - describe '#exists?' do - context 'when the namespace does not exist' do + describe '#repository_exists?' do + context 'when the repository does not exist' do it 'returns false' do - expect(subject.exists?(storage, "non-existing")).to be(false) + expect(subject.repository_exists?(storage, "non-existing.git")).to be(false) end end - context 'when the namespace exists' do + context 'when the repository exists' do it 'returns true' do - subject.add_namespace(storage, "mepmep") + project = create(:project, :repository, :legacy_storage) - expect(subject.exists?(storage, "mepmep")).to be(true) + expect(subject.repository_exists?(storage, project.repository.disk_path + ".git")).to be(true) end end end - describe '#repository_exists?' do - context 'when the storage path does not exist' do - subject { described_class.new.repository_exists?(storage, "non-existing.git") } - - it { is_expected.to be_falsey } - end - - context 'when the repository does not exist' do - let(:project) { create(:project, :repository, :legacy_storage) } - - subject { described_class.new.repository_exists?(storage, "#{project.repository.disk_path}-some-other-repo.git") } - - it { is_expected.to be_falsey } - end - - context 'when the repository exists' do - let(:project) { create(:project, :repository, :legacy_storage) } - - subject { described_class.new.repository_exists?(storage, "#{project.repository.disk_path}.git") } - - it { is_expected.to be_truthy } - end - end - describe '#remove' do it 'removes the namespace' do subject.add_namespace(storage, "mepmep") subject.rm_namespace(storage, "mepmep") - expect(subject.exists?(storage, "mepmep")).to be(false) + expect(TestEnv.storage_dir_exists?(storage, "mepmep")).to be(false) end end @@ -461,8 +437,8 @@ describe Gitlab::Shell do subject.add_namespace(storage, "mepmep") subject.mv_namespace(storage, "mepmep", "2mep") - expect(subject.exists?(storage, "mepmep")).to be(false) - expect(subject.exists?(storage, "2mep")).to be(true) + expect(TestEnv.storage_dir_exists?(storage, "mepmep")).to be(false) + expect(TestEnv.storage_dir_exists?(storage, "2mep")).to be(true) end end end diff --git a/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb b/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb index 8410467ef1f..27eea963402 100644 --- a/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/correlation_logger_spec.rb @@ -19,7 +19,7 @@ describe Gitlab::SidekiqMiddleware::CorrelationLogger do end end - it 'injects into payload the correlation id' do + it 'injects into payload the correlation id', :sidekiq_might_not_need_inline do expect_any_instance_of(described_class).to receive(:call).and_call_original expect_any_instance_of(TestWorker).to receive(:perform).with(1234) do diff --git a/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb index ec4c8560f22..df16b9d073c 100644 --- a/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb @@ -44,12 +44,14 @@ describe Gitlab::SidekiqMiddleware::Metrics do it 'sets queue specific metrics' do labels = { queue: :test } + labels_with_job_status = { queue: :test, job_status: :done } allow(middleware).to receive(:get_thread_cputime).and_return(1, 3) + allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(2, 3) - expect(user_execution_seconds_metric).to receive(:observe).with(labels, 2) expect(running_jobs_metric).to receive(:increment).with(labels, 1) expect(running_jobs_metric).to receive(:increment).with(labels, -1) - expect(completion_seconds_metric).to receive(:observe).with(labels, kind_of(Numeric)) + expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, 2) + expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, 1) middleware.call(worker, {}, :test) { nil } end @@ -74,8 +76,18 @@ describe Gitlab::SidekiqMiddleware::Metrics do context 'when error is raised' do it 'sets sidekiq_jobs_failed_total and reraises' do - expect(failed_total_metric).to receive(:increment) - expect { middleware.call(worker, {}, :test) { raise } }.to raise_error + labels = { queue: :test } + labels_with_job_status = { queue: :test, job_status: :fail } + allow(middleware).to receive(:get_thread_cputime).and_return(1, 4) + allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(2, 6) + + expect(running_jobs_metric).to receive(:increment).with(labels, 1) + expect(running_jobs_metric).to receive(:increment).with(labels, -1) + expect(failed_total_metric).to receive(:increment).with(labels, 1) + expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, 3) + expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, 4) + + expect { middleware.call(worker, {}, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed") end end end diff --git a/spec/lib/gitlab/sql/recursive_cte_spec.rb b/spec/lib/gitlab/sql/recursive_cte_spec.rb index 20e36c224b0..b15be56dd6d 100644 --- a/spec/lib/gitlab/sql/recursive_cte_spec.rb +++ b/spec/lib/gitlab/sql/recursive_cte_spec.rb @@ -20,7 +20,7 @@ describe Gitlab::SQL::RecursiveCTE do [rel1.except(:order).to_sql, rel2.except(:order).to_sql] end - expect(sql).to eq("#{name} AS (#{sql1}\nUNION\n#{sql2})") + expect(sql).to eq("#{name} AS ((#{sql1})\nUNION\n(#{sql2}))") end end diff --git a/spec/lib/gitlab/sql/union_spec.rb b/spec/lib/gitlab/sql/union_spec.rb index f8f6da19fa5..f736614ae53 100644 --- a/spec/lib/gitlab/sql/union_spec.rb +++ b/spec/lib/gitlab/sql/union_spec.rb @@ -14,7 +14,7 @@ describe Gitlab::SQL::Union do it 'returns a String joining relations together using a UNION' do union = described_class.new([relation_1, relation_2]) - expect(union.to_sql).to eq("#{to_sql(relation_1)}\nUNION\n#{to_sql(relation_2)}") + expect(union.to_sql).to eq("(#{to_sql(relation_1)})\nUNION\n(#{to_sql(relation_2)})") end it 'skips Model.none segements' do @@ -22,7 +22,7 @@ describe Gitlab::SQL::Union do union = described_class.new([empty_relation, relation_1, relation_2]) expect {User.where("users.id IN (#{union.to_sql})").to_a}.not_to raise_error - expect(union.to_sql).to eq("#{to_sql(relation_1)}\nUNION\n#{to_sql(relation_2)}") + expect(union.to_sql).to eq("(#{to_sql(relation_1)})\nUNION\n(#{to_sql(relation_2)})") end it 'uses UNION ALL when removing duplicates is disabled' do diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb index 50488dba48c..4615599be7e 100644 --- a/spec/lib/gitlab/tracking_spec.rb +++ b/spec/lib/gitlab/tracking_spec.rb @@ -13,14 +13,17 @@ describe Gitlab::Tracking do describe '.snowplow_options' do it 'returns useful client options' do - expect(described_class.snowplow_options(nil)).to eq( + expected_fields = { namespace: 'gl', hostname: 'gitfoo.com', cookieDomain: '.gitfoo.com', appId: '_abc123_', formTracking: true, - linkClickTracking: true - ) + linkClickTracking: true, + userId: nil + } + + expect(subject.snowplow_options(nil, nil)).to match(expected_fields) end it 'enables features using feature flags' do @@ -29,11 +32,12 @@ describe Gitlab::Tracking do :additional_snowplow_tracking, '_group_' ).and_return(false) - - expect(described_class.snowplow_options('_group_')).to include( + addition_feature_fields = { formTracking: false, linkClickTracking: false - ) + } + + expect(subject.snowplow_options('_group_', nil)).to include(addition_feature_fields) end end diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index 08d3c638f9e..4ed2c232f97 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -150,7 +150,7 @@ describe Gitlab::UrlBuilder do wiki_page = build(:wiki_page) url = described_class.build(wiki_page) - expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}" + expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_page_path}/#{wiki_page.slug}" end end end diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb index c25bd14fcba..4e7c43a6856 100644 --- a/spec/lib/gitlab/user_access_spec.rb +++ b/spec/lib/gitlab/user_access_spec.rb @@ -148,7 +148,7 @@ describe Gitlab::UserAccess do ) end - it 'allows users that have push access to the canonical project to push to the MR branch' do + it 'allows users that have push access to the canonical project to push to the MR branch', :sidekiq_might_not_need_inline do canonical_project.add_developer(user) expect(access.can_push_to_branch?('awesome-feature')).to be_truthy diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb index 890918d4a7c..a68434c8c66 100644 --- a/spec/lib/gitlab/utils_spec.rb +++ b/spec/lib/gitlab/utils_spec.rb @@ -252,4 +252,41 @@ describe Gitlab::Utils do expect(described_class.string_to_ip_object('1:0:0:0:0:0:0:0/124')).to eq(IPAddr.new('1:0:0:0:0:0:0:0/124')) end end + + describe '.allow_hash_values' do + it 'removes keys that do not pass the inclusion filters' do + symbols = %i[x y z] + ints = (0..100) + strings = %w[foo bar baz].to_set + + hash = { + a: :x, + b: 100, + c: 'foo', + d: :irrelevant, + aa: :w, + bb: 200, + cc: 'food', + dd: :totally_irrelevant + } + allowed = { + a: symbols, + b: ints, + c: strings, + aa: symbols, + bb: ints, + cc: strings + } + + described_class.allow_hash_values(hash, allowed) + + expect(hash).to eq({ + a: :x, + b: 100, + c: 'foo', + d: :irrelevant, + dd: :totally_irrelevant + }) + end + end end diff --git a/spec/lib/gitlab/wiki_file_finder_spec.rb b/spec/lib/gitlab/wiki_file_finder_spec.rb index fdd95d5e6e6..aeba081f3d3 100644 --- a/spec/lib/gitlab/wiki_file_finder_spec.rb +++ b/spec/lib/gitlab/wiki_file_finder_spec.rb @@ -15,7 +15,7 @@ describe Gitlab::WikiFileFinder do it_behaves_like 'file finder' do subject { described_class.new(project, project.wiki.default_branch) } - let(:expected_file_by_name) { 'Files/Title.md' } + let(:expected_file_by_path) { 'Files/Title.md' } let(:expected_file_by_content) { 'CHANGELOG.md' } end end diff --git a/spec/lib/quality/helm_client_spec.rb b/spec/lib/quality/helm_client_spec.rb index 7abb9688d5a..da5ba4c4d99 100644 --- a/spec/lib/quality/helm_client_spec.rb +++ b/spec/lib/quality/helm_client_spec.rb @@ -107,5 +107,25 @@ RSpec.describe Quality::HelmClient do expect(subject.delete(release_name: release_name)).to eq('') end + + context 'with multiple release names' do + let(:release_name) { ['my-release', 'my-release-2'] } + + it 'raises an error if the Helm command fails' do + expect(Gitlab::Popen).to receive(:popen_with_detail) + .with([%(helm delete --tiller-namespace "#{namespace}" --purge #{release_name.join(' ')})]) + .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false))) + + expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError) + end + + it 'calls helm delete with multiple release names' do + expect(Gitlab::Popen).to receive(:popen_with_detail) + .with([%(helm delete --tiller-namespace "#{namespace}" --purge #{release_name.join(' ')})]) + .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true))) + + expect(subject.delete(release_name: release_name)).to eq('') + end + end end end diff --git a/spec/lib/quality/kubernetes_client_spec.rb b/spec/lib/quality/kubernetes_client_spec.rb index 4e77dcc97e6..a42f6151a5e 100644 --- a/spec/lib/quality/kubernetes_client_spec.rb +++ b/spec/lib/quality/kubernetes_client_spec.rb @@ -29,5 +29,30 @@ RSpec.describe Quality::KubernetesClient do # We're not verifying the output here, just silencing it expect { subject.cleanup(release_name: release_name) }.to output.to_stdout end + + context 'with multiple releases' do + let(:release_name) { ['my-release', 'my-release-2'] } + + it 'raises an error if the Kubernetes command fails' do + expect(Gitlab::Popen).to receive(:popen_with_detail) + .with([%(kubectl --namespace "#{namespace}" delete ) \ + 'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \ + "--now --ignore-not-found --include-uninitialized -l 'release in (#{release_name.join(', ')})'"]) + .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false))) + + expect { subject.cleanup(release_name: release_name) }.to raise_error(described_class::CommandFailedError) + end + + it 'calls kubectl with the correct arguments' do + expect(Gitlab::Popen).to receive(:popen_with_detail) + .with([%(kubectl --namespace "#{namespace}" delete ) \ + 'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \ + "--now --ignore-not-found --include-uninitialized -l 'release in (#{release_name.join(', ')})'"]) + .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true))) + + # We're not verifying the output here, just silencing it + expect { subject.cleanup(release_name: release_name) }.to output.to_stdout + end + end end end diff --git a/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb b/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb index 826c5a2324b..f4155eab1bf 100644 --- a/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb +++ b/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb @@ -32,7 +32,7 @@ describe ScheduleSetConfidentialNoteEventsOnServices, :migration, :sidekiq do end end - it 'correctly processes services' do + it 'correctly processes services', :sidekiq_might_not_need_inline do perform_enqueued_jobs do expect(services_table.where(confidential_note_events: nil).count).to eq 4 expect(services_table.where(confidential_note_events: true).count).to eq 1 diff --git a/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb b/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb index 65a918d5440..913b4d3f114 100644 --- a/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb +++ b/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb @@ -20,7 +20,7 @@ describe BackfillStoreProjectFullPathInRepo, :migration do describe '#up' do shared_examples_for 'writes the full path to git config' do - it 'writes the git config' do + it 'writes the git config', :sidekiq_might_not_need_inline do expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service| allow(repository_service).to receive(:cleanup) expect(repository_service).to receive(:set_config).with('gitlab.fullpath' => expected_path) @@ -29,7 +29,7 @@ describe BackfillStoreProjectFullPathInRepo, :migration do migration.up end - it 'retries in case of failure' do + it 'retries in case of failure', :sidekiq_might_not_need_inline do repository_service = spy(:repository_service) allow(Gitlab::GitalyClient::RepositoryService).to receive(:new).and_return(repository_service) @@ -40,7 +40,7 @@ describe BackfillStoreProjectFullPathInRepo, :migration do migration.up end - it 'cleans up repository before writing the config' do + it 'cleans up repository before writing the config', :sidekiq_might_not_need_inline do expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service| expect(repository_service).to receive(:cleanup).ordered expect(repository_service).to receive(:set_config).ordered @@ -87,7 +87,7 @@ describe BackfillStoreProjectFullPathInRepo, :migration do context 'project in group' do let!(:project) { projects.create!(namespace_id: group.id, name: 'baz', path: 'baz') } - it 'deletes the gitlab full config value' do + it 'deletes the gitlab full config value', :sidekiq_might_not_need_inline do expect_any_instance_of(Gitlab::GitalyClient::RepositoryService) .to receive(:delete_config).with(['gitlab.fullpath']) diff --git a/spec/migrations/fill_file_store_spec.rb b/spec/migrations/fill_file_store_spec.rb index a87d910c73b..806c9283634 100644 --- a/spec/migrations/fill_file_store_spec.rb +++ b/spec/migrations/fill_file_store_spec.rb @@ -23,7 +23,7 @@ describe FillFileStore, :migration do uploads.create!(size: 10, path: 'path', uploader: 'uploader', mount_point: 'file_name', store: nil) end - it 'correctly migrates nullified file_store/store column' do + it 'correctly migrates nullified file_store/store column', :sidekiq_might_not_need_inline do expect(job_artifacts.where(file_store: nil).count).to eq(1) expect(lfs_objects.where(file_store: nil).count).to eq(1) expect(uploads.where(store: nil).count).to eq(1) diff --git a/spec/migrations/fix_wrong_pages_access_level_spec.rb b/spec/migrations/fix_wrong_pages_access_level_spec.rb index 73df6e3b16d..73d8218b95c 100644 --- a/spec/migrations/fix_wrong_pages_access_level_spec.rb +++ b/spec/migrations/fix_wrong_pages_access_level_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require Rails.root.join('db', 'post_migrate', '20190703185326_fix_wrong_pages_access_level.rb') -describe FixWrongPagesAccessLevel, :migration, :sidekiq, schema: 20190628185004 do +describe FixWrongPagesAccessLevel, :migration, :sidekiq_might_not_need_inline, schema: 20190628185004 do using RSpec::Parameterized::TableSyntax let(:migration_class) { described_class::MIGRATION } diff --git a/spec/migrations/migrate_legacy_artifacts_to_job_artifacts_spec.rb b/spec/migrations/migrate_legacy_artifacts_to_job_artifacts_spec.rb index be39d9cd75a..98bbe0ed5a2 100644 --- a/spec/migrations/migrate_legacy_artifacts_to_job_artifacts_spec.rb +++ b/spec/migrations/migrate_legacy_artifacts_to_job_artifacts_spec.rb @@ -42,7 +42,7 @@ describe MigrateLegacyArtifactsToJobArtifacts, :migration, :sidekiq do end end - it 'migrates legacy artifacts to ci_job_artifacts table' do + it 'migrates legacy artifacts to ci_job_artifacts table', :sidekiq_might_not_need_inline do migrate! expect(job_artifacts.order(:job_id, :file_type).pluck('project_id, job_id, file_type, file_store, size, expire_at, file, file_sha256, file_location')) diff --git a/spec/migrations/schedule_digest_personal_access_tokens_spec.rb b/spec/migrations/schedule_digest_personal_access_tokens_spec.rb index aca95ffee08..ff859d07ff2 100644 --- a/spec/migrations/schedule_digest_personal_access_tokens_spec.rb +++ b/spec/migrations/schedule_digest_personal_access_tokens_spec.rb @@ -34,7 +34,7 @@ describe ScheduleDigestPersonalAccessTokens, :migration, :sidekiq do end end - it 'schedules background migrations' do + it 'schedules background migrations', :sidekiq_might_not_need_inline do perform_enqueued_jobs do plain_text_token = 'token IS NOT NULL' diff --git a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb index cd431d23fa3..a0241f1d20c 100644 --- a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb +++ b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb @@ -34,7 +34,7 @@ describe ScheduleFillValidTimeForPagesDomainCertificates, :migration, :sidekiq d end end - it 'sets certificate valid_not_before/not_after' do + it 'sets certificate valid_not_before/not_after', :sidekiq_might_not_need_inline do perform_enqueued_jobs do migrate! diff --git a/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb b/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb index db312242bea..1ddb468f6b7 100644 --- a/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb +++ b/spec/migrations/schedule_fix_gitlab_com_pages_access_level_spec.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + require 'spec_helper' require Rails.root.join('db', 'post_migrate', '20191017045817_schedule_fix_gitlab_com_pages_access_level.rb') -describe ScheduleFixGitlabComPagesAccessLevel, :migration, :sidekiq, schema: 2019_10_16_072826 do +describe ScheduleFixGitlabComPagesAccessLevel, :migration, :sidekiq_might_not_need_inline, schema: 2019_10_16_072826 do using RSpec::Parameterized::TableSyntax let(:migration_name) { 'FixGitlabComPagesAccessLevel' } diff --git a/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb b/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb index cb3cdb44271..845b0515177 100644 --- a/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb +++ b/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb @@ -32,7 +32,7 @@ describe ScheduleSetConfidentialNoteEventsOnWebhooks, :migration, :sidekiq do end end - it 'correctly processes web hooks' do + it 'correctly processes web hooks', :sidekiq_might_not_need_inline do perform_enqueued_jobs do expect(web_hooks_table.where(confidential_note_events: nil).count).to eq 4 expect(web_hooks_table.where(confidential_note_events: true).count).to eq 1 diff --git a/spec/migrations/schedule_sync_issuables_state_id_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_spec.rb index bc94f8820bd..4f841e8ce04 100644 --- a/spec/migrations/schedule_sync_issuables_state_id_spec.rb +++ b/spec/migrations/schedule_sync_issuables_state_id_spec.rb @@ -33,7 +33,7 @@ describe ScheduleSyncIssuablesStateId, :migration, :sidekiq do describe '#up' do context 'issues' do - it 'migrates state column to integer' do + it 'migrates state column to integer', :sidekiq_might_not_need_inline 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') @@ -55,7 +55,7 @@ describe ScheduleSyncIssuablesStateId, :migration, :sidekiq do end context 'merge requests' do - it 'migrates state column to integer' do + it 'migrates state column to integer', :sidekiq_might_not_need_inline 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') diff --git a/spec/migrations/schedule_to_archive_legacy_traces_spec.rb b/spec/migrations/schedule_to_archive_legacy_traces_spec.rb index 3f05c4aefd3..a81fb1494c7 100644 --- a/spec/migrations/schedule_to_archive_legacy_traces_spec.rb +++ b/spec/migrations/schedule_to_archive_legacy_traces_spec.rb @@ -25,7 +25,7 @@ describe ScheduleToArchiveLegacyTraces, :migration do create_legacy_trace(@build_running, 'This job is not done yet') end - it 'correctly archive legacy traces' do + it 'correctly archive legacy traces', :sidekiq_might_not_need_inline do expect(job_artifacts.count).to eq(0) expect(File.exist?(legacy_trace_path(@build_success))).to be_truthy expect(File.exist?(legacy_trace_path(@build_failed))).to be_truthy diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb index 59db347582b..96d81f4cc49 100644 --- a/spec/models/ci/build_trace_chunk_spec.rb +++ b/spec/models/ci/build_trace_chunk_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do @@ -63,7 +65,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :redis } before do - build_trace_chunk.send(:unsafe_set_data!, 'Sample data in redis') + build_trace_chunk.send(:unsafe_set_data!, +'Sample data in redis') end it { is_expected.to eq('Sample data in redis') } @@ -71,7 +73,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do context 'when data_store is database' do let(:data_store) { :database } - let(:raw_data) { 'Sample data in database' } + let(:raw_data) { +'Sample data in database' } it { is_expected.to eq('Sample data in database') } end @@ -80,7 +82,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :fog } before do - build_trace_chunk.send(:unsafe_set_data!, 'Sample data in fog') + build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog') end it { is_expected.to eq('Sample data in fog') } @@ -90,7 +92,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do describe '#append' do subject { build_trace_chunk.append(new_data, offset) } - let(:new_data) { 'Sample new data' } + let(:new_data) { +'Sample new data' } let(:offset) { 0 } let(:merged_data) { data + new_data.to_s } @@ -143,7 +145,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when new_data is empty' do - let(:new_data) { '' } + let(:new_data) { +'' } it 'does not append' do subject @@ -172,7 +174,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do shared_examples_for 'Scheduling sidekiq worker to flush data to persist store' do context 'when new data fulfilled chunk size' do - let(:new_data) { 'a' * described_class::CHUNK_SIZE } + let(:new_data) { +'a' * described_class::CHUNK_SIZE } it 'schedules trace chunk flush worker' do expect(Ci::BuildTraceChunkFlushWorker).to receive(:perform_async).once @@ -180,7 +182,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do subject end - it 'migrates data to object storage' do + it 'migrates data to object storage', :sidekiq_might_not_need_inline do perform_enqueued_jobs do subject @@ -194,7 +196,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do shared_examples_for 'Scheduling no sidekiq worker' do context 'when new data fulfilled chunk size' do - let(:new_data) { 'a' * described_class::CHUNK_SIZE } + let(:new_data) { +'a' * described_class::CHUNK_SIZE } it 'does not schedule trace chunk flush worker' do expect(Ci::BuildTraceChunkFlushWorker).not_to receive(:perform_async) @@ -219,7 +221,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :redis } context 'when there are no data' do - let(:data) { '' } + let(:data) { +'' } it 'has no data' do expect(build_trace_chunk.data).to be_empty @@ -230,7 +232,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when there are some data' do - let(:data) { 'Sample data in redis' } + let(:data) { +'Sample data in redis' } before do build_trace_chunk.send(:unsafe_set_data!, data) @@ -249,7 +251,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :database } context 'when there are no data' do - let(:data) { '' } + let(:data) { +'' } it 'has no data' do expect(build_trace_chunk.data).to be_empty @@ -260,7 +262,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when there are some data' do - let(:raw_data) { 'Sample data in database' } + let(:raw_data) { +'Sample data in database' } let(:data) { raw_data } it 'has data' do @@ -276,7 +278,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :fog } context 'when there are no data' do - let(:data) { '' } + let(:data) { +'' } it 'has no data' do expect(build_trace_chunk.data).to be_empty @@ -287,7 +289,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when there are some data' do - let(:data) { 'Sample data in fog' } + let(:data) { +'Sample data in fog' } before do build_trace_chunk.send(:unsafe_set_data!, data) @@ -332,7 +334,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do context 'when data_store is redis' do let(:data_store) { :redis } - let(:data) { 'Sample data in redis' } + let(:data) { +'Sample data in redis' } before do build_trace_chunk.send(:unsafe_set_data!, data) @@ -343,7 +345,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do context 'when data_store is database' do let(:data_store) { :database } - let(:raw_data) { 'Sample data in database' } + let(:raw_data) { +'Sample data in database' } let(:data) { raw_data } it_behaves_like 'truncates' @@ -351,7 +353,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do context 'when data_store is fog' do let(:data_store) { :fog } - let(:data) { 'Sample data in fog' } + let(:data) { +'Sample data in fog' } before do build_trace_chunk.send(:unsafe_set_data!, data) @@ -368,7 +370,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :redis } context 'when data exists' do - let(:data) { 'Sample data in redis' } + let(:data) { +'Sample data in redis' } before do build_trace_chunk.send(:unsafe_set_data!, data) @@ -386,7 +388,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :database } context 'when data exists' do - let(:raw_data) { 'Sample data in database' } + let(:raw_data) { +'Sample data in database' } let(:data) { raw_data } it { is_expected.to eq(data.bytesize) } @@ -401,7 +403,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :fog } context 'when data exists' do - let(:data) { 'Sample data in fog' } + let(:data) { +'Sample data in fog' } let(:key) { "tmp/builds/#{build.id}/chunks/#{chunk_index}.log" } before do @@ -443,7 +445,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when data size reached CHUNK_SIZE' do - let(:data) { 'a' * described_class::CHUNK_SIZE } + let(:data) { +'a' * described_class::CHUNK_SIZE } it 'persists the data' do expect(build_trace_chunk.redis?).to be_truthy @@ -463,7 +465,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when data size has not reached CHUNK_SIZE' do - let(:data) { 'Sample data in redis' } + let(:data) { +'Sample data in redis' } it 'does not persist the data and the orignal data is intact' do expect { subject }.to raise_error(described_class::FailedToPersistDataError) @@ -492,7 +494,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when data size reached CHUNK_SIZE' do - let(:data) { 'a' * described_class::CHUNK_SIZE } + let(:data) { +'a' * described_class::CHUNK_SIZE } it 'persists the data' do expect(build_trace_chunk.database?).to be_truthy @@ -512,7 +514,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when data size has not reached CHUNK_SIZE' do - let(:data) { 'Sample data in database' } + let(:data) { +'Sample data in database' } it 'does not persist the data and the orignal data is intact' do expect { subject }.to raise_error(described_class::FailedToPersistDataError) @@ -561,7 +563,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when data size has not reached CHUNK_SIZE' do - let(:data) { 'Sample data in fog' } + let(:data) { +'Sample data in fog' } it 'does not raise error' do expect { subject }.not_to raise_error @@ -582,7 +584,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end shared_examples_for 'deletes all build_trace_chunk and data in redis' do - it do + it 'deletes all build_trace_chunk and data in redis', :sidekiq_might_not_need_inline do Gitlab::Redis::SharedState.with do |redis| expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(3) end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index de0ce9932e8..5e5a94f8cda 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1346,7 +1346,7 @@ describe Ci::Pipeline, :mailer do end end - describe '#duration' do + describe '#duration', :sidekiq_might_not_need_inline do context 'when multiple builds are finished' do before do travel_to(current + 30) do @@ -1422,7 +1422,7 @@ describe Ci::Pipeline, :mailer do end describe '#finished_at' do - it 'updates on transitioning to success' do + it 'updates on transitioning to success', :sidekiq_might_not_need_inline do build.success expect(pipeline.reload.finished_at).not_to be_nil @@ -2102,7 +2102,7 @@ describe Ci::Pipeline, :mailer do it { is_expected.not_to include('created', 'preparing', 'pending') } end - describe '#status' do + describe '#status', :sidekiq_might_not_need_inline do let(:build) do create(:ci_build, :created, pipeline: pipeline, name: 'test') end @@ -2675,7 +2675,7 @@ describe Ci::Pipeline, :mailer do stub_full_request(hook.url, method: :post) end - context 'with multiple builds' do + context 'with multiple builds', :sidekiq_might_not_need_inline do context 'when build is queued' do before do build_a.enqueue @@ -2930,7 +2930,7 @@ describe Ci::Pipeline, :mailer do end shared_examples 'sending a notification' do - it 'sends an email' do + it 'sends an email', :sidekiq_might_not_need_inline do should_only_email(pipeline.user, kind: :bcc) end end diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index 9806b49d7a6..60b139a7610 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -156,6 +156,15 @@ describe Clusters::Applications::Ingress do it 'includes modsecurity core ruleset enablement' do expect(subject.values).to include("enable-owasp-modsecurity-crs: 'true'") end + + it 'includes modsecurity.conf content' do + expect(subject.values).to include('modsecurity.conf') + # Includes file content from Ingress#modsecurity_config_content + expect(subject.values).to include('SecAuditLog') + + expect(subject.values).to include('extraVolumes') + expect(subject.values).to include('extraVolumeMounts') + end end context 'when ingress_modsecurity is disabled' do @@ -172,6 +181,15 @@ describe Clusters::Applications::Ingress do it 'excludes modsecurity core ruleset enablement' do expect(subject.values).not_to include('enable-owasp-modsecurity-crs') end + + it 'excludes modsecurity.conf content' do + expect(subject.values).not_to include('modsecurity.conf') + # Excludes file content from Ingress#modsecurity_config_content + expect(subject.values).not_to include('SecAuditLog') + + expect(subject.values).not_to include('extraVolumes') + expect(subject.values).not_to include('extraVolumeMounts') + end end end end diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index c2c57379461..8a3a7eee25d 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -152,6 +152,16 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do end end + describe '.for_project_namespace' do + subject { described_class.for_project_namespace(namespace_id) } + + let!(:cluster) { create(:cluster, :project) } + let!(:another_cluster) { create(:cluster, :project) } + let(:namespace_id) { cluster.first_project.namespace_id } + + it { is_expected.to contain_exactly(cluster) } + end + describe 'validations' do subject { cluster.valid? } diff --git a/spec/models/clusters/clusters_hierarchy_spec.rb b/spec/models/clusters/clusters_hierarchy_spec.rb index fc35b8257e9..1957e1fc5ee 100644 --- a/spec/models/clusters/clusters_hierarchy_spec.rb +++ b/spec/models/clusters/clusters_hierarchy_spec.rb @@ -42,6 +42,28 @@ describe Clusters::ClustersHierarchy do it 'returns clusters for project' do expect(base_and_ancestors(cluster.project)).to eq([cluster]) end + + context 'cluster has management project' do + let(:management_project) { create(:project, namespace: cluster.first_project.namespace) } + + before do + cluster.update!(management_project: management_project) + end + + context 'management_project is in same namespace as cluster' do + it 'returns cluster for management_project' do + expect(base_and_ancestors(management_project)).to eq([cluster]) + end + end + + context 'management_project is in a different namespace from cluster' do + let(:management_project) { create(:project) } + + it 'returns nothing' do + expect(base_and_ancestors(management_project)).to be_empty + end + end + end end context 'cluster has management project' do @@ -50,16 +72,12 @@ describe Clusters::ClustersHierarchy do let(:group) { create(:group) } let(:project) { create(:project, group: group) } - let(:management_project) { create(:project) } + let(:management_project) { create(:project, group: group) } it 'returns clusters for management_project' do expect(base_and_ancestors(management_project)).to eq([group_cluster]) end - it 'returns nothing if include_management_project is false' do - expect(base_and_ancestors(management_project, include_management_project: false)).to be_empty - end - it 'returns clusters for project' do expect(base_and_ancestors(project)).to eq([project_cluster, group_cluster]) end @@ -70,17 +88,21 @@ describe Clusters::ClustersHierarchy do end context 'project in nested group with clusters at some levels' do - let!(:child) { create(:cluster, :group, groups: [child_group], management_project: management_project) } - let!(:ancestor) { create(:cluster, :group, groups: [ancestor_group]) } + let!(:child) { create(:cluster, :group, groups: [child_group]) } + let!(:ancestor) { create(:cluster, :group, groups: [ancestor_group], management_project: management_project) } let(:ancestor_group) { create(:group) } let(:parent_group) { create(:group, parent: ancestor_group) } let(:child_group) { create(:group, parent: parent_group) } let(:project) { create(:project, group: child_group) } - let(:management_project) { create(:project) } + let(:management_project) { create(:project, group: child_group) } + + it 'returns clusters for management_project' do + expect(base_and_ancestors(management_project)).to eq([ancestor, child]) + end it 'returns clusters for management_project' do - expect(base_and_ancestors(management_project)).to eq([child]) + expect(base_and_ancestors(management_project, include_management_project: false)).to eq([child, ancestor]) end it 'returns clusters for project' do diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 95e9b0d0f92..1e1b679a32c 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -522,7 +522,7 @@ describe CommitStatus do let(:stage) { Ci::Stage.first } - it 'creates a new stage' do + it 'creates a new stage', :sidekiq_might_not_need_inline do expect { commit_status }.to change { Ci::Stage.count }.by(1) expect(stage.name).to eq 'test' @@ -548,7 +548,7 @@ describe CommitStatus do status: :success) end - it 'uses existing stage' do + it 'uses existing stage', :sidekiq_might_not_need_inline do expect { commit_status }.not_to change { Ci::Stage.count } expect(commit_status.stage_id).to eq stage.id diff --git a/spec/models/concerns/deployment_platform_spec.rb b/spec/models/concerns/deployment_platform_spec.rb index 2cac42f56ff..9164c3a75c5 100644 --- a/spec/models/concerns/deployment_platform_spec.rb +++ b/spec/models/concerns/deployment_platform_spec.rb @@ -13,7 +13,11 @@ describe DeploymentPlatform do end context 'when project is the cluster\'s management project ' do - let!(:cluster_with_management_project) { create(:cluster, :provided_by_user, management_project: project) } + let(:another_project) { create(:project, namespace: project.namespace) } + + let!(:cluster_with_management_project) do + create(:cluster, :provided_by_user, projects: [another_project], management_project: project) + end context 'cluster_management_project feature is enabled' do it 'returns the cluster with management project' do @@ -66,7 +70,11 @@ describe DeploymentPlatform do end context 'when project is the cluster\'s management project ' do - let!(:cluster_with_management_project) { create(:cluster, :provided_by_user, management_project: project) } + let(:another_project) { create(:project, namespace: project.namespace) } + + let!(:cluster_with_management_project) do + create(:cluster, :provided_by_user, projects: [another_project], management_project: project) + end context 'cluster_management_project feature is enabled' do it 'returns the cluster with management project' do diff --git a/spec/models/concerns/from_union_spec.rb b/spec/models/concerns/from_union_spec.rb index ee427a667c6..735e14b47ec 100644 --- a/spec/models/concerns/from_union_spec.rb +++ b/spec/models/concerns/from_union_spec.rb @@ -15,7 +15,7 @@ describe FromUnion do it 'selects from the results of the UNION' do query = model.from_union([model.where(id: 1), model.where(id: 2)]) - expect(query.to_sql).to match(/FROM \(SELECT.+UNION.+SELECT.+\) users/m) + expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\nUNION\n\(SELECT.+\)\) users/m) end it 'supports the use of a custom alias for the sub query' do @@ -24,7 +24,7 @@ describe FromUnion do alias_as: 'kittens' ) - expect(query.to_sql).to match(/FROM \(SELECT.+UNION.+SELECT.+\) kittens/m) + expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\nUNION\n\(SELECT.+\)\) kittens/m) end it 'supports keeping duplicate rows' do @@ -34,7 +34,7 @@ describe FromUnion do ) expect(query.to_sql) - .to match(/FROM \(SELECT.+UNION ALL.+SELECT.+\) users/m) + .to match(/FROM \(\(SELECT.+\)\nUNION ALL\n\(SELECT.+\)\) users/m) end end end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 85a8f35393b..c1f6302ee50 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -259,7 +259,7 @@ describe Environment, :use_clean_rails_memory_store_caching do let(:head_commit) { project.commit } let(:commit) { project.commit.parent } - it 'returns deployment id for the environment' do + it 'returns deployment id for the environment', :sidekiq_might_not_need_inline do expect(environment.first_deployment_for(commit.id)).to eq deployment1 end @@ -267,7 +267,7 @@ describe Environment, :use_clean_rails_memory_store_caching do expect(environment.first_deployment_for(head_commit.id)).to eq nil end - it 'returns a UTF-8 ref' do + it 'returns a UTF-8 ref', :sidekiq_might_not_need_inline do expect(environment.first_deployment_for(commit.id).ref).to be_utf8 end end diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb index 01d331f518b..eea81d7c128 100644 --- a/spec/models/environment_status_spec.rb +++ b/spec/models/environment_status_spec.rb @@ -113,7 +113,7 @@ describe EnvironmentStatus do head_pipeline: pipeline) end - it 'returns environment status' do + it 'returns environment status', :sidekiq_might_not_need_inline do expect(subject.count).to eq(1) expect(subject[0].environment).to eq(environment) expect(subject[0].merge_request).to eq(merge_request) diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index a4d202dc4f8..94f1b0cba2e 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -16,7 +16,7 @@ describe SystemHook do end end - describe "execute" do + describe "execute", :sidekiq_might_not_need_inline do let(:system_hook) { create(:system_hook) } let(:user) { create(:user) } let(:project) { create(:project, namespace: user.namespace) } diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 5a421cad0f8..91a743c4377 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1190,7 +1190,7 @@ describe MergeRequest do context 'diverged on fork' do subject(:merge_request_fork_with_divergence) { create(:merge_request, :diverged, source_project: forked_project, target_project: project) } - it 'counts commits that are on target branch but not on source branch' do + it 'counts commits that are on target branch but not on source branch', :sidekiq_might_not_need_inline do expect(subject.diverged_commits_count).to eq(29) end end @@ -2391,7 +2391,7 @@ describe MergeRequest do create(:deployment, :success, environment: source_environment, ref: 'feature', sha: merge_request.diff_head_sha) end - it 'selects deployed environments' do + it 'selects deployed environments', :sidekiq_might_not_need_inline do expect(merge_request.environments_for(user)).to contain_exactly(source_environment) end @@ -2402,7 +2402,7 @@ describe MergeRequest do create(:deployment, :success, environment: target_environment, tag: true, sha: merge_request.diff_head_sha) end - it 'selects deployed environments' do + it 'selects deployed environments', :sidekiq_might_not_need_inline do expect(merge_request.environments_for(user)).to contain_exactly(source_environment, target_environment) end end @@ -2996,7 +2996,7 @@ describe MergeRequest do describe '#unlock_mr' do subject { create(:merge_request, state: 'locked', merge_jid: 123) } - it 'updates merge request head pipeline and sets merge_jid to nil' do + it 'updates merge request head pipeline and sets merge_jid to nil', :sidekiq_might_not_need_inline do pipeline = create(:ci_empty_pipeline, project: subject.project, ref: subject.source_branch, sha: subject.source_branch_sha) subject.unlock_mr diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb index 8a847bbe24e..0b4dcc62ff6 100644 --- a/spec/models/project_import_state_spec.rb +++ b/spec/models/project_import_state_spec.rb @@ -27,7 +27,7 @@ describe ProjectImportState, type: :model do expect(project.wiki.repository).to receive(:after_import).and_call_original end - it 'imports a project' do + it 'imports a project', :sidekiq_might_not_need_inline do expect(RepositoryImportWorker).to receive(:perform_async).and_call_original expect { import_state.schedule }.to change { import_state.jid } diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb index 2e1f6964692..309dc51191b 100644 --- a/spec/models/project_services/irker_service_spec.rb +++ b/spec/models/project_services/irker_service_spec.rb @@ -60,7 +60,7 @@ describe IrkerService do @irker_server.close end - it 'sends valid JSON messages to an Irker listener' do + it 'sends valid JSON messages to an Irker listener', :sidekiq_might_not_need_inline do irker.execute(sample_data) conn = @irker_server.accept diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index be2ea2e63ee..b4d9ce28829 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -4284,22 +4284,25 @@ describe Project do describe '#check_repository_path_availability' do let(:project) { build(:project, :repository, :legacy_storage) } - subject { project.check_repository_path_availability } context 'when the repository already exists' do let(:project) { create(:project, :repository, :legacy_storage) } - it { is_expected.to be_falsey } + it 'returns false when repository already exists' do + expect(project.check_repository_path_availability).to be_falsey + end end context 'when the repository does not exist' do - it { is_expected.to be_truthy } + it 'returns false when repository already exists' do + expect(project.check_repository_path_availability).to be_truthy + end it 'skips gitlab-shell exists?' do project.skip_disk_validation = true expect(project.gitlab_shell).not_to receive(:repository_exists?) - is_expected.to be_truthy + expect(project.check_repository_path_availability).to be_truthy end end end @@ -4631,7 +4634,7 @@ describe Project do end describe '#any_branch_allows_collaboration?' do - it 'allows access when there are merge requests open allowing collaboration' do + it 'allows access when there are merge requests open allowing collaboration', :sidekiq_might_not_need_inline do expect(project.any_branch_allows_collaboration?(user)) .to be_truthy end @@ -4645,7 +4648,7 @@ describe Project do end describe '#branch_allows_collaboration?' do - it 'allows access if the user can merge the merge request' do + it 'allows access if the user can merge the merge request', :sidekiq_might_not_need_inline do expect(project.branch_allows_collaboration?(user, 'awesome-feature-1')) .to be_truthy end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 31d1d1fd7d1..f5c827e5a29 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -28,7 +28,9 @@ describe ProjectWiki do describe '#web_url' do it 'returns the full web URL to the wiki' do - expect(subject.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.full_path}/wikis/home") + home_url = Gitlab::Routing.url_helpers.project_wiki_url(project, :home) + + expect(subject.web_url).to eq(home_url) end end @@ -71,9 +73,23 @@ describe ProjectWiki do describe "#wiki_base_path" do it "returns the wiki base path" do - wiki_base_path = "#{Gitlab.config.gitlab.relative_url_root}/#{project.full_path}/wikis" + wiki_path = Gitlab::Routing.url_helpers.project_wikis_path(project) + + expect(subject.wiki_base_path).to eq(wiki_path) + end + end - expect(subject.wiki_base_path).to eq(wiki_base_path) + describe "#wiki_page_path" do + let(:page) { create(:wiki_page, wiki: project_wiki) } + + describe 'suffixed with /:page_slug' do + subject { "#{project_wiki.wiki_page_path}/#{page.slug}" } + + it "equals the project_wiki_path" do + path = Gitlab::Routing.url_helpers.project_wiki_path(project, page) + + expect(subject).to eq(path) + end end end diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 0aac325c2b2..297367853f0 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -92,7 +92,7 @@ RSpec.describe Release do end end - describe 'evidence' do + describe 'evidence', :sidekiq_might_not_need_inline do describe '#create_evidence!' do context 'when a release is created' do it 'creates one Evidence object too' do diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb index 63d0bf3f314..79d45da8a1e 100644 --- a/spec/models/remote_mirror_spec.rb +++ b/spec/models/remote_mirror_spec.rb @@ -189,7 +189,7 @@ describe RemoteMirror, :mailer do remote_mirror.project.add_maintainer(user) end - it 'notifies the project maintainers' do + it 'notifies the project maintainers', :sidekiq_might_not_need_inline do perform_enqueued_jobs { subject } should_email(user) diff --git a/spec/models/shard_spec.rb b/spec/models/shard_spec.rb index 83104711b55..4da86858b54 100644 --- a/spec/models/shard_spec.rb +++ b/spec/models/shard_spec.rb @@ -1,4 +1,5 @@ -# frozen_string_literals: true +# frozen_string_literal: true + require 'spec_helper' describe Shard do diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb index e9ea234f75d..f4e073dc38f 100644 --- a/spec/models/spam_log_spec.rb +++ b/spec/models/spam_log_spec.rb @@ -20,7 +20,7 @@ describe SpamLog do expect { spam_log.remove_user(deleted_by: admin) }.to change { spam_log.user.blocked? }.to(true) end - it 'removes the user' do + it 'removes the user', :sidekiq_might_not_need_inline do spam_log = build(:spam_log) user = spam_log.user diff --git a/spec/models/wiki_directory_spec.rb b/spec/models/wiki_directory_spec.rb index 5fbcccf897e..aff21888605 100644 --- a/spec/models/wiki_directory_spec.rb +++ b/spec/models/wiki_directory_spec.rb @@ -1,14 +1,94 @@ # frozen_string_literal: true require 'spec_helper' +require 'set' RSpec.describe WikiDirectory do + include GitHelpers + + let(:project) { create(:project, :wiki_repo) } + let(:user) { project.owner } + let(:wiki) { ProjectWiki.new(project, user) } + describe 'validations' do subject { build(:wiki_directory) } it { is_expected.to validate_presence_of(:slug) } end + describe '.group_by_directory' do + context 'when there are no pages' do + it 'returns an empty array' do + expect(described_class.group_by_directory(nil)).to eq([]) + expect(described_class.group_by_directory([])).to eq([]) + end + end + + context 'when there are pages' do + before do + create_page('dir_1/dir_1_1/page_3', 'content') + create_page('page_1', 'content') + create_page('dir_1/page_2', 'content') + create_page('dir_2', 'page with dir name') + create_page('dir_2/page_5', 'content') + create_page('page_6', 'content') + create_page('dir_2/page_4', 'content') + end + + let(:page_1) { wiki.find_page('page_1') } + let(:page_6) { wiki.find_page('page_6') } + let(:page_dir_2) { wiki.find_page('dir_2') } + + let(:dir_1) do + described_class.new('dir_1', [wiki.find_page('dir_1/page_2')]) + end + let(:dir_1_1) do + described_class.new('dir_1/dir_1_1', [wiki.find_page('dir_1/dir_1_1/page_3')]) + end + let(:dir_2) do + pages = [wiki.find_page('dir_2/page_5'), + wiki.find_page('dir_2/page_4')] + described_class.new('dir_2', pages) + end + + context "#list_pages" do + shared_examples "a correct grouping" do + let(:grouped_slugs) { grouped_entries.map(&method(:slugs)) } + let(:expected_slugs) { expected_grouped_entries.map(&method(:slugs)).map(&method(:match_array)) } + + it 'returns an array with pages and directories' do + expect(grouped_slugs).to match_array(expected_slugs) + end + end + + context 'sort by title' do + let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages) } + + let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] } + + it_behaves_like "a correct grouping" + end + + context 'sort by created_at' do + let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages(sort: 'created_at')) } + let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] } + + it_behaves_like "a correct grouping" + end + + it 'returns an array with retained order with directories at the top' do + expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6'] + + grouped_entries = described_class.group_by_directory(wiki.list_pages) + + actual_order = grouped_entries.flat_map(&method(:slugs)) + + expect(actual_order).to eq(expected_order) + end + end + end + end + describe '#initialize' do context 'when there are pages' do let(:pages) { [build(:wiki_page)] } @@ -40,7 +120,112 @@ RSpec.describe WikiDirectory do it 'returns the relative path to the partial to be used' do directory = build(:wiki_directory) - expect(directory.to_partial_path).to eq('projects/wikis/wiki_directory') + expect(directory.to_partial_path).to eq('projects/wiki_directories/wiki_directory') + end + end + + describe 'attributes' do + def page_path(index) + "dir-path/page-#{index}" + end + + let(:page_paths) { (1..3).map { |n| page_path(n) } } + + let(:pages) do + page_paths.map { |p| wiki.find_page(p) } end + + subject { described_class.new('dir-path', pages) } + + context 'there are no pages' do + let(:pages) { [] } + + it { is_expected.to have_attributes(page_count: 0, last_version: be_nil) } + end + + context 'there is one page' do + before do + create_page("dir-path/singleton", "Just this page") + end + + let(:the_page) { wiki.find_page("dir-path/singleton") } + let(:pages) { [the_page] } + + it { is_expected.to have_attributes(page_count: 1, last_version: the_page.last_version) } + end + + context 'there are a few pages, each with a single version' do + before do + page_paths.each_with_index do |path, n| + Timecop.freeze(Time.local(1990) + n.minutes) do + create_page(path, "this is page #{n}") + end + end + end + + let(:expected_last_version) { pages.last.last_version } + + it { is_expected.to have_attributes(page_count: 3, last_version: expected_last_version) } + end + + context 'there are a few pages, each with a few versions' do + before do + page_paths.each_with_index do |path, n| + t = Time.local(1990) + n.minutes + Timecop.freeze(t) do + create_page(path, "This is page #{n}") + (2..3).each do |v| + Timecop.freeze(t + v.seconds) do + update_page(path, "Now at version #{v}") + end + end + end + end + end + + it { is_expected.to have_attributes(page_count: 3, last_version: pages.last.last_version) } + end + end + + private + + def create_page(name, content) + wiki.wiki.write_page(name, :markdown, content, commit_details) + set_time(name) + end + + def update_page(name, content) + wiki.wiki.update_page(name, name, :markdown, content, update_commit_details) + set_time(name) + end + + def set_time(name) + return unless Timecop.frozen? + + new_date = Time.now + page = wiki.find_page(name).page + commit = page.version.commit + repo = commit.instance_variable_get(:@repository) + + rug_commit = rugged_repo_at_path(repo.relative_path).lookup(commit.id) + rug_commit.amend( + message: rug_commit.message, + tree: rug_commit.tree, + author: rug_commit.author.merge(time: new_date), + committer: rug_commit.committer.merge(time: new_date), + update_ref: 'HEAD' + ) + end + + def commit_details + Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test commit") + end + + def update_commit_details + Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test update") + end + + def slugs(thing) + Array.wrap(thing.respond_to?(:pages) ? thing.pages.map(&:slug) : thing.slug) end end diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 18c62c917dc..8f3730f97ac 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -9,87 +9,6 @@ describe WikiPage do subject { described_class.new(wiki) } - describe '.group_by_directory' do - context 'when there are no pages' do - it 'returns an empty array' do - expect(described_class.group_by_directory(nil)).to eq([]) - expect(described_class.group_by_directory([])).to eq([]) - end - end - - context 'when there are pages' do - before do - create_page('dir_1/dir_1_1/page_3', 'content') - create_page('page_1', 'content') - create_page('dir_1/page_2', 'content') - create_page('dir_2', 'page with dir name') - create_page('dir_2/page_5', 'content') - create_page('page_6', 'content') - create_page('dir_2/page_4', 'content') - end - - let(:page_1) { wiki.find_page('page_1') } - let(:page_6) { wiki.find_page('page_6') } - let(:page_dir_2) { wiki.find_page('dir_2') } - - let(:dir_1) do - WikiDirectory.new('dir_1', [wiki.find_page('dir_1/page_2')]) - end - let(:dir_1_1) do - WikiDirectory.new('dir_1/dir_1_1', [wiki.find_page('dir_1/dir_1_1/page_3')]) - end - let(:dir_2) do - pages = [wiki.find_page('dir_2/page_5'), - wiki.find_page('dir_2/page_4')] - WikiDirectory.new('dir_2', pages) - end - - context "#list_pages" do - context 'sort by title' do - let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages) } - let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] } - - it 'returns an array with pages and directories' do - grouped_entries.each_with_index do |page_or_dir, i| - expected_page_or_dir = expected_grouped_entries[i] - expected_slugs = get_slugs(expected_page_or_dir) - slugs = get_slugs(page_or_dir) - - expect(slugs).to match_array(expected_slugs) - end - end - end - - context 'sort by created_at' do - let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages(sort: 'created_at')) } - let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] } - - it 'returns an array with pages and directories' do - grouped_entries.each_with_index do |page_or_dir, i| - expected_page_or_dir = expected_grouped_entries[i] - expected_slugs = get_slugs(expected_page_or_dir) - slugs = get_slugs(page_or_dir) - - expect(slugs).to match_array(expected_slugs) - end - end - end - - it 'returns an array with retained order with directories at the top' do - expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6'] - - grouped_entries = described_class.group_by_directory(wiki.list_pages) - - actual_order = - grouped_entries.flat_map do |page_or_dir| - get_slugs(page_or_dir) - end - expect(actual_order).to eq(expected_order) - end - end - end - end - describe '.unhyphenize' do it 'removes hyphens from a name' do name = 'a-name--with-hyphens' @@ -505,7 +424,7 @@ describe WikiPage do it 'returns the relative path to the partial to be used' do page = build(:wiki_page) - expect(page.to_partial_path).to eq('projects/wikis/wiki_page') + expect(page.to_partial_path).to eq('projects/wiki_pages/wiki_page') end end @@ -585,12 +504,4 @@ describe WikiPage do page = wiki.wiki.page(title: title, dir: dir) wiki.delete_page(page, "test commit") end - - def get_slugs(page_or_dir) - if page_or_dir.is_a? WikiPage - [page_or_dir.slug] - else - page_or_dir.pages.present? ? page_or_dir.pages.map(&:slug) : [] - end - end end diff --git a/spec/presenters/release_presenter_spec.rb b/spec/presenters/release_presenter_spec.rb new file mode 100644 index 00000000000..8bca38f7054 --- /dev/null +++ b/spec/presenters/release_presenter_spec.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ReleasePresenter do + include Gitlab::Routing.url_helpers + + let_it_be(:project) { create(:project, :repository) } + let(:developer) { create(:user) } + let(:guest) { create(:user) } + let(:user) { developer } + let(:release) { create(:release, project: project) } + let(:presenter) { described_class.new(release, current_user: user) } + + before do + project.add_developer(developer) + project.add_guest(guest) + end + + describe '#commit_path' do + subject { presenter.commit_path } + + it 'returns commit path' do + is_expected.to eq(project_commit_path(project, release.commit.id)) + end + + context 'when commit is not found' do + let(:release) { create(:release, project: project, sha: 'not-found') } + + it { is_expected.to be_nil } + end + + context 'when user is guest' do + let(:user) { guest } + + it { is_expected.to be_nil } + end + end + + describe '#tag_path' do + subject { presenter.tag_path } + + it 'returns tag path' do + is_expected.to eq(project_tag_path(project, release.tag)) + end + + context 'when user is guest' do + let(:user) { guest } + + it { is_expected.to be_nil } + end + end + + describe '#merge_requests_url' do + subject { presenter.merge_requests_url } + + it 'returns merge requests url' do + is_expected.to match /#{project_merge_requests_url(project)}/ + end + + context 'when release_mr_issue_urls feature flag is disabled' do + before do + stub_feature_flags(release_mr_issue_urls: false) + end + + it { is_expected.to be_nil } + end + end + + describe '#issues_url' do + subject { presenter.issues_url } + + it 'returns merge requests url' do + is_expected.to match /#{project_issues_url(project)}/ + end + + context 'when release_mr_issue_urls feature flag is disabled' do + before do + stub_feature_flags(release_mr_issue_urls: false) + end + + it { is_expected.to be_nil } + end + end +end diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb index 6cb02ba2f6b..2b5e8226403 100644 --- a/spec/requests/api/commit_statuses_spec.rb +++ b/spec/requests/api/commit_statuses_spec.rb @@ -278,7 +278,7 @@ describe API::CommitStatuses do } end - it 'update the correct pipeline' do + it 'update the correct pipeline', :sidekiq_might_not_need_inline do subject expect(first_pipeline.reload.status).to eq('created') @@ -302,7 +302,7 @@ describe API::CommitStatuses do expect(json_response['status']).to eq('success') end - it 'retries a commit status' do + it 'retries a commit status', :sidekiq_might_not_need_inline do expect(CommitStatus.count).to eq 2 expect(CommitStatus.first).to be_retried expect(CommitStatus.last.pipeline).to be_success diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 90ff1d12bf1..1648e3afa4b 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -369,7 +369,7 @@ describe API::Commits do valid_c_params[:start_project] = public_project.id end - it 'adds a new commit to forked_project and returns a 201' do + it 'adds a new commit to forked_project and returns a 201', :sidekiq_might_not_need_inline do expect_request_with_status(201) { post api(url, guest), params: valid_c_params } .to change { last_commit_id(forked_project, valid_c_params[:branch]) } .and not_change { last_commit_id(public_project, valid_c_params[:start_branch]) } @@ -381,14 +381,14 @@ describe API::Commits do valid_c_params[:start_project] = public_project.full_path end - it 'adds a new commit to forked_project and returns a 201' do + it 'adds a new commit to forked_project and returns a 201', :sidekiq_might_not_need_inline do expect_request_with_status(201) { post api(url, guest), params: valid_c_params } .to change { last_commit_id(forked_project, valid_c_params[:branch]) } .and not_change { last_commit_id(public_project, valid_c_params[:start_branch]) } end end - context 'when branch already exists' do + context 'when branch already exists', :sidekiq_might_not_need_inline do before do valid_c_params.delete(:start_branch) valid_c_params[:branch] = 'master' @@ -835,7 +835,7 @@ describe API::Commits do } end - it 'allows pushing to the source branch of the merge request' do + it 'allows pushing to the source branch of the merge request', :sidekiq_might_not_need_inline do post api(url, user), params: push_params('feature') expect(response).to have_gitlab_http_status(:created) @@ -1417,7 +1417,7 @@ describe API::Commits do let(:project_id) { forked_project.id } - it 'allows access from a maintainer that to the source branch' do + it 'allows access from a maintainer that to the source branch', :sidekiq_might_not_need_inline do post api(route, user), params: { branch: 'feature' } expect(response).to have_gitlab_http_status(:created) diff --git a/spec/requests/api/group_clusters_spec.rb b/spec/requests/api/group_clusters_spec.rb index 46e3dd650cc..97465647a87 100644 --- a/spec/requests/api/group_clusters_spec.rb +++ b/spec/requests/api/group_clusters_spec.rb @@ -286,12 +286,15 @@ describe API::GroupClusters do let(:update_params) do { domain: domain, - platform_kubernetes_attributes: platform_kubernetes_attributes + platform_kubernetes_attributes: platform_kubernetes_attributes, + management_project_id: management_project_id } end let(:domain) { 'new-domain.com' } let(:platform_kubernetes_attributes) { {} } + let(:management_project) { create(:project, group: group) } + let(:management_project_id) { management_project.id } let(:cluster) do create(:cluster, :group, :provided_by_gcp, @@ -308,6 +311,8 @@ describe API::GroupClusters do context 'authorized user' do before do + management_project.add_maintainer(current_user) + put api("/groups/#{group.id}/clusters/#{cluster.id}", current_user), params: update_params cluster.reload @@ -320,6 +325,7 @@ describe API::GroupClusters do it 'updates cluster attributes' do expect(cluster.domain).to eq('new-domain.com') + expect(cluster.management_project).to eq(management_project) end end @@ -332,6 +338,7 @@ describe API::GroupClusters do it 'does not update cluster attributes' do expect(cluster.domain).to eq('old-domain.com') + expect(cluster.management_project).to be_nil end it 'returns validation errors' do @@ -339,6 +346,18 @@ describe API::GroupClusters do end end + context 'current user does not have access to management_project_id' do + let(:management_project_id) { create(:project).id } + + it 'responds with 400' do + expect(response).to have_gitlab_http_status(400) + end + + it 'returns validation errors' do + expect(json_response['message']['management_project_id'].first).to match('don\'t have permission') + end + end + context 'with a GCP cluster' do context 'when user tries to change GCP specific fields' do let(:platform_kubernetes_attributes) do diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb index 01a2e33c0d9..02d1e4bf2f1 100644 --- a/spec/requests/api/internal/base_spec.rb +++ b/spec/requests/api/internal/base_spec.rb @@ -316,6 +316,7 @@ describe API::Internal::Base do expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path) expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) + expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-get-all-lfs-pointers-go' => 'true', 'gitaly-feature-inforef-uploadpack-cache' => 'true') expect(user.reload.last_activity_on).to eql(Date.today) end end @@ -335,6 +336,7 @@ describe API::Internal::Base do expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path) expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) + expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-get-all-lfs-pointers-go' => 'true', 'gitaly-feature-inforef-uploadpack-cache' => 'true') expect(user.reload.last_activity_on).to be_nil end end @@ -407,7 +409,6 @@ describe API::Internal::Base do context "custom action" do let(:access_checker) { double(Gitlab::GitAccess) } - let(:message) { 'CustomActionError message' } let(:payload) do { 'action' => 'geo_proxy_to_primary', @@ -418,8 +419,8 @@ describe API::Internal::Base do } } end - - let(:custom_action_result) { Gitlab::GitAccessResult::CustomAction.new(payload, message) } + let(:console_messages) { ['informational message'] } + let(:custom_action_result) { Gitlab::GitAccessResult::CustomAction.new(payload, console_messages) } before do project.add_guest(user) @@ -446,8 +447,8 @@ describe API::Internal::Base do expect(response).to have_gitlab_http_status(300) expect(json_response['status']).to be_truthy - expect(json_response['message']).to eql(message) expect(json_response['payload']).to eql(payload) + expect(json_response['gl_console_messages']).to eql(console_messages) expect(user.reload.last_activity_on).to be_nil end end @@ -577,6 +578,7 @@ describe API::Internal::Base do expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path) expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) + expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-get-all-lfs-pointers-go' => 'true', 'gitaly-feature-inforef-uploadpack-cache' => 'true') end end diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index 89ee6f896f9..760bacff75e 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -595,7 +595,7 @@ describe API::Jobs do context 'find proper job' do shared_examples 'a valid file' do - context 'when artifacts are stored locally' do + context 'when artifacts are stored locally', :sidekiq_might_not_need_inline do let(:download_headers) do { 'Content-Transfer-Encoding' => 'binary', 'Content-Disposition' => @@ -674,7 +674,7 @@ describe API::Jobs do let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC } let(:public_builds) { true } - it 'allows to access artifacts' do + it 'allows to access artifacts', :sidekiq_might_not_need_inline do expect(response).to have_gitlab_http_status(200) expect(response.headers.to_h) .to include('Content-Type' => 'application/json', @@ -711,7 +711,7 @@ describe API::Jobs do let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE } let(:public_builds) { true } - it 'returns a specific artifact file for a valid path' do + it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do expect(Gitlab::Workhorse) .to receive(:send_artifacts_entry) .and_call_original @@ -732,7 +732,7 @@ describe API::Jobs do sha: project.commit('improve/awesome').sha) end - it 'returns a specific artifact file for a valid path' do + it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do get_artifact_file(artifact, 'improve/awesome') expect(response).to have_gitlab_http_status(200) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index e9bf8e7adc7..721998ede6a 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -921,7 +921,7 @@ describe API::MergeRequests do allow_collaboration: true) end - it 'includes the `allow_collaboration` field' do + it 'includes the `allow_collaboration` field', :sidekiq_might_not_need_inline do get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user) expect(json_response['allow_collaboration']).to be_truthy @@ -1406,7 +1406,7 @@ describe API::MergeRequests do expect(response).to have_gitlab_http_status(400) end - it 'allows setting `allow_collaboration`' do + it 'allows setting `allow_collaboration`', :sidekiq_might_not_need_inline do post api("/projects/#{forked_project.id}/merge_requests", user2), params: { title: 'Test merge_request', source_branch: "feature_conflict", target_branch: "master", author: user2, target_project_id: project.id, allow_collaboration: true } expect(response).to have_gitlab_http_status(201) @@ -1438,7 +1438,7 @@ describe API::MergeRequests do end end - it "returns 201 when target_branch is specified and for the same project" do + it "returns 201 when target_branch is specified and for the same project", :sidekiq_might_not_need_inline do post api("/projects/#{forked_project.id}/merge_requests", user2), params: { title: 'Test merge_request', target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: forked_project.id } expect(response).to have_gitlab_http_status(201) diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index 3ac63dc381b..cce52cfc1ca 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -673,7 +673,7 @@ describe API::Pipelines do let!(:build) { create(:ci_build, :running, pipeline: pipeline) } context 'authorized user' do - it 'retries failed builds' do + it 'retries failed builds', :sidekiq_might_not_need_inline do post api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", user) expect(response).to have_gitlab_http_status(200) diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb index a7b919de2ef..04e59238877 100644 --- a/spec/requests/api/project_clusters_spec.rb +++ b/spec/requests/api/project_clusters_spec.rb @@ -281,11 +281,14 @@ describe API::ProjectClusters do let(:api_url) { 'https://kubernetes.example.com' } let(:namespace) { 'new-namespace' } let(:platform_kubernetes_attributes) { { namespace: namespace } } + let(:management_project) { create(:project, namespace: project.namespace) } + let(:management_project_id) { management_project.id } let(:update_params) do { domain: 'new-domain.com', - platform_kubernetes_attributes: platform_kubernetes_attributes + platform_kubernetes_attributes: platform_kubernetes_attributes, + management_project_id: management_project_id } end @@ -310,6 +313,8 @@ describe API::ProjectClusters do context 'authorized user' do before do + management_project.add_maintainer(current_user) + put api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: update_params cluster.reload @@ -323,6 +328,7 @@ describe API::ProjectClusters do it 'updates cluster attributes' do expect(cluster.domain).to eq('new-domain.com') expect(cluster.platform_kubernetes.namespace).to eq('new-namespace') + expect(cluster.management_project).to eq(management_project) end end @@ -336,6 +342,7 @@ describe API::ProjectClusters do it 'does 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.management_project).not_to eq(management_project) end it 'returns validation errors' do @@ -343,6 +350,18 @@ describe API::ProjectClusters do end end + context 'current user does not have access to management_project_id' do + let(:management_project_id) { create(:project).id } + + it 'responds with 400' do + expect(response).to have_gitlab_http_status(400) + end + + it 'returns validation errors' do + expect(json_response['message']['management_project_id'].first).to match('don\'t have permission') + end + end + context 'with a GCP cluster' do context 'when user tries to change GCP specific fields' do let(:platform_kubernetes_attributes) do diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb index 7de8935097a..4f1003efafe 100644 --- a/spec/requests/api/project_export_spec.rb +++ b/spec/requests/api/project_export_spec.rb @@ -370,7 +370,7 @@ describe API::ProjectExport do end context 'when overriding description' do - it 'starts' do + it 'starts', :sidekiq_might_not_need_inline do params = { description: "Foo" } expect_any_instance_of(Projects::ImportExport::ExportService).to receive(:execute) diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb index d2b1fb063b8..579d1a36c22 100644 --- a/spec/requests/api/project_import_spec.rb +++ b/spec/requests/api/project_import_spec.rb @@ -153,7 +153,7 @@ describe API::ProjectImport do expect(import_project.import_data.data['override_params']).to be_empty end - it 'correctly overrides params during the import' do + it 'correctly overrides params during the import', :sidekiq_might_not_need_inline do override_params = { 'description' => 'Hello world' } perform_enqueued_jobs do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 2d8ef9c06dc..0e343210f5e 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -15,7 +15,7 @@ shared_examples 'languages and percentages JSON response' do end context "when the languages haven't been detected yet" do - it 'returns expected language values' do + it 'returns expected language values', :sidekiq_might_not_need_inline do get api("/projects/#{project.id}/languages", user) expect(response).to have_gitlab_http_status(:ok) @@ -606,6 +606,7 @@ describe API::Projects do merge_requests_enabled: false, wiki_enabled: false, resolve_outdated_diff_discussions: false, + remove_source_branch_after_merge: true, only_allow_merge_if_pipeline_succeeds: false, request_access_enabled: true, only_allow_merge_if_all_discussions_are_resolved: false, @@ -722,6 +723,22 @@ describe API::Projects do expect(json_response['resolve_outdated_diff_discussions']).to be_truthy end + it 'sets a project as not removing source branches' do + project = attributes_for(:project, remove_source_branch_after_merge: false) + + post api('/projects', user), params: project + + expect(json_response['remove_source_branch_after_merge']).to be_falsey + end + + it 'sets a project as removing source branches' do + project = attributes_for(:project, remove_source_branch_after_merge: true) + + post api('/projects', user), params: project + + expect(json_response['remove_source_branch_after_merge']).to be_truthy + end + it 'sets a project as allowing merge even if build fails' do project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: false) @@ -980,6 +997,22 @@ describe API::Projects do expect(json_response['resolve_outdated_diff_discussions']).to be_truthy end + it 'sets a project as not removing source branches' do + project = attributes_for(:project, remove_source_branch_after_merge: false) + + post api("/projects/user/#{user.id}", admin), params: project + + expect(json_response['remove_source_branch_after_merge']).to be_falsey + end + + it 'sets a project as removing source branches' do + project = attributes_for(:project, remove_source_branch_after_merge: true) + + post api("/projects/user/#{user.id}", admin), params: project + + expect(json_response['remove_source_branch_after_merge']).to be_truthy + end + it 'sets a project as allowing merge even if build fails' do project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: false) post api("/projects/user/#{user.id}", admin), params: project @@ -1157,6 +1190,7 @@ describe API::Projects do expect(json_response['wiki_access_level']).to be_present expect(json_response['builds_access_level']).to be_present expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions) + expect(json_response['remove_source_branch_after_merge']).to be_truthy expect(json_response['container_registry_enabled']).to be_present expect(json_response['created_at']).to be_present expect(json_response['last_activity_at']).to be_present diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb index 8abdcaa2e0e..0d8130f5e49 100644 --- a/spec/requests/api/search_spec.rb +++ b/spec/requests/api/search_spec.rb @@ -436,6 +436,7 @@ describe API::Search do expect(response).to have_gitlab_http_status(200) expect(json_response.size).to eq(2) + expect(json_response.first['path']).to eq('PROCESS.md') expect(json_response.first['filename']).to eq('PROCESS.md') end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index ee4e783e9ac..50e82ca5481 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -636,7 +636,7 @@ describe API::Users do describe "GET /users/sign_up" do context 'when experimental signup_flow is active' do before do - stub_experiment(signup_flow: true) + stub_experiment_for_user(signup_flow: true) end it "shows sign up page" do @@ -648,7 +648,7 @@ describe API::Users do context 'when experimental signup_flow is not active' do before do - stub_experiment(signup_flow: false) + stub_experiment_for_user(signup_flow: false) end it "redirects to sign in page" do @@ -1277,7 +1277,7 @@ describe API::Users do admin end - it "deletes user" do + it "deletes user", :sidekiq_might_not_need_inline do perform_enqueued_jobs { delete api("/users/#{user.id}", admin) } expect(response).to have_gitlab_http_status(204) @@ -1312,7 +1312,7 @@ describe API::Users do end context "hard delete disabled" do - it "moves contributions to the ghost user" do + it "moves contributions to the ghost user", :sidekiq_might_not_need_inline do perform_enqueued_jobs { delete api("/users/#{user.id}", admin) } expect(response).to have_gitlab_http_status(204) @@ -1322,7 +1322,7 @@ describe API::Users do end context "hard delete enabled" do - it "removes contributions" do + it "removes contributions", :sidekiq_might_not_need_inline do perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) } expect(response).to have_gitlab_http_status(204) diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 07e56619f40..1cabfb55803 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -87,7 +87,7 @@ describe 'Git HTTP requests' do end shared_examples_for 'pulls are allowed' do - it do + it 'allows pulls' do download(path, env) do |response| expect(response).to have_gitlab_http_status(:ok) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) @@ -96,7 +96,7 @@ describe 'Git HTTP requests' do end shared_examples_for 'pushes are allowed' do - it do + it 'allows pushes', :sidekiq_might_not_need_inline do upload(path, env) do |response| expect(response).to have_gitlab_http_status(:ok) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 25390f8a23e..afbc5835f02 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -48,7 +48,7 @@ describe 'cycle analytics events' do expect(json_response['events'].first['iid']).to eq(first_mr_iid) end - it 'lists the test events' do + it 'lists the test events', :sidekiq_might_not_need_inline do get project_cycle_analytics_test_path(project, format: :json) expect(json_response['events']).not_to be_empty @@ -64,14 +64,14 @@ describe 'cycle analytics events' do expect(json_response['events'].first['iid']).to eq(first_mr_iid) end - it 'lists the staging events' do + it 'lists the staging events', :sidekiq_might_not_need_inline do get project_cycle_analytics_staging_path(project, format: :json) expect(json_response['events']).not_to be_empty expect(json_response['events'].first['date']).not_to be_empty end - it 'lists the production events' do + it 'lists the production events', :sidekiq_might_not_need_inline do get project_cycle_analytics_production_path(project, format: :json) first_issue_iid = project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s @@ -81,7 +81,7 @@ describe 'cycle analytics events' do end context 'specific branch' do - it 'lists the test events' do + it 'lists the test events', :sidekiq_might_not_need_inline do branch = project.merge_requests.first.source_branch get project_cycle_analytics_test_path(project, format: :json, branch: branch) diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index acdbf064a73..3e57bb70287 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -3,9 +3,12 @@ require 'spec_helper' describe 'project routing' do before do allow(Project).to receive(:find_by_full_path).and_return(false) - allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq', any_args).and_return(true) + allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq', any_args).and_return(project) end + set(:namespace) { create(:namespace, name: 'gitlab') } + set(:project) { create(:project, namespace: namespace, name: 'gitlabhq') } + # Shared examples for a resource inside a Project # # By default it tests all the default REST actions: index, create, new, edit, @@ -145,24 +148,39 @@ describe 'project routing' do it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/autocomplete_sources/labels", "/gitlab/gitlabhq/-/autocomplete_sources/labels" end - # pages_project_wikis GET /:project_id/wikis/pages(.:format) projects/wikis#pages - # history_project_wiki GET /:project_id/wikis/:id/history(.:format) projects/wikis#history - # project_wikis POST /:project_id/wikis(.:format) projects/wikis#create - # edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) projects/wikis#edit - # project_wiki GET /:project_id/wikis/:id(.:format) projects/wikis#show - # DELETE /:project_id/wikis/:id(.:format) projects/wikis#destroy + # GET /:project_id/wikis/pages(.:format) projects/wikis#pages + # GET /:project_id/-/wiki_pages/:id/history(.:format) projects/wiki_pages#history + # POST /:project_id/-/wiki_pages(.:format) projects/wiki_pages#create + # GET /:project_id/-/wiki_pages/:id/edit(.:format) projects/wiki_pages#edit + # GET /:project_id/-/wiki_pages/:id(.:format) projects/wiki_pages#show + # DELETE /:project_id/-/wiki_pages/:id(.:format) projects/wiki_pages#destroy describe Projects::WikisController, 'routing' do - it 'to #pages' do - expect(get('/gitlab/gitlabhq/wikis/pages')).to route_to('projects/wikis#pages', namespace_id: 'gitlab', project_id: 'gitlabhq') + let(:wiki) { ProjectWiki.new(project, project.owner) } + let(:wiki_page) { create(:wiki_page, wiki: wiki) } + + it '#pages' do + expect(get('/gitlab/gitlabhq/wikis/pages')) + .to route_to('projects/wikis#pages', + namespace_id: 'gitlab', + project_id: 'gitlabhq') end - it 'to #history' do - expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + describe '#history' do + let(:history_path) { project_wiki_history_path(project, wiki_page) } + + it 'routes to history' do + expect(get(history_path)) + .to route_to('projects/wiki_pages#history', + namespace_id: namespace.path, + project_id: project.name, + id: wiki_page.slug) + end end it_behaves_like 'RESTful project resources' do let(:actions) { [:create, :edit, :show, :destroy] } - let(:controller) { 'wikis' } + let(:controller) { 'wiki_pages' } + let(:controller_path) { '-/wiki_pages' } end end diff --git a/spec/routing/wiki_routing_spec.rb b/spec/routing/wiki_routing_spec.rb new file mode 100644 index 00000000000..94349dbaa74 --- /dev/null +++ b/spec/routing/wiki_routing_spec.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# We build URIs to wiki pages manually in various places (most notably +# in markdown generation). To ensure these do not get out of sync, these +# tests verify that our path generation assumptions are sound. +describe 'Wiki path generation assumptions' do + set(:project) { create(:project, :public, :repository) } + + let(:project_wiki) { ProjectWiki.new(project, project.owner) } + let(:some_page_name) { 'some-wiki-page' } + let(:wiki_page) do + create(:wiki_page, wiki: project_wiki, attrs: { title: some_page_name }) + end + + describe 'WikiProject#wiki_page_path', 'routing' do + it 'is consistent with routing to wiki#show' do + uri = URI.parse(project_wiki.wiki_page_path) + path = ::File.join(uri.path, some_page_name) + + expect(get('/' + path)).to route_to('projects/wiki_pages#show', + id: some_page_name, + namespace_id: project.namespace.to_param, + project_id: project.to_param) + end + end + + describe 'project_wiki_path', 'routing' do + describe 'GET' do + it 'routes to the :show action' do + path = project_wiki_path(project, wiki_page) + + expect(get('/' + path)).to route_to('projects/wiki_pages#show', + id: wiki_page.slug, + namespace_id: project.namespace.to_param, + project_id: project.to_param) + end + end + end + + describe 'project_wiki_pages_new_path', 'routing' do + describe 'GET' do + it 'routes to the :new action' do + path = project_wiki_pages_new_path(project) + + expect(get('/' + path)).to route_to('projects/wiki_pages#new', + namespace_id: project.namespace.to_param, + project_id: project.to_param) + end + end + end + + # Early versions of the wiki paths routed all wiki pages at + # /wikis/:id - this test exists to guarantee that we support + # old URIs that may be out there, saved in bookmarks, on other wikis, etc. + describe 'legacy route support', type: 'request' do + let(:path) { ::File.join(project_wikis_path(project), some_page_name) } + + before do + get(path) + end + + it 'routes to new wiki paths' do + dest = project_wiki_path(project, wiki_page) + + expect(response).to redirect_to(dest) + end + + context 'the page is nested in a directory' do + let(:some_page_name) { 'some-dir/some-deep-dir/some-page' } + let(:path) { ::File.join(project_wikis_path(project), some_page_name) } + + it 'still routes correctly' do + dest = project_wiki_path(project, wiki_page) + + expect(response).to redirect_to(dest) + end + end + + context 'the user requested the old history path' do + let(:some_page_name) { 'some-dir/some-deep-dir/some-page' } + let(:path) { ::File.join(project_wikis_path(project), some_page_name, 'history') } + + it 'redirects to the new history path' do + dest = project_wiki_history_path(project, wiki_page) + + expect(response).to redirect_to(dest) + end + end + + context 'the user requested the old edit path' do + let(:some_page_name) { 'some-dir/some-deep-dir/some-page' } + let(:path) { ::File.join(project_wikis_path(project), some_page_name, 'edit') } + + it 'redirects to the new history path' do + dest = project_wiki_edit_path(project, wiki_page) + + expect(response).to redirect_to(dest) + end + end + end +end diff --git a/spec/serializers/merge_request_diff_entity_spec.rb b/spec/serializers/merge_request_diff_entity_spec.rb index 062f17963c0..59ec0b22158 100644 --- a/spec/serializers/merge_request_diff_entity_spec.rb +++ b/spec/serializers/merge_request_diff_entity_spec.rb @@ -7,14 +7,15 @@ describe MergeRequestDiffEntity do let(:request) { EntityRequest.new(project: project) } let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) } let(:merge_request_diffs) { merge_request.merge_request_diffs } + let(:merge_request_diff) { merge_request_diffs.first } let(:entity) do - described_class.new(merge_request_diffs.first, request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs) + described_class.new(merge_request_diff, request: request, merge_request: merge_request, merge_request_diffs: merge_request_diffs) end - context 'as json' do - subject { entity.as_json } + subject { entity.as_json } + context 'as json' do it 'exposes needed attributes' do expect(subject).to include( :version_index, :created_at, :commits_count, @@ -23,4 +24,16 @@ describe MergeRequestDiffEntity do ) end end + + describe '#short_commit_sha' do + it 'returns short sha' do + expect(subject[:short_commit_sha]).to eq('b83d6e39') + end + + it 'returns nil if head_commit_sha does not exist' do + allow(merge_request_diff).to receive(:head_commit_sha).and_return(nil) + + expect(subject[:short_commit_sha]).to eq(nil) + end + end end diff --git a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb index 931b52470c4..c396539cf56 100644 --- a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb +++ b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb @@ -225,7 +225,7 @@ describe AutoMerge::MergeWhenPipelineSucceedsService do test.drop end - it 'merges when all stages succeeded' do + it 'merges when all stages succeeded', :sidekiq_might_not_need_inline do expect(MergeWorker).to receive(:perform_async) build.success diff --git a/spec/services/ci/cancel_user_pipelines_service_spec.rb b/spec/services/ci/cancel_user_pipelines_service_spec.rb index 251f21feaef..b18bf48a50a 100644 --- a/spec/services/ci/cancel_user_pipelines_service_spec.rb +++ b/spec/services/ci/cancel_user_pipelines_service_spec.rb @@ -12,7 +12,7 @@ describe Ci::CancelUserPipelinesService do let(:pipeline) { create(:ci_pipeline, :running, user: user) } let!(:build) { create(:ci_build, :running, pipeline: pipeline) } - it 'cancels all running pipelines and related jobs' do + it 'cancels all running pipelines and related jobs', :sidekiq_might_not_need_inline do subject expect(pipeline.reload).to be_canceled diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index fd5f72c4c46..2c63e621074 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -97,7 +97,7 @@ describe Ci::CreatePipelineService do end context 'when the head pipeline sha equals merge request sha' do - it 'updates head pipeline of each merge request' do + it 'updates head pipeline of each merge request', :sidekiq_might_not_need_inline do merge_request_1 merge_request_2 @@ -140,7 +140,7 @@ describe Ci::CreatePipelineService do let!(:project) { fork_project(target_project, nil, repository: true) } let!(:target_project) { create(:project, :repository) } - it 'updates head pipeline for merge request' do + it 'updates head pipeline for merge request', :sidekiq_might_not_need_inline do merge_request = create(:merge_request, source_branch: 'feature', target_branch: "master", source_project: project, @@ -172,7 +172,7 @@ describe Ci::CreatePipelineService do stub_ci_pipeline_yaml_file('some invalid syntax') end - it 'updates merge request head pipeline reference' do + it 'updates merge request head pipeline reference', :sidekiq_might_not_need_inline do merge_request = create(:merge_request, source_branch: 'master', target_branch: 'feature', source_project: project) @@ -192,7 +192,7 @@ describe Ci::CreatePipelineService do .and_return('some commit [ci skip]') end - it 'updates merge request head pipeline' do + it 'updates merge request head pipeline', :sidekiq_might_not_need_inline do merge_request = create(:merge_request, source_branch: 'master', target_branch: 'feature', source_project: project) @@ -218,21 +218,21 @@ describe Ci::CreatePipelineService do expect(pipeline.reload).to have_attributes(status: 'pending', auto_canceled_by_id: nil) end - it 'auto cancel pending non-HEAD pipelines' do + it 'auto cancel pending non-HEAD pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit pipeline expect(pipeline_on_previous_commit.reload).to have_attributes(status: 'canceled', auto_canceled_by_id: pipeline.id) end - it 'cancels running outdated pipelines' do + it 'cancels running outdated pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit.run head_pipeline = execute_service expect(pipeline_on_previous_commit.reload).to have_attributes(status: 'canceled', auto_canceled_by_id: head_pipeline.id) end - it 'cancel created outdated pipelines' do + it 'cancel created outdated pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit.update(status: 'created') pipeline @@ -346,7 +346,7 @@ describe Ci::CreatePipelineService do context 'when only interruptible builds are running' do context 'when build marked explicitly by interruptible is running' do - it 'cancels running outdated pipelines' do + it 'cancels running outdated pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit .builds .find_by_name('build_1_2') @@ -360,7 +360,7 @@ describe Ci::CreatePipelineService do end context 'when build that is not marked as interruptible is running' do - it 'cancels running outdated pipelines' do + it 'cancels running outdated pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit .builds .find_by_name('build_2_1') @@ -376,7 +376,7 @@ describe Ci::CreatePipelineService do end context 'when an uninterruptible build is running' do - it 'does not cancel running outdated pipelines' do + it 'does not cancel running outdated pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit .builds .find_by_name('build_3_1') @@ -391,7 +391,7 @@ describe Ci::CreatePipelineService do end context 'when an build is waiting on an interruptible scheduled task' do - it 'cancels running outdated pipelines' do + it 'cancels running outdated pipelines', :sidekiq_might_not_need_inline do allow(Ci::BuildScheduleWorker).to receive(:perform_at) pipeline_on_previous_commit @@ -407,7 +407,7 @@ describe Ci::CreatePipelineService do end context 'when a uninterruptible build has finished' do - it 'does not cancel running outdated pipelines' do + it 'does not cancel running outdated pipelines', :sidekiq_might_not_need_inline do pipeline_on_previous_commit .builds .find_by_name('build_3_1') @@ -1236,7 +1236,7 @@ describe Ci::CreatePipelineService do let!(:project) { fork_project(target_project, nil, repository: true) } let!(:target_project) { create(:project, :repository) } - it 'creates a legacy detached merge request pipeline in the forked project' do + it 'creates a legacy detached merge request pipeline in the forked project', :sidekiq_might_not_need_inline do expect(pipeline).to be_persisted expect(project.ci_pipelines).to eq([pipeline]) expect(target_project.ci_pipelines).to be_empty diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index 05adec8b745..991f8cdfac5 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -27,7 +27,7 @@ describe Ci::ProcessPipelineService, '#execute' do create_build('deploy', stage_idx: 2) end - it 'processes a pipeline' do + it 'processes a pipeline', :sidekiq_might_not_need_inline do expect(process_pipeline).to be_truthy succeed_pending @@ -58,7 +58,7 @@ describe Ci::ProcessPipelineService, '#execute' do create_build('test_job', stage_idx: 1, allow_failure: true) end - it 'automatically triggers a next stage when build finishes' do + it 'automatically triggers a next stage when build finishes', :sidekiq_might_not_need_inline do expect(process_pipeline).to be_truthy expect(builds_statuses).to eq ['pending'] @@ -72,7 +72,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when optional manual actions are defined' do + context 'when optional manual actions are defined', :sidekiq_might_not_need_inline do before do create_build('build', stage_idx: 0) create_build('test', stage_idx: 1) @@ -241,7 +241,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when delayed jobs are defined' do + context 'when delayed jobs are defined', :sidekiq_might_not_need_inline do context 'when the scene is timed incremental rollout' do before do create_build('build', stage_idx: 0) @@ -458,7 +458,7 @@ describe Ci::ProcessPipelineService, '#execute' do process_pipeline end - it 'skips second stage and continues on third stage' do + it 'skips second stage and continues on third stage', :sidekiq_might_not_need_inline do expect(all_builds_statuses).to eq(%w[pending created created]) builds.first.success @@ -502,7 +502,7 @@ describe Ci::ProcessPipelineService, '#execute' do play_manual_action('deploy') end - it 'queues the action and pipeline' do + it 'queues the action and pipeline', :sidekiq_might_not_need_inline do expect(all_builds_statuses).to eq(%w[pending]) expect(pipeline.reload).to be_pending @@ -510,7 +510,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when blocking manual actions are defined' do + context 'when blocking manual actions are defined', :sidekiq_might_not_need_inline do before do create_build('code:test', stage_idx: 0) create_build('staging:deploy', stage_idx: 1, when: 'manual') @@ -618,7 +618,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when second stage has only on_failure jobs' do + context 'when second stage has only on_failure jobs', :sidekiq_might_not_need_inline do before do create_build('check', stage_idx: 0) create_build('build', stage_idx: 1, when: 'on_failure') @@ -636,7 +636,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when failed build in the middle stage is retried' do + context 'when failed build in the middle stage is retried', :sidekiq_might_not_need_inline do context 'when failed build is the only unsuccessful build in the stage' do before do create_build('build:1', stage_idx: 0) @@ -683,7 +683,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when builds with auto-retries are configured' do + context 'when builds with auto-retries are configured', :sidekiq_might_not_need_inline do before do create_build('build:1', stage_idx: 0, user: user, options: { script: 'aa', retry: 2 }) create_build('test:1', stage_idx: 1, user: user, when: :on_failure) @@ -712,7 +712,7 @@ describe Ci::ProcessPipelineService, '#execute' do end end - context 'when pipeline with needs is created' do + context 'when pipeline with needs is created', :sidekiq_might_not_need_inline do let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) } let!(:mac_build) { create_build('mac:build', stage: 'build', stage_idx: 0) } let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1) } diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb index 3ee45375dca..8c2d8c9246e 100644 --- a/spec/services/clusters/update_service_spec.rb +++ b/spec/services/clusters/update_service_spec.rb @@ -90,5 +90,115 @@ describe Clusters::UpdateService do end end end + + context 'when params includes :management_project_id' do + context 'management_project is non-existent' do + let(:params) do + { management_project_id: 0 } + end + + it 'does not update management_project_id' do + is_expected.to eq(false) + + expect(cluster.errors[:management_project_id]).to include('Project does not exist or you don\'t have permission to perform this action') + + cluster.reload + expect(cluster.management_project_id).to be_nil + end + end + + shared_examples 'setting a management project' do + context 'user is authorized to adminster manangement_project' do + before do + management_project.add_maintainer(cluster.user) + end + + let(:params) do + { management_project_id: management_project.id } + end + + it 'updates management_project_id' do + is_expected.to eq(true) + + expect(cluster.management_project).to eq(management_project) + end + end + + context 'user is not authorized to adminster manangement_project' do + let(:params) do + { management_project_id: management_project.id } + end + + it 'does not update management_project_id' do + is_expected.to eq(false) + + expect(cluster.errors[:management_project_id]).to include('Project does not exist or you don\'t have permission to perform this action') + + cluster.reload + expect(cluster.management_project_id).to be_nil + end + end + end + + context 'project cluster' do + include_examples 'setting a management project' do + let(:management_project) { create(:project, namespace: cluster.first_project.namespace) } + end + + context 'manangement_project is outside of the namespace scope' do + before do + management_project.update(group: create(:group)) + end + + let(:params) do + { management_project_id: management_project.id } + end + + it 'does not update management_project_id' do + is_expected.to eq(false) + + expect(cluster.errors[:management_project_id]).to include('Project does not exist or you don\'t have permission to perform this action') + + cluster.reload + expect(cluster.management_project_id).to be_nil + end + end + end + + context 'group cluster' do + let(:cluster) { create(:cluster, :group) } + + include_examples 'setting a management project' do + let(:management_project) { create(:project, group: cluster.first_group) } + end + + context 'manangement_project is outside of the namespace scope' do + before do + management_project.update(group: create(:group)) + end + + let(:params) do + { management_project_id: management_project.id } + end + + it 'does not update management_project_id' do + is_expected.to eq(false) + + expect(cluster.errors[:management_project_id]).to include('Project does not exist or you don\'t have permission to perform this action') + + cluster.reload + expect(cluster.management_project_id).to be_nil + end + end + end + + context 'instance cluster' do + let(:cluster) { create(:cluster, :instance) } + + include_examples 'setting a management project' do + let(:management_project) { create(:project) } + end + end + end end end diff --git a/spec/services/git/branch_hooks_service_spec.rb b/spec/services/git/branch_hooks_service_spec.rb index 085b49f31ab..b1c64bc3c0a 100644 --- a/spec/services/git/branch_hooks_service_spec.rb +++ b/spec/services/git/branch_hooks_service_spec.rb @@ -345,7 +345,7 @@ describe Git::BranchHooksService do end end - context 'when the project is forked' do + context 'when the project is forked', :sidekiq_might_not_need_inline do let(:upstream_project) { project } let(:forked_project) { fork_project(upstream_project, user, repository: true) } diff --git a/spec/services/git/branch_push_service_spec.rb b/spec/services/git/branch_push_service_spec.rb index bf68eb0af20..febd4992682 100644 --- a/spec/services/git/branch_push_service_spec.rb +++ b/spec/services/git/branch_push_service_spec.rb @@ -246,7 +246,7 @@ describe Git::BranchPushService, services: true do allow(project.repository).to receive(:commits_between).and_return([commit]) end - it "creates a note if a pushed commit mentions an issue" do + it "creates a note if a pushed commit mentions an issue", :sidekiq_might_not_need_inline do expect(SystemNoteService).to receive(:cross_reference).with(issue, commit, commit_author) execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref) @@ -260,7 +260,7 @@ describe Git::BranchPushService, services: true do execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref) end - it "defaults to the pushing user if the commit's author is not known" do + it "defaults to the pushing user if the commit's author is not known", :sidekiq_might_not_need_inline do allow(commit).to receive_messages( author_name: 'unknown name', author_email: 'unknown@email.com' @@ -270,7 +270,7 @@ describe Git::BranchPushService, services: true do execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref) end - it "finds references in the first push to a non-default branch" do + it "finds references in the first push to a non-default branch", :sidekiq_might_not_need_inline do allow(project.repository).to receive(:commits_between).with(blankrev, newrev).and_return([]) allow(project.repository).to receive(:commits_between).with("master", newrev).and_return([commit]) @@ -305,7 +305,7 @@ describe Git::BranchPushService, services: true do end context "while saving the 'first_mentioned_in_commit_at' metric for an issue" do - it 'sets the metric for referenced issues' do + it 'sets the metric for referenced issues', :sidekiq_might_not_need_inline do execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref) expect(issue.reload.metrics.first_mentioned_in_commit_at).to be_like_time(commit_time) @@ -344,12 +344,12 @@ describe Git::BranchPushService, services: true do end context "to default branches" do - it "closes issues" do + it "closes issues", :sidekiq_might_not_need_inline do execute_service(project, commit_author, oldrev: oldrev, newrev: newrev, ref: ref) expect(Issue.find(issue.id)).to be_closed end - it "adds a note indicating that the issue is now closed" do + it "adds a note indicating that the issue is now closed", :sidekiq_might_not_need_inline do expect(SystemNoteService).to receive(:change_status).with(issue, project, commit_author, "closed", closing_commit) execute_service(project, commit_author, oldrev: oldrev, newrev: newrev, ref: ref) end @@ -366,7 +366,7 @@ describe Git::BranchPushService, services: true do allow(project).to receive(:default_branch).and_return('not-master') end - it "creates cross-reference notes" do + it "creates cross-reference notes", :sidekiq_might_not_need_inline do expect(SystemNoteService).to receive(:cross_reference).with(issue, closing_commit, commit_author) execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref) end @@ -407,7 +407,7 @@ describe Git::BranchPushService, services: true do context "mentioning an issue" do let(:message) { "this is some work.\n\nrelated to JIRA-1" } - it "initiates one api call to jira server to mention the issue" do + it "initiates one api call to jira server to mention the issue", :sidekiq_might_not_need_inline do execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref) expect(WebMock).to have_requested(:post, jira_api_comment_url('JIRA-1')).with( @@ -434,7 +434,7 @@ describe Git::BranchPushService, services: true do allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return("JIRA-1") end - context "using right markdown" do + context "using right markdown", :sidekiq_might_not_need_inline do it "initiates one api call to jira server to close the issue" do execute_service(project, commit_author, oldrev: oldrev, newrev: newrev, ref: ref) @@ -473,7 +473,7 @@ describe Git::BranchPushService, services: true do end end - context 'when internal issues are enabled' do + context 'when internal issues are enabled', :sidekiq_might_not_need_inline do let(:issue) { create(:issue, project: project) } let(:message) { "this is some work.\n\ncloses JIRA-1 \n\n closes #{issue.to_reference}" } diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb index d13739cefd9..055d0243d4b 100644 --- a/spec/services/groups/destroy_service_spec.rb +++ b/spec/services/groups/destroy_service_spec.rb @@ -26,7 +26,7 @@ describe Groups::DestroyService do end shared_examples 'group destruction' do |async| - context 'database records' do + context 'database records', :sidekiq_might_not_need_inline do before do destroy_group(group, user, async) end @@ -37,7 +37,7 @@ describe Groups::DestroyService do it { expect(NotificationSetting.unscoped.all).not_to include(notification_setting) } end - context 'mattermost team' do + context 'mattermost team', :sidekiq_might_not_need_inline do let!(:chat_team) { create(:chat_team, namespace: group) } it 'destroys the team too' do @@ -47,7 +47,7 @@ describe Groups::DestroyService do end end - context 'file system' do + context 'file system', :sidekiq_might_not_need_inline do context 'Sidekiq inline' do before do # Run sidekiq immediately to check that renamed dir will be removed @@ -55,8 +55,8 @@ describe Groups::DestroyService do end it 'verifies that paths have been deleted' do - expect(gitlab_shell.exists?(project.repository_storage, group.path)).to be_falsey - expect(gitlab_shell.exists?(project.repository_storage, remove_path)).to be_falsey + expect(TestEnv.storage_dir_exists?(project.repository_storage, group.path)).to be_falsey + expect(TestEnv.storage_dir_exists?(project.repository_storage, remove_path)).to be_falsey end end end @@ -73,13 +73,13 @@ describe Groups::DestroyService do after do # Clean up stale directories - gitlab_shell.rm_namespace(project.repository_storage, group.path) - gitlab_shell.rm_namespace(project.repository_storage, remove_path) + TestEnv.rm_storage_dir(project.repository_storage, group.path) + TestEnv.rm_storage_dir(project.repository_storage, remove_path) end it 'verifies original paths and projects still exist' do - expect(gitlab_shell.exists?(project.repository_storage, group.path)).to be_truthy - expect(gitlab_shell.exists?(project.repository_storage, remove_path)).to be_falsey + expect(TestEnv.storage_dir_exists?(project.repository_storage, group.path)).to be_truthy + expect(TestEnv.storage_dir_exists?(project.repository_storage, remove_path)).to be_falsey expect(Project.unscoped.count).to eq(1) expect(Group.unscoped.count).to eq(2) end diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index 1f7d564b6ec..dce62d1d20e 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -70,7 +70,7 @@ describe Issues::CloseService do end describe '#close_issue' do - context "closed by a merge request" do + context "closed by a merge request", :sidekiq_might_not_need_inline do it 'mentions closure via a merge request' do perform_enqueued_jobs do described_class.new(project, user).close_issue(issue, closed_via: closing_merge_request) @@ -100,7 +100,7 @@ describe Issues::CloseService do end end - context "closed by a commit" do + context "closed by a commit", :sidekiq_might_not_need_inline do it 'mentions closure via a commit' do perform_enqueued_jobs do described_class.new(project, user).close_issue(issue, closed_via: closing_commit) @@ -146,7 +146,7 @@ describe Issues::CloseService do expect(issue.closed_by_id).to be(user.id) end - it 'sends email to user2 about assign of new issue' do + it 'sends email to user2 about assign of new issue', :sidekiq_might_not_need_inline do email = ActionMailer::Base.deliveries.last expect(email.to.first).to eq(user2.email) expect(email.subject).to include(issue.title) diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 154bfec0da2..1eec3b97ea1 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -169,7 +169,7 @@ describe Issues::UpdateService, :mailer do end end - context 'with background jobs processed' do + context 'with background jobs processed', :sidekiq_might_not_need_inline do before do perform_enqueued_jobs do update_issue(opts) @@ -366,7 +366,7 @@ describe Issues::UpdateService, :mailer do it_behaves_like 'system notes for milestones' - it 'sends notifications for subscribers of changed milestone' do + it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do issue.milestone = create(:milestone, project: project) issue.save @@ -398,7 +398,7 @@ describe Issues::UpdateService, :mailer do it_behaves_like 'system notes for milestones' - it 'sends notifications for subscribers of changed milestone' do + it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do perform_enqueued_jobs do update_issue(milestone: create(:milestone, project: project)) end @@ -435,7 +435,7 @@ describe Issues::UpdateService, :mailer do end end - it 'sends notifications for subscribers of newly added labels' do + it 'sends notifications for subscribers of newly added labels', :sidekiq_might_not_need_inline do opts = { label_ids: [label.id] } perform_enqueued_jobs do diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb index effcaf53535..73ac0bd7716 100644 --- a/spec/services/members/destroy_service_spec.rb +++ b/spec/services/members/destroy_service_spec.rb @@ -45,7 +45,7 @@ describe Members::DestroyService do shared_examples 'a service destroying a member with access' do it_behaves_like 'a service destroying a member' - it 'invalidates cached counts for assigned issues and merge requests', :aggregate_failures do + it 'invalidates cached counts for assigned issues and merge requests', :aggregate_failures, :sidekiq_might_not_need_inline do create(:issue, project: group_project, assignees: [member_user]) create(:merge_request, source_project: group_project, assignees: [member_user]) create(:todo, :pending, project: group_project, user: member_user) diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index d546a092680..46e86d5b4cb 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -80,7 +80,7 @@ describe MergeRequests::BuildService do end it 'does not assign force_remove_source_branch' do - expect(merge_request.force_remove_source_branch?).to be_falsey + expect(merge_request.force_remove_source_branch?).to be_truthy end context 'with force_remove_source_branch parameter' do @@ -90,6 +90,36 @@ describe MergeRequests::BuildService do it 'assigns force_remove_source_branch' do expect(merge_request.force_remove_source_branch?).to be_truthy end + + context 'with project setting remove_source_branch_after_merge false' do + before do + project.remove_source_branch_after_merge = false + end + + it 'assigns force_remove_source_branch' do + expect(merge_request.force_remove_source_branch?).to be_truthy + end + end + end + + context 'with project setting remove_source_branch_after_merge true' do + before do + project.remove_source_branch_after_merge = true + end + + it 'assigns force_remove_source_branch' do + expect(merge_request.force_remove_source_branch?).to be_truthy + end + + context 'with force_remove_source_branch parameter false' do + before do + params[:force_remove_source_branch] = '0' + end + + it 'does not assign force_remove_source_branch' do + expect(merge_request.force_remove_source_branch?).to be(false) + end + end end context 'missing source branch' do @@ -130,7 +160,7 @@ describe MergeRequests::BuildService do let!(:project) { fork_project(target_project, user, namespace: user.namespace, repository: true) } let(:source_project) { project } - it 'creates compare object with target branch as default branch' do + it 'creates compare object with target branch as default branch', :sidekiq_might_not_need_inline do expect(merge_request.compare).to be_present expect(merge_request.target_branch).to eq(project.default_branch) end diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb index 29b7e0f17e2..b037b73752e 100644 --- a/spec/services/merge_requests/close_service_spec.rb +++ b/spec/services/merge_requests/close_service_spec.rb @@ -38,7 +38,7 @@ describe MergeRequests::CloseService do .with(@merge_request, 'close') end - it 'sends email to user2 about assign of new merge_request' do + it 'sends email to user2 about assign of new merge_request', :sidekiq_might_not_need_inline do email = ActionMailer::Base.deliveries.last expect(email.to.first).to eq(user2.email) expect(email.subject).to include(merge_request.title) diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb index 51a5c51f6c3..7145cfe7897 100644 --- a/spec/services/merge_requests/create_from_issue_service_spec.rb +++ b/spec/services/merge_requests/create_from_issue_service_spec.rb @@ -36,25 +36,25 @@ describe MergeRequests::CreateFromIssueService do expect(result[:message]).to eq('Invalid issue iid') end - it 'creates a branch based on issue title' do + it 'creates a branch based on issue title', :sidekiq_might_not_need_inline do service.execute expect(target_project.repository.branch_exists?(issue.to_branch_name)).to be_truthy end - it 'creates a branch using passed name' do + it 'creates a branch using passed name', :sidekiq_might_not_need_inline do service_with_custom_source_branch.execute expect(target_project.repository.branch_exists?(custom_source_branch)).to be_truthy end - it 'creates the new_merge_request system note' do + it 'creates the new_merge_request system note', :sidekiq_might_not_need_inline do expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest)) service.execute end - it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do + it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created', :sidekiq_might_not_need_inline do expect_any_instance_of(MergeRequest).to receive(:valid?).at_least(:once).and_return(false) expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, issue.to_branch_name, branch_project: target_project) @@ -62,35 +62,35 @@ describe MergeRequests::CreateFromIssueService do service.execute end - it 'creates a merge request' do + it 'creates a merge request', :sidekiq_might_not_need_inline do expect { service.execute }.to change(target_project.merge_requests, :count).by(1) end - it 'sets the merge request author to current user' do + it 'sets the merge request author to current user', :sidekiq_might_not_need_inline do result = service.execute expect(result[:merge_request].author).to eq(user) end - it 'sets the merge request source branch to the new issue branch' do + it 'sets the merge request source branch to the new issue branch', :sidekiq_might_not_need_inline do result = service.execute expect(result[:merge_request].source_branch).to eq(issue.to_branch_name) end - it 'sets the merge request source branch to the passed branch name' do + it 'sets the merge request source branch to the passed branch name', :sidekiq_might_not_need_inline do result = service_with_custom_source_branch.execute expect(result[:merge_request].source_branch).to eq(custom_source_branch) end - it 'sets the merge request target branch to the project default branch' do + it 'sets the merge request target branch to the project default branch', :sidekiq_might_not_need_inline do result = service.execute expect(result[:merge_request].target_branch).to eq(target_project.default_branch) end - it 'executes quick actions if the build service sets them in the description' do + it 'executes quick actions if the build service sets them in the description', :sidekiq_might_not_need_inline do allow(service).to receive(:merge_request).and_wrap_original do |m, *args| m.call(*args).tap do |merge_request| merge_request.description = "/assign #{user.to_reference}" @@ -102,7 +102,7 @@ describe MergeRequests::CreateFromIssueService do expect(result[:merge_request].assignees).to eq([user]) end - context 'when ref branch is set' do + context 'when ref branch is set', :sidekiq_might_not_need_inline do subject { described_class.new(project, user, ref: 'feature', **service_params).execute } it 'sets the merge request source branch to the new issue branch' do @@ -193,7 +193,7 @@ describe MergeRequests::CreateFromIssueService do it_behaves_like 'a service that creates a merge request from an issue' - it 'sets the merge request title to: "WIP: $issue-branch-name' do + it 'sets the merge request title to: "WIP: $issue-branch-name', :sidekiq_might_not_need_inline do result = service.execute expect(result[:merge_request].title).to eq("WIP: #{issue.to_branch_name.titleize.humanize}") diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index 699f2a98088..3db1471bf3c 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -57,7 +57,7 @@ describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do expect(Todo.where(attributes).count).to be_zero end - it 'creates exactly 1 create MR event' do + it 'creates exactly 1 create MR event', :sidekiq_might_not_need_inline do attributes = { action: Event::CREATED, target_id: merge_request.id, @@ -216,7 +216,7 @@ describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do target_project.add_maintainer(user) end - it 'create legacy detached merge request pipeline for fork merge request' do + it 'create legacy detached merge request pipeline for fork merge request', :sidekiq_might_not_need_inline do expect(merge_request.actual_head_pipeline) .to be_legacy_detached_merge_request_pipeline end @@ -477,7 +477,7 @@ describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do project.add_developer(user) end - it 'creates the merge request' do + it 'creates the merge request', :sidekiq_might_not_need_inline do merge_request = described_class.new(project, user, opts).execute expect(merge_request).to be_persisted diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb index ff4cdd3e7e2..75b9c2304a6 100644 --- a/spec/services/merge_requests/push_options_handler_service_spec.rb +++ b/spec/services/merge_requests/push_options_handler_service_spec.rb @@ -46,7 +46,7 @@ describe MergeRequests::PushOptionsHandlerService do expect(last_mr.assignees).to contain_exactly(user) end - context 'when project has been forked' do + context 'when project has been forked', :sidekiq_might_not_need_inline do let(:forked_project) { fork_project(project, user, repository: true) } let(:service) { described_class.new(forked_project, user, changes, push_options) } diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb index 7b8c94c86fe..9c535664c26 100644 --- a/spec/services/merge_requests/rebase_service_spec.rb +++ b/spec/services/merge_requests/rebase_service_spec.rb @@ -174,7 +174,7 @@ describe MergeRequests::RebaseService do target_branch: 'master', target_project: project) end - it 'rebases source branch' do + it 'rebases source branch', :sidekiq_might_not_need_inline do parent_sha = forked_project.repository.commit(merge_request_from_fork.source_branch).parents.first.sha target_branch_sha = project.repository.commit(merge_request_from_fork.target_branch).sha expect(parent_sha).to eq(target_branch_sha) diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 2dc932c9f2c..58302ce14ba 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -137,7 +137,7 @@ describe MergeRequests::RefreshService do subject { service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') } - it 'updates the head_pipeline_id for @merge_request' do + it 'updates the head_pipeline_id for @merge_request', :sidekiq_might_not_need_inline do expect { subject }.to change { @merge_request.reload.head_pipeline_id }.from(nil).to(pipeline.id) end @@ -200,7 +200,7 @@ describe MergeRequests::RefreshService do context 'when service runs on forked project' do let(:project) { @fork_project } - it 'creates legacy detached merge request pipeline for fork merge request' do + it 'creates legacy detached merge request pipeline for fork merge request', :sidekiq_might_not_need_inline do expect { subject } .to change { @fork_merge_request.pipelines_for_merge_request.count }.by(1) @@ -232,7 +232,7 @@ describe MergeRequests::RefreshService do subject end - it 'sets the latest detached merge request pipeline as a head pipeline' do + it 'sets the latest detached merge request pipeline as a head pipeline', :sidekiq_might_not_need_inline do @merge_request.reload expect(@merge_request.actual_head_pipeline).to be_merge_request_event end @@ -304,7 +304,7 @@ describe MergeRequests::RefreshService do end end - context 'push to origin repo target branch' do + context 'push to origin repo target branch', :sidekiq_might_not_need_inline do context 'when all MRs to the target branch had diffs' do before do service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature') @@ -354,7 +354,7 @@ describe MergeRequests::RefreshService do end end - context 'manual merge of source branch' do + context 'manual merge of source branch', :sidekiq_might_not_need_inline do before do # Merge master -> feature branch @project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, 'Test message') @@ -374,7 +374,7 @@ describe MergeRequests::RefreshService do end end - context 'push to fork repo source branch' do + context 'push to fork repo source branch', :sidekiq_might_not_need_inline do let(:refresh_service) { service.new(@fork_project, @user) } def refresh @@ -431,7 +431,7 @@ describe MergeRequests::RefreshService do end end - context 'push to fork repo target branch' do + context 'push to fork repo target branch', :sidekiq_might_not_need_inline do describe 'changes to merge requests' do before do service.new(@fork_project, @user).execute(@oldrev, @newrev, 'refs/heads/feature') @@ -457,7 +457,7 @@ describe MergeRequests::RefreshService do end end - context 'forked projects with the same source branch name as target branch' do + context 'forked projects with the same source branch name as target branch', :sidekiq_might_not_need_inline do let!(:first_commit) do @fork_project.repository.create_file(@user, 'test1.txt', 'Test data', message: 'Test commit', @@ -537,7 +537,7 @@ describe MergeRequests::RefreshService do context 'push new branch that exists in a merge request' do let(:refresh_service) { service.new(@fork_project, @user) } - it 'refreshes the merge request' do + it 'refreshes the merge request', :sidekiq_might_not_need_inline do expect(refresh_service).to receive(:execute_hooks) .with(@fork_merge_request, 'update', old_rev: Gitlab::Git::BLANK_SHA) allow_any_instance_of(Repository).to receive(:merge_base).and_return(@oldrev) diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb index 7a98437f724..25ab79d70c3 100644 --- a/spec/services/merge_requests/reopen_service_spec.rb +++ b/spec/services/merge_requests/reopen_service_spec.rb @@ -37,7 +37,7 @@ describe MergeRequests::ReopenService do .with(merge_request, 'reopen') end - it 'sends email to user2 about reopen of merge_request' do + it 'sends email to user2 about reopen of merge_request', :sidekiq_might_not_need_inline do email = ActionMailer::Base.deliveries.last expect(email.to.first).to eq(user2.email) expect(email.subject).to include(merge_request.title) diff --git a/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb b/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb index 0a10a9ee13b..dc2bd5bf3d0 100644 --- a/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb +++ b/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb @@ -38,7 +38,7 @@ describe MergeRequests::ResolvedDiscussionNotificationService do subject.execute(merge_request) end - it "sends a notification email" do + it "sends a notification email", :sidekiq_might_not_need_inline do expect_any_instance_of(NotificationService).to receive(:resolve_all_discussions).with(merge_request, user) subject.execute(merge_request) diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index d3c4c436901..8c796475de0 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -98,7 +98,7 @@ describe MergeRequests::UpdateService, :mailer do ) end - it 'sends email to user2 about assign of new merge request and email to user3 about merge request unassignment' do + it 'sends email to user2 about assign of new merge request and email to user3 about merge request unassignment', :sidekiq_might_not_need_inline do deliveries = ActionMailer::Base.deliveries email = deliveries.last recipients = deliveries.last(2).flat_map(&:to) @@ -181,7 +181,7 @@ describe MergeRequests::UpdateService, :mailer do end end - it 'merges the MR' do + it 'merges the MR', :sidekiq_might_not_need_inline do expect(@merge_request).to be_valid expect(@merge_request.state).to eq('merged') expect(@merge_request.merge_error).to be_nil @@ -202,7 +202,7 @@ describe MergeRequests::UpdateService, :mailer do end end - it 'merges the MR' do + it 'merges the MR', :sidekiq_might_not_need_inline do expect(@merge_request).to be_valid expect(@merge_request.state).to eq('merged') end @@ -332,7 +332,7 @@ describe MergeRequests::UpdateService, :mailer do it_behaves_like 'system notes for milestones' - it 'sends notifications for subscribers of changed milestone' do + it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do merge_request.milestone = create(:milestone, project: project) merge_request.save @@ -364,7 +364,7 @@ describe MergeRequests::UpdateService, :mailer do it_behaves_like 'system notes for milestones' - it 'sends notifications for subscribers of changed milestone' do + it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do perform_enqueued_jobs do update_merge_request(milestone: create(:milestone, project: project)) end @@ -431,7 +431,7 @@ describe MergeRequests::UpdateService, :mailer do project.add_developer(subscriber) end - it 'sends notifications for subscribers of newly added labels' do + it 'sends notifications for subscribers of newly added labels', :sidekiq_might_not_need_inline do opts = { label_ids: [label.id] } perform_enqueued_jobs do diff --git a/spec/services/namespaces/statistics_refresher_service_spec.rb b/spec/services/namespaces/statistics_refresher_service_spec.rb index f4d9c96f7f4..9d42e917efe 100644 --- a/spec/services/namespaces/statistics_refresher_service_spec.rb +++ b/spec/services/namespaces/statistics_refresher_service_spec.rb @@ -23,7 +23,7 @@ describe Namespaces::StatisticsRefresherService, '#execute' do end end - context 'with a root storage statistics relation' do + context 'with a root storage statistics relation', :sidekiq_might_not_need_inline do before do Namespace::AggregationSchedule.safe_find_or_create_by!(namespace_id: group.id) end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index aa67b87a645..2481cd5c006 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -682,7 +682,7 @@ describe NotificationService, :mailer do context 'when recipients for a new release exist' do let(:release) { create(:release) } - it 'calls new_release_email for each relevant recipient' do + it 'calls new_release_email for each relevant recipient', :sidekiq_might_not_need_inline do user_1 = create(:user) user_2 = create(:user) user_3 = create(:user) diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb index 8585d495ffb..bf637b70aaf 100644 --- a/spec/services/projects/after_rename_service_spec.rb +++ b/spec/services/projects/after_rename_service_spec.rb @@ -222,7 +222,7 @@ describe Projects::AfterRenameService do def expect_repository_exist(full_path_with_extension) expect( - gitlab_shell.exists?( + TestEnv.storage_dir_exists?( project.repository_storage, full_path_with_extension ) diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index 2331281bd8e..642986bb176 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -81,7 +81,7 @@ describe Projects::DestroyService do end let!(:async) { true } - it 'destroys them' do + it 'destroys them', :sidekiq_might_not_need_inline do expect(RemoteMirror.count).to eq(0) end end @@ -102,7 +102,7 @@ describe Projects::DestroyService do end let!(:async) { true } - it 'destroys project and export' do + it 'destroys project and export', :sidekiq_might_not_need_inline do expect { destroy_project(project_with_export, user) }.to change(ImportExportUpload, :count).by(-1) expect(Project.all).not_to include(project_with_export) @@ -153,7 +153,7 @@ describe Projects::DestroyService do end end - context 'with async_execute' do + context 'with async_execute', :sidekiq_might_not_need_inline do let(:async) { true } context 'async delete of project with private issue visibility' do @@ -346,21 +346,21 @@ describe Projects::DestroyService do let(:path) { project.disk_path + '.git' } before do - expect(project.gitlab_shell.exists?(project.repository_storage, path)).to be_truthy - expect(project.gitlab_shell.exists?(project.repository_storage, remove_path)).to be_falsey + expect(TestEnv.storage_dir_exists?(project.repository_storage, path)).to be_truthy + expect(TestEnv.storage_dir_exists?(project.repository_storage, remove_path)).to be_falsey # Dont run sidekiq to check if renamed repository exists Sidekiq::Testing.fake! { destroy_project(project, user, {}) } - expect(project.gitlab_shell.exists?(project.repository_storage, path)).to be_falsey - expect(project.gitlab_shell.exists?(project.repository_storage, remove_path)).to be_truthy + expect(TestEnv.storage_dir_exists?(project.repository_storage, path)).to be_falsey + expect(TestEnv.storage_dir_exists?(project.repository_storage, remove_path)).to be_truthy end it 'restores the repositories' do Sidekiq::Testing.fake! { described_class.new(project, user).attempt_repositories_rollback } - expect(project.gitlab_shell.exists?(project.repository_storage, path)).to be_truthy - expect(project.gitlab_shell.exists?(project.repository_storage, remove_path)).to be_falsey + expect(TestEnv.storage_dir_exists?(project.repository_storage, path)).to be_truthy + expect(TestEnv.storage_dir_exists?(project.repository_storage, remove_path)).to be_falsey end end diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index 7e7e80ca240..5a3796fec3d 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -79,7 +79,7 @@ describe Projects::ForkService do expect(fork_network.projects).to contain_exactly(@from_project, to_project) end - it 'imports the repository of the forked project' do + it 'imports the repository of the forked project', :sidekiq_might_not_need_inline do to_project = fork_project(@from_project, @to_user, repository: true) expect(to_project.empty_repo?).to be_falsy diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index 31bd0f0f836..c848a5397e1 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -151,7 +151,7 @@ describe Projects::UpdateService do context 'when we update project but not enabling a wiki' do it 'does not try to create an empty wiki' do - Gitlab::Shell.new.rm_directory(project.repository_storage, project.wiki.path) + TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path) result = update_project(project, user, { name: 'test1' }) @@ -172,7 +172,7 @@ describe Projects::UpdateService do context 'when enabling a wiki' do it 'creates a wiki' do project.project_feature.update(wiki_access_level: ProjectFeature::DISABLED) - Gitlab::Shell.new.rm_directory(project.repository_storage, project.wiki.path) + TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path) result = update_project(project, user, project_feature_attributes: { wiki_access_level: ProjectFeature::ENABLED }) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 83101add724..e2ed7581ad4 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -115,51 +115,36 @@ describe SystemNoteService do end describe '.merge_when_pipeline_succeeds' do - let(:pipeline) { build(:ci_pipeline_without_jobs )} - let(:noteable) do - create(:merge_request, source_project: project, target_project: project) - end - - subject { described_class.merge_when_pipeline_succeeds(noteable, project, author, pipeline.sha) } + it 'calls MergeRequestsService' do + sha = double - it_behaves_like 'a system note' do - let(:action) { 'merge' } - end + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:merge_when_pipeline_succeeds).with(sha) + end - it "posts the 'merge when pipeline succeeds' system note" do - expect(subject.note).to match(%r{enabled an automatic merge when the pipeline for (\w+/\w+@)?\h{40} succeeds}) + described_class.merge_when_pipeline_succeeds(noteable, project, author, sha) end end describe '.cancel_merge_when_pipeline_succeeds' do - let(:noteable) do - create(:merge_request, source_project: project, target_project: project) - end - - subject { described_class.cancel_merge_when_pipeline_succeeds(noteable, project, author) } - - it_behaves_like 'a system note' do - let(:action) { 'merge' } - end + it 'calls MergeRequestsService' do + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:cancel_merge_when_pipeline_succeeds) + end - it "posts the 'merge when pipeline succeeds' system note" do - expect(subject.note).to eq "canceled the automatic merge" + described_class.cancel_merge_when_pipeline_succeeds(noteable, project, author) end end describe '.abort_merge_when_pipeline_succeeds' do - let(:noteable) do - create(:merge_request, source_project: project, target_project: project) - end + it 'calls MergeRequestsService' do + reason = double - subject { described_class.abort_merge_when_pipeline_succeeds(noteable, project, author, 'merge request was closed') } - - it_behaves_like 'a system note' do - let(:action) { 'merge' } - end + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:abort_merge_when_pipeline_succeeds).with(reason) + end - it "posts the 'merge when pipeline succeeds' system note" do - expect(subject.note).to eq "aborted the automatic merge because merge request was closed" + described_class.abort_merge_when_pipeline_succeeds(noteable, project, author, reason) end end @@ -196,77 +181,55 @@ describe SystemNoteService do end describe '.change_branch' do - subject { described_class.change_branch(noteable, project, author, 'target', old_branch, new_branch) } - - let(:old_branch) { 'old_branch'} - let(:new_branch) { 'new_branch'} - - it_behaves_like 'a system note' do - let(:action) { 'branch' } - end + it 'calls MergeRequestsService' do + old_branch = double + new_branch = double + branch_type = double - context 'when target branch name changed' do - it 'sets the note text' do - expect(subject.note).to eq "changed target branch from `#{old_branch}` to `#{new_branch}`" + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:change_branch).with(branch_type, old_branch, new_branch) end + + described_class.change_branch(noteable, project, author, branch_type, old_branch, new_branch) end end describe '.change_branch_presence' do - subject { described_class.change_branch_presence(noteable, project, author, :source, 'feature', :delete) } - - it_behaves_like 'a system note' do - let(:action) { 'branch' } - end + it 'calls MergeRequestsService' do + presence = double + branch = double + branch_type = double - context 'when source branch deleted' do - it 'sets the note text' do - expect(subject.note).to eq "deleted source branch `feature`" + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:change_branch_presence).with(branch_type, branch, presence) end + + described_class.change_branch_presence(noteable, project, author, branch_type, branch, presence) end end describe '.new_issue_branch' do - let(:branch) { '1-mepmep' } + it 'calls MergeRequestsService' do + branch = double + branch_project = double - subject { described_class.new_issue_branch(noteable, project, author, branch, branch_project: branch_project) } - - shared_examples_for 'a system note for new issue branch' do - it_behaves_like 'a system note' do - let(:action) { 'branch' } - end - - context 'when a branch is created from the new branch button' do - it 'sets the note text' do - expect(subject.note).to start_with("created branch [`#{branch}`]") - end + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:new_issue_branch).with(branch, branch_project: branch_project) end - end - context 'branch_project is set' do - let(:branch_project) { create(:project, :repository) } - - it_behaves_like 'a system note for new issue branch' - end - - context 'branch_project is not set' do - let(:branch_project) { nil } - - it_behaves_like 'a system note for new issue branch' + described_class.new_issue_branch(noteable, project, author, branch, branch_project: branch_project) end end describe '.new_merge_request' do - subject { described_class.new_merge_request(noteable, project, author, merge_request) } - - let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + it 'calls MergeRequestsService' do + merge_request = double - it_behaves_like 'a system note' do - let(:action) { 'merge' } - end + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:new_merge_request).with(merge_request) + end - it 'sets the new merge request note text' do - expect(subject.note).to eq("created merge request #{merge_request.to_reference(project)} to address this issue") + described_class.new_merge_request(noteable, project, author, merge_request) end end @@ -642,57 +605,24 @@ describe SystemNoteService do end describe '.handle_merge_request_wip' do - context 'adding wip note' do - let(:noteable) { create(:merge_request, source_project: project, title: 'WIP Lorem ipsum') } - - subject { described_class.handle_merge_request_wip(noteable, project, author) } - - it_behaves_like 'a system note' do - let(:action) { 'title' } + it 'calls MergeRequestsService' do + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:handle_merge_request_wip) end - it 'sets the note text' do - expect(subject.note).to eq 'marked as a **Work In Progress**' - end - end - - context 'removing wip note' do - let(:noteable) { create(:merge_request, source_project: project, title: 'Lorem ipsum') } - - subject { described_class.handle_merge_request_wip(noteable, project, author) } - - it_behaves_like 'a system note' do - let(:action) { 'title' } - end - - it 'sets the note text' do - expect(subject.note).to eq 'unmarked as a **Work In Progress**' - end + described_class.handle_merge_request_wip(noteable, project, author) end end describe '.add_merge_request_wip_from_commit' do - let(:noteable) do - create(:merge_request, source_project: project, target_project: project) - end - - subject do - described_class.add_merge_request_wip_from_commit( - noteable, - project, - author, - noteable.diff_head_commit - ) - end + it 'calls MergeRequestsService' do + commit = double - it_behaves_like 'a system note' do - let(:action) { 'title' } - end + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:add_merge_request_wip_from_commit).with(commit) + end - it "posts the 'marked as a Work In Progress from commit' system note" do - expect(subject.note).to match( - /marked as a \*\*Work In Progress\*\* from #{Commit.reference_pattern}/ - ) + described_class.add_merge_request_wip_from_commit(noteable, project, author, commit) end end @@ -709,75 +639,25 @@ describe SystemNoteService do end describe '.resolve_all_discussions' do - let(:noteable) { create(:merge_request, source_project: project, target_project: project) } - - subject { described_class.resolve_all_discussions(noteable, project, author) } - - it_behaves_like 'a system note' do - let(:action) { 'discussion' } - end + it 'calls MergeRequestsService' do + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:resolve_all_discussions) + end - it 'sets the note text' do - expect(subject.note).to eq 'resolved all threads' + described_class.resolve_all_discussions(noteable, project, author) end end describe '.diff_discussion_outdated' do - let(:discussion) { create(:diff_note_on_merge_request, project: project).to_discussion } - let(:merge_request) { discussion.noteable } - let(:change_position) { discussion.position } + it 'calls MergeRequestsService' do + discussion = double + change_position = double - def reloaded_merge_request - MergeRequest.find(merge_request.id) - end - - subject { described_class.diff_discussion_outdated(discussion, project, author, change_position) } - - it_behaves_like 'a system note' do - let(:expected_noteable) { discussion.first_note.noteable } - let(:action) { 'outdated' } - end - - context 'when the change_position is valid for the discussion' do - it 'creates a new note in the discussion' do - # we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded. - expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1) - end - - it 'links to the diff in the system note' do - diff_id = merge_request.merge_request_diff.id - line_code = change_position.line_code(project.repository) - link = diffs_project_merge_request_path(project, merge_request, diff_id: diff_id, anchor: line_code) - - expect(subject.note).to eq("changed this line in [version 1 of the diff](#{link})") + expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service| + expect(service).to receive(:diff_discussion_outdated).with(discussion, change_position) end - context 'discussion is on an image' do - let(:discussion) { create(:image_diff_note_on_merge_request, project: project).to_discussion } - - it 'links to the diff in the system note' do - diff_id = merge_request.merge_request_diff.id - file_hash = change_position.file_hash - link = diffs_project_merge_request_path(project, merge_request, diff_id: diff_id, anchor: file_hash) - - expect(subject.note).to eq("changed this file in [version 1 of the diff](#{link})") - end - end - end - - context 'when the change_position does not point to a valid version' do - before do - allow(merge_request).to receive(:version_params_for).and_return(nil) - end - - it 'creates a new note in the discussion' do - # we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded. - expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1) - end - - it 'does not create a link' do - expect(subject.note).to eq('changed this line in version 1 of the diff') - end + described_class.diff_discussion_outdated(discussion, project, author, change_position) end end diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb index 5023abad4cd..ba484d95c9c 100644 --- a/spec/services/system_notes/issuables_service_spec.rb +++ b/spec/services/system_notes/issuables_service_spec.rb @@ -395,7 +395,7 @@ describe ::SystemNotes::IssuablesService do end end - context 'commit with cross-reference from fork' do + context 'commit with cross-reference from fork', :sidekiq_might_not_need_inline do let(:author2) { create(:project_member, :reporter, user: create(:user), project: project).user } let(:forked_project) { fork_project(project, author2, repository: true) } let(:commit2) { forked_project.commit } diff --git a/spec/services/system_notes/merge_requests_service_spec.rb b/spec/services/system_notes/merge_requests_service_spec.rb new file mode 100644 index 00000000000..cccc2818676 --- /dev/null +++ b/spec/services/system_notes/merge_requests_service_spec.rb @@ -0,0 +1,243 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ::SystemNotes::MergeRequestsService do + include Gitlab::Routing + + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :repository, group: group) } + let_it_be(:author) { create(:user) } + + let(:noteable) { create(:merge_request, source_project: project, target_project: project) } + + let(:service) { described_class.new(noteable: noteable, project: project, author: author) } + + describe '.merge_when_pipeline_succeeds' do + let(:pipeline) { build(:ci_pipeline_without_jobs )} + + subject { service.merge_when_pipeline_succeeds(pipeline.sha) } + + it_behaves_like 'a system note' do + let(:action) { 'merge' } + end + + it "posts the 'merge when pipeline succeeds' system note" do + expect(subject.note).to match(%r{enabled an automatic merge when the pipeline for (\w+/\w+@)?\h{40} succeeds}) + end + end + + describe '.cancel_merge_when_pipeline_succeeds' do + subject { service.cancel_merge_when_pipeline_succeeds } + + it_behaves_like 'a system note' do + let(:action) { 'merge' } + end + + it "posts the 'merge when pipeline succeeds' system note" do + expect(subject.note).to eq "canceled the automatic merge" + end + end + + describe '.abort_merge_when_pipeline_succeeds' do + subject { service.abort_merge_when_pipeline_succeeds('merge request was closed') } + + it_behaves_like 'a system note' do + let(:action) { 'merge' } + end + + it "posts the 'merge when pipeline succeeds' system note" do + expect(subject.note).to eq "aborted the automatic merge because merge request was closed" + end + end + + describe '.handle_merge_request_wip' do + context 'adding wip note' do + let(:noteable) { create(:merge_request, source_project: project, title: 'WIP Lorem ipsum') } + + subject { service.handle_merge_request_wip } + + it_behaves_like 'a system note' do + let(:action) { 'title' } + end + + it 'sets the note text' do + expect(subject.note).to eq 'marked as a **Work In Progress**' + end + end + + context 'removing wip note' do + subject { service.handle_merge_request_wip } + + it_behaves_like 'a system note' do + let(:action) { 'title' } + end + + it 'sets the note text' do + expect(subject.note).to eq 'unmarked as a **Work In Progress**' + end + end + end + + describe '.add_merge_request_wip_from_commit' do + subject { service.add_merge_request_wip_from_commit(noteable.diff_head_commit) } + + it_behaves_like 'a system note' do + let(:action) { 'title' } + end + + it "posts the 'marked as a Work In Progress from commit' system note" do + expect(subject.note).to match( + /marked as a \*\*Work In Progress\*\* from #{Commit.reference_pattern}/ + ) + end + end + + describe '.resolve_all_discussions' do + subject { service.resolve_all_discussions } + + it_behaves_like 'a system note' do + let(:action) { 'discussion' } + end + + it 'sets the note text' do + expect(subject.note).to eq 'resolved all threads' + end + end + + describe '.diff_discussion_outdated' do + let(:discussion) { create(:diff_note_on_merge_request, project: project).to_discussion } + let(:merge_request) { discussion.noteable } + let(:change_position) { discussion.position } + + def reloaded_merge_request + MergeRequest.find(merge_request.id) + end + + let(:service) { described_class.new(project: project, author: author) } + + subject { service.diff_discussion_outdated(discussion, change_position) } + + it_behaves_like 'a system note' do + let(:expected_noteable) { discussion.first_note.noteable } + let(:action) { 'outdated' } + end + + context 'when the change_position is valid for the discussion' do + it 'creates a new note in the discussion' do + # we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded. + expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1) + end + + it 'links to the diff in the system note' do + diff_id = merge_request.merge_request_diff.id + line_code = change_position.line_code(project.repository) + link = diffs_project_merge_request_path(project, merge_request, diff_id: diff_id, anchor: line_code) + + expect(subject.note).to eq("changed this line in [version 1 of the diff](#{link})") + end + + context 'discussion is on an image' do + let(:discussion) { create(:image_diff_note_on_merge_request, project: project).to_discussion } + + it 'links to the diff in the system note' do + diff_id = merge_request.merge_request_diff.id + file_hash = change_position.file_hash + link = diffs_project_merge_request_path(project, merge_request, diff_id: diff_id, anchor: file_hash) + + expect(subject.note).to eq("changed this file in [version 1 of the diff](#{link})") + end + end + end + + context 'when the change_position does not point to a valid version' do + before do + allow(merge_request).to receive(:version_params_for).and_return(nil) + end + + it 'creates a new note in the discussion' do + # we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded. + expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1) + end + + it 'does not create a link' do + expect(subject.note).to eq('changed this line in version 1 of the diff') + end + end + end + + describe '.change_branch' do + subject { service.change_branch('target', old_branch, new_branch) } + + let(:old_branch) { 'old_branch'} + let(:new_branch) { 'new_branch'} + + it_behaves_like 'a system note' do + let(:action) { 'branch' } + end + + context 'when target branch name changed' do + it 'sets the note text' do + expect(subject.note).to eq "changed target branch from `#{old_branch}` to `#{new_branch}`" + end + end + end + + describe '.change_branch_presence' do + subject { service.change_branch_presence(:source, 'feature', :delete) } + + it_behaves_like 'a system note' do + let(:action) { 'branch' } + end + + context 'when source branch deleted' do + it 'sets the note text' do + expect(subject.note).to eq "deleted source branch `feature`" + end + end + end + + describe '.new_issue_branch' do + let(:branch) { '1-mepmep' } + + subject { service.new_issue_branch(branch, branch_project: branch_project) } + + shared_examples_for 'a system note for new issue branch' do + it_behaves_like 'a system note' do + let(:action) { 'branch' } + end + + context 'when a branch is created from the new branch button' do + it 'sets the note text' do + expect(subject.note).to start_with("created branch [`#{branch}`]") + end + end + end + + context 'branch_project is set' do + let(:branch_project) { create(:project, :repository) } + + it_behaves_like 'a system note for new issue branch' + end + + context 'branch_project is not set' do + let(:branch_project) { nil } + + it_behaves_like 'a system note for new issue branch' + end + end + + describe '.new_merge_request' do + subject { service.new_merge_request(merge_request) } + + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: generate(:branch), target_project: project) } + + it_behaves_like 'a system note' do + let(:action) { 'merge' } + end + + it 'sets the new merge request note text' do + expect(subject.note).to eq("created merge request #{merge_request.to_reference(project)} to address this issue") + end + end +end diff --git a/spec/sidekiq/cron/job_gem_dependency_spec.rb b/spec/sidekiq/cron/job_gem_dependency_spec.rb index 2e7de75fd08..20347b4d306 100644 --- a/spec/sidekiq/cron/job_gem_dependency_spec.rb +++ b/spec/sidekiq/cron/job_gem_dependency_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Sidekiq::Cron::Job do diff --git a/spec/support/controllers/authorization_helpers.rb b/spec/support/controllers/authorization_helpers.rb new file mode 100644 index 00000000000..e1786e0ca8a --- /dev/null +++ b/spec/support/controllers/authorization_helpers.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +def forbid_controller_ability!(ability) + allow(controller).to receive(:can?).and_call_original + allow(controller).to receive(:can?).with(anything, ability, any_args).and_return(false) +end diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb index c57abbd96c6..2096ec90c5b 100644 --- a/spec/support/cycle_analytics_helpers/test_generation.rb +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -29,7 +29,7 @@ module CycleAnalyticsHelpers scenarios.each do |start_time_conditions, end_time_conditions| context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do - it "finds the median of available durations between the two conditions" do + it "finds the median of available durations between the two conditions", :sidekiq_might_not_need_inline do time_differences = Array.new(5) do |index| data = data_fn[self] start_time = (index * 10).days.from_now diff --git a/spec/support/helpers/capybara_helpers.rb b/spec/support/helpers/capybara_helpers.rb index a7baa7042c9..13ec179b734 100644 --- a/spec/support/helpers/capybara_helpers.rb +++ b/spec/support/helpers/capybara_helpers.rb @@ -46,4 +46,14 @@ module CapybaraHelpers def javascript_test? Capybara.current_driver == Capybara.javascript_driver end + + def scroll_to(element) + raise 'JS not available' unless javascript_test? + + script = <<-JS + arguments[0].scrollIntoView(true); + JS + + page.driver.browser.execute_script(script, element.native) + end end diff --git a/spec/support/helpers/dropzone_helper.rb b/spec/support/helpers/dropzone_helper.rb index a0f261b312e..3f37673dadd 100644 --- a/spec/support/helpers/dropzone_helper.rb +++ b/spec/support/helpers/dropzone_helper.rb @@ -14,6 +14,8 @@ module DropzoneHelper # If it's 'false', then the helper will NOT wait for backend response # It lets to test behaviors while AJAX is processing. def dropzone_file(files, max_file_size = 0, wait_for_queuecomplete = true) + # Assert that there is a dropzone to use (waiting until it is ready) + expect(page).to have_css('.div-dropzone') # Generate a fake file input that Capybara can attach to page.execute_script <<-JS.strip_heredoc $('#fakeFileInput').remove(); diff --git a/spec/support/helpers/git_helpers.rb b/spec/support/helpers/git_helpers.rb index 99c5871ba54..05e31a1154a 100644 --- a/spec/support/helpers/git_helpers.rb +++ b/spec/support/helpers/git_helpers.rb @@ -2,8 +2,11 @@ module GitHelpers def rugged_repo(repository) - path = File.join(TestEnv.repos_path, repository.disk_path + '.git') + rugged_repo_at_path(repository.disk_path + '.git') + end + def rugged_repo_at_path(relative_path) + path = File.join(TestEnv.repos_path, relative_path) Rugged::Repository.new(path) end end diff --git a/spec/support/helpers/smime_helper.rb b/spec/support/helpers/smime_helper.rb index 656b3e196ba..3ad19cd3da0 100644 --- a/spec/support/helpers/smime_helper.rb +++ b/spec/support/helpers/smime_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module SmimeHelper include OpenSSL diff --git a/spec/support/helpers/stub_experiments.rb b/spec/support/helpers/stub_experiments.rb index ed868e22c6e..7a5a188ab4d 100644 --- a/spec/support/helpers/stub_experiments.rb +++ b/spec/support/helpers/stub_experiments.rb @@ -9,7 +9,19 @@ module StubExperiments # - `stub_experiment(signup_flow: false)` ... Disable `signup_flow` experiment globally. def stub_experiment(experiments) experiments.each do |experiment_key, enabled| - allow(Gitlab::Experimentation).to receive(:enabled?).with(experiment_key, any_args) { enabled } + allow(Gitlab::Experimentation).to receive(:enabled?).with(experiment_key) { enabled } + end + end + + # Stub Experiment for user with `key: true/false` + # + # @param [Hash] experiment where key is feature name and value is boolean whether enabled or not. + # + # Examples + # - `stub_experiment_for_user(signup_flow: false)` ... Disable `signup_flow` experiment for user. + def stub_experiment_for_user(experiments) + experiments.each do |experiment_key, enabled| + allow(Gitlab::Experimentation).to receive(:enabled_for_user?).with(experiment_key, anything) { enabled } end end end diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index a409dd2ef26..538380a625c 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -243,6 +243,22 @@ module TestEnv FileUtils.chmod_R 0755, target_repo_path end + def rm_storage_dir(storage, dir) + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repos_path = Gitlab.config.repositories.storages[storage].legacy_disk_path + target_repo_refs_path = File.join(repos_path, dir) + FileUtils.remove_dir(target_repo_refs_path) + end + rescue Errno::ENOENT + end + + def storage_dir_exists?(storage, dir) + Gitlab::GitalyClient::StorageSettings.allow_disk_access do + repos_path = Gitlab.config.repositories.storages[storage].legacy_disk_path + File.exist?(File.join(repos_path, dir)) + end + end + def create_bare_repository(path) FileUtils.mkdir_p(path) diff --git a/spec/support/helpers/wiki_helpers.rb b/spec/support/helpers/wiki_helpers.rb index 06cea728b42..0cf70fd4ef7 100644 --- a/spec/support/helpers/wiki_helpers.rb +++ b/spec/support/helpers/wiki_helpers.rb @@ -12,4 +12,10 @@ module WikiHelpers ::Wikis::CreateAttachmentService.new(project, user, opts) .execute[:result][:file_path] end + + # Generate the form field name for a given attribute of an object. + # This is rather general, but is currently only used in the wiki featur tests. + def form_field_name(obj, attr_name) + "#{ActiveModel::Naming.param_key(obj)}[#{attr_name}]" + end end diff --git a/spec/support/matchers/issuable_matchers.rb b/spec/support/matchers/issuable_matchers.rb index 743f0b8c932..ab15a80bf60 100644 --- a/spec/support/matchers/issuable_matchers.rb +++ b/spec/support/matchers/issuable_matchers.rb @@ -2,7 +2,8 @@ RSpec::Matchers.define :have_header_with_correct_id_and_link do |level, text, id, parent = ".md"| match do |actual| - node = find("#{parent} h#{level} a#user-content-#{id}") + # anchors may be invisible + node = find("#{parent} h#{level} a#user-content-#{id}", visible: false) expect(node[:href]).to end_with("##{id}") diff --git a/spec/support/shared_examples/file_finder.rb b/spec/support/shared_examples/file_finder.rb index 984a06ccd1a..f4b28b94090 100644 --- a/spec/support/shared_examples/file_finder.rb +++ b/spec/support/shared_examples/file_finder.rb @@ -4,19 +4,19 @@ shared_examples 'file finder' do let(:query) { 'files' } let(:search_results) { subject.find(query) } - it 'finds by name' do - blob = search_results.find { |blob| blob.filename == expected_file_by_name } + it 'finds by path' do + blob = search_results.find { |blob| blob.path == expected_file_by_path } - expect(blob.filename).to eq(expected_file_by_name) + expect(blob.path).to eq(expected_file_by_path) expect(blob).to be_a(Gitlab::Search::FoundBlob) expect(blob.ref).to eq(subject.ref) expect(blob.data).not_to be_empty end it 'finds by content' do - blob = search_results.find { |blob| blob.filename == expected_file_by_content } + blob = search_results.find { |blob| blob.path == expected_file_by_content } - expect(blob.filename).to eq(expected_file_by_content) + expect(blob.path).to eq(expected_file_by_content) expect(blob).to be_a(Gitlab::Search::FoundBlob) expect(blob.ref).to eq(subject.ref) expect(blob.data).not_to be_empty diff --git a/spec/support/shared_examples/models/with_uploads_shared_examples.rb b/spec/support/shared_examples/models/with_uploads_shared_examples.rb index 822836c771e..3d622ba8195 100644 --- a/spec/support/shared_examples/models/with_uploads_shared_examples.rb +++ b/spec/support/shared_examples/models/with_uploads_shared_examples.rb @@ -18,7 +18,7 @@ shared_examples_for 'model with uploads' do |supports_fileuploads| end end - context 'with not mounted uploads', :sidekiq, skip: !supports_fileuploads do + context 'with not mounted uploads', :sidekiq_might_not_need_inline, skip: !supports_fileuploads do context 'with local files' do let!(:uploads) { create_list(:upload, 2, uploader: FileUploader, model: model_object) } 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 index ac7c17915de..a77d729aa2c 100644 --- 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 @@ -7,7 +7,7 @@ shared_examples 'merge quick action' do visit project_merge_request_path(project, merge_request) end - it 'merges the MR' do + it 'merges the MR', :sidekiq_might_not_need_inline do add_note("/merge") expect(page).to have_content 'Scheduled to merge this merge request when the pipeline succeeds.' diff --git a/spec/support/shared_examples/requests/api/notes.rb b/spec/support/shared_examples/requests/api/notes.rb index 354ae7288b1..4ce78d885bc 100644 --- a/spec/support/shared_examples/requests/api/notes.rb +++ b/spec/support/shared_examples/requests/api/notes.rb @@ -139,7 +139,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name| expect(response).to have_gitlab_http_status(401) end - it "creates an activity event when a note is created" do + it "creates an activity event when a note is created", :sidekiq_might_not_need_inline do expect(Event).to receive(:create!) post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: { body: 'hi!' } diff --git a/spec/support/shared_examples/updating_mentions_shared_examples.rb b/spec/support/shared_examples/updating_mentions_shared_examples.rb index 9a8f8012762..3295ab72987 100644 --- a/spec/support/shared_examples/updating_mentions_shared_examples.rb +++ b/spec/support/shared_examples/updating_mentions_shared_examples.rb @@ -27,7 +27,7 @@ RSpec.shared_examples 'updating mentions' do |service_class| update_mentionable(title: "For #{mentioned_user.to_reference}") end - it 'emails only the newly-mentioned user' do + it 'emails only the newly-mentioned user', :sidekiq_might_not_need_inline do should_only_email(mentioned_user) end end @@ -37,7 +37,7 @@ RSpec.shared_examples 'updating mentions' do |service_class| update_mentionable(description: "For #{mentioned_user.to_reference}") end - it 'emails only the newly-mentioned user' do + it 'emails only the newly-mentioned user', :sidekiq_might_not_need_inline do should_only_email(mentioned_user) end end @@ -51,7 +51,7 @@ RSpec.shared_examples 'updating mentions' do |service_class| ) end - it 'emails group members' do + it 'emails group members', :sidekiq_might_not_need_inline do should_email(mentioned_user) should_email(group_member1) should_email(group_member2) @@ -81,7 +81,7 @@ RSpec.shared_examples 'updating mentions' do |service_class| ) end - it 'emails mentioned user' do + it 'emails mentioned user', :sidekiq_might_not_need_inline do should_only_email(mentioned_user) end end diff --git a/spec/support/shared_examples/wiki_file_attachments_examples.rb b/spec/support/shared_examples/wiki_file_attachments_examples.rb index 22fbfb48928..a43b7c0300f 100644 --- a/spec/support/shared_examples/wiki_file_attachments_examples.rb +++ b/spec/support/shared_examples/wiki_file_attachments_examples.rb @@ -42,7 +42,7 @@ shared_examples 'wiki file attachments' do end end - context 'uploading is complete', :quarantine do + context 'uploading is complete' do it 'shows "Attach a file" button on uploading complete' do attach_with_dropzone wait_for_requests @@ -52,11 +52,11 @@ shared_examples 'wiki file attachments' do end it 'the markdown link is added to the page' do - fill_in(:wiki_content, with: '') + fill_in(:wiki_page_content, with: '') attach_with_dropzone(true) wait_for_requests - expect(page.find('#wiki_content').value) + expect(page.find('#wiki_page_content').value) .to match(%r{\!\[dk\]\(uploads/\h{32}/dk\.png\)$}) end @@ -70,7 +70,7 @@ shared_examples 'wiki file attachments' do img_link = page.find('a.no-attachment-icon img')['src'] expect(link).to eq img_link - expect(URI.parse(link).path).to eq File.join(wiki.wiki_base_path, file_path) + expect(URI.parse(link).path).to eq File.join(wiki.wiki_page_path, file_path) end it 'the file has been added to the wiki repository' do diff --git a/spec/support/sidekiq.rb b/spec/support/sidekiq.rb index 585c458a64e..246efedc7e5 100644 --- a/spec/support/sidekiq.rb +++ b/spec/support/sidekiq.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'sidekiq/testing/inline' +require 'sidekiq/testing' # If Sidekiq::Testing.inline! is used, SQL transactions done inside # Sidekiq worker are included in the SQL query limit (in a real @@ -27,7 +27,9 @@ Sidekiq::Testing.server_middleware do |chain| end RSpec.configure do |config| - config.after(:each, :sidekiq) do + config.around(:each, :sidekiq) do |example| + Sidekiq::Worker.clear_all + example.run Sidekiq::Worker.clear_all end @@ -36,4 +38,19 @@ RSpec.configure do |config| connection.redis.flushdb end end + + # As we'll review the examples with this tag, we should either: + # - fix the example to not require Sidekiq inline mode (and remove this tag) + # - explicitly keep the inline mode and change the tag for `:sidekiq_inline` instead + config.around(:example, :sidekiq_might_not_need_inline) do |example| + Sidekiq::Worker.clear_all + Sidekiq::Testing.inline! { example.run } + Sidekiq::Worker.clear_all + end + + config.around(:example, :sidekiq_inline) do |example| + Sidekiq::Worker.clear_all + Sidekiq::Testing.inline! { example.run } + Sidekiq::Worker.clear_all + end end diff --git a/spec/uploaders/workers/object_storage/background_move_worker_spec.rb b/spec/uploaders/workers/object_storage/background_move_worker_spec.rb index cf4872d6904..38b70d33993 100644 --- a/spec/uploaders/workers/object_storage/background_move_worker_spec.rb +++ b/spec/uploaders/workers/object_storage/background_move_worker_spec.rb @@ -22,7 +22,7 @@ describe ObjectStorage::BackgroundMoveWorker do stub_lfs_object_storage(background_upload: true) end - it 'uploads object to storage' do + it 'uploads object to storage', :sidekiq_might_not_need_inline do expect { perform }.to change { lfs_object.reload.file_store }.from(local).to(remote) end @@ -65,7 +65,7 @@ describe ObjectStorage::BackgroundMoveWorker do stub_artifacts_object_storage(background_upload: true) end - it "migrates file to remote storage" do + it "migrates file to remote storage", :sidekiq_might_not_need_inline do perform expect(artifact.reload.file_store).to eq(remote) @@ -91,7 +91,7 @@ describe ObjectStorage::BackgroundMoveWorker do let(:subject_class) { project.class } let(:subject_id) { project.id } - it "migrates file to remote storage" do + it "migrates file to remote storage", :sidekiq_might_not_need_inline do perform project.reload BatchLoader::Executor.clear_current @@ -104,7 +104,7 @@ describe ObjectStorage::BackgroundMoveWorker do let(:subject_class) { Upload } let(:subject_id) { project.avatar.upload.id } - it "migrates file to remote storage" do + it "migrates file to remote storage", :sidekiq_might_not_need_inline do perform expect(project.reload.avatar).not_to be_file_storage diff --git a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb index 71d74b06f85..755a40a7e4c 100644 --- a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe 'projects/merge_requests/_commits.html.haml' do +describe 'projects/merge_requests/_commits.html.haml', :sidekiq_might_not_need_inline do include Devise::Test::ControllerHelpers include ProjectForksHelper diff --git a/spec/workers/hashed_storage/migrator_worker_spec.rb b/spec/workers/hashed_storage/migrator_worker_spec.rb index 12c1a26104e..9180da87058 100644 --- a/spec/workers/hashed_storage/migrator_worker_spec.rb +++ b/spec/workers/hashed_storage/migrator_worker_spec.rb @@ -15,7 +15,7 @@ describe HashedStorage::MigratorWorker do worker.perform(5, 10) end - it 'migrates projects in the specified range' do + it 'migrates projects in the specified range', :sidekiq_might_not_need_inline do perform_enqueued_jobs do worker.perform(ids.min, ids.max) end diff --git a/spec/workers/hashed_storage/rollbacker_worker_spec.rb b/spec/workers/hashed_storage/rollbacker_worker_spec.rb index 5fcb1adf9ae..3ca2601df0f 100644 --- a/spec/workers/hashed_storage/rollbacker_worker_spec.rb +++ b/spec/workers/hashed_storage/rollbacker_worker_spec.rb @@ -15,7 +15,7 @@ describe HashedStorage::RollbackerWorker do worker.perform(5, 10) end - it 'rollsback projects in the specified range' do + it 'rollsback projects in the specified range', :sidekiq_might_not_need_inline do perform_enqueued_jobs do worker.perform(ids.min, ids.max) end diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb index 9326db34209..4926c14a6ab 100644 --- a/spec/workers/pipeline_schedule_worker_spec.rb +++ b/spec/workers/pipeline_schedule_worker_spec.rb @@ -28,7 +28,7 @@ describe PipelineScheduleWorker do context 'when there is a scheduled pipeline within next_run_at' do shared_examples 'successful scheduling' do - it 'creates a new pipeline' do + it 'creates a new pipeline', :sidekiq_might_not_need_inline do expect { subject }.to change { project.ci_pipelines.count }.by(1) expect(Ci::Pipeline.last).to be_schedule diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index 7f3c4881b89..fa02762d716 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -105,7 +105,7 @@ describe ProjectCacheWorker do end context 'when a lease could be obtained' do - it 'updates the project statistics twice' do + it 'updates the project statistics twice', :sidekiq_might_not_need_inline do stub_exclusive_lease(lease_key, timeout: lease_timeout) expect(Projects::UpdateStatisticsService).to receive(:new) diff --git a/spec/workers/repository_check/single_repository_worker_spec.rb b/spec/workers/repository_check/single_repository_worker_spec.rb index 65e1c5e9d5d..6870e15424f 100644 --- a/spec/workers/repository_check/single_repository_worker_spec.rb +++ b/spec/workers/repository_check/single_repository_worker_spec.rb @@ -68,7 +68,7 @@ describe RepositoryCheck::SingleRepositoryWorker do it 'creates missing wikis' do project = create(:project, :wiki_enabled) - Gitlab::Shell.new.rm_directory(project.repository_storage, project.wiki.path) + TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path) subject.perform(project.id) @@ -77,12 +77,12 @@ describe RepositoryCheck::SingleRepositoryWorker do it 'does not create a wiki if the main repo does not exist at all' do project = create(:project, :repository) - Gitlab::Shell.new.rm_directory(project.repository_storage, project.path) - Gitlab::Shell.new.rm_directory(project.repository_storage, project.wiki.path) + TestEnv.rm_storage_dir(project.repository_storage, project.path) + TestEnv.rm_storage_dir(project.repository_storage, project.wiki.path) subject.perform(project.id) - expect(Gitlab::Shell.new.exists?(project.repository_storage, project.wiki.path)).to eq(false) + expect(TestEnv.storage_dir_exists?(project.repository_storage, project.wiki.path)).to eq(false) end def create_push_event(project) diff --git a/spec/workers/stuck_merge_jobs_worker_spec.rb b/spec/workers/stuck_merge_jobs_worker_spec.rb index 09efed6d2cf..8ceaf1fc555 100644 --- a/spec/workers/stuck_merge_jobs_worker_spec.rb +++ b/spec/workers/stuck_merge_jobs_worker_spec.rb @@ -22,7 +22,7 @@ describe StuckMergeJobsWorker do expect(mr_without_sha.merge_jid).to be_nil end - it 'updates merge request to opened when locked but has not been merged' do + it 'updates merge request to opened when locked but has not been merged', :sidekiq_might_not_need_inline do allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return(%w(123)) merge_request = create(:merge_request, :locked, merge_jid: '123', state: :locked) pipeline = create(:ci_empty_pipeline, project: merge_request.project, ref: merge_request.source_branch, sha: merge_request.source_branch_sha) |