diff options
author | James Edwards-Jones <jedwardsjones@gitlab.com> | 2017-02-03 17:25:26 +0000 |
---|---|---|
committer | James Edwards-Jones <jedwardsjones@gitlab.com> | 2017-02-03 17:25:26 +0000 |
commit | 1af3f3b673be8f85b37d455b101954e62c2a3add (patch) | |
tree | 56f09bef2ca41964fae3efaf4f15be7fe1640ba4 /spec | |
parent | 67c8526033241f6bd190fa16622970b3919e6dbd (diff) | |
parent | bd8f2b15b3d5267075a626ce86f3a06cc650fcbf (diff) | |
download | gitlab-ce-1af3f3b673be8f85b37d455b101954e62c2a3add.tar.gz |
Merge branch 'master' into jej-pages-picked-from-ee
Diffstat (limited to 'spec')
96 files changed, 1474 insertions, 549 deletions
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb index 32b0e42c3cd..19e948d8fb8 100644 --- a/spec/controllers/projects/snippets_controller_spec.rb +++ b/spec/controllers/projects/snippets_controller_spec.rb @@ -6,8 +6,8 @@ describe Projects::SnippetsController do let(:user2) { create(:user) } before do - project.team << [user, :master] - project.team << [user2, :master] + project.add_master(user) + project.add_master(user2) end describe 'GET #index' do @@ -69,6 +69,86 @@ describe Projects::SnippetsController do end end + describe 'POST #create' do + def create_snippet(project, snippet_params = {}) + sign_in(user) + + project.add_developer(user) + + post :create, { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + project_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) + } + end + + context 'when the snippet is spam' do + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the project is private' do + let(:private_project) { create(:project_empty_repo, :private) } + + context 'when the snippet is public' do + it 'creates the snippet' do + expect { create_snippet(private_project, visibility_level: Snippet::PUBLIC) }. + to change { Snippet.count }.by(1) + end + end + end + + context 'when the project is public' do + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) + end + end + + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + expect(response).to render_template(:new) + end + + it 'creates a spam log' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end + end + end + + describe 'POST #mark_as_spam' do + let(:snippet) { create(:project_snippet, :private, project: project, author: user) } + + before do + allow_any_instance_of(AkismetService).to receive_messages(submit_spam: true) + stub_application_setting(akismet_enabled: true) + end + + def mark_as_spam + admin = create(:admin) + create(:user_agent_detail, subject: snippet) + project.add_master(admin) + sign_in(admin) + + post :mark_as_spam, + namespace_id: project.namespace.path, + project_id: project.path, + id: snippet.id + end + + it 'updates the snippet' do + mark_as_spam + + expect(snippet.reload).not_to be_submittable_as_spam + end + end + %w[show raw].each do |action| describe "GET ##{action}" do context 'when the project snippet is private' do diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb index 99d0bcfa8d1..80f84a388ce 100644 --- a/spec/controllers/projects/templates_controller_spec.rb +++ b/spec/controllers/projects/templates_controller_spec.rb @@ -14,7 +14,8 @@ describe Projects::TemplatesController do before do project.add_user(user, Gitlab::Access::MASTER) - project.repository.commit_file(user, file_path_1, "something valid", "test 3", "master", false) + project.repository.commit_file(user, file_path_1, 'something valid', + message: 'test 3', branch_name: 'master', update: false) end describe '#show' do diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index d76fe9f580f..dadcb90cfc2 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -138,6 +138,65 @@ describe SnippetsController do end end + describe 'POST #create' do + def create_snippet(snippet_params = {}) + sign_in(user) + + post :create, { + personal_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) + } + end + + context 'when the snippet is spam' do + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) + end + end + + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + expect(response).to render_template(:new) + end + + it 'creates a spam log' do + expect { create_snippet(visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end + end + + describe 'POST #mark_as_spam' do + let(:snippet) { create(:personal_snippet, :public, author: user) } + + before do + allow_any_instance_of(AkismetService).to receive_messages(submit_spam: true) + stub_application_setting(akismet_enabled: true) + end + + def mark_as_spam + admin = create(:admin) + create(:user_agent_detail, subject: snippet) + sign_in(admin) + + post :mark_as_spam, id: snippet.id + end + + it 'updates the snippet' do + mark_as_spam + + expect(snippet.reload).not_to be_submittable_as_spam + end + end + %w(raw download).each do |action| describe "GET #{action}" do context 'when the personal snippet is private' do diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 992580a6b34..715b2a27b30 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -106,6 +106,42 @@ FactoryGirl.define do path { 'gitlabhq' } test_repo + + transient do + create_template nil + end + + after :create do |project, evaluator| + TestEnv.copy_repo(project) + + if evaluator.create_template + args = evaluator.create_template + + project.add_user(args[:user], args[:access]) + + project.repository.commit_file( + args[:user], + ".gitlab/#{args[:path]}/bug.md", + 'something valid', + message: 'test 3', + branch_name: 'master', + update: false) + project.repository.commit_file( + args[:user], + ".gitlab/#{args[:path]}/template_test.md", + 'template_test', + message: 'test 1', + branch_name: 'master', + update: false) + project.repository.commit_file( + args[:user], + ".gitlab/#{args[:path]}/feature_proposal.md", + 'feature_proposal', + message: 'test 2', + branch_name: 'master', + update: false) + end + end end factory :forked_project_with_submodules, parent: :empty_project do diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index e177059d959..9d5ce876c29 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -9,8 +9,8 @@ describe 'Admin Builds' do let(:pipeline) { create(:ci_pipeline) } context 'All tab' do - context 'when have builds' do - it 'shows all builds' do + context 'when have jobs' do + it 'shows all jobs' do create(:ci_build, pipeline: pipeline, status: :pending) create(:ci_build, pipeline: pipeline, status: :running) create(:ci_build, pipeline: pipeline, status: :success) @@ -19,26 +19,26 @@ describe 'Admin Builds' do visit admin_builds_path expect(page).to have_selector('.nav-links li.active', text: 'All') - expect(page).to have_selector('.row-content-block', text: 'All builds') + expect(page).to have_selector('.row-content-block', text: 'All jobs') expect(page.all('.build-link').size).to eq(4) expect(page).to have_link 'Cancel all' end end - context 'when have no builds' do + context 'when have no jobs' do it 'shows a message' do visit admin_builds_path expect(page).to have_selector('.nav-links li.active', text: 'All') - expect(page).to have_content 'No builds to show' + expect(page).to have_content 'No jobs to show' expect(page).not_to have_link 'Cancel all' end end end context 'Pending tab' do - context 'when have pending builds' do - it 'shows pending builds' do + context 'when have pending jobs' do + it 'shows pending jobs' do build1 = create(:ci_build, pipeline: pipeline, status: :pending) build2 = create(:ci_build, pipeline: pipeline, status: :running) build3 = create(:ci_build, pipeline: pipeline, status: :success) @@ -55,22 +55,22 @@ describe 'Admin Builds' do end end - context 'when have no builds pending' do + context 'when have no jobs pending' do it 'shows a message' do create(:ci_build, pipeline: pipeline, status: :success) visit admin_builds_path(scope: :pending) expect(page).to have_selector('.nav-links li.active', text: 'Pending') - expect(page).to have_content 'No builds to show' + expect(page).to have_content 'No jobs to show' expect(page).not_to have_link 'Cancel all' end end end context 'Running tab' do - context 'when have running builds' do - it 'shows running builds' do + context 'when have running jobs' do + it 'shows running jobs' do build1 = create(:ci_build, pipeline: pipeline, status: :running) build2 = create(:ci_build, pipeline: pipeline, status: :success) build3 = create(:ci_build, pipeline: pipeline, status: :failed) @@ -87,22 +87,22 @@ describe 'Admin Builds' do end end - context 'when have no builds running' do + context 'when have no jobs running' do it 'shows a message' do create(:ci_build, pipeline: pipeline, status: :success) visit admin_builds_path(scope: :running) expect(page).to have_selector('.nav-links li.active', text: 'Running') - expect(page).to have_content 'No builds to show' + expect(page).to have_content 'No jobs to show' expect(page).not_to have_link 'Cancel all' end end end context 'Finished tab' do - context 'when have finished builds' do - it 'shows finished builds' do + context 'when have finished jobs' do + it 'shows finished jobs' do build1 = create(:ci_build, pipeline: pipeline, status: :pending) build2 = create(:ci_build, pipeline: pipeline, status: :running) build3 = create(:ci_build, pipeline: pipeline, status: :success) @@ -117,14 +117,14 @@ describe 'Admin Builds' do end end - context 'when have no builds finished' do + context 'when have no jobs finished' do it 'shows a message' do create(:ci_build, pipeline: pipeline, status: :running) visit admin_builds_path(scope: :finished) expect(page).to have_selector('.nav-links li.active', text: 'Finished') - expect(page).to have_content 'No builds to show' + expect(page).to have_content 'No jobs to show' expect(page).to have_link 'Cancel all' end end diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb new file mode 100644 index 00000000000..d9be4e5dbdd --- /dev/null +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +feature 'Dashboard shortcuts', feature: true, js: true do + before do + login_as :user + visit dashboard_projects_path + end + + scenario 'Navigate to tabs' do + find('body').native.send_key('g') + find('body').native.send_key('p') + + ensure_active_main_tab('Projects') + + find('body').native.send_key('g') + find('body').native.send_key('i') + + ensure_active_main_tab('Issues') + + find('body').native.send_key('g') + find('body').native.send_key('m') + + ensure_active_main_tab('Merge Requests') + end + + def ensure_active_main_tab(content) + expect(find('.nav-sidebar li.active')).to have_content(content) + end +end diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 31156fcf994..93139dc9e94 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' feature 'GFM autocomplete', feature: true, js: true do include WaitForAjax - let(:user) { create(:user, username: 'someone.special') } + let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } let(:project) { create(:project) } let(:label) { create(:label, project: project, title: 'special+') } let(:issue) { create(:issue, project: project) } @@ -59,6 +59,19 @@ feature 'GFM autocomplete', feature: true, js: true do expect(find('#at-view-64')).to have_selector('.cur:first-of-type') end + it 'includes items for assignee dropdowns with non-ASCII characters in name' do + page.within '.timeline-content-form' do + find('#note_note').native.send_keys('') + find('#note_note').native.send_keys("@#{user.name[0...8]}") + end + + expect(page).to have_selector('.atwho-container') + + wait_for_ajax + + expect(find('#at-view-64')).to have_content(user.name) + end + it 'selects the first item for non-assignee dropdowns if a query is entered' do page.within '.timeline-content-form' do find('#note_note').native.send_keys('') diff --git a/spec/features/issues/group_label_sidebar_spec.rb b/spec/features/issues/group_label_sidebar_spec.rb new file mode 100644 index 00000000000..fc8515cfe9b --- /dev/null +++ b/spec/features/issues/group_label_sidebar_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +describe 'Group label on issue', :feature do + it 'renders link to the project issues page' do + group = create(:group) + project = create(:empty_project, :public, namespace: group) + feature = create(:group_label, group: group, title: 'feature') + issue = create(:labeled_issue, project: project, labels: [feature]) + label_link = namespace_project_issues_path( + project.namespace, + project, + label_name: [feature.name] + ) + + visit namespace_project_issue_path(project.namespace, project, issue) + + link = find('.issuable-show-labels a') + + expect(link[:href]).to eq(label_link) + end +end diff --git a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb index 7e2907cd26f..d2f5c4afc93 100644 --- a/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb +++ b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb @@ -50,7 +50,7 @@ feature 'Only allow merge requests to be merged if the build succeeds', feature: visit_merge_request(merge_request) expect(page).not_to have_button 'Accept Merge Request' - expect(page).to have_content('Please retry the build or push a new commit to fix the failure.') + expect(page).to have_content('Please retry the job or push a new commit to fix the failure.') end end @@ -61,7 +61,7 @@ feature 'Only allow merge requests to be merged if the build succeeds', feature: visit_merge_request(merge_request) expect(page).not_to have_button 'Accept Merge Request' - expect(page).to have_content('Please retry the build or push a new commit to fix the failure.') + expect(page).to have_content('Please retry the job or push a new commit to fix the failure.') end end diff --git a/spec/features/merge_requests/toggler_behavior_spec.rb b/spec/features/merge_requests/toggler_behavior_spec.rb new file mode 100644 index 00000000000..44a9b545ff8 --- /dev/null +++ b/spec/features/merge_requests/toggler_behavior_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +feature 'toggler_behavior', js: true, feature: true do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:merge_request) { create(:merge_request, source_project: project, author: user) } + let(:note) { create(:diff_note_on_merge_request, noteable: merge_request, project: project) } + let(:fragment_id) { "#note_#{note.id}" } + + before do + login_as :admin + project = merge_request.source_project + visit "#{namespace_project_merge_request_path(project.namespace, project, merge_request)}#{fragment_id}" + page.current_window.resize_to(1000, 300) + end + + describe 'scroll position' do + it 'should be scrolled down to fragment' do + page_height = page.current_window.size[1] + page_scroll_y = page.evaluate_script("window.scrollY") + fragment_position_top = page.evaluate_script("$('#{fragment_id}').offset().top") + expect(find('.js-toggle-content').visible?).to eq true + expect(find(fragment_id).visible?).to eq true + expect(fragment_position_top).to be >= page_scroll_y + expect(fragment_position_top).to be < (page_scroll_y + page_height) + end + end +end diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index b785b2f7704..fab2d532e06 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -89,7 +89,7 @@ describe 'Comments', feature: true do end end - it 'should reset the edit note form textarea with the original content of the note if cancelled' do + it 'resets the edit note form textarea with the original content of the note if cancelled' do within('.current-note-edit-form') do fill_in 'note[note]', with: 'Some new content' find('.btn-cancel').click @@ -198,7 +198,7 @@ describe 'Comments', feature: true do end describe 'the note form' do - it "shouldn't add a second form for same row" do + it "does not add a second form for same row" do click_diff_line is_expected. @@ -206,7 +206,7 @@ describe 'Comments', feature: true do count: 1) end - it 'should be removed when canceled' do + it 'is removed when canceled' do is_expected.to have_css('.js-temp-notes-holder') page.within("form[data-line-code='#{line_code}']") do diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index 11d27feab0b..f7e0115643e 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -27,7 +27,7 @@ feature 'Builds', :feature do visit namespace_project_builds_path(project.namespace, project, scope: :pending) end - it "shows Pending tab builds" do + it "shows Pending tab jobs" do expect(page).to have_link 'Cancel running' expect(page).to have_selector('.nav-links li.active', text: 'Pending') expect(page).to have_content build.short_sha @@ -42,7 +42,7 @@ feature 'Builds', :feature do visit namespace_project_builds_path(project.namespace, project, scope: :running) end - it "shows Running tab builds" do + it "shows Running tab jobs" do expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page).to have_link 'Cancel running' expect(page).to have_content build.short_sha @@ -57,20 +57,20 @@ feature 'Builds', :feature do visit namespace_project_builds_path(project.namespace, project, scope: :finished) end - it "shows Finished tab builds" do + it "shows Finished tab jobs" do expect(page).to have_selector('.nav-links li.active', text: 'Finished') - expect(page).to have_content 'No builds to show' + expect(page).to have_content 'No jobs to show' expect(page).to have_link 'Cancel running' end end - context "All builds" do + context "All jobs" do before do project.builds.running_or_pending.each(&:success) visit namespace_project_builds_path(project.namespace, project) end - it "shows All tab builds" do + it "shows All tab jobs" do expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_content build.short_sha expect(page).to have_content build.ref @@ -98,7 +98,7 @@ feature 'Builds', :feature do end describe "GET /:project/builds/:id" do - context "Build from project" do + context "Job from project" do before do visit namespace_project_build_path(project.namespace, project, build) end @@ -111,7 +111,7 @@ feature 'Builds', :feature do end end - context "Build from other project" do + context "Job from other project" do before do visit namespace_project_build_path(project.namespace, project, build2) end @@ -149,7 +149,7 @@ feature 'Builds', :feature do context 'when expire date is defined' do let(:expire_at) { Time.now + 7.days } - context 'when user has ability to update build' do + context 'when user has ability to update job' do it 'keeps artifacts when keep button is clicked' do expect(page).to have_content 'The artifacts will be removed' @@ -160,7 +160,7 @@ feature 'Builds', :feature do end end - context 'when user does not have ability to update build' do + context 'when user does not have ability to update job' do let(:user_access_level) { :guest } it 'does not have keep button' do @@ -197,8 +197,8 @@ feature 'Builds', :feature do visit namespace_project_build_path(project.namespace, project, build) end - context 'when build has an initial trace' do - it 'loads build trace' do + context 'when job has an initial trace' do + it 'loads job trace' do expect(page).to have_content 'BUILD TRACE' build.append_trace(' and more trace', 11) @@ -242,32 +242,32 @@ feature 'Builds', :feature do end end - context 'when build starts environment' do + context 'when job starts environment' do let(:environment) { create(:environment, project: project) } let(:pipeline) { create(:ci_pipeline, project: project) } - context 'build is successfull and has deployment' do + context 'job is successfull and has deployment' do let(:deployment) { create(:deployment) } let(:build) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) } - it 'shows a link for the build' do + it 'shows a link for the job' do visit namespace_project_build_path(project.namespace, project, build) expect(page).to have_link environment.name end end - context 'build is complete and not successfull' do + context 'job is complete and not successfull' do let(:build) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) } - it 'shows a link for the build' do + it 'shows a link for the job' do visit namespace_project_build_path(project.namespace, project, build) expect(page).to have_link environment.name end end - context 'build creates a new deployment' do + context 'job creates a new deployment' do let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) } let(:build) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } @@ -281,7 +281,7 @@ feature 'Builds', :feature do end describe "POST /:project/builds/:id/cancel" do - context "Build from project" do + context "Job from project" do before do build.run! visit namespace_project_build_path(project.namespace, project, build) @@ -295,7 +295,7 @@ feature 'Builds', :feature do end end - context "Build from other project" do + context "Job from other project" do before do build.run! visit namespace_project_build_path(project.namespace, project, build) @@ -307,13 +307,13 @@ feature 'Builds', :feature do end describe "POST /:project/builds/:id/retry" do - context "Build from project" do + context "Job from project" do before do build.run! visit namespace_project_build_path(project.namespace, project, build) click_link 'Cancel' page.within('.build-header') do - click_link 'Retry build' + click_link 'Retry job' end end diff --git a/spec/features/projects/files/editing_a_file_spec.rb b/spec/features/projects/files/editing_a_file_spec.rb index fe047e00409..36a80d7575d 100644 --- a/spec/features/projects/files/editing_a_file_spec.rb +++ b/spec/features/projects/files/editing_a_file_spec.rb @@ -7,7 +7,7 @@ feature 'User wants to edit a file', feature: true do let(:user) { create(:user) } let(:commit_params) do { - source_branch: project.default_branch, + start_branch: project.default_branch, target_branch: project.default_branch, commit_message: "Committing First Update", file_path: ".gitignore", diff --git a/spec/features/projects/files/project_owner_creates_license_file_spec.rb b/spec/features/projects/files/project_owner_creates_license_file_spec.rb index a521ce50f35..64094af29c0 100644 --- a/spec/features/projects/files/project_owner_creates_license_file_spec.rb +++ b/spec/features/projects/files/project_owner_creates_license_file_spec.rb @@ -6,7 +6,8 @@ feature 'project owner creates a license file', feature: true, js: true do let(:project_master) { create(:user) } let(:project) { create(:project) } background do - project.repository.remove_file(project_master, 'LICENSE', 'Remove LICENSE', 'master') + project.repository.remove_file(project_master, 'LICENSE', + message: 'Remove LICENSE', branch_name: 'master') project.team << [project_master, :master] login_as(project_master) visit namespace_project_path(project.namespace, project) diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index 6dae5c64b30..e90a033b8c4 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -18,8 +18,20 @@ feature 'issuable templates', feature: true, js: true do let(:description_addition) { ' appending to description' } background do - project.repository.commit_file(user, '.gitlab/issue_templates/bug.md', template_content, 'added issue template', 'master', false) - project.repository.commit_file(user, '.gitlab/issue_templates/test.md', longtemplate_content, 'added issue template', 'master', false) + project.repository.commit_file( + user, + '.gitlab/issue_templates/bug.md', + template_content, + message: 'added issue template', + branch_name: 'master', + update: false) + project.repository.commit_file( + user, + '.gitlab/issue_templates/test.md', + longtemplate_content, + message: 'added issue template', + branch_name: 'master', + update: false) visit edit_namespace_project_issue_path project.namespace, project, issue fill_in :'issue[title]', with: 'test issue title' end @@ -67,7 +79,13 @@ feature 'issuable templates', feature: true, js: true do let(:issue) { create(:issue, author: user, assignee: user, project: project) } background do - project.repository.commit_file(user, '.gitlab/issue_templates/bug.md', template_content, 'added issue template', 'master', false) + project.repository.commit_file( + user, + '.gitlab/issue_templates/bug.md', + template_content, + message: 'added issue template', + branch_name: 'master', + update: false) visit edit_namespace_project_issue_path project.namespace, project, issue fill_in :'issue[title]', with: 'test issue title' fill_in :'issue[description]', with: prior_description @@ -86,7 +104,13 @@ feature 'issuable templates', feature: true, js: true do let(:merge_request) { create(:merge_request, :with_diffs, source_project: project) } background do - project.repository.commit_file(user, '.gitlab/merge_request_templates/feature-proposal.md', template_content, 'added merge request template', 'master', false) + project.repository.commit_file( + user, + '.gitlab/merge_request_templates/feature-proposal.md', + template_content, + message: 'added merge request template', + branch_name: 'master', + update: false) visit edit_namespace_project_merge_request_path project.namespace, project, merge_request fill_in :'merge_request[title]', with: 'test merge request title' end @@ -111,7 +135,13 @@ feature 'issuable templates', feature: true, js: true do fork_project.team << [fork_user, :master] create(:forked_project_link, forked_to_project: fork_project, forked_from_project: project) login_as fork_user - project.repository.commit_file(fork_user, '.gitlab/merge_request_templates/feature-proposal.md', template_content, 'added merge request template', 'master', false) + project.repository.commit_file( + fork_user, + '.gitlab/merge_request_templates/feature-proposal.md', + template_content, + message: 'added merge request template', + branch_name: 'master', + update: false) visit edit_namespace_project_merge_request_path project.namespace, project, merge_request fill_in :'merge_request[title]', with: 'test merge request title' end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 917b545e98b..0b5ccc8c515 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -91,10 +91,10 @@ describe 'Pipeline', :feature, :js do end end - it 'should be possible to retry the success build' do + it 'should be possible to retry the success job' do find('#ci-badge-build .ci-action-icon-container').trigger('click') - expect(page).not_to have_content('Retry build') + expect(page).not_to have_content('Retry job') end end @@ -113,11 +113,11 @@ describe 'Pipeline', :feature, :js do it 'should be possible to retry the failed build' do find('#ci-badge-test .ci-action-icon-container').trigger('click') - expect(page).not_to have_content('Retry build') + expect(page).not_to have_content('Retry job') end end - context 'when pipeline has manual builds' do + context 'when pipeline has manual jobs' do it 'shows the skipped icon and a play action for the manual build' do page.within('#ci-badge-manual-build') do expect(page).to have_selector('.js-ci-status-icon-manual') @@ -129,14 +129,14 @@ describe 'Pipeline', :feature, :js do end end - it 'should be possible to play the manual build' do + it 'should be possible to play the manual job' do find('#ci-badge-manual-build .ci-action-icon-container').trigger('click') - expect(page).not_to have_content('Play build') + expect(page).not_to have_content('Play job') end end - context 'when pipeline has external build' do + context 'when pipeline has external job' do it 'shows the success icon and the generic comit status build' do expect(page).to have_selector('.js-ci-status-icon-success') expect(page).to have_content('jenkins') @@ -146,12 +146,12 @@ describe 'Pipeline', :feature, :js do end context 'page tabs' do - it 'shows Pipeline and Builds tabs with link' do + it 'shows Pipeline and Jobs tabs with link' do expect(page).to have_link('Pipeline') - expect(page).to have_link('Builds') + expect(page).to have_link('Jobs') end - it 'shows counter in Builds tab' do + it 'shows counter in Jobs tab' do expect(page.find('.js-builds-counter').text).to eq(pipeline.statuses.count.to_s) end @@ -160,7 +160,7 @@ describe 'Pipeline', :feature, :js do end end - context 'retrying builds' do + context 'retrying jobs' do it { expect(page).not_to have_content('retried') } context 'when retrying' do @@ -170,7 +170,7 @@ describe 'Pipeline', :feature, :js do end end - context 'canceling builds' do + context 'canceling jobs' do it { expect(page).not_to have_selector('.ci-canceled') } context 'when canceling' do @@ -191,7 +191,7 @@ describe 'Pipeline', :feature, :js do visit builds_namespace_project_pipeline_path(project.namespace, project, pipeline) end - it 'shows a list of builds' do + it 'shows a list of jobs' do expect(page).to have_content('Test') expect(page).to have_content(build_passed.id) expect(page).to have_content('Deploy') @@ -203,26 +203,26 @@ describe 'Pipeline', :feature, :js do expect(page).to have_link('Play') end - it 'shows Builds tab pane as active' do + it 'shows jobs tab pane as active' do expect(page).to have_css('#js-tab-builds.active') end context 'page tabs' do - it 'shows Pipeline and Builds tabs with link' do + it 'shows Pipeline and Jobs tabs with link' do expect(page).to have_link('Pipeline') - expect(page).to have_link('Builds') + expect(page).to have_link('Jobs') end - it 'shows counter in Builds tab' do + it 'shows counter in Jobs tab' do expect(page.find('.js-builds-counter').text).to eq(pipeline.statuses.count.to_s) end - it 'shows Builds tab as active' do + it 'shows Jobs tab as active' do expect(page).to have_css('li.js-builds-tab-link.active') end end - context 'retrying builds' do + context 'retrying jobs' do it { expect(page).not_to have_content('retried') } context 'when retrying' do @@ -233,7 +233,7 @@ describe 'Pipeline', :feature, :js do end end - context 'canceling builds' do + context 'canceling jobs' do it { expect(page).not_to have_selector('.ci-canceled') } context 'when canceling' do @@ -244,7 +244,7 @@ describe 'Pipeline', :feature, :js do end end - context 'playing manual build' do + context 'playing manual job' do before do within '.pipeline-holder' do click_link('Play') diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb index 472491188c9..38fe2d92885 100644 --- a/spec/features/projects/ref_switcher_spec.rb +++ b/spec/features/projects/ref_switcher_spec.rb @@ -17,14 +17,15 @@ feature 'Ref switcher', feature: true, js: true do page.within '.project-refs-form' do input = find('input[type="search"]') - input.set 'expand' + input.set 'binary' + wait_for_ajax input.native.send_keys :down input.native.send_keys :down input.native.send_keys :enter end - expect(page).to have_title 'expand-collapse-files' + expect(page).to have_title 'binary-encoding' end it "user selects ref with special characters" do diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb index 4bfaa499272..034b75c2e51 100644 --- a/spec/features/projects/settings/merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/merge_requests_settings_spec.rb @@ -11,41 +11,41 @@ feature 'Project settings > Merge Requests', feature: true, js: true do login_as(user) end - context 'when Merge Request and Builds are initially enabled' do + context 'when Merge Request and Pipelines are initially enabled' do before do project.project_feature.update_attribute('merge_requests_access_level', ProjectFeature::ENABLED) end - context 'when Builds are initially enabled' do + context 'when Pipelines are initially enabled' do before do project.project_feature.update_attribute('builds_access_level', ProjectFeature::ENABLED) visit edit_project_path(project) end scenario 'shows the Merge Requests settings' do - expect(page).to have_content('Only allow merge requests to be merged if the build succeeds') + expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') select 'Disabled', from: "project_project_feature_attributes_merge_requests_access_level" - expect(page).not_to have_content('Only allow merge requests to be merged if the build succeeds') + expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved') end end - context 'when Builds are initially disabled' do + context 'when Pipelines are initially disabled' do before do project.project_feature.update_attribute('builds_access_level', ProjectFeature::DISABLED) visit edit_project_path(project) end scenario 'shows the Merge Requests settings that do not depend on Builds feature' do - expect(page).not_to have_content('Only allow merge requests to be merged if the build succeeds') + expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') select 'Everyone with access', from: "project_project_feature_attributes_builds_access_level" - expect(page).to have_content('Only allow merge requests to be merged if the build succeeds') + expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') end end @@ -58,12 +58,12 @@ feature 'Project settings > Merge Requests', feature: true, js: true do end scenario 'does not show the Merge Requests settings' do - expect(page).not_to have_content('Only allow merge requests to be merged if the build succeeds') + expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved') select 'Everyone with access', from: "project_project_feature_attributes_merge_requests_access_level" - expect(page).to have_content('Only allow merge requests to be merged if the build succeeds') + expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') end end diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 468bcc7badc..eae097126ce 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -134,7 +134,7 @@ describe DiffHelper do let(:new_pos) { 50 } let(:text) { 'some_text' } - it "should generate foldable top match line for inline view with empty text by default" do + it "generates foldable top match line for inline view with empty text by default" do output = diff_match_line old_pos, new_pos expect(output).to be_html_safe @@ -143,7 +143,7 @@ describe DiffHelper do expect(output).to have_css 'td:nth-child(3):not(.parallel).line_content.match', text: '' end - it "should allow to define text and bottom option" do + it "allows to define text and bottom option" do output = diff_match_line old_pos, new_pos, text: text, bottom: true expect(output).to be_html_safe @@ -152,7 +152,7 @@ describe DiffHelper do expect(output).to have_css 'td:nth-child(3):not(.parallel).line_content.match', text: text end - it "should generate match line for parallel view" do + it "generates match line for parallel view" do output = diff_match_line old_pos, new_pos, text: text, view: :parallel expect(output).to be_html_safe @@ -162,7 +162,7 @@ describe DiffHelper do expect(output).to have_css 'td:nth-child(4).line_content.match.parallel', text: text end - it "should allow to generate only left match line for parallel view" do + it "allows to generate only left match line for parallel view" do output = diff_match_line old_pos, nil, text: text, view: :parallel expect(output).to be_html_safe @@ -171,7 +171,7 @@ describe DiffHelper do expect(output).not_to have_css 'td:nth-child(3)' end - it "should allow to generate only right match line for parallel view" do + it "allows to generate only right match line for parallel view" do output = diff_match_line nil, new_pos, text: text, view: :parallel expect(output).to be_html_safe diff --git a/spec/javascripts/.eslintrc b/spec/javascripts/.eslintrc index 3cd419b37c9..fbd9bb9f0ff 100644 --- a/spec/javascripts/.eslintrc +++ b/spec/javascripts/.eslintrc @@ -22,9 +22,10 @@ }, "plugins": ["jasmine"], "rules": { - "prefer-arrow-callback": 0, "func-names": 0, "jasmine/no-suite-dupes": [1, "branch"], - "jasmine/no-spec-dupes": [1, "branch"] + "jasmine/no-spec-dupes": [1, "branch"], + "no-console": 0, + "prefer-arrow-callback": 0 } } diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js index 71446b9df61..f1bfd529983 100644 --- a/spec/javascripts/awards_handler_spec.js +++ b/spec/javascripts/awards_handler_spec.js @@ -113,7 +113,7 @@ }); }); describe('::getAwardUrl', function() { - return it('should return the url for request', function() { + return it('returns the url for request', function() { return expect(awardsHandler.getAwardUrl()).toBe('http://test.host/frontend-fixtures/issues-project/issues/1/toggle_award_emoji'); }); }); diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6 index 8d3e2237fda..7a399b307ad 100644 --- a/spec/javascripts/boards/mock_data.js.es6 +++ b/spec/javascripts/boards/mock_data.js.es6 @@ -56,3 +56,8 @@ const boardsMockInterceptor = (request, next) => { status: 200 })); }; + +window.listObj = listObj; +window.listObjDuplicate = listObjDuplicate; +window.BoardsMockData = BoardsMockData; +window.boardsMockInterceptor = boardsMockInterceptor; diff --git a/spec/javascripts/environments/environment_spec.js.es6 b/spec/javascripts/environments/environment_spec.js.es6 index 20e11ca3738..239cd69dd3a 100644 --- a/spec/javascripts/environments/environment_spec.js.es6 +++ b/spec/javascripts/environments/environment_spec.js.es6 @@ -8,12 +8,12 @@ //= require ./mock_data describe('Environment', () => { - preloadFixtures('environments/environments'); + preloadFixtures('static/environments/environments.html.raw'); let component; beforeEach(() => { - loadFixtures('environments/environments'); + loadFixtures('static/environments/environments.html.raw'); }); describe('successfull request', () => { diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6 index 8ecd01f9a83..58f6fb96afb 100644 --- a/spec/javascripts/environments/mock_data.js.es6 +++ b/spec/javascripts/environments/mock_data.js.es6 @@ -1,4 +1,4 @@ -/* eslint-disable no-unused-vars */ + const environmentsList = [ { id: 31, @@ -134,6 +134,8 @@ const environmentsList = [ }, ]; +window.environmentsList = environmentsList; + const environment = { id: 4, name: 'production', @@ -147,3 +149,5 @@ const environment = { created_at: '2016-12-16T11:51:04.690Z', updated_at: '2016-12-16T12:04:51.133Z', }; + +window.environment = environment; diff --git a/spec/javascripts/filtered_search/dropdown_user_spec.js.es6 b/spec/javascripts/filtered_search/dropdown_user_spec.js.es6 new file mode 100644 index 00000000000..5eba4343a1d --- /dev/null +++ b/spec/javascripts/filtered_search/dropdown_user_spec.js.es6 @@ -0,0 +1,40 @@ +//= require filtered_search/dropdown_utils +//= require filtered_search/filtered_search_tokenizer +//= require filtered_search/filtered_search_dropdown +//= require filtered_search/dropdown_user + +(() => { + describe('Dropdown User', () => { + describe('getSearchInput', () => { + let dropdownUser; + + beforeEach(() => { + spyOn(gl.FilteredSearchDropdown.prototype, 'constructor').and.callFake(() => {}); + spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {}); + spyOn(gl.DropdownUtils, 'getSearchInput').and.callFake(() => {}); + + dropdownUser = new gl.DropdownUser(); + }); + + it('should not return the double quote found in value', () => { + spyOn(gl.FilteredSearchTokenizer, 'processTokens').and.returnValue({ + lastToken: { + value: '"johnny appleseed', + }, + }); + + expect(dropdownUser.getSearchInput()).toBe('johnny appleseed'); + }); + + it('should not return the single quote found in value', () => { + spyOn(gl.FilteredSearchTokenizer, 'processTokens').and.returnValue({ + lastToken: { + value: '\'larry boy', + }, + }); + + expect(dropdownUser.getSearchInput()).toBe('larry boy'); + }); + }); + }); +})(); diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 index c8b5c2b36ad..a508dacf7f0 100644 --- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 +++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js.es6 @@ -23,6 +23,7 @@ `); spyOn(gl.FilteredSearchManager.prototype, 'bindEvents').and.callFake(() => {}); + spyOn(gl.FilteredSearchManager.prototype, 'cleanup').and.callFake(() => {}); spyOn(gl.FilteredSearchManager.prototype, 'loadSearchParamsFromURL').and.callFake(() => {}); spyOn(gl.FilteredSearchDropdownManager.prototype, 'setDropdown').and.callFake(() => {}); spyOn(gl.utils, 'getParameterByName').and.returnValue(null); diff --git a/spec/javascripts/fixtures/environments/table.html.haml b/spec/javascripts/fixtures/environments/table.html.haml index 1ea1725c561..59edc0396d2 100644 --- a/spec/javascripts/fixtures/environments/table.html.haml +++ b/spec/javascripts/fixtures/environments/table.html.haml @@ -3,7 +3,7 @@ %tr %th Environment %th Last deployment - %th Build + %th Job %th Commit %th %th diff --git a/spec/javascripts/gl_dropdown_spec.js.es6 b/spec/javascripts/gl_dropdown_spec.js.es6 index 06fa64b1b4e..4e7eed2767c 100644 --- a/spec/javascripts/gl_dropdown_spec.js.es6 +++ b/spec/javascripts/gl_dropdown_spec.js.es6 @@ -44,6 +44,7 @@ describe('Dropdown', function describeDropdown() { preloadFixtures('static/gl_dropdown.html.raw'); + loadJSONFixtures('projects.json'); function initDropDown(hasRemote, isFilterable) { this.dropdownButtonElement = $('#js-project-dropdown', this.dropdownContainerElement).glDropdown({ diff --git a/spec/javascripts/helpers/class_spec_helper.js.es6 b/spec/javascripts/helpers/class_spec_helper.js.es6 index 92a20687ec5..d3c37d39431 100644 --- a/spec/javascripts/helpers/class_spec_helper.js.es6 +++ b/spec/javascripts/helpers/class_spec_helper.js.es6 @@ -1,5 +1,3 @@ -/* eslint-disable no-unused-vars */ - class ClassSpecHelper { static itShouldBeAStaticMethod(base, method) { return it('should be a static method', () => { @@ -7,3 +5,5 @@ class ClassSpecHelper { }); } } + +window.ClassSpecHelper = ClassSpecHelper; diff --git a/spec/javascripts/issuable_time_tracker_spec.js.es6 b/spec/javascripts/issuable_time_tracker_spec.js.es6 index a1e979e8d09..c5671af235e 100644 --- a/spec/javascripts/issuable_time_tracker_spec.js.es6 +++ b/spec/javascripts/issuable_time_tracker_spec.js.es6 @@ -4,7 +4,7 @@ //= require issuable/time_tracking/components/time_tracker function initTimeTrackingComponent(opts) { - fixture.set(` + setFixtures(` <div> <div id="mock-container"></div> </div> diff --git a/spec/javascripts/lib/utils/common_utils_spec.js.es6 b/spec/javascripts/lib/utils/common_utils_spec.js.es6 index 1ce8f28e568..32c96e2a088 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js.es6 +++ b/spec/javascripts/lib/utils/common_utils_spec.js.es6 @@ -10,9 +10,9 @@ // IE11 will return a relative pathname while other browsers will return a full pathname. // parseUrl uses an anchor element for parsing an url. With relative urls, the anchor // element will create an absolute url relative to the current execution context. - // The JavaScript test suite is executed at '/teaspoon' which will lead to an absolute - // url starting with '/teaspoon'. - expect(gl.utils.parseUrl('" test="asf"').pathname).toEqual('/teaspoon/%22%20test=%22asf%22'); + // The JavaScript test suite is executed at '/' which will lead to an absolute url + // starting with '/'. + expect(gl.utils.parseUrl('" test="asf"').pathname).toContain('/%22%20test=%22asf%22'); }); }); @@ -42,9 +42,13 @@ }); describe('gl.utils.getParameterByName', () => { + beforeEach(() => { + window.history.pushState({}, null, '?scope=all&p=2'); + }); + it('should return valid parameter', () => { - const value = gl.utils.getParameterByName('reporter'); - expect(value).toBe('Console'); + const value = gl.utils.getParameterByName('scope'); + expect(value).toBe('all'); }); it('should return invalid parameter', () => { diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index bf45100af03..6f1d6406897 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,6 +1,7 @@ /* eslint-disable space-before-function-paren, quotes, comma-dangle, dot-notation, quote-props, no-var, max-len */ /*= require merge_request_widget */ +/*= require smart_interval */ /*= require lib/utils/datetime_utility */ (function() { @@ -21,7 +22,11 @@ normal: "Build {{status}}" }, gitlab_icon: "gitlab_logo.png", - builds_path: "http://sampledomain.local/sampleBuildsPath" + ci_pipeline: 80, + ci_sha: "12a34bc5", + builds_path: "http://sampledomain.local/sampleBuildsPath", + commits_path: "http://sampledomain.local/commits", + pipeline_path: "http://sampledomain.local/pipelines" }; this["class"] = new window.gl.MergeRequestWidget(this.opts); }); @@ -118,10 +123,11 @@ }); }); - return describe('getCIStatus', function() { + describe('getCIStatus', function() { beforeEach(function() { this.ciStatusData = { "title": "Sample MR title", + "pipeline": 80, "sha": "12a34bc5", "status": "success", "coverage": 98 @@ -165,6 +171,22 @@ this["class"].getCIStatus(true); return expect(spy).not.toHaveBeenCalled(); }); + it('should update the pipeline URL when the pipeline changes', function() { + var spy; + spy = spyOn(this["class"], 'updatePipelineUrls').and.stub(); + this["class"].getCIStatus(false); + this.ciStatusData.pipeline += 1; + this["class"].getCIStatus(false); + return expect(spy).toHaveBeenCalled(); + }); + it('should update the commit URL when the sha changes', function() { + var spy; + spy = spyOn(this["class"], 'updateCommitUrls').and.stub(); + this["class"].getCIStatus(false); + this.ciStatusData.sha = "9b50b99a"; + this["class"].getCIStatus(false); + return expect(spy).toHaveBeenCalled(); + }); }); }); }).call(this); diff --git a/spec/javascripts/project_title_spec.js b/spec/javascripts/project_title_spec.js index 0202c9ba85e..e562385a6c6 100644 --- a/spec/javascripts/project_title_spec.js +++ b/spec/javascripts/project_title_spec.js @@ -17,6 +17,8 @@ describe('Project Title', function() { preloadFixtures('static/project_title.html.raw'); + loadJSONFixtures('projects.json'); + beforeEach(function() { loadFixtures('static/project_title.html.raw'); return this.project = new Project(); diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js index 942778229b5..3a01a534557 100644 --- a/spec/javascripts/right_sidebar_spec.js +++ b/spec/javascripts/right_sidebar_spec.js @@ -37,6 +37,8 @@ describe('RightSidebar', function() { var fixtureName = 'issues/open-issue.html.raw'; preloadFixtures(fixtureName); + loadJSONFixtures('todos.json'); + beforeEach(function() { loadFixtures(fixtureName); this.sidebar = new Sidebar; diff --git a/spec/javascripts/shortcuts_issuable_spec.js b/spec/javascripts/shortcuts_issuable_spec.js index 386fc8f514e..e0a5a7927bb 100644 --- a/spec/javascripts/shortcuts_issuable_spec.js +++ b/spec/javascripts/shortcuts_issuable_spec.js @@ -11,9 +11,9 @@ beforeEach(function() { loadFixtures(fixtureName); document.querySelector('.js-new-note-form').classList.add('js-main-target-form'); - return this.shortcut = new ShortcutsIssuable(); + this.shortcut = new ShortcutsIssuable(); }); - return describe('#replyWithSelectedText', function() { + describe('#replyWithSelectedText', function() { var stubSelection; // Stub window.gl.utils.getSelectedFragment to return a node with the provided HTML. stubSelection = function(html) { @@ -24,56 +24,57 @@ }; }; beforeEach(function() { - return this.selector = 'form.js-main-target-form textarea#note_note'; + this.selector = 'form.js-main-target-form textarea#note_note'; }); describe('with empty selection', function() { - return it('does nothing', function() { - stubSelection(''); + it('does not return an error', function() { this.shortcut.replyWithSelectedText(); - return expect($(this.selector).val()).toBe(''); + expect($(this.selector).val()).toBe(''); + }); + it('triggers `input`', function() { + var focused = false; + $(this.selector).on('focus', function() { + focused = true; + }); + this.shortcut.replyWithSelectedText(); + expect(focused).toBe(true); }); }); describe('with any selection', function() { beforeEach(function() { - return stubSelection('<p>Selected text.</p>'); + stubSelection('<p>Selected text.</p>'); }); it('leaves existing input intact', function() { $(this.selector).val('This text was already here.'); expect($(this.selector).val()).toBe('This text was already here.'); this.shortcut.replyWithSelectedText(); - return expect($(this.selector).val()).toBe("This text was already here.\n\n> Selected text.\n\n"); + expect($(this.selector).val()).toBe("This text was already here.\n\n> Selected text.\n\n"); }); it('triggers `input`', function() { - var triggered; - triggered = false; + var triggered = false; $(this.selector).on('input', function() { - return triggered = true; + triggered = true; }); this.shortcut.replyWithSelectedText(); - return expect(triggered).toBe(true); + expect(triggered).toBe(true); }); - return it('triggers `focus`', function() { - var focused; - focused = false; - $(this.selector).on('focus', function() { - return focused = true; - }); + it('triggers `focus`', function() { this.shortcut.replyWithSelectedText(); - return expect(focused).toBe(true); + expect(document.activeElement).toBe(document.querySelector(this.selector)); }); }); describe('with a one-line selection', function() { - return it('quotes the selection', function() { + it('quotes the selection', function() { stubSelection('<p>This text has been selected.</p>'); this.shortcut.replyWithSelectedText(); - return expect($(this.selector).val()).toBe("> This text has been selected.\n\n"); + expect($(this.selector).val()).toBe("> This text has been selected.\n\n"); }); }); - return describe('with a multi-line selection', function() { - return it('quotes the selected lines as a group', function() { + describe('with a multi-line selection', function() { + it('quotes the selected lines as a group', function() { stubSelection("<p>Selected line one.</p>\n\n<p>Selected line two.</p>\n\n<p>Selected line three.</p>"); this.shortcut.replyWithSelectedText(); - return expect($(this.selector).val()).toBe("> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n"); + expect($(this.selector).val()).toBe("> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n"); }); }); }); diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js index 80163fd72d3..0e2fb07ba7f 100644 --- a/spec/javascripts/u2f/authenticate_spec.js +++ b/spec/javascripts/u2f/authenticate_spec.js @@ -25,19 +25,20 @@ document.querySelector('#js-login-2fa-device'), document.querySelector('.js-2fa-form') ); + + // bypass automatic form submission within renderAuthenticated + spyOn(this.component, 'renderAuthenticated').and.returnValue(true); + return this.component.start(); }); it('allows authenticating via a U2F device', function() { - var authenticatedMessage, deviceResponse, inProgressMessage; + var inProgressMessage; inProgressMessage = this.container.find("p"); expect(inProgressMessage.text()).toContain("Trying to communicate with your device"); this.u2fDevice.respondToAuthenticateRequest({ deviceData: "this is data from the device" }); - authenticatedMessage = this.container.find("p"); - deviceResponse = this.container.find('#js-device-response'); - expect(authenticatedMessage.text()).toContain('We heard back from your U2F device. You have been authenticated.'); - return expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}'); + expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}'); }); return describe("errors", function() { it("displays an error message", function() { @@ -51,7 +52,7 @@ return expect(errorMessage.text()).toContain("There was a problem communicating with your device"); }); return it("allows retrying authentication after an error", function() { - var authenticatedMessage, retryButton, setupButton; + var retryButton, setupButton; setupButton = this.container.find("#js-login-u2f-device"); setupButton.trigger('click'); this.u2fDevice.respondToAuthenticateRequest({ @@ -64,8 +65,7 @@ this.u2fDevice.respondToAuthenticateRequest({ deviceData: "this is data from the device" }); - authenticatedMessage = this.container.find("p"); - return expect(authenticatedMessage.text()).toContain("We heard back from your U2F device. You have been authenticated."); + expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}'); }); }); }); diff --git a/spec/javascripts/vue_pagination/pagination_spec.js.es6 b/spec/javascripts/vue_pagination/pagination_spec.js.es6 index 1a7f2bb5fb8..efb11211ce2 100644 --- a/spec/javascripts/vue_pagination/pagination_spec.js.es6 +++ b/spec/javascripts/vue_pagination/pagination_spec.js.es6 @@ -1,7 +1,6 @@ //= require vue //= require lib/utils/common_utils //= require vue_pagination/index -/* global fixture, gl */ describe('Pagination component', () => { let component; @@ -17,7 +16,7 @@ describe('Pagination component', () => { }; it('should render and start at page 1', () => { - fixture.set('<div class="test-pagination-container"></div>'); + setFixtures('<div class="test-pagination-container"></div>'); component = new window.gl.VueGlPagination({ el: document.querySelector('.test-pagination-container'), @@ -40,7 +39,7 @@ describe('Pagination component', () => { }); it('should go to the previous page', () => { - fixture.set('<div class="test-pagination-container"></div>'); + setFixtures('<div class="test-pagination-container"></div>'); component = new window.gl.VueGlPagination({ el: document.querySelector('.test-pagination-container'), @@ -61,7 +60,7 @@ describe('Pagination component', () => { }); it('should go to the next page', () => { - fixture.set('<div class="test-pagination-container"></div>'); + setFixtures('<div class="test-pagination-container"></div>'); component = new window.gl.VueGlPagination({ el: document.querySelector('.test-pagination-container'), @@ -82,7 +81,7 @@ describe('Pagination component', () => { }); it('should go to the last page', () => { - fixture.set('<div class="test-pagination-container"></div>'); + setFixtures('<div class="test-pagination-container"></div>'); component = new window.gl.VueGlPagination({ el: document.querySelector('.test-pagination-container'), @@ -103,7 +102,7 @@ describe('Pagination component', () => { }); it('should go to the first page', () => { - fixture.set('<div class="test-pagination-container"></div>'); + setFixtures('<div class="test-pagination-container"></div>'); component = new window.gl.VueGlPagination({ el: document.querySelector('.test-pagination-container'), @@ -124,7 +123,7 @@ describe('Pagination component', () => { }); it('should do nothing', () => { - fixture.set('<div class="test-pagination-container"></div>'); + setFixtures('<div class="test-pagination-container"></div>'); component = new window.gl.VueGlPagination({ el: document.querySelector('.test-pagination-container'), diff --git a/spec/lib/banzai/cross_project_reference_spec.rb b/spec/lib/banzai/cross_project_reference_spec.rb index 81b9a513ce3..deaabceef1c 100644 --- a/spec/lib/banzai/cross_project_reference_spec.rb +++ b/spec/lib/banzai/cross_project_reference_spec.rb @@ -24,7 +24,7 @@ describe Banzai::CrossProjectReference, lib: true do it 'returns the referenced project' do project2 = double('referenced project') - expect(Project).to receive(:find_with_namespace). + expect(Project).to receive(:find_by_full_path). with('cross/reference').and_return(project2) expect(project_from_ref('cross/reference')).to eq project2 diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb new file mode 100644 index 00000000000..f85a5dcbd8b --- /dev/null +++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Banzai::Filter::PlantumlFilter, lib: true do + include FilterSpecHelper + + it 'should replace plantuml pre tag with img tag' do + stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080") + input = '<pre class="plantuml"><code>Bob -> Sara : Hello</code><pre>' + output = '<div class="imageblock"><div class="content"><img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq"></div></div>' + doc = filter(input) + + expect(doc.to_s).to eq output + end + + it 'should not replace plantuml pre tag with img tag if disabled' do + stub_application_setting(plantuml_enabled: false) + input = '<pre class="plantuml"><code>Bob -> Sara : Hello</code><pre>' + output = '<pre class="plantuml"><code>Bob -> Sara : Hello</code><pre></pre></pre>' + doc = filter(input) + + expect(doc.to_s).to eq output + end + + it 'should not replace plantuml pre tag with img tag if url is invalid' do + stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid") + input = '<pre class="plantuml"><code>Bob -> Sara : Hello</code><pre>' + output = '<div class="listingblock"><div class="content"><pre class="plantuml plantuml-error"> PlantUML Error: cannot connect to PlantUML server at "invalid"</pre></div></div>' + doc = filter(input) + + expect(doc.to_s).to eq output + end +end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index f824e2e1efe..49349035b3b 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -4,6 +4,33 @@ module Ci describe GitlabCiYamlProcessor, lib: true do let(:path) { 'path' } + describe '#build_attributes' do + context 'Coverage entry' do + subject { described_class.new(config, path).build_attributes(:rspec) } + + let(:config_base) { { rspec: { script: "rspec" } } } + let(:config) { YAML.dump(config_base) } + + context 'when config has coverage set at the global scope' do + before do + config_base.update(coverage: '/\(\d+\.\d+\) covered/') + end + + context "and 'rspec' job doesn't have coverage set" do + it { is_expected.to include(coverage_regex: '\(\d+\.\d+\) covered') } + end + + context "but 'rspec' job also has coverage set" do + before do + config_base[:rspec][:coverage] = '/Code coverage: \d+\.\d+/' + end + + it { is_expected.to include(coverage_regex: 'Code coverage: \d+\.\d+') } + end + end + end + end + describe "#builds_for_ref" do let(:type) { 'test' } @@ -21,6 +48,7 @@ module Ci stage_idx: 1, name: "rspec", commands: "pwd\nrspec", + coverage_regex: nil, tag_list: [], options: {}, allow_failure: false, @@ -435,6 +463,7 @@ module Ci stage_idx: 1, name: "rspec", commands: "pwd\nrspec", + coverage_regex: nil, tag_list: [], options: { image: "ruby:2.1", @@ -463,6 +492,7 @@ module Ci stage_idx: 1, name: "rspec", commands: "pwd\nrspec", + coverage_regex: nil, tag_list: [], options: { image: "ruby:2.5", @@ -702,6 +732,7 @@ module Ci stage_idx: 1, name: "rspec", commands: "pwd\nrspec", + coverage_regex: nil, tag_list: [], options: { image: "ruby:2.1", @@ -913,6 +944,7 @@ module Ci stage_idx: 1, name: "normal_job", commands: "test", + coverage_regex: nil, tag_list: [], options: {}, when: "on_success", @@ -958,6 +990,7 @@ module Ci stage_idx: 0, name: "job1", commands: "execute-script-for-job", + coverage_regex: nil, tag_list: [], options: {}, when: "on_success", @@ -970,6 +1003,7 @@ module Ci stage_idx: 0, name: "job2", commands: "execute-script-for-job", + coverage_regex: nil, tag_list: [], options: {}, when: "on_success", diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index f251c0dd25a..b234de4c772 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -58,58 +58,102 @@ describe Gitlab::Auth, lib: true do expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_authentication_abilities)) end - it 'recognizes user lfs tokens' do - user = create(:user) - token = Gitlab::LfsToken.new(user).token + context 'while using LFS authenticate' do + it 'recognizes user lfs tokens' do + user = create(:user) + token = Gitlab::LfsToken.new(user).token - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: user.username) - expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :lfs_token, full_authentication_abilities)) - end + expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: user.username) + expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :lfs_token, full_authentication_abilities)) + end - it 'recognizes deploy key lfs tokens' do - key = create(:deploy_key) - token = Gitlab::LfsToken.new(key).token + it 'recognizes deploy key lfs tokens' do + key = create(:deploy_key) + token = Gitlab::LfsToken.new(key).token - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") - expect(gl_auth.find_for_git_client("lfs+deploy-key-#{key.id}", token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(key, nil, :lfs_deploy_token, read_authentication_abilities)) - end + expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") + expect(gl_auth.find_for_git_client("lfs+deploy-key-#{key.id}", token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(key, nil, :lfs_deploy_token, read_authentication_abilities)) + end - context "while using OAuth tokens as passwords" do - it 'succeeds for OAuth tokens with the `api` scope' do + it 'does not try password auth before oauth' do user = create(:user) - application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) - token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "api") + token = Gitlab::LfsToken.new(user).token + + expect(gl_auth).not_to receive(:find_with_user_password) + gl_auth.find_for_git_client(user.username, token, project: nil, ip: 'ip') + end + end + + context 'while using OAuth tokens as passwords' do + let(:user) { create(:user) } + let(:token_w_api_scope) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') } + let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) } + + it 'succeeds for OAuth tokens with the `api` scope' do expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'oauth2') - expect(gl_auth.find_for_git_client("oauth2", token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :oauth, read_authentication_abilities)) + expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :oauth, read_authentication_abilities)) end it 'fails for OAuth tokens with other scopes' do - user = create(:user) - application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) - token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "read_user") + token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'read_user') expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'oauth2') expect(gl_auth.find_for_git_client("oauth2", token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, nil)) end + + it 'does not try password auth before oauth' do + expect(gl_auth).not_to receive(:find_with_user_password) + + gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip') + end end - context "while using personal access tokens as passwords" do - it 'succeeds for personal access tokens with the `api` scope' do - user = create(:user) - personal_access_token = create(:personal_access_token, user: user, scopes: ['api']) + context 'while using personal access tokens as passwords' do + let(:user) { create(:user) } + let(:token_w_api_scope) { create(:personal_access_token, user: user, scopes: ['api']) } + it 'succeeds for personal access tokens with the `api` scope' do expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: user.email) - expect(gl_auth.find_for_git_client(user.email, personal_access_token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :personal_token, full_authentication_abilities)) + expect(gl_auth.find_for_git_client(user.email, token_w_api_scope.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :personal_token, full_authentication_abilities)) end it 'fails for personal access tokens with other scopes' do - user = create(:user) personal_access_token = create(:personal_access_token, user: user, scopes: ['read_user']) expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: user.email) expect(gl_auth.find_for_git_client(user.email, personal_access_token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, nil)) end + + it 'does not try password auth before personal access tokens' do + expect(gl_auth).not_to receive(:find_with_user_password) + + gl_auth.find_for_git_client(user.email, token_w_api_scope.token, project: nil, ip: 'ip') + end + end + + context 'while using regular user and password' do + it 'falls through lfs authentication' do + user = create( + :user, + username: 'normal_user', + password: 'my-secret', + ) + + expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) + .to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_authentication_abilities)) + end + + it 'falls through oauth authentication when the username is oauth2' do + user = create( + :user, + username: 'oauth2', + password: 'my-secret', + ) + + expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) + .to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_authentication_abilities)) + end end it 'returns double nil for invalid credentials' do diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index 1e81eaef18c..b6e924d67be 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -24,7 +24,7 @@ describe Gitlab::ChatCommands::Command, service: true do it 'displays the help message' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to start_with('Available commands') + expect(subject[:text]).to start_with('Unknown command') expect(subject[:text]).to match('/gitlab issue show') end end @@ -34,47 +34,7 @@ describe Gitlab::ChatCommands::Command, service: true do it 'rejects the actions' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to start_with('Whoops! That action is not allowed') - end - end - - context 'issue is successfully created' do - let(:params) { { text: "issue create my new issue" } } - - before do - project.team << [user, :master] - end - - it 'presents the issue' do - expect(subject[:text]).to match("my new issue") - end - - it 'shows a link to the new issue' do - expect(subject[:text]).to match(/\/issues\/\d+/) - end - end - - context 'searching for an issue' do - let(:params) { { text: 'issue search find me' } } - let!(:issue) { create(:issue, project: project, title: 'find me') } - - before do - project.team << [user, :master] - end - - context 'a single issue is found' do - it 'presents the issue' do - expect(subject[:text]).to match(issue.title) - end - end - - context 'multiple issues found' do - let!(:issue2) { create(:issue, project: project, title: "someone find me") } - - it 'shows a link to the new issue' do - expect(subject[:text]).to match(issue.title) - expect(subject[:text]).to match(issue2.title) - end + expect(subject[:text]).to start_with('Whoops! This action is not allowed') end end @@ -90,7 +50,7 @@ describe Gitlab::ChatCommands::Command, service: true do context 'and user can not create deployment' do it 'returns action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to start_with('Whoops! That action is not allowed') + expect(subject[:text]).to start_with('Whoops! This action is not allowed') end end @@ -100,7 +60,7 @@ describe Gitlab::ChatCommands::Command, service: true do end it 'returns action' do - expect(subject[:text]).to include('Deployment from staging to production started.') + expect(subject[:text]).to include('Deployment started from staging to production') expect(subject[:response_type]).to be(:in_channel) end @@ -130,7 +90,7 @@ describe Gitlab::ChatCommands::Command, service: true do context 'IssueCreate is triggered' do let(:params) { { text: 'issue create my title' } } - it { is_expected.to eq(Gitlab::ChatCommands::IssueCreate) } + it { is_expected.to eq(Gitlab::ChatCommands::IssueNew) } end context 'IssueSearch is triggered' do diff --git a/spec/lib/gitlab/chat_commands/deploy_spec.rb b/spec/lib/gitlab/chat_commands/deploy_spec.rb index bd8099c92da..b3358a32161 100644 --- a/spec/lib/gitlab/chat_commands/deploy_spec.rb +++ b/spec/lib/gitlab/chat_commands/deploy_spec.rb @@ -15,8 +15,9 @@ describe Gitlab::ChatCommands::Deploy, service: true do end context 'if no environment is defined' do - it 'returns nil' do - expect(subject).to be_nil + it 'does not execute an action' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to eq("No action found to be executed") end end @@ -26,8 +27,9 @@ describe Gitlab::ChatCommands::Deploy, service: true do let!(:deployment) { create(:deployment, environment: staging, deployable: build) } context 'without actions' do - it 'returns nil' do - expect(subject).to be_nil + it 'does not execute an action' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to eq("No action found to be executed") end end @@ -37,8 +39,8 @@ describe Gitlab::ChatCommands::Deploy, service: true do end it 'returns success result' do - expect(subject.type).to eq(:success) - expect(subject.message).to include('Deployment from staging to production started') + expect(subject[:response_type]).to be(:in_channel) + expect(subject[:text]).to start_with('Deployment started from staging to production') end context 'when duplicate action exists' do @@ -47,8 +49,8 @@ describe Gitlab::ChatCommands::Deploy, service: true do end it 'returns error' do - expect(subject.type).to eq(:error) - expect(subject.message).to include('Too many actions defined') + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to eq('Too many actions defined') end end @@ -59,9 +61,9 @@ describe Gitlab::ChatCommands::Deploy, service: true do name: 'teardown', environment: 'production') end - it 'returns success result' do - expect(subject.type).to eq(:success) - expect(subject.message).to include('Deployment from staging to production started') + it 'returns the success message' do + expect(subject[:response_type]).to be(:in_channel) + expect(subject[:text]).to start_with('Deployment started from staging to production') end end end diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_new_spec.rb index 6c71e79ff6d..84c22328064 100644 --- a/spec/lib/gitlab/chat_commands/issue_create_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_new_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::ChatCommands::IssueCreate, service: true do +describe Gitlab::ChatCommands::IssueNew, service: true do describe '#execute' do let(:project) { create(:empty_project) } let(:user) { create(:user) } @@ -18,7 +18,7 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do it 'creates the issue' do expect { subject }.to change { project.issues.count }.by(1) - expect(subject.title).to eq('bird is the word') + expect(subject[:response_type]).to be(:in_channel) end end @@ -41,6 +41,16 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do expect { subject }.to change { project.issues.count }.by(1) end end + + context 'issue cannot be created' do + let!(:issue) { create(:issue, project: project, title: 'bird is the word') } + let(:regex_match) { described_class.match("issue create #{'a' * 512}}") } + + it 'displays the errors' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to match("- Title is too long") + end + end end describe '.match' do diff --git a/spec/lib/gitlab/chat_commands/issue_search_spec.rb b/spec/lib/gitlab/chat_commands/issue_search_spec.rb index 24c06a967fa..551ccb79a58 100644 --- a/spec/lib/gitlab/chat_commands/issue_search_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_search_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' describe Gitlab::ChatCommands::IssueSearch, service: true do describe '#execute' do - let!(:issue) { create(:issue, title: 'find me') } + let!(:issue) { create(:issue, project: project, title: 'find me') } let!(:confidential) { create(:issue, :confidential, project: project, title: 'mepmep find') } - let(:project) { issue.project } + let(:project) { create(:empty_project) } let(:user) { issue.author } let(:regex_match) { described_class.match("issue search find") } @@ -14,7 +14,8 @@ describe Gitlab::ChatCommands::IssueSearch, service: true do context 'when the user has no access' do it 'only returns the open issues' do - expect(subject).not_to include(confidential) + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to match("not found") end end @@ -24,13 +25,14 @@ describe Gitlab::ChatCommands::IssueSearch, service: true do end it 'returns all results' do - expect(subject).to include(confidential, issue) + expect(subject).to have_key(:attachments) + expect(subject[:text]).to eq("Here are the 2 issues I found:") end end context 'without hits on the query' do it 'returns an empty collection' do - expect(subject).to be_empty + expect(subject[:text]).to match("not found") end end end diff --git a/spec/lib/gitlab/chat_commands/issue_show_spec.rb b/spec/lib/gitlab/chat_commands/issue_show_spec.rb index 2eab73e49e5..1f20d0a44ce 100644 --- a/spec/lib/gitlab/chat_commands/issue_show_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_show_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe Gitlab::ChatCommands::IssueShow, service: true do describe '#execute' do - let(:issue) { create(:issue) } - let(:project) { issue.project } + let(:issue) { create(:issue, project: project) } + let(:project) { create(:empty_project) } let(:user) { issue.author } let(:regex_match) { described_class.match("issue show #{issue.iid}") } @@ -16,15 +16,19 @@ describe Gitlab::ChatCommands::IssueShow, service: true do end context 'the issue exists' do + let(:title) { subject[:attachments].first[:title] } + it 'returns the issue' do - expect(subject.iid).to be issue.iid + expect(subject[:response_type]).to be(:in_channel) + expect(title).to start_with(issue.title) end context 'when its reference is given' do let(:regex_match) { described_class.match("issue show #{issue.to_reference}") } it 'shows the issue' do - expect(subject.iid).to be issue.iid + expect(subject[:response_type]).to be(:in_channel) + expect(title).to start_with(issue.title) end end end @@ -32,17 +36,24 @@ describe Gitlab::ChatCommands::IssueShow, service: true do context 'the issue does not exist' do let(:regex_match) { described_class.match("issue show 2343242") } - it "returns nil" do - expect(subject).to be_nil + it "returns not found" do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to match("not found") end end end - describe 'self.match' do + describe '.match' do it 'matches the iid' do match = described_class.match("issue show 123") expect(match[:iid]).to eq("123") end + + it 'accepts a reference' do + match = described_class.match("issue show #{Issue.reference_prefix}123") + + expect(match[:iid]).to eq("123") + end end end diff --git a/spec/lib/gitlab/chat_commands/presenters/access_spec.rb b/spec/lib/gitlab/chat_commands/presenters/access_spec.rb new file mode 100644 index 00000000000..ae41d75ab0c --- /dev/null +++ b/spec/lib/gitlab/chat_commands/presenters/access_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Presenters::Access do + describe '#access_denied' do + subject { described_class.new.access_denied } + + it { is_expected.to be_a(Hash) } + + it 'displays an error message' do + expect(subject[:text]).to match("is not allowed") + expect(subject[:response_type]).to be(:ephemeral) + end + end + + describe '#not_found' do + subject { described_class.new.not_found } + + it { is_expected.to be_a(Hash) } + + it 'tells the user the resource was not found' do + expect(subject[:text]).to match("not found!") + expect(subject[:response_type]).to be(:ephemeral) + end + end + + describe '#authorize' do + context 'with an authorization URL' do + subject { described_class.new('http://authorize.me').authorize } + + it { is_expected.to be_a(Hash) } + + it 'tells the user to authorize' do + expect(subject[:text]).to match("connect your GitLab account") + expect(subject[:response_type]).to be(:ephemeral) + end + end + + context 'without authorization url' do + subject { described_class.new.authorize } + + it { is_expected.to be_a(Hash) } + + it 'tells the user to authorize' do + expect(subject[:text]).to match("Couldn't identify you") + expect(subject[:response_type]).to be(:ephemeral) + end + end + end +end diff --git a/spec/lib/gitlab/chat_commands/presenters/deploy_spec.rb b/spec/lib/gitlab/chat_commands/presenters/deploy_spec.rb new file mode 100644 index 00000000000..dc2dd300072 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/presenters/deploy_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Presenters::Deploy do + let(:build) { create(:ci_build) } + + describe '#present' do + subject { described_class.new(build).present('staging', 'prod') } + + it { is_expected.to have_key(:text) } + it { is_expected.to have_key(:response_type) } + it { is_expected.to have_key(:status) } + it { is_expected.not_to have_key(:attachments) } + + it 'messages the channel of the deploy' do + expect(subject[:response_type]).to be(:in_channel) + expect(subject[:text]).to start_with("Deployment started from staging to prod") + end + end + + describe '#no_actions' do + subject { described_class.new(nil).no_actions } + + it { is_expected.to have_key(:text) } + it { is_expected.to have_key(:response_type) } + it { is_expected.to have_key(:status) } + it { is_expected.not_to have_key(:attachments) } + + it 'tells the user there is no action' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to eq("No action found to be executed") + end + end + + describe '#too_many_actions' do + subject { described_class.new([]).too_many_actions } + + it { is_expected.to have_key(:text) } + it { is_expected.to have_key(:response_type) } + it { is_expected.to have_key(:status) } + it { is_expected.not_to have_key(:attachments) } + + it 'tells the user there is no action' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to eq("Too many actions defined") + end + end +end diff --git a/spec/lib/gitlab/chat_commands/presenters/issue_new_spec.rb b/spec/lib/gitlab/chat_commands/presenters/issue_new_spec.rb new file mode 100644 index 00000000000..17fcdbc2452 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/presenters/issue_new_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Presenters::IssueNew do + let(:project) { create(:empty_project) } + let(:issue) { create(:issue, project: project) } + let(:attachment) { subject[:attachments].first } + + subject { described_class.new(issue).present } + + it { is_expected.to be_a(Hash) } + + it 'shows the issue' do + expect(subject[:response_type]).to be(:in_channel) + expect(subject).to have_key(:attachments) + expect(attachment[:title]).to start_with(issue.title) + end +end diff --git a/spec/lib/gitlab/chat_commands/presenters/issue_search_spec.rb b/spec/lib/gitlab/chat_commands/presenters/issue_search_spec.rb new file mode 100644 index 00000000000..ec6d3e34a96 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/presenters/issue_search_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Presenters::IssueSearch do + let(:project) { create(:empty_project) } + let(:message) { subject[:text] } + + before { create_list(:issue, 2, project: project) } + + subject { described_class.new(project.issues).present } + + it 'formats the message correct' do + is_expected.to have_key(:text) + is_expected.to have_key(:status) + is_expected.to have_key(:response_type) + is_expected.to have_key(:attachments) + end + + it 'shows a list of results' do + expect(subject[:response_type]).to be(:ephemeral) + + expect(message).to start_with("Here are the 2 issues I found") + end +end diff --git a/spec/lib/gitlab/chat_commands/presenters/issue_show_spec.rb b/spec/lib/gitlab/chat_commands/presenters/issue_show_spec.rb new file mode 100644 index 00000000000..5b678d31fce --- /dev/null +++ b/spec/lib/gitlab/chat_commands/presenters/issue_show_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Presenters::IssueShow do + let(:project) { create(:empty_project) } + let(:issue) { create(:issue, project: project) } + let(:attachment) { subject[:attachments].first } + + subject { described_class.new(issue).present } + + it { is_expected.to be_a(Hash) } + + it 'shows the issue' do + expect(subject[:response_type]).to be(:in_channel) + expect(subject).to have_key(:attachments) + expect(attachment[:title]).to start_with(issue.title) + end + + context 'with upvotes' do + before do + create(:award_emoji, :upvote, awardable: issue) + end + + it 'shows the upvote count' do + expect(subject[:response_type]).to be(:in_channel) + expect(attachment[:text]).to start_with("**Open** · :+1: 1") + end + end + + context 'confidential issue' do + let(:issue) { create(:issue, project: project) } + + it 'shows an ephemeral response' do + expect(subject[:response_type]).to be(:in_channel) + expect(attachment[:text]).to start_with("**Open**") + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/coverage_spec.rb b/spec/lib/gitlab/ci/config/entry/coverage_spec.rb new file mode 100644 index 00000000000..4c6bd859552 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/coverage_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Coverage do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context "when entry config value doesn't have the surrounding '/'" do + let(:config) { 'Code coverage: \d+\.\d+' } + + describe '#errors' do + subject { entry.errors } + it { is_expected.to include(/coverage config must be a regular expression/) } + end + + describe '#valid?' do + subject { entry } + it { is_expected.not_to be_valid } + end + end + + context "when entry config value has the surrounding '/'" do + let(:config) { '/Code coverage: \d+\.\d+/' } + + describe '#value' do + subject { entry.value } + it { is_expected.to eq(config[1...-1]) } + end + + describe '#errors' do + subject { entry.errors } + it { is_expected.to be_empty } + end + + describe '#valid?' do + subject { entry } + it { is_expected.to be_valid } + end + end + + context 'when entry value is not valid' do + let(:config) { '(malformed regexp' } + + describe '#errors' do + subject { entry.errors } + it { is_expected.to include(/coverage config must be a regular expression/) } + end + + describe '#valid?' do + subject { entry } + it { is_expected.not_to be_valid } + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index e64c8d46bd8..d4f1780b174 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -4,12 +4,17 @@ describe Gitlab::Ci::Config::Entry::Global do let(:global) { described_class.new(hash) } describe '.nodes' do - it 'can contain global config keys' do - expect(described_class.nodes).to include :before_script + it 'returns a hash' do + expect(described_class.nodes).to be_a(Hash) end - it 'returns a hash' do - expect(described_class.nodes).to be_a Hash + context 'when filtering all the entry/node names' do + it 'contains the expected node names' do + node_names = described_class.nodes.keys + expect(node_names).to match_array(%i[before_script image services + after_script variables stages + types cache coverage]) + end end end @@ -35,7 +40,7 @@ describe Gitlab::Ci::Config::Entry::Global do end it 'creates node object for each entry' do - expect(global.descendants.count).to eq 8 + expect(global.descendants.count).to eq 9 end it 'creates node object using valid class' do @@ -176,7 +181,7 @@ describe Gitlab::Ci::Config::Entry::Global do describe '#nodes' do it 'instantizes all nodes' do - expect(global.descendants.count).to eq 8 + expect(global.descendants.count).to eq 9 end it 'contains unspecified nodes' do diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index fc9b8b86dc4..d20f4ec207d 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -3,6 +3,20 @@ require 'spec_helper' describe Gitlab::Ci::Config::Entry::Job do let(:entry) { described_class.new(config, name: :rspec) } + describe '.nodes' do + context 'when filtering all the entry/node names' do + subject { described_class.nodes.keys } + + let(:result) do + %i[before_script script stage type after_script cache + image services only except variables artifacts + environment coverage] + end + + it { is_expected.to match_array result } + end + end + describe 'validations' do before { entry.compose! } diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 1e21270d928..5893485634d 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -12,11 +12,11 @@ describe Gitlab::Diff::Highlight, lib: true do context "with a diff file" do let(:subject) { Gitlab::Diff::Highlight.new(diff_file, repository: project.repository).highlight } - it 'should return Gitlab::Diff::Line elements' do + it 'returns Gitlab::Diff::Line elements' do expect(subject.first).to be_an_instance_of(Gitlab::Diff::Line) end - it 'should not modify "match" lines' do + it 'does not modify "match" lines' do expect(subject[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') expect(subject[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') end @@ -43,11 +43,11 @@ describe Gitlab::Diff::Highlight, lib: true do context "with diff lines" do let(:subject) { Gitlab::Diff::Highlight.new(diff_file.diff_lines, repository: project.repository).highlight } - it 'should return Gitlab::Diff::Line elements' do + it 'returns Gitlab::Diff::Line elements' do expect(subject.first).to be_an_instance_of(Gitlab::Diff::Line) end - it 'should not modify "match" lines' do + it 'does not modify "match" lines' do expect(subject[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') expect(subject[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') end diff --git a/spec/lib/gitlab/diff/parallel_diff_spec.rb b/spec/lib/gitlab/diff/parallel_diff_spec.rb index fe5fa048413..0f779339c54 100644 --- a/spec/lib/gitlab/diff/parallel_diff_spec.rb +++ b/spec/lib/gitlab/diff/parallel_diff_spec.rb @@ -12,7 +12,7 @@ describe Gitlab::Diff::ParallelDiff, lib: true do subject { described_class.new(diff_file) } describe '#parallelize' do - it 'should return an array of arrays containing the parsed diff' do + it 'returns an array of arrays containing the parsed diff' do diff_lines = diff_file.highlighted_diff_lines expected = [ # Unchanged lines diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb index f5822fed37c..8e3e4034c8f 100644 --- a/spec/lib/gitlab/diff/position_tracer_spec.rb +++ b/spec/lib/gitlab/diff/position_tracer_spec.rb @@ -99,7 +99,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do Files::CreateService.new( project, current_user, - source_branch: branch_name, + start_branch: branch_name, target_branch: branch_name, commit_message: "Create file", file_path: file_name, @@ -112,7 +112,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do Files::UpdateService.new( project, current_user, - source_branch: branch_name, + start_branch: branch_name, target_branch: branch_name, commit_message: "Update file", file_path: file_name, @@ -125,7 +125,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do Files::DeleteService.new( project, current_user, - source_branch: branch_name, + start_branch: branch_name, target_branch: branch_name, commit_message: "Delete file", file_path: file_name @@ -1640,7 +1640,9 @@ describe Gitlab::Diff::PositionTracer, lib: true do } merge_request = create(:merge_request, source_branch: second_create_file_commit.sha, target_branch: branch_name, source_project: project) - repository.merge(current_user, merge_request, options) + + repository.merge(current_user, merge_request.diff_head_sha, merge_request, options) + project.commit(branch_name) end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index b080be62b34..116ab16ae74 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -209,7 +209,13 @@ describe Gitlab::GitAccess, lib: true do stub_git_hooks project.repository.add_branch(user, unprotected_branch, 'feature') target_branch = project.repository.lookup('feature') - source_branch = project.repository.commit_file(user, FFaker::InternetSE.login_user_name, FFaker::HipsterIpsum.paragraph, FFaker::HipsterIpsum.sentence, unprotected_branch, false) + source_branch = project.repository.commit_file( + user, + FFaker::InternetSE.login_user_name, + FFaker::HipsterIpsum.paragraph, + message: FFaker::HipsterIpsum.sentence, + branch_name: unprotected_branch, + update: false) rugged = project.repository.rugged author = { email: "email@example.com", time: Time.now, name: "Example Git User" } diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb index fadfe4d378e..e177d883158 100644 --- a/spec/lib/gitlab/highlight_spec.rb +++ b/spec/lib/gitlab/highlight_spec.rb @@ -12,7 +12,7 @@ describe Gitlab::Highlight, lib: true do Gitlab::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb') end - it 'should properly highlight all the lines' do + it 'highlights all the lines properly' do expect(lines[4]).to eq(%Q{<span id="LC5" class="line"> <span class="kp">extend</span> <span class="nb">self</span></span>\n}) expect(lines[21]).to eq(%Q{<span id="LC22" class="line"> <span class="k">unless</span> <span class="no">File</span><span class="p">.</span><span class="nf">directory?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>\n}) expect(lines[26]).to eq(%Q{<span id="LC27" class="line"> <span class="vi">@cmd_status</span> <span class="o">=</span> <span class="mi">0</span></span>\n}) diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 6aa10a6509a..5231ab0ba3f 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -52,6 +52,7 @@ snippets: - project - notes - award_emoji +- user_agent_detail releases: - project project_members: diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 493bc2db21a..95b230e4f5c 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -222,6 +222,7 @@ CommitStatus: - queued_at - token - lock_version +- coverage_regex Ci::Variable: - id - project_id diff --git a/spec/lib/gitlab/ldap/access_spec.rb b/spec/lib/gitlab/ldap/access_spec.rb index b9d12c3c24c..9dd997aa7dc 100644 --- a/spec/lib/gitlab/ldap/access_spec.rb +++ b/spec/lib/gitlab/ldap/access_spec.rb @@ -14,7 +14,7 @@ describe Gitlab::LDAP::Access, lib: true do it { is_expected.to be_falsey } - it 'should block user in GitLab' do + it 'blocks user in GitLab' do expect(access).to receive(:block_user).with(user, 'does not exist anymore') access.allowed? diff --git a/spec/lib/gitlab/template/issue_template_spec.rb b/spec/lib/gitlab/template/issue_template_spec.rb index 45cec65a284..1335a2b8f35 100644 --- a/spec/lib/gitlab/template/issue_template_spec.rb +++ b/spec/lib/gitlab/template/issue_template_spec.rb @@ -4,16 +4,14 @@ describe Gitlab::Template::IssueTemplate do subject { described_class } let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:file_path_1) { '.gitlab/issue_templates/bug.md' } - let(:file_path_2) { '.gitlab/issue_templates/template_test.md' } - let(:file_path_3) { '.gitlab/issue_templates/feature_proposal.md' } - - before do - project.add_user(user, Gitlab::Access::MASTER) - project.repository.commit_file(user, file_path_1, "something valid", "test 3", "master", false) - project.repository.commit_file(user, file_path_2, "template_test", "test 1", "master", false) - project.repository.commit_file(user, file_path_3, "feature_proposal", "test 2", "master", false) + + let(:project) do + create(:project, + :repository, + create_template: { + user: user, + access: Gitlab::Access::MASTER, + path: 'issue_templates' }) end describe '.all' do diff --git a/spec/lib/gitlab/template/merge_request_template_spec.rb b/spec/lib/gitlab/template/merge_request_template_spec.rb index ae51b79be22..320b870309a 100644 --- a/spec/lib/gitlab/template/merge_request_template_spec.rb +++ b/spec/lib/gitlab/template/merge_request_template_spec.rb @@ -4,16 +4,14 @@ describe Gitlab::Template::MergeRequestTemplate do subject { described_class } let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:file_path_1) { '.gitlab/merge_request_templates/bug.md' } - let(:file_path_2) { '.gitlab/merge_request_templates/template_test.md' } - let(:file_path_3) { '.gitlab/merge_request_templates/feature_proposal.md' } - - before do - project.add_user(user, Gitlab::Access::MASTER) - project.repository.commit_file(user, file_path_1, "something valid", "test 3", "master", false) - project.repository.commit_file(user, file_path_2, "template_test", "test 1", "master", false) - project.repository.commit_file(user, file_path_3, "feature_proposal", "test 2", "master", false) + + let(:project) do + create(:project, + :repository, + create_template: { + user: user, + access: Gitlab::Access::MASTER, + path: 'merge_request_templates' }) end describe '.all' do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 47cd5075a7d..4080092405d 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -221,6 +221,47 @@ describe Ci::Build, :models do end end + describe '#coverage_regex' do + subject { build.coverage_regex } + + context 'when project has build_coverage_regex set' do + let(:project_regex) { '\(\d+\.\d+\) covered' } + + before do + project.build_coverage_regex = project_regex + end + + context 'and coverage_regex attribute is not set' do + it { is_expected.to eq(project_regex) } + end + + context 'but coverage_regex attribute is also set' do + let(:build_regex) { 'Code coverage: \d+\.\d+' } + + before do + build.coverage_regex = build_regex + end + + it { is_expected.to eq(build_regex) } + end + end + + context 'when neither project nor build has coverage regex set' do + it { is_expected.to be_nil } + end + end + + describe '#update_coverage' do + context "regarding coverage_regex's value," do + it "saves the correct extracted coverage value" do + build.coverage_regex = '\(\d+.\d+\%\) covered' + allow(build).to receive(:trace) { 'Coverage 1033 / 1051 LOC (98.29%) covered' } + expect(build).to receive(:update_attributes).with(coverage: 98.29) { true } + expect(build.update_coverage).to be true + end + end + end + describe 'deployment' do describe '#last_deployment' do subject { build.last_deployment } @@ -443,11 +484,11 @@ describe Ci::Build, :models do let!(:build) { create(:ci_build, :trace, :success, :artifacts) } subject { build.erased? } - context 'build has not been erased' do + context 'job has not been erased' do it { is_expected.to be_falsey } end - context 'build has been erased' do + context 'job has been erased' do before do build.erase end diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 3b7cc7d9e2e..9053485939e 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -27,15 +27,13 @@ describe 'CycleAnalytics#code', feature: true do context "when a regular merge request (that doesn't close the issue) is created" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) + issue = create(:issue, project: project) - create_commit_referencing_issue(issue) - create_merge_request_closing_issue(issue, message: "Closes nothing") + create_commit_referencing_issue(issue) + create_merge_request_closing_issue(issue, message: "Closes nothing") - merge_merge_requests_closing_issue(issue) - deploy_master - end + merge_merge_requests_closing_issue(issue) + deploy_master expect(subject[:code].median).to be_nil end @@ -60,14 +58,12 @@ describe 'CycleAnalytics#code', feature: true do context "when a regular merge request (that doesn't close the issue) is created" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) + issue = create(:issue, project: project) - create_commit_referencing_issue(issue) - create_merge_request_closing_issue(issue, message: "Closes nothing") + create_commit_referencing_issue(issue) + create_merge_request_closing_issue(issue, message: "Closes nothing") - merge_merge_requests_closing_issue(issue) - end + merge_merge_requests_closing_issue(issue) expect(subject[:code].median).to be_nil end diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 5c73edbbc53..fc7d18bd40e 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -33,14 +33,12 @@ describe 'CycleAnalytics#issue', models: true do context "when a regular label (instead of a list label) is added to the issue" do it "returns nil" do - 5.times do - regular_label = create(:label) - issue = create(:issue, project: project) - issue.update(label_ids: [regular_label.id]) + regular_label = create(:label) + issue = create(:issue, project: project) + issue.update(label_ids: [regular_label.id]) - create_merge_request_closing_issue(issue) - merge_merge_requests_closing_issue(issue) - end + create_merge_request_closing_issue(issue) + merge_merge_requests_closing_issue(issue) expect(subject[:issue].median).to be_nil end diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 591bbdddf55..b9fe492fe2c 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -21,7 +21,13 @@ describe 'CycleAnalytics#production', feature: true do ["production deploy happens after merge request is merged (along with other changes)", lambda do |context, data| # Make other changes on master - sha = context.project.repository.commit_file(context.user, context.random_git_name, "content", "commit message", 'master', false) + sha = context.project.repository.commit_file( + context.user, + context.random_git_name, + 'content', + message: 'commit message', + branch_name: 'master', + update: false) context.project.repository.commit(sha) context.deploy_master @@ -29,11 +35,9 @@ describe 'CycleAnalytics#production', feature: true do context "when a regular merge request (that doesn't close the issue) is merged and deployed" do it "returns nil" do - 5.times do - merge_request = create(:merge_request) - MergeRequests::MergeService.new(project, user).execute(merge_request) - deploy_master - end + merge_request = create(:merge_request) + MergeRequests::MergeService.new(project, user).execute(merge_request) + deploy_master expect(subject[:production].median).to be_nil end @@ -41,12 +45,10 @@ describe 'CycleAnalytics#production', feature: true do context "when the deployment happens to a non-production environment" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) - merge_request = create_merge_request_closing_issue(issue) - MergeRequests::MergeService.new(project, user).execute(merge_request) - deploy_master(environment: 'staging') - end + issue = create(:issue, project: project) + merge_request = create_merge_request_closing_issue(issue) + MergeRequests::MergeService.new(project, user).execute(merge_request) + deploy_master(environment: 'staging') expect(subject[:production].median).to be_nil end diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 33d2c0a7416..febb18c9884 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -23,9 +23,7 @@ describe 'CycleAnalytics#review', feature: true do context "when a regular merge request (that doesn't close the issue) is created and merged" do it "returns nil" do - 5.times do - MergeRequests::MergeService.new(project, user).execute(create(:merge_request)) - end + MergeRequests::MergeService.new(project, user).execute(create(:merge_request)) expect(subject[:review].median).to be_nil end diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index 00693d67475..9a024d533a1 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -29,10 +29,10 @@ describe 'CycleAnalytics#staging', feature: true do sha = context.project.repository.commit_file( context.user, context.random_git_name, - "content", - "commit message", - 'master', - false) + 'content', + message: 'commit message', + branch_name: 'master', + update: false) context.project.repository.commit(sha) context.deploy_master @@ -40,11 +40,9 @@ describe 'CycleAnalytics#staging', feature: true do context "when a regular merge request (that doesn't close the issue) is merged and deployed" do it "returns nil" do - 5.times do - merge_request = create(:merge_request) - MergeRequests::MergeService.new(project, user).execute(merge_request) - deploy_master - end + merge_request = create(:merge_request) + MergeRequests::MergeService.new(project, user).execute(merge_request) + deploy_master expect(subject[:staging].median).to be_nil end @@ -52,12 +50,10 @@ describe 'CycleAnalytics#staging', feature: true do context "when the deployment happens to a non-production environment" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) - merge_request = create_merge_request_closing_issue(issue) - MergeRequests::MergeService.new(project, user).execute(merge_request) - deploy_master(environment: 'staging') - end + issue = create(:issue, project: project) + merge_request = create_merge_request_closing_issue(issue) + MergeRequests::MergeService.new(project, user).execute(merge_request) + deploy_master(environment: 'staging') expect(subject[:staging].median).to be_nil end diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index f857ea6cbec..c2ba012a0e6 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -24,16 +24,14 @@ describe 'CycleAnalytics#test', feature: true do context "when the pipeline is for a regular merge request (that doesn't close an issue)" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) - merge_request = create_merge_request_closing_issue(issue) - pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) + issue = create(:issue, project: project) + merge_request = create_merge_request_closing_issue(issue) + pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) - pipeline.run! - pipeline.succeed! + pipeline.run! + pipeline.succeed! - merge_merge_requests_closing_issue(issue) - end + merge_merge_requests_closing_issue(issue) expect(subject[:test].median).to be_nil end @@ -41,12 +39,10 @@ describe 'CycleAnalytics#test', feature: true do context "when the pipeline is not for a merge request" do it "returns nil" do - 5.times do - pipeline = create(:ci_pipeline, ref: "refs/heads/master", sha: project.repository.commit('master').sha) + pipeline = create(:ci_pipeline, ref: "refs/heads/master", sha: project.repository.commit('master').sha) - pipeline.run! - pipeline.succeed! - end + pipeline.run! + pipeline.succeed! expect(subject[:test].median).to be_nil end @@ -54,16 +50,14 @@ describe 'CycleAnalytics#test', feature: true do context "when the pipeline is dropped (failed)" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) - merge_request = create_merge_request_closing_issue(issue) - pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) + issue = create(:issue, project: project) + merge_request = create_merge_request_closing_issue(issue) + pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) - pipeline.run! - pipeline.drop! + pipeline.run! + pipeline.drop! - merge_merge_requests_closing_issue(issue) - end + merge_merge_requests_closing_issue(issue) expect(subject[:test].median).to be_nil end @@ -71,16 +65,14 @@ describe 'CycleAnalytics#test', feature: true do context "when the pipeline is cancelled" do it "returns nil" do - 5.times do - issue = create(:issue, project: project) - merge_request = create_merge_request_closing_issue(issue) - pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) + issue = create(:issue, project: project) + merge_request = create_merge_request_closing_issue(issue) + pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) - pipeline.run! - pipeline.cancel! + pipeline.run! + pipeline.cancel! - merge_merge_requests_closing_issue(issue) - end + merge_merge_requests_closing_issue(issue) expect(subject[:test].median).to be_nil end diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index 90d14c2c0b9..e4be0aba7a6 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -117,7 +117,7 @@ describe ProjectMember, models: true do users = create_list(:user, 2) described_class.add_users_to_projects( - [projects.first.id, projects.second], + [projects.first.id, projects.second.id], [users.first.id, users.second], described_class::MASTER) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 829b69093c9..53b98ba05f8 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -15,7 +15,12 @@ describe Repository, models: true do let(:merge_commit) do merge_request = create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) - merge_commit_id = repository.merge(user, merge_request, commit_options) + + merge_commit_id = repository.merge(user, + merge_request.diff_head_sha, + merge_request, + commit_options) + repository.commit(merge_commit_id) end @@ -289,17 +294,39 @@ describe Repository, models: true do describe "#commit_dir" do it "commits a change that creates a new directory" do expect do - repository.commit_dir(user, 'newdir', 'Create newdir', 'master') + repository.commit_dir(user, 'newdir', + message: 'Create newdir', branch_name: 'master') end.to change { repository.commits('master').count }.by(1) newdir = repository.tree('master', 'newdir') expect(newdir.path).to eq('newdir') end + context "when committing to another project" do + let(:forked_project) { create(:project) } + + it "creates a fork and commit to the forked project" do + expect do + repository.commit_dir(user, 'newdir', + message: 'Create newdir', branch_name: 'patch', + start_branch_name: 'master', start_project: forked_project) + end.to change { repository.commits('master').count }.by(0) + + expect(repository.branch_exists?('patch')).to be_truthy + expect(forked_project.repository.branch_exists?('patch')).to be_falsy + + newdir = repository.tree('patch', 'newdir') + expect(newdir.path).to eq('newdir') + end + end + context "when an author is specified" do it "uses the given email/name to set the commit's author" do expect do - repository.commit_dir(user, "newdir", "Add newdir", 'master', author_email: author_email, author_name: author_name) + repository.commit_dir(user, 'newdir', + message: 'Add newdir', + branch_name: 'master', + author_email: author_email, author_name: author_name) end.to change { repository.commits('master').count }.by(1) last_commit = repository.commit @@ -314,8 +341,9 @@ describe Repository, models: true do it 'commits change to a file successfully' do expect do repository.commit_file(user, 'CHANGELOG', 'Changelog!', - 'Updates file content', - 'master', true) + message: 'Updates file content', + branch_name: 'master', + update: true) end.to change { repository.commits('master').count }.by(1) blob = repository.blob_at('master', 'CHANGELOG') @@ -326,8 +354,12 @@ describe Repository, models: true do context "when an author is specified" do it "uses the given email/name to set the commit's author" do expect do - repository.commit_file(user, "README", 'README!', 'Add README', - 'master', true, author_email: author_email, author_name: author_name) + repository.commit_file(user, 'README', 'README!', + message: 'Add README', + branch_name: 'master', + update: true, + author_email: author_email, + author_name: author_name) end.to change { repository.commits('master').count }.by(1) last_commit = repository.commit @@ -342,7 +374,7 @@ describe Repository, models: true do it 'updates filename successfully' do expect do repository.update_file(user, 'NEWLICENSE', 'Copyright!', - branch: 'master', + branch_name: 'master', previous_path: 'LICENSE', message: 'Changes filename') end.to change { repository.commits('master').count }.by(1) @@ -355,15 +387,16 @@ describe Repository, models: true do context "when an author is specified" do it "uses the given email/name to set the commit's author" do - repository.commit_file(user, "README", 'README!', 'Add README', 'master', true) + repository.commit_file(user, 'README', 'README!', + message: 'Add README', branch_name: 'master', update: true) expect do - repository.update_file(user, 'README', "Updated README!", - branch: 'master', - previous_path: 'README', - message: 'Update README', - author_email: author_email, - author_name: author_name) + repository.update_file(user, 'README', 'Updated README!', + branch_name: 'master', + previous_path: 'README', + message: 'Update README', + author_email: author_email, + author_name: author_name) end.to change { repository.commits('master').count }.by(1) last_commit = repository.commit @@ -376,10 +409,12 @@ describe Repository, models: true do describe "#remove_file" do it 'removes file successfully' do - repository.commit_file(user, "README", 'README!', 'Add README', 'master', true) + repository.commit_file(user, 'README', 'README!', + message: 'Add README', branch_name: 'master', update: true) expect do - repository.remove_file(user, "README", "Remove README", 'master') + repository.remove_file(user, 'README', + message: 'Remove README', branch_name: 'master') end.to change { repository.commits('master').count }.by(1) expect(repository.blob_at('master', 'README')).to be_nil @@ -387,10 +422,13 @@ describe Repository, models: true do context "when an author is specified" do it "uses the given email/name to set the commit's author" do - repository.commit_file(user, "README", 'README!', 'Add README', 'master', true) + repository.commit_file(user, 'README', 'README!', + message: 'Add README', branch_name: 'master', update: true) expect do - repository.remove_file(user, "README", "Remove README", 'master', author_email: author_email, author_name: author_name) + repository.remove_file(user, 'README', + message: 'Remove README', branch_name: 'master', + author_email: author_email, author_name: author_name) end.to change { repository.commits('master').count }.by(1) last_commit = repository.commit @@ -538,11 +576,14 @@ describe Repository, models: true do describe "#license_blob", caching: true do before do - repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'master') + repository.remove_file( + user, 'LICENSE', message: 'Remove LICENSE', branch_name: 'master') end it 'handles when HEAD points to non-existent ref' do - repository.commit_file(user, 'LICENSE', 'Copyright!', 'Add LICENSE', 'master', false) + repository.commit_file( + user, 'LICENSE', 'Copyright!', + message: 'Add LICENSE', branch_name: 'master', update: false) allow(repository).to receive(:file_on_head). and_raise(Rugged::ReferenceError) @@ -551,21 +592,27 @@ describe Repository, models: true do end it 'looks in the root_ref only' do - repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'markdown') - repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'markdown', false) + repository.remove_file(user, 'LICENSE', + message: 'Remove LICENSE', branch_name: 'markdown') + repository.commit_file(user, 'LICENSE', + Licensee::License.new('mit').content, + message: 'Add LICENSE', branch_name: 'markdown', update: false) expect(repository.license_blob).to be_nil end it 'detects license file with no recognizable open-source license content' do - repository.commit_file(user, 'LICENSE', 'Copyright!', 'Add LICENSE', 'master', false) + repository.commit_file(user, 'LICENSE', 'Copyright!', + message: 'Add LICENSE', branch_name: 'master', update: false) expect(repository.license_blob.name).to eq('LICENSE') end %w[LICENSE LICENCE LiCensE LICENSE.md LICENSE.foo COPYING COPYING.md].each do |filename| it "detects '#{filename}'" do - repository.commit_file(user, filename, Licensee::License.new('mit').content, "Add #{filename}", 'master', false) + repository.commit_file(user, filename, + Licensee::License.new('mit').content, + message: "Add #{filename}", branch_name: 'master', update: false) expect(repository.license_blob.name).to eq(filename) end @@ -574,7 +621,8 @@ describe Repository, models: true do describe '#license_key', caching: true do before do - repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'master') + repository.remove_file(user, 'LICENSE', + message: 'Remove LICENSE', branch_name: 'master') end it 'returns nil when no license is detected' do @@ -588,13 +636,16 @@ describe Repository, models: true do end it 'detects license file with no recognizable open-source license content' do - repository.commit_file(user, 'LICENSE', 'Copyright!', 'Add LICENSE', 'master', false) + repository.commit_file(user, 'LICENSE', 'Copyright!', + message: 'Add LICENSE', branch_name: 'master', update: false) expect(repository.license_key).to be_nil end it 'returns the license key' do - repository.commit_file(user, 'LICENSE', Licensee::License.new('mit').content, 'Add LICENSE', 'master', false) + repository.commit_file(user, 'LICENSE', + Licensee::License.new('mit').content, + message: 'Add LICENSE', branch_name: 'master', update: false) expect(repository.license_key).to eq('mit') end @@ -707,7 +758,7 @@ describe Repository, models: true do allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) expect do - repository.rm_branch(user, 'new_feature') + repository.rm_branch(user, 'feature') end.to raise_error(GitHooksService::PreReceiveError) end @@ -728,36 +779,51 @@ describe Repository, models: true do context 'when pre hooks were successful' do before do - expect_any_instance_of(GitHooksService).to receive(:execute). - with(user, repository.path_to_repo, old_rev, new_rev, 'refs/heads/feature'). - and_yield.and_return(true) + service = GitHooksService.new + expect(GitHooksService).to receive(:new).and_return(service) + expect(service).to receive(:execute). + with( + user, + repository.path_to_repo, + old_rev, + new_rev, + 'refs/heads/feature'). + and_yield(service).and_return(true) end it 'runs without errors' do expect do - repository.update_branch_with_hooks(user, 'feature') { new_rev } + GitOperationService.new(user, repository).with_branch('feature') do + new_rev + end end.not_to raise_error end it 'ensures the autocrlf Git option is set to :input' do - expect(repository).to receive(:update_autocrlf_option) + service = GitOperationService.new(user, repository) - repository.update_branch_with_hooks(user, 'feature') { new_rev } + expect(service).to receive(:update_autocrlf_option) + + service.with_branch('feature') { new_rev } end context "when the branch wasn't empty" do it 'updates the head' do expect(repository.find_branch('feature').dereferenced_target.id).to eq(old_rev) - repository.update_branch_with_hooks(user, 'feature') { new_rev } + + GitOperationService.new(user, repository).with_branch('feature') do + new_rev + end + expect(repository.find_branch('feature').dereferenced_target.id).to eq(new_rev) end end end context 'when the update adds more than one commit' do - it 'runs without errors' do - old_rev = '33f3729a45c02fc67d00adb1b8bca394b0e761d9' + let(:old_rev) { '33f3729a45c02fc67d00adb1b8bca394b0e761d9' } + it 'runs without errors' do # old_rev is an ancestor of new_rev expect(repository.rugged.merge_base(old_rev, new_rev)).to eq(old_rev) @@ -767,22 +833,28 @@ describe Repository, models: true do branch = 'feature-ff-target' repository.add_branch(user, branch, old_rev) - expect { repository.update_branch_with_hooks(user, branch) { new_rev } }.not_to raise_error + expect do + GitOperationService.new(user, repository).with_branch(branch) do + new_rev + end + end.not_to raise_error end end context 'when the update would remove commits from the target branch' do - it 'raises an exception' do - branch = 'master' - old_rev = repository.find_branch(branch).dereferenced_target.sha + let(:branch) { 'master' } + let(:old_rev) { repository.find_branch(branch).dereferenced_target.sha } + it 'raises an exception' do # The 'master' branch is NOT an ancestor of new_rev. expect(repository.rugged.merge_base(old_rev, new_rev)).not_to eq(old_rev) # Updating 'master' to new_rev would lose the commits on 'master' that # are not contained in new_rev. This should not be allowed. expect do - repository.update_branch_with_hooks(user, branch) { new_rev } + GitOperationService.new(user, repository).with_branch(branch) do + new_rev + end end.to raise_error(Repository::CommitError) end end @@ -792,7 +864,9 @@ describe Repository, models: true do allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) expect do - repository.update_branch_with_hooks(user, 'feature') { new_rev } + GitOperationService.new(user, repository).with_branch('feature') do + new_rev + end end.to raise_error(GitHooksService::PreReceiveError) end end @@ -800,7 +874,6 @@ describe Repository, models: true do context 'when target branch is different from source branch' do before do allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, '']) - allow(repository).to receive(:update_ref!) end it 'expires branch cache' do @@ -809,7 +882,10 @@ describe Repository, models: true do expect(repository).not_to receive(:expire_emptiness_caches) expect(repository).to receive(:expire_branches_cache) - repository.update_branch_with_hooks(user, 'new-feature') { new_rev } + GitOperationService.new(user, repository). + with_branch('new-feature') do + new_rev + end end end @@ -827,7 +903,9 @@ describe Repository, models: true do expect(empty_repository).to receive(:expire_branches_cache) empty_repository.commit_file(user, 'CHANGELOG', 'Changelog!', - 'Updates file content', 'master', false) + message: 'Updates file content', + branch_name: 'master', + update: false) end end end @@ -877,7 +955,7 @@ describe Repository, models: true do end it 'sets autocrlf to :input' do - repository.update_autocrlf_option + GitOperationService.new(nil, repository).send(:update_autocrlf_option) expect(repository.raw_repository.autocrlf).to eq(:input) end @@ -892,7 +970,7 @@ describe Repository, models: true do expect(repository.raw_repository).not_to receive(:autocrlf=). with(:input) - repository.update_autocrlf_option + GitOperationService.new(nil, repository).send(:update_autocrlf_option) end end end @@ -1009,8 +1087,11 @@ describe Repository, models: true do it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do merge_request = create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) - merge_commit_id = repository.merge(user, merge_request, commit_options) - repository.commit(merge_commit_id) + + merge_commit_id = repository.merge(user, + merge_request.diff_head_sha, + merge_request, + commit_options) expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id) end @@ -1388,9 +1469,10 @@ describe Repository, models: true do describe '#rm_tag' do it 'removes a tag' do expect(repository).to receive(:before_remove_tag) - expect(repository.rugged.tags).to receive(:delete).with('v1.1.0') - repository.rm_tag('v1.1.0') + repository.rm_tag(create(:user), 'v1.1.0') + + expect(repository.find_tag('v1.1.0')).to be_nil end end @@ -1458,16 +1540,16 @@ describe Repository, models: true do end end - describe '#update_ref!' do + describe '#update_ref' do it 'can create a ref' do - repository.update_ref!('refs/heads/foobar', 'refs/heads/master', Gitlab::Git::BLANK_SHA) + GitOperationService.new(nil, repository).send(:update_ref, 'refs/heads/foobar', 'refs/heads/master', Gitlab::Git::BLANK_SHA) expect(repository.find_branch('foobar')).not_to be_nil end it 'raises CommitError when the ref update fails' do expect do - repository.update_ref!('refs/heads/master', 'refs/heads/master', Gitlab::Git::BLANK_SHA) + GitOperationService.new(nil, repository).send(:update_ref, 'refs/heads/master', 'refs/heads/master', Gitlab::Git::BLANK_SHA) end.to raise_error(Repository::CommitError) end end diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 645e36683bc..f197fadebab 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -67,7 +67,7 @@ describe API::Builds, api: true do context 'unauthorized user' do let(:api_user) { nil } - it 'should not return project builds' do + it 'does not return project builds' do expect(response).to have_http_status(401) end end @@ -86,7 +86,7 @@ describe API::Builds, api: true do context 'when commit exists in repository' do context 'when user is authorized' do - context 'when pipeline has builds' do + context 'when pipeline has jobs' do before do create(:ci_pipeline, project: project, sha: project.commit.id) create(:ci_build, pipeline: pipeline) @@ -95,7 +95,7 @@ describe API::Builds, api: true do get api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", api_user) end - it 'returns project builds for specific commit' do + it 'returns project jobs for specific commit' do expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.size).to eq 2 @@ -111,7 +111,7 @@ describe API::Builds, api: true do end end - context 'when pipeline has no builds' do + context 'when pipeline has no jobs' do before do branch_head = project.commit('feature').id get api("/projects/#{project.id}/repository/commits/#{branch_head}/builds", api_user) @@ -133,7 +133,7 @@ describe API::Builds, api: true do get api("/projects/#{project.id}/repository/commits/#{project.commit.id}/builds", nil) end - it 'does not return project builds' do + it 'does not return project jobs' do expect(response).to have_http_status(401) expect(json_response.except('message')).to be_empty end @@ -147,7 +147,7 @@ describe API::Builds, api: true do end context 'authorized user' do - it 'returns specific build data' do + it 'returns specific job data' do expect(response).to have_http_status(200) expect(json_response['name']).to eq('test') end @@ -165,7 +165,7 @@ describe API::Builds, api: true do context 'unauthorized user' do let(:api_user) { nil } - it 'does not return specific build data' do + it 'does not return specific job data' do expect(response).to have_http_status(401) end end @@ -176,7 +176,7 @@ describe API::Builds, api: true do get api("/projects/#{project.id}/builds/#{build.id}/artifacts", api_user) end - context 'build with artifacts' do + context 'job with artifacts' do let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) } context 'authorized user' do @@ -185,7 +185,7 @@ describe API::Builds, api: true do 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' } end - it 'returns specific build artifacts' do + it 'returns specific job artifacts' do expect(response).to have_http_status(200) expect(response.headers).to include(download_headers) end @@ -194,13 +194,13 @@ describe API::Builds, api: true do context 'unauthorized user' do let(:api_user) { nil } - it 'does not return specific build artifacts' do + it 'does not return specific job artifacts' do expect(response).to have_http_status(401) end end end - it 'does not return build artifacts if not uploaded' do + it 'does not return job artifacts if not uploaded' do expect(response).to have_http_status(404) end end @@ -241,7 +241,7 @@ describe API::Builds, api: true do end end - context 'non-existing build' do + context 'non-existing job' do shared_examples 'not found' do it { expect(response).to have_http_status(:not_found) } end @@ -254,7 +254,7 @@ describe API::Builds, api: true do it_behaves_like 'not found' end - context 'has no such build' do + context 'has no such job' do before do get path_for_ref(pipeline.ref, 'NOBUILD') end @@ -263,7 +263,7 @@ describe API::Builds, api: true do end end - context 'find proper build' do + context 'find proper job' do shared_examples 'a valid file' do let(:download_headers) do { 'Content-Transfer-Encoding' => 'binary', @@ -311,7 +311,7 @@ describe API::Builds, api: true do end context 'authorized user' do - it 'returns specific build trace' do + it 'returns specific job trace' do expect(response).to have_http_status(200) expect(response.body).to eq(build.trace) end @@ -320,7 +320,7 @@ describe API::Builds, api: true do context 'unauthorized user' do let(:api_user) { nil } - it 'does not return specific build trace' do + it 'does not return specific job trace' do expect(response).to have_http_status(401) end end @@ -333,7 +333,7 @@ describe API::Builds, api: true do context 'authorized user' do context 'user with :update_build persmission' do - it 'cancels running or pending build' do + it 'cancels running or pending job' do expect(response).to have_http_status(201) expect(project.builds.first.status).to eq('canceled') end @@ -342,7 +342,7 @@ describe API::Builds, api: true do context 'user without :update_build permission' do let(:api_user) { reporter.user } - it 'does not cancel build' do + it 'does not cancel job' do expect(response).to have_http_status(403) end end @@ -351,7 +351,7 @@ describe API::Builds, api: true do context 'unauthorized user' do let(:api_user) { nil } - it 'does not cancel build' do + it 'does not cancel job' do expect(response).to have_http_status(401) end end @@ -366,7 +366,7 @@ describe API::Builds, api: true do context 'authorized user' do context 'user with :update_build permission' do - it 'retries non-running build' do + it 'retries non-running job' do expect(response).to have_http_status(201) expect(project.builds.first.status).to eq('canceled') expect(json_response['status']).to eq('pending') @@ -376,7 +376,7 @@ describe API::Builds, api: true do context 'user without :update_build permission' do let(:api_user) { reporter.user } - it 'does not retry build' do + it 'does not retry job' do expect(response).to have_http_status(403) end end @@ -385,7 +385,7 @@ describe API::Builds, api: true do context 'unauthorized user' do let(:api_user) { nil } - it 'does not retry build' do + it 'does not retry job' do expect(response).to have_http_status(401) end end @@ -396,23 +396,23 @@ describe API::Builds, api: true do post api("/projects/#{project.id}/builds/#{build.id}/erase", user) end - context 'build is erasable' do + context 'job is erasable' do let(:build) { create(:ci_build, :trace, :artifacts, :success, project: project, pipeline: pipeline) } - it 'erases build content' do + it 'erases job content' do expect(response.status).to eq 201 expect(build.trace).to be_empty expect(build.artifacts_file.exists?).to be_falsy expect(build.artifacts_metadata.exists?).to be_falsy end - it 'updates build' do + it 'updates job' do expect(build.reload.erased_at).to be_truthy expect(build.reload.erased_by).to eq user end end - context 'build is not erasable' do + context 'job is not erasable' do let(:build) { create(:ci_build, :trace, project: project, pipeline: pipeline) } it 'responds with forbidden' do @@ -452,20 +452,20 @@ describe API::Builds, api: true do post api("/projects/#{project.id}/builds/#{build.id}/play", user) end - context 'on an playable build' do + context 'on an playable job' do let(:build) { create(:ci_build, :manual, project: project, pipeline: pipeline) } - it 'plays the build' do + it 'plays the job' do expect(response).to have_http_status 200 expect(json_response['user']['id']).to eq(user.id) expect(json_response['id']).to eq(build.id) end end - context 'on a non-playable build' do + context 'on a non-playable job' do it 'returns a status code 400, Bad Request' do expect(response).to have_http_status 400 - expect(response.body).to match("Unplayable Build") + expect(response.body).to match("Unplayable Job") end end end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 1187d2e609d..a027c23bb88 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -326,7 +326,7 @@ describe API::Groups, api: true do expect(response).to have_http_status(404) end - it "should only return projects to which user has access" do + it "only returns projects to which user has access" do project3.team << [user3, :developer] get api("/groups/#{group1.id}/projects", user3) @@ -338,7 +338,7 @@ describe API::Groups, api: true do end context "when authenticated as admin" do - it "should return any existing group" do + it "returns any existing group" do get api("/groups/#{group2.id}/projects", admin) expect(response).to have_http_status(200) @@ -346,7 +346,7 @@ describe API::Groups, api: true do expect(json_response.first['name']).to eq(project2.name) end - it "should not return a non existing group" do + it "does not return a non existing group" do get api("/groups/1328/projects", admin) expect(response).to have_http_status(404) @@ -354,7 +354,7 @@ describe API::Groups, api: true do end context 'when using group path in URL' do - it 'should return any existing group' do + it 'returns any existing group' do get api("/groups/#{group1.path}/projects", admin) expect(response).to have_http_status(200) diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index 01032c0929b..45d5ae267c5 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -4,6 +4,7 @@ describe API::ProjectSnippets, api: true do include ApiHelpers let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } let(:admin) { create(:admin) } describe 'GET /projects/:project_id/snippets/:id' do @@ -22,7 +23,7 @@ describe API::ProjectSnippets, api: true do let(:user) { create(:user) } it 'returns all snippets available to team member' do - project.team << [user, :developer] + project.add_developer(user) public_snippet = create(:project_snippet, :public, project: project) internal_snippet = create(:project_snippet, :internal, project: project) private_snippet = create(:project_snippet, :private, project: project) @@ -50,7 +51,7 @@ describe API::ProjectSnippets, api: true do title: 'Test Title', file_name: 'test.rb', code: 'puts "hello world"', - visibility_level: Gitlab::VisibilityLevel::PUBLIC + visibility_level: Snippet::PUBLIC } end @@ -72,6 +73,51 @@ describe API::ProjectSnippets, api: true do expect(response).to have_http_status(400) end + + context 'when the snippet is spam' do + def create_snippet(project, snippet_params = {}) + project.add_developer(user) + + post api("/projects/#{project.id}/snippets", user), params.merge(snippet_params) + end + + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the project is private' do + let(:private_project) { create(:project_empty_repo, :private) } + + context 'when the snippet is public' do + it 'creates the snippet' do + expect { create_snippet(private_project, visibility_level: Snippet::PUBLIC) }. + to change { Snippet.count }.by(1) + end + end + end + + context 'when the project is public' do + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(project, visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) + end + end + + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + expect(response).to have_http_status(400) + end + + it 'creates a spam log' do + expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end + end end describe 'PUT /projects/:project_id/snippets/:id/' do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index a1db81ce18c..753dde0ca3a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -459,7 +459,7 @@ describe API::Projects, api: true do before { project } before { admin } - it 'should create new project without path and return 201' do + it 'creates new project without path and return 201' do expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1) expect(response).to have_http_status(201) end diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index f6fb6ea5506..6b9a739b439 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -80,7 +80,7 @@ describe API::Snippets, api: true do title: 'Test Title', file_name: 'test.rb', content: 'puts "hello world"', - visibility_level: Gitlab::VisibilityLevel::PUBLIC + visibility_level: Snippet::PUBLIC } end @@ -101,6 +101,36 @@ describe API::Snippets, api: true do expect(response).to have_http_status(400) end + + context 'when the snippet is spam' do + def create_snippet(snippet_params = {}) + post api('/snippets', user), params.merge(snippet_params) + end + + before do + allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true) + end + + context 'when the snippet is private' do + it 'creates the snippet' do + expect { create_snippet(visibility_level: Snippet::PRIVATE) }. + to change { Snippet.count }.by(1) + end + end + + context 'when the snippet is public' do + it 'rejects the shippet' do + expect { create_snippet(visibility_level: Snippet::PUBLIC) }. + not_to change { Snippet.count } + expect(response).to have_http_status(400) + end + + it 'creates a spam log' do + expect { create_snippet(visibility_level: Snippet::PUBLIC) }. + to change { SpamLog.count }.by(1) + end + end + end end describe 'PUT /snippets/:id' do diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 5bf5bf0739e..8692f9da976 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -305,6 +305,13 @@ describe API::Users, api: true do expect(user.reload.bio).to eq('new test bio') end + it "updates user with new password and forces reset on next login" do + put api("/users/#{user.id}", admin), password: '12345678' + + expect(response).to have_http_status(200) + expect(user.reload.password_expires_at).to be <= Time.now + end + it "updates user with organization" do put api("/users/#{user.id}", admin), { organization: 'GitLab' } diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 8dbe5f0b025..d85afdeab42 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -288,7 +288,7 @@ describe Ci::API::Builds do expect(build.reload.trace).to eq 'BUILD TRACE' end - context 'build has been erased' do + context 'job has been erased' do let(:build) { create(:ci_build, runner_id: runner.id, erased_at: Time.now) } it 'responds with forbidden' do @@ -458,7 +458,7 @@ describe Ci::API::Builds do before { build.run! } describe "POST /builds/:id/artifacts/authorize" do - context "should authorize posting artifact to running build" do + context "authorizes posting artifact to running build" do it "using token as parameter" do post authorize_url, { token: build.token }, headers @@ -492,7 +492,7 @@ describe Ci::API::Builds do end end - context "should fail to post too large artifact" do + context "fails to post too large artifact" do it "using token as parameter" do stub_application_setting(max_artifacts_size: 0) diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 43be785ad9d..a5bc62ef6c2 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe 'project routing' do before do - allow(Project).to receive(:find_with_namespace).and_return(false) - allow(Project).to receive(:find_with_namespace).with('gitlab/gitlabhq').and_return(true) + allow(Project).to receive(:find_by_full_path).and_return(false) + allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq').and_return(true) end # Shared examples for a resource inside a Project @@ -93,13 +93,13 @@ describe 'project routing' do end context 'name with dot' do - before { allow(Project).to receive(:find_with_namespace).with('gitlab/gitlabhq.keys').and_return(true) } + before { allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq.keys').and_return(true) } it { expect(get('/gitlab/gitlabhq.keys')).to route_to('projects#show', namespace_id: 'gitlab', id: 'gitlabhq.keys') } end context 'with nested group' do - before { allow(Project).to receive(:find_with_namespace).with('gitlab/subgroup/gitlabhq').and_return(true) } + before { allow(Project).to receive(:find_by_full_path).with('gitlab/subgroup/gitlabhq').and_return(true) } it { expect(get('/gitlab/subgroup/gitlabhq')).to route_to('projects#show', namespace_id: 'gitlab/subgroup', id: 'gitlabhq') } end diff --git a/spec/services/compare_service_spec.rb b/spec/services/compare_service_spec.rb index 3760f19aaa2..0a7fc58523f 100644 --- a/spec/services/compare_service_spec.rb +++ b/spec/services/compare_service_spec.rb @@ -3,17 +3,17 @@ require 'spec_helper' describe CompareService, services: true do let(:project) { create(:project) } let(:user) { create(:user) } - let(:service) { described_class.new } + let(:service) { described_class.new(project, 'feature') } describe '#execute' do context 'compare with base, like feature...fix' do - subject { service.execute(project, 'feature', project, 'fix', straight: false) } + subject { service.execute(project, 'fix', straight: false) } it { expect(subject.diffs.size).to eq(1) } end context 'straight compare, like feature..fix' do - subject { service.execute(project, 'feature', project, 'fix', straight: true) } + subject { service.execute(project, 'fix', straight: true) } it { expect(subject.diffs.size).to eq(3) } end diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb index b7dc99ed887..f2c2009bcbf 100644 --- a/spec/services/event_create_service_spec.rb +++ b/spec/services/event_create_service_spec.rb @@ -9,7 +9,7 @@ describe EventCreateService, services: true do it { expect(service.open_issue(issue, issue.author)).to be_truthy } - it "should create new event" do + it "creates new event" do expect { service.open_issue(issue, issue.author) }.to change { Event.count } end end @@ -19,7 +19,7 @@ describe EventCreateService, services: true do it { expect(service.close_issue(issue, issue.author)).to be_truthy } - it "should create new event" do + it "creates new event" do expect { service.close_issue(issue, issue.author) }.to change { Event.count } end end @@ -29,7 +29,7 @@ describe EventCreateService, services: true do it { expect(service.reopen_issue(issue, issue.author)).to be_truthy } - it "should create new event" do + it "creates new event" do expect { service.reopen_issue(issue, issue.author) }.to change { Event.count } end end diff --git a/spec/services/files/update_service_spec.rb b/spec/services/files/update_service_spec.rb index d3c37c7820f..35e6e139238 100644 --- a/spec/services/files/update_service_spec.rb +++ b/spec/services/files/update_service_spec.rb @@ -6,7 +6,10 @@ describe Files::UpdateService do let(:project) { create(:project) } let(:user) { create(:user) } let(:file_path) { 'files/ruby/popen.rb' } - let(:new_contents) { "New Content" } + let(:new_contents) { 'New Content' } + let(:target_branch) { project.default_branch } + let(:last_commit_sha) { nil } + let(:commit_params) do { file_path: file_path, @@ -14,9 +17,9 @@ describe Files::UpdateService do file_content: new_contents, file_content_encoding: "text", last_commit_sha: last_commit_sha, - source_project: project, - source_branch: project.default_branch, - target_branch: project.default_branch, + start_project: project, + start_branch: project.default_branch, + target_branch: target_branch } end @@ -54,18 +57,6 @@ describe Files::UpdateService do end context "when the last_commit_sha is not supplied" do - let(:commit_params) do - { - file_path: file_path, - commit_message: "Update File", - file_content: new_contents, - file_content_encoding: "text", - source_project: project, - source_branch: project.default_branch, - target_branch: project.default_branch, - } - end - it "returns a hash with the :success status " do results = subject.execute @@ -80,5 +71,15 @@ describe Files::UpdateService do expect(results.data).to eq(new_contents) end end + + context 'when target branch is different than source branch' do + let(:target_branch) { "#{project.default_branch}-new" } + + it 'fires hooks only once' do + expect(GitHooksService).to receive(:new).once.and_call_original + + subject.execute + end + end end end diff --git a/spec/services/git_hooks_service_spec.rb b/spec/services/git_hooks_service_spec.rb index 41b0968b8b4..3318dfb22b6 100644 --- a/spec/services/git_hooks_service_spec.rb +++ b/spec/services/git_hooks_service_spec.rb @@ -21,7 +21,7 @@ describe GitHooksService, services: true do hook = double(trigger: [true, nil]) expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook) - expect(service.execute(user, @repo_path, @blankrev, @newrev, @ref) { }).to eq([true, nil]) + service.execute(user, @repo_path, @blankrev, @newrev, @ref) { } end end diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb index 5f6a7716beb..d55a7657c0e 100644 --- a/spec/services/merge_requests/close_service_spec.rb +++ b/spec/services/merge_requests/close_service_spec.rb @@ -29,7 +29,7 @@ describe MergeRequests::CloseService, services: true do it { expect(@merge_request).to be_valid } it { expect(@merge_request).to be_closed } - it 'should execute hooks with close action' do + it 'executes hooks with close action' do expect(service).to have_received(:execute_hooks). with(@merge_request, 'close') end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 314ea670a71..2cc21acab7b 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -89,7 +89,7 @@ describe MergeRequests::RefreshService, services: true do # Merge master -> feature branch author = { email: 'test@gitlab.com', time: Time.now, name: "Me" } commit_options = { message: 'Test message', committer: author, author: author } - @project.repository.merge(@user, @merge_request, commit_options) + @project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, commit_options) commit = @project.repository.commit('feature') service.new(@project, @user).execute(@oldrev, commit.id, 'refs/heads/feature') reload_mrs diff --git a/spec/services/merge_requests/resolve_service_spec.rb b/spec/services/merge_requests/resolve_service_spec.rb index 388abb6a0df..a0e51681725 100644 --- a/spec/services/merge_requests/resolve_service_spec.rb +++ b/spec/services/merge_requests/resolve_service_spec.rb @@ -66,7 +66,13 @@ describe MergeRequests::ResolveService do context 'when the source project is a fork and does not contain the HEAD of the target branch' do let!(:target_head) do - project.repository.commit_file(user, 'new-file-in-target', '', 'Add new file in target', 'conflict-start', false) + project.repository.commit_file( + user, + 'new-file-in-target', + '', + message: 'Add new file in target', + branch_name: 'conflict-start', + update: false) end before do diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index 75c95d70951..6ed55289ed9 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -35,7 +35,13 @@ module CycleAnalyticsHelpers project.repository.add_branch(user, source_branch, 'master') end - sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) + sha = project.repository.commit_file( + user, + random_git_name, + 'content', + message: 'commit message', + branch_name: source_branch, + update: false) project.repository.commit(sha) opts = { diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb index 10b90b40ba7..19b32c84d81 100644 --- a/spec/support/cycle_analytics_helpers/test_generation.rb +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -63,22 +63,20 @@ module CycleAnalyticsHelpers # test case. allow(self).to receive(:project) { other_project } - 5.times do - data = data_fn[self] - start_time = Time.now - end_time = rand(1..10).days.from_now - - start_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(start_time) { condition_fn[self, data] } - end + data = data_fn[self] + start_time = Time.now + end_time = rand(1..10).days.from_now - end_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(end_time) { condition_fn[self, data] } - end + start_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(start_time) { condition_fn[self, data] } + end - Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } end + Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn + # Turn off the stub before checking assertions allow(self).to receive(:project).and_call_original @@ -114,17 +112,15 @@ module CycleAnalyticsHelpers context "start condition NOT PRESENT: #{start_time_conditions.map(&:first).to_sentence}" do context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do it "returns nil" do - 5.times do - data = data_fn[self] - end_time = rand(1..10).days.from_now - - end_time_conditions.each_with_index do |(condition_name, condition_fn), index| - Timecop.freeze(end_time + index.days) { condition_fn[self, data] } - end + data = data_fn[self] + end_time = rand(1..10).days.from_now - Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn + end_time_conditions.each_with_index do |(condition_name, condition_fn), index| + Timecop.freeze(end_time + index.days) { condition_fn[self, data] } end + Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn + expect(subject[phase].median).to be_nil end end @@ -133,17 +129,15 @@ module CycleAnalyticsHelpers context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do context "end condition NOT PRESENT: #{end_time_conditions.map(&:first).to_sentence}" do it "returns nil" do - 5.times do - data = data_fn[self] - start_time = Time.now - - start_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(start_time) { condition_fn[self, data] } - end + data = data_fn[self] + start_time = Time.now - post_fn[self, data] if post_fn + start_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(start_time) { condition_fn[self, data] } end + post_fn[self, data] if post_fn + expect(subject[phase].median).to be_nil end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 90f1a9c8798..b87232a350b 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -36,7 +36,8 @@ module TestEnv 'conflict-non-utf8' => 'd0a293c', 'conflict-too-large' => '39fa04f', 'deleted-image-test' => '6c17798', - 'wip' => 'b9238ee' + 'wip' => 'b9238ee', + 'csv' => '3dd0896' } # gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily diff --git a/spec/tasks/gitlab/mail_google_schema_whitelisting.rb b/spec/tasks/gitlab/mail_google_schema_whitelisting.rb index 80fc8c48fed..8d1cff7a261 100644 --- a/spec/tasks/gitlab/mail_google_schema_whitelisting.rb +++ b/spec/tasks/gitlab/mail_google_schema_whitelisting.rb @@ -20,7 +20,7 @@ describe 'gitlab:mail_google_schema_whitelisting rake task' do Rake.application.invoke_task "gitlab:mail_google_schema_whitelisting" end - it 'should run the task without errors' do + it 'runs the task without errors' do expect { run_rake_task }.not_to raise_error end end diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index 44870cfcfb3..b6f6e7b7a2b 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -15,7 +15,7 @@ describe 'projects/builds/show', :view do allow(view).to receive(:can?).and_return(true) end - describe 'build information in header' do + describe 'job information in header' do let(:build) do create(:ci_build, :success, environment: 'staging') end @@ -28,11 +28,11 @@ describe 'projects/builds/show', :view do expect(rendered).to have_css('.ci-status.ci-success', text: 'passed') end - it 'does not render a link to the build' do + it 'does not render a link to the job' do expect(rendered).not_to have_link('passed') end - it 'shows build id' do + it 'shows job id' do expect(rendered).to have_css('.js-build-id', text: build.id) end @@ -45,8 +45,8 @@ describe 'projects/builds/show', :view do end end - describe 'environment info in build view' do - context 'build with latest deployment' do + describe 'environment info in job view' do + context 'job with latest deployment' do let(:build) do create(:ci_build, :success, environment: 'staging') end @@ -57,7 +57,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'This build is the most recent deployment' + expected_text = 'This job is the most recent deployment' render expect(rendered).to have_css( @@ -65,7 +65,7 @@ describe 'projects/builds/show', :view do end end - context 'build with outdated deployment' do + context 'job with outdated deployment' do let(:build) do create(:ci_build, :success, environment: 'staging', pipeline: pipeline) end @@ -87,7 +87,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'This build is an out-of-date deployment ' \ + expected_text = 'This job is an out-of-date deployment ' \ "to staging.\nView the most recent deployment ##{second_deployment.iid}." render @@ -95,7 +95,7 @@ describe 'projects/builds/show', :view do end end - context 'build failed to deploy' do + context 'job failed to deploy' do let(:build) do create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) end @@ -105,7 +105,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'The deployment of this build to staging did not succeed.' + expected_text = 'The deployment of this job to staging did not succeed.' render expect(rendered).to have_css( @@ -113,7 +113,7 @@ describe 'projects/builds/show', :view do end end - context 'build will deploy' do + context 'job will deploy' do let(:build) do create(:ci_build, :running, environment: 'staging', pipeline: pipeline) end @@ -124,7 +124,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'This build is creating a deployment to staging' + expected_text = 'This job is creating a deployment to staging' render expect(rendered).to have_css( @@ -137,7 +137,7 @@ describe 'projects/builds/show', :view do end it 'shows that deployment will be overwritten' do - expected_text = 'This build is creating a deployment to staging' + expected_text = 'This job is creating a deployment to staging' render expect(rendered).to have_css( @@ -150,7 +150,7 @@ describe 'projects/builds/show', :view do context 'when environment does not exist' do it 'shows deployment message' do - expected_text = 'This build is creating a deployment to staging' + expected_text = 'This job is creating a deployment to staging' render expect(rendered).to have_css( @@ -161,7 +161,7 @@ describe 'projects/builds/show', :view do end end - context 'build that failed to deploy and environment has not been created' do + context 'job that failed to deploy and environment has not been created' do let(:build) do create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) end @@ -171,7 +171,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'The deployment of this build to staging did not succeed' + expected_text = 'The deployment of this job to staging did not succeed' render expect(rendered).to have_css( @@ -179,7 +179,7 @@ describe 'projects/builds/show', :view do end end - context 'build that will deploy and environment has not been created' do + context 'job that will deploy and environment has not been created' do let(:build) do create(:ci_build, :running, environment: 'staging', pipeline: pipeline) end @@ -189,7 +189,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'This build is creating a deployment to staging' + expected_text = 'This job is creating a deployment to staging' render expect(rendered).to have_css( @@ -200,7 +200,7 @@ describe 'projects/builds/show', :view do end end - context 'when build is running' do + context 'when job is running' do before do build.run! render @@ -211,7 +211,7 @@ describe 'projects/builds/show', :view do end end - context 'when build is not running' do + context 'when job is not running' do before do build.success! render diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index e471a68a49a..5ef8cf1105b 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -107,7 +107,8 @@ describe GitGarbageCollectWorker do tree: old_commit.tree, parents: [old_commit], ) - project.repository.update_ref!( + GitOperationService.new(nil, project.repository).send( + :update_ref, "refs/heads/#{SecureRandom.hex(6)}", new_commit_sha, Gitlab::Git::BLANK_SHA diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 984acdade36..5919b99a6ed 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -74,7 +74,7 @@ describe PostReceive do context "webhook" do it "fetches the correct project" do - expect(Project).to receive(:find_with_namespace).with(project.path_with_namespace).and_return(project) + expect(Project).to receive(:find_by_full_path).with(project.path_with_namespace).and_return(project) PostReceive.new.perform(pwd(project), key_id, base64_changes) end @@ -89,7 +89,7 @@ describe PostReceive do end it "asks the project to trigger all hooks" do - allow(Project).to receive(:find_with_namespace).and_return(project) + allow(Project).to receive(:find_by_full_path).and_return(project) expect(project).to receive(:execute_hooks).twice expect(project).to receive(:execute_services).twice @@ -97,7 +97,7 @@ describe PostReceive do end it "enqueues a UpdateMergeRequestsWorker job" do - allow(Project).to receive(:find_with_namespace).and_return(project) + allow(Project).to receive(:find_by_full_path).and_return(project) expect(UpdateMergeRequestsWorker).to receive(:perform_async).with(project.id, project.owner.id, any_args) PostReceive.new.perform(pwd(project), key_id, base64_changes) diff --git a/spec/workers/project_destroy_worker_spec.rb b/spec/workers/project_destroy_worker_spec.rb index 1b910d9b91e..1f4c39eb64a 100644 --- a/spec/workers/project_destroy_worker_spec.rb +++ b/spec/workers/project_destroy_worker_spec.rb @@ -8,14 +8,14 @@ describe ProjectDestroyWorker do describe "#perform" do it "deletes the project" do - subject.perform(project.id, project.owner, {}) + subject.perform(project.id, project.owner.id, {}) expect(Project.all).not_to include(project) expect(Dir.exist?(path)).to be_falsey end it "deletes the project but skips repo deletion" do - subject.perform(project.id, project.owner, { "skip_repo" => true }) + subject.perform(project.id, project.owner.id, { "skip_repo" => true }) expect(Project.all).not_to include(project) expect(Dir.exist?(path)).to be_truthy |