From f0691ec7c589543f9e294bf0d9cbc9eea2c2f166 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Sat, 16 Jul 2016 07:12:12 +0000 Subject: Revert "Merge branch 'revert-bdb6f1e6' into 'master'" This reverts merge request !5290 --- spec/features/issues/move_spec.rb | 2 +- spec/features/issues_spec.rb | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb index 7773c486b4e..055210399a7 100644 --- a/spec/features/issues/move_spec.rb +++ b/spec/features/issues/move_spec.rb @@ -55,7 +55,7 @@ feature 'issue move to another project' do first('.select2-choice').click end - fill_in('s2id_autogen2_search', with: new_project_search.name) + fill_in('s2id_autogen1_search', with: new_project_search.name) page.within '.select2-drop' do expect(page).to have_content(new_project_search.name) diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index d51c9abea19..d00cffa4e2b 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -50,9 +50,8 @@ describe 'Issues', feature: true do expect(page).to have_content "Assignee #{@user.name}" - first('#s2id_issue_assignee_id').click - sleep 2 # wait for ajax stuff to complete - first('.user-result').click + first('.js-user-search').click + click_link 'Unassigned' click_button 'Save changes' -- cgit v1.2.1 From 75892aebabf96f6cce9057b67f21d403d70a1d95 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 18 Jul 2016 13:23:45 +0100 Subject: Added tests for new/edit issue form --- spec/features/issues/form_spec.rb | 85 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 spec/features/issues/form_spec.rb (limited to 'spec') diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb new file mode 100644 index 00000000000..6c14dff6a37 --- /dev/null +++ b/spec/features/issues/form_spec.rb @@ -0,0 +1,85 @@ +require 'rails_helper' + +describe 'New/edit issue', feature: true, js: true do + let!(:project) { create(:project) } + let!(:user) { create(:user)} + let!(:milestone) { create(:milestone, project: project) } + let!(:label) { create(:label, project: project) } + let!(:label2) { create(:label, project: project) } + let!(:issue) { create(:issue, project: project, assignee: user, milestone: milestone) } + + before do + project.team << [user, :master] + login_as(user) + end + + context 'new issue' do + before do + visit new_namespace_project_issue_path(project.namespace, project) + end + + it 'should allow user to create new issue' do + fill_in 'issue_title', with: 'title' + fill_in 'issue_description', with: 'title' + + click_button 'Assignee' + click_link user.name + + page.find '.js-assignee-search' do + expect(page).to have_content user.name + end + + click_button 'Milestone' + click_link milestone.title + + page.find '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + click_link label.title + click_link label2.title + + page.find '.js-label-select' do + expect(page).to have_content label2.title + end + + click_button 'Submit issue' + + page.find '.issuable-sidebar' do + expect(page).to have_content user.name + expect(page).to have_content milestone.title + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end + end + + context 'edit issue' do + before do + visit edit_namespace_project_issue_path(project.namespace, project, issue) + end + + it 'should allow user to update issue' do + expect(page).to have_content user.name + expect(page).to have_content milestone.title + + click_button 'Labels' + click_link label.title + click_link label2.title + + page.find '.js-label-select' do + expect(page).to have_content label2.title + end + + click_button 'Save changes' + + page.find '.issuable-sidebar' do + expect(page).to have_content user.name + expect(page).to have_content milestone.title + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end + end +end -- cgit v1.2.1 From feeb489302dcf82e0e1f7e014c34824d52f8a882 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 18 Jul 2016 14:21:30 +0100 Subject: Added spec tests for merge request form including from forked project --- spec/features/merge_requests/form_spec.rb | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 spec/features/merge_requests/form_spec.rb (limited to 'spec') diff --git a/spec/features/merge_requests/form_spec.rb b/spec/features/merge_requests/form_spec.rb new file mode 100644 index 00000000000..8da33b0f3c3 --- /dev/null +++ b/spec/features/merge_requests/form_spec.rb @@ -0,0 +1,87 @@ +require 'rails_helper' + +describe 'New/edit merge request', feature: true, js: true do + let!(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let(:fork_project) { create(:project, forked_from_project: project) } + let!(:user) { create(:user)} + let!(:milestone) { create(:milestone, project: project) } + let!(:label) { create(:label, project: project) } + let!(:label2) { create(:label, project: project) } + + before do + project.team << [user, :master] + end + + context 'owned projects' do + before do + merge_request = create(:merge_request, + source_project: project, + target_project: project, + source_branch: 'fix', + target_branch: 'master' + ) + + login_as(user) + + visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'should update merge request' do + update_merge_request + end + end + + context 'forked project' do + before do + fork_project.team << [user, :master] + + merge_request = create(:merge_request, + source_project: fork_project, + target_project: project, + source_branch: 'fix', + target_branch: 'master' + ) + + login_as(user) + + visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'should update merge request' do + update_merge_request + end + end + + def update_merge_request + click_button 'Assignee' + click_link user.name + + page.find '.js-assignee-search' do + expect(page).to have_content user.name + end + + click_button 'Milestone' + click_link milestone.title + + page.find '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + click_link label.title + click_link label2.title + + page.find '.js-label-select' do + expect(page).to have_content label2.title + end + + click_button 'Save changes' + + page.find '.issuable-sidebar' do + expect(page).to have_content user.name + expect(page).to have_content milestone.title + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end +end -- cgit v1.2.1 From 357ad44a744db07b6c849bf262f00100b448382b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 18 Jul 2016 15:13:56 +0100 Subject: Fixed Rubocop errors --- spec/features/merge_requests/form_spec.rb | 85 ++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 30 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/form_spec.rb b/spec/features/merge_requests/form_spec.rb index 8da33b0f3c3..9d6706ee9b3 100644 --- a/spec/features/merge_requests/form_spec.rb +++ b/spec/features/merge_requests/form_spec.rb @@ -19,7 +19,7 @@ describe 'New/edit merge request', feature: true, js: true do target_project: project, source_branch: 'fix', target_branch: 'master' - ) + ) login_as(user) @@ -27,7 +27,36 @@ describe 'New/edit merge request', feature: true, js: true do end it 'should update merge request' do - update_merge_request + click_button 'Assignee' + click_link user.name + + page.find '.js-assignee-search' do + expect(page).to have_content user.name + end + + click_button 'Milestone' + click_link milestone.title + + page.find '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + click_link label.title + click_link label2.title + + page.find '.js-label-select' do + expect(page).to have_content label2.title + end + + click_button 'Save changes' + + page.find '.issuable-sidebar' do + expect(page).to have_content user.name + expect(page).to have_content milestone.title + expect(page).to have_content label.title + expect(page).to have_content label2.title + end end end @@ -40,7 +69,7 @@ describe 'New/edit merge request', feature: true, js: true do target_project: project, source_branch: 'fix', target_branch: 'master' - ) + ) login_as(user) @@ -48,40 +77,36 @@ describe 'New/edit merge request', feature: true, js: true do end it 'should update merge request' do - update_merge_request - end - end - - def update_merge_request - click_button 'Assignee' - click_link user.name + click_button 'Assignee' + click_link user.name - page.find '.js-assignee-search' do - expect(page).to have_content user.name - end + page.find '.js-assignee-search' do + expect(page).to have_content user.name + end - click_button 'Milestone' - click_link milestone.title + click_button 'Milestone' + click_link milestone.title - page.find '.js-milestone-select' do - expect(page).to have_content milestone.title - end + page.find '.js-milestone-select' do + expect(page).to have_content milestone.title + end - click_button 'Labels' - click_link label.title - click_link label2.title + click_button 'Labels' + click_link label.title + click_link label2.title - page.find '.js-label-select' do - expect(page).to have_content label2.title - end + page.find '.js-label-select' do + expect(page).to have_content label2.title + end - click_button 'Save changes' + click_button 'Save changes' - page.find '.issuable-sidebar' do - expect(page).to have_content user.name - expect(page).to have_content milestone.title - expect(page).to have_content label.title - expect(page).to have_content label2.title + page.find '.issuable-sidebar' do + expect(page).to have_content user.name + expect(page).to have_content milestone.title + expect(page).to have_content label.title + expect(page).to have_content label2.title + end end end end -- cgit v1.2.1 From 47d8fb84d80d23432c9afea055da4c56ea749206 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 19 Jul 2016 10:05:38 +0100 Subject: Uses the selected values from the controller not the params Added tests for new merge requests from forked project & owned project --- spec/features/issues/form_spec.rb | 90 +++++++--- spec/features/merge_requests/form_spec.rb | 281 +++++++++++++++++++++++------- 2 files changed, 283 insertions(+), 88 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index 6c14dff6a37..2d0dae6f150 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -23,34 +23,49 @@ describe 'New/edit issue', feature: true, js: true do fill_in 'issue_description', with: 'title' click_button 'Assignee' - click_link user.name - - page.find '.js-assignee-search' do + page.within '.dropdown-menu-user' do + click_link user.name + end + expect(find('input[name="issue[assignee_id]"]', visible: false).value).to match(user.id.to_s) + page.within '.js-assignee-search' do expect(page).to have_content user.name end click_button 'Milestone' - click_link milestone.title - - page.find '.js-milestone-select' do + page.within '.issue-milestone' do + click_link milestone.title + end + expect(find('input[name="issue[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) + page.within '.js-milestone-select' do expect(page).to have_content milestone.title end click_button 'Labels' - click_link label.title - click_link label2.title - - page.find '.js-label-select' do - expect(page).to have_content label2.title + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + page.within '.js-label-select' do + expect(page).to have_content label.title end + expect(page.all('input[name="issue[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="issue[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) click_button 'Submit issue' - page.find '.issuable-sidebar' do - expect(page).to have_content user.name - expect(page).to have_content milestone.title - expect(page).to have_content label.title - expect(page).to have_content label2.title + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end + + page.within '.milestone' do + expect(page).to have_content milestone.title + end + + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end end end end @@ -61,24 +76,43 @@ describe 'New/edit issue', feature: true, js: true do end it 'should allow user to update issue' do - expect(page).to have_content user.name - expect(page).to have_content milestone.title + expect(find('input[name="issue[assignee_id]"]', visible: false).value).to match(user.id.to_s) + expect(find('input[name="issue[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) - click_button 'Labels' - click_link label.title - click_link label2.title + page.within '.js-user-search' do + expect(page).to have_content user.name + end - page.find '.js-label-select' do - expect(page).to have_content label2.title + page.within '.js-milestone-select' do + expect(page).to have_content milestone.title end + click_button 'Labels' + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + page.within '.js-label-select' do + expect(page).to have_content label.title + end + expect(page.all('input[name="issue[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="issue[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) + click_button 'Save changes' - page.find '.issuable-sidebar' do - expect(page).to have_content user.name - expect(page).to have_content milestone.title - expect(page).to have_content label.title - expect(page).to have_content label2.title + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end + + page.within '.milestone' do + expect(page).to have_content milestone.title + end + + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end end end end diff --git a/spec/features/merge_requests/form_spec.rb b/spec/features/merge_requests/form_spec.rb index 9d6706ee9b3..b9591644cd2 100644 --- a/spec/features/merge_requests/form_spec.rb +++ b/spec/features/merge_requests/form_spec.rb @@ -14,48 +14,129 @@ describe 'New/edit merge request', feature: true, js: true do context 'owned projects' do before do - merge_request = create(:merge_request, - source_project: project, - target_project: project, - source_branch: 'fix', - target_branch: 'master' - ) - login_as(user) - - visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) end + + context 'new merge request' do + before do + visit new_namespace_project_merge_request_path( + project.namespace, + project, + merge_request: { + source_project_id: project.id, + target_project_id: project.id, + source_branch: 'fix', + target_branch: 'master' + }) + end - it 'should update merge request' do - click_button 'Assignee' - click_link user.name + it 'should create new merge request' do + click_button 'Assignee' + page.within '.dropdown-menu-user' do + click_link user.name + end + expect(find('input[name="merge_request[assignee_id]"]', visible: false).value).to match(user.id.to_s) + page.within '.js-assignee-search' do + expect(page).to have_content user.name + end - page.find '.js-assignee-search' do - expect(page).to have_content user.name - end + click_button 'Milestone' + page.within '.issue-milestone' do + click_link milestone.title + end + expect(find('input[name="merge_request[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) + page.within '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + page.within '.js-label-select' do + expect(page).to have_content label.title + end + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) + + click_button 'Submit merge request' + + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end - click_button 'Milestone' - click_link milestone.title + page.within '.milestone' do + expect(page).to have_content milestone.title + end - page.find '.js-milestone-select' do - expect(page).to have_content milestone.title + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end end + end - click_button 'Labels' - click_link label.title - click_link label2.title + context 'edit merge request' do + before do + merge_request = create(:merge_request, + source_project: project, + target_project: project, + source_branch: 'fix', + target_branch: 'master' + ) - page.find '.js-label-select' do - expect(page).to have_content label2.title + visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) end - click_button 'Save changes' + it 'should update merge request' do + click_button 'Assignee' + page.within '.dropdown-menu-user' do + click_link user.name + end + expect(find('input[name="merge_request[assignee_id]"]', visible: false).value).to match(user.id.to_s) + page.within '.js-assignee-search' do + expect(page).to have_content user.name + end + + click_button 'Milestone' + page.within '.issue-milestone' do + click_link milestone.title + end + expect(find('input[name="merge_request[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) + page.within '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) + page.within '.js-label-select' do + expect(page).to have_content label.title + end + + click_button 'Save changes' + + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end + + page.within '.milestone' do + expect(page).to have_content milestone.title + end - page.find '.issuable-sidebar' do - expect(page).to have_content user.name - expect(page).to have_content milestone.title - expect(page).to have_content label.title - expect(page).to have_content label2.title + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end end end end @@ -63,49 +144,129 @@ describe 'New/edit merge request', feature: true, js: true do context 'forked project' do before do fork_project.team << [user, :master] + login_as(user) + end - merge_request = create(:merge_request, - source_project: fork_project, - target_project: project, - source_branch: 'fix', - target_branch: 'master' - ) + context 'new merge request' do + before do + visit new_namespace_project_merge_request_path( + fork_project.namespace, + fork_project, + merge_request: { + source_project_id: fork_project.id, + target_project_id: project.id, + source_branch: 'fix', + target_branch: 'master' + }) + end - login_as(user) + it 'should create new merge request' do + click_button 'Assignee' + page.within '.dropdown-menu-user' do + click_link user.name + end + expect(find('input[name="merge_request[assignee_id]"]', visible: false).value).to match(user.id.to_s) + page.within '.js-assignee-search' do + expect(page).to have_content user.name + end - visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) - end + click_button 'Milestone' + page.within '.issue-milestone' do + click_link milestone.title + end + expect(find('input[name="merge_request[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) + page.within '.js-milestone-select' do + expect(page).to have_content milestone.title + end - it 'should update merge request' do - click_button 'Assignee' - click_link user.name + click_button 'Labels' + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + page.within '.js-label-select' do + expect(page).to have_content label.title + end + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) - page.find '.js-assignee-search' do - expect(page).to have_content user.name - end + click_button 'Submit merge request' + + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end - click_button 'Milestone' - click_link milestone.title + page.within '.milestone' do + expect(page).to have_content milestone.title + end - page.find '.js-milestone-select' do - expect(page).to have_content milestone.title + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end end + end - click_button 'Labels' - click_link label.title - click_link label2.title + context 'edit merge request' do + before do + merge_request = create(:merge_request, + source_project: fork_project, + target_project: project, + source_branch: 'fix', + target_branch: 'master' + ) - page.find '.js-label-select' do - expect(page).to have_content label2.title + visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) end - click_button 'Save changes' + it 'should update merge request' do + click_button 'Assignee' + page.within '.dropdown-menu-user' do + click_link user.name + end + expect(find('input[name="merge_request[assignee_id]"]', visible: false).value).to match(user.id.to_s) + page.within '.js-assignee-search' do + expect(page).to have_content user.name + end + + click_button 'Milestone' + page.within '.issue-milestone' do + click_link milestone.title + end + expect(find('input[name="merge_request[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) + page.within '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="merge_request[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) + page.within '.js-label-select' do + expect(page).to have_content label.title + end + + click_button 'Save changes' + + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end + + page.within '.milestone' do + expect(page).to have_content milestone.title + end - page.find '.issuable-sidebar' do - expect(page).to have_content user.name - expect(page).to have_content milestone.title - expect(page).to have_content label.title - expect(page).to have_content label2.title + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end + end end end end -- cgit v1.2.1 From a87e0dacfcc8067cdb829768fa95dc7139f3cc50 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 19 Jul 2016 11:01:34 +0100 Subject: Fixed failing issuable filter specs --- spec/features/issues/filter_issues_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 4b9b5394b61..d2d9b8594c9 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -95,9 +95,9 @@ describe 'Filter issues', feature: true do wait_for_ajax page.within '.labels-filter' do - expect(page).to have_content 'No Label' + expect(page).to have_content 'Labels' end - expect(find('.js-label-select .dropdown-toggle-text')).to have_content('No Label') + expect(find('.js-label-select .dropdown-toggle-text')).to have_content('Labels') end it 'should filter by no label' do -- cgit v1.2.1 From a6e312bf1dd01aa653761c5bf1e848df9707c0cb Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 21 Jul 2016 08:52:37 +0100 Subject: Updated wording in the specs --- spec/features/issues/form_spec.rb | 4 ++-- spec/features/merge_requests/form_spec.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index 2d0dae6f150..8771cc8e157 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -18,7 +18,7 @@ describe 'New/edit issue', feature: true, js: true do visit new_namespace_project_issue_path(project.namespace, project) end - it 'should allow user to create new issue' do + it 'allows user to create new issue' do fill_in 'issue_title', with: 'title' fill_in 'issue_description', with: 'title' @@ -75,7 +75,7 @@ describe 'New/edit issue', feature: true, js: true do visit edit_namespace_project_issue_path(project.namespace, project, issue) end - it 'should allow user to update issue' do + it 'allows user to update issue' do expect(find('input[name="issue[assignee_id]"]', visible: false).value).to match(user.id.to_s) expect(find('input[name="issue[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) diff --git a/spec/features/merge_requests/form_spec.rb b/spec/features/merge_requests/form_spec.rb index b9591644cd2..7594cbf54e8 100644 --- a/spec/features/merge_requests/form_spec.rb +++ b/spec/features/merge_requests/form_spec.rb @@ -16,7 +16,7 @@ describe 'New/edit merge request', feature: true, js: true do before do login_as(user) end - + context 'new merge request' do before do visit new_namespace_project_merge_request_path( @@ -30,7 +30,7 @@ describe 'New/edit merge request', feature: true, js: true do }) end - it 'should create new merge request' do + it 'creates new merge request' do click_button 'Assignee' page.within '.dropdown-menu-user' do click_link user.name @@ -91,7 +91,7 @@ describe 'New/edit merge request', feature: true, js: true do visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) end - it 'should update merge request' do + it 'updates merge request' do click_button 'Assignee' page.within '.dropdown-menu-user' do click_link user.name @@ -160,7 +160,7 @@ describe 'New/edit merge request', feature: true, js: true do }) end - it 'should create new merge request' do + it 'creates new merge request' do click_button 'Assignee' page.within '.dropdown-menu-user' do click_link user.name -- cgit v1.2.1 From a81de9ab4fc3c3720449069e91ee2431fd9eb024 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 26 Aug 2016 12:49:32 +0530 Subject: Add a spec for the `CycleAnalytics#issue` method. --- spec/models/cycle_analytics/issue_spec.rb | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 spec/models/cycle_analytics/issue_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb new file mode 100644 index 00000000000..ba66c99631c --- /dev/null +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -0,0 +1,80 @@ +require 'spec_helper' + +describe 'CycleAnalytics#issue', models: true do + let(:project) { create(:project) } + subject { CycleAnalytics.new } + + context "when calculating the median of times between: + start: issue created_at + end: milestone first added to issue + OR + list-label first added to issue + " do + context "when a milestone is added to the issue" do + it "calculates the median of available durations" do + start_and_end_times = Array.new(5) do + start_time = Time.now + end_time = rand(1..10).days.from_now + + milestone = create(:milestone, project: project) + issue = Timecop.freeze(start_time) { create(:issue, project: project) } + Timecop.freeze(end_time) { issue.update(milestone: milestone) } + + [start_time, end_time] + end + + median_start_time, median_end_time = start_and_end_times[2] + expect(subject.issue).to eq(median_end_time - median_start_time) + end + end + + context "when a label is added to the issue" do + it "calculates the median of available durations when the label is a list-label" do + start_and_end_times = Array.new(5) do + start_time = Time.now + end_time = rand(1..10).days.from_now + + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(start_time) { create(:issue, project: project) } + Timecop.freeze(end_time) { issue.update(label_ids: [list_label.id]) } + + [start_time, end_time] + end + + median_start_time, median_end_time = start_and_end_times[2] + expect(subject.issue).to eq(median_end_time - median_start_time) + end + + it "does not make a calculation for regular labels" do + 5.times do + start_time = Time.now + end_time = rand(1..10).days.from_now + + regular_label = create(:label) + issue = Timecop.freeze(start_time) { create(:issue, project: project) } + Timecop.freeze(end_time) { issue.update(label_ids: [regular_label.id]) } + + [start_time, end_time] + end + + expect(subject.issue).to be_nil + end + end + + context "when a milestone and list-label are both added to the issue" do + it "uses the time the milestone was added as the 'end time'" do + start_time = Time.now + milestone_add_time = rand(1..10).days.from_now + list_label_add_time = rand(1..10).days.from_now + + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(start_time) { create(:issue, project: project) } + Timecop.freeze(milestone_add_time) { issue.update(milestone: milestone) } + Timecop.freeze(list_label_add_time) { issue.update(label_ids: [list_label.id]) } + + expect(subject.issue).to eq(milestone_add_time - start_time) + end + end + end +end -- cgit v1.2.1 From df6c9c33b69e411d4f7d27cc46e9769a07d12285 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 26 Aug 2016 15:45:00 +0530 Subject: Scope Cycle Analytics queries to a project --- spec/models/cycle_analytics/issue_spec.rb | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index ba66c99631c..6fdce020642 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } - subject { CycleAnalytics.new } + subject { CycleAnalytics.new(project) } context "when calculating the median of times between: start: issue created_at @@ -26,6 +26,16 @@ describe 'CycleAnalytics#issue', models: true do median_start_time, median_end_time = start_and_end_times[2] expect(subject.issue).to eq(median_end_time - median_start_time) end + + it "does not include issues from other projects" do + 5.times do + milestone = create(:milestone, project: project) + issue = create(:issue) + issue.update(milestone: milestone) + end + + expect(subject.issue).to be_nil + end end context "when a label is added to the issue" do @@ -47,14 +57,9 @@ describe 'CycleAnalytics#issue', models: true do it "does not make a calculation for regular labels" do 5.times do - start_time = Time.now - end_time = rand(1..10).days.from_now - regular_label = create(:label) - issue = Timecop.freeze(start_time) { create(:issue, project: project) } - Timecop.freeze(end_time) { issue.update(label_ids: [regular_label.id]) } - - [start_time, end_time] + issue = create(:issue, project: project) + issue.update(label_ids: [regular_label.id]) end expect(subject.issue).to be_nil -- cgit v1.2.1 From 331080bca683fdab73520f68c53f6a5367d17f22 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 26 Aug 2016 16:18:52 +0530 Subject: Fetch cycle analytics data for a specific date range. 1. Supported date ranges are 30 / 90 days ago. The default is 90 days ago. 2. All issues created before "x days ago" are filtered out, even if they have other related data (test runs, merge requests) within the filter range. --- spec/models/cycle_analytics/issue_spec.rb | 36 +++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 6fdce020642..4dc7f62af98 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } - subject { CycleAnalytics.new(project) } + let(:from_date) { 10.days.ago } + subject { CycleAnalytics.new(project, from: from_date) } context "when calculating the median of times between: start: issue created_at @@ -26,16 +27,6 @@ describe 'CycleAnalytics#issue', models: true do median_start_time, median_end_time = start_and_end_times[2] expect(subject.issue).to eq(median_end_time - median_start_time) end - - it "does not include issues from other projects" do - 5.times do - milestone = create(:milestone, project: project) - issue = create(:issue) - issue.update(milestone: milestone) - end - - expect(subject.issue).to be_nil - end end context "when a label is added to the issue" do @@ -80,6 +71,29 @@ describe 'CycleAnalytics#issue', models: true do expect(subject.issue).to eq(milestone_add_time - start_time) end + + + it "does not include issues from other projects" do + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = create(:issue) + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) + + expect(subject.issue).to be_nil + end + + it "excludes issues created before the 'from' date" do + before_from_date = from_date - 5.days + + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) + + expect(subject.issue).to be_nil + end end end end -- cgit v1.2.1 From 0f748605941248290d258b86408c26f33c2ff7b4 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 2 Sep 2016 12:19:40 +0530 Subject: Add tests for the `plan` cycle analytics phase. Clean up the `issue` tests as well --- spec/models/cycle_analytics/issue_spec.rb | 120 +++++++++++++-------------- spec/models/cycle_analytics/plan_spec.rb | 131 ++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 63 deletions(-) create mode 100644 spec/models/cycle_analytics/plan_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 4dc7f62af98..a176a15b2b7 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -5,33 +5,28 @@ describe 'CycleAnalytics#issue', models: true do let(:from_date) { 10.days.ago } subject { CycleAnalytics.new(project, from: from_date) } - context "when calculating the median of times between: - start: issue created_at - end: milestone first added to issue - OR - list-label first added to issue - " do - context "when a milestone is added to the issue" do - it "calculates the median of available durations" do - start_and_end_times = Array.new(5) do - start_time = Time.now - end_time = rand(1..10).days.from_now - - milestone = create(:milestone, project: project) - issue = Timecop.freeze(start_time) { create(:issue, project: project) } - Timecop.freeze(end_time) { issue.update(milestone: milestone) } + context "when a milestone is added to the issue" do + it "calculates the median of available durations (between issue creation and milestone addition)" do + time_differences = Array.new(5) do + start_time = Time.now + end_time = rand(1..10).days.from_now - [start_time, end_time] - end + milestone = create(:milestone, project: project) + issue = Timecop.freeze(start_time) { create(:issue, project: project) } + Timecop.freeze(end_time) { issue.update(milestone: milestone) } - median_start_time, median_end_time = start_and_end_times[2] - expect(subject.issue).to eq(median_end_time - median_start_time) + end_time - start_time end + + median_time_difference = time_differences.sort[2] + expect(subject.issue).to eq(median_time_difference) end + end - context "when a label is added to the issue" do - it "calculates the median of available durations when the label is a list-label" do - start_and_end_times = Array.new(5) do + context "when a label is added to the issue" do + context "when the label is a list-label" do + it "calculates the median of available durations (between issue creation and label addition)" do + time_differences = Array.new(5) do start_time = Time.now end_time = rand(1..10).days.from_now @@ -39,61 +34,60 @@ describe 'CycleAnalytics#issue', models: true do issue = Timecop.freeze(start_time) { create(:issue, project: project) } Timecop.freeze(end_time) { issue.update(label_ids: [list_label.id]) } - [start_time, end_time] + end_time - start_time end - median_start_time, median_end_time = start_and_end_times[2] - expect(subject.issue).to eq(median_end_time - median_start_time) + median_time_difference = time_differences.sort[2] + expect(subject.issue).to eq(median_time_difference) end + end - it "does not make a calculation for regular labels" do - 5.times do - regular_label = create(:label) - issue = create(:issue, project: project) - issue.update(label_ids: [regular_label.id]) - end - - expect(subject.issue).to be_nil + it "does not make a calculation for regular labels" do + 5.times do + regular_label = create(:label) + issue = create(:issue, project: project) + issue.update(label_ids: [regular_label.id]) end + + expect(subject.issue).to be_nil end + end - context "when a milestone and list-label are both added to the issue" do - it "uses the time the milestone was added as the 'end time'" do - start_time = Time.now - milestone_add_time = rand(1..10).days.from_now - list_label_add_time = rand(1..10).days.from_now + context "when a milestone and list-label are both added to the issue" do + it "calculates the median of available durations (between issue creation and milestone addition)" do + start_time = Time.now + milestone_add_time = rand(1..10).days.from_now + list_label_add_time = rand(1..10).days.from_now - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = Timecop.freeze(start_time) { create(:issue, project: project) } - Timecop.freeze(milestone_add_time) { issue.update(milestone: milestone) } - Timecop.freeze(list_label_add_time) { issue.update(label_ids: [list_label.id]) } - - expect(subject.issue).to eq(milestone_add_time - start_time) - end + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(start_time) { create(:issue, project: project) } + Timecop.freeze(milestone_add_time) { issue.update(milestone: milestone) } + Timecop.freeze(list_label_add_time) { issue.update(label_ids: [list_label.id]) } + expect(subject.issue).to eq(milestone_add_time - start_time) + end - it "does not include issues from other projects" do - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = create(:issue) - issue.update(milestone: milestone) - issue.update(label_ids: [list_label.id]) + it "does not include issues from other projects" do + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = create(:issue) + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) - expect(subject.issue).to be_nil - end + expect(subject.issue).to be_nil + end - it "excludes issues created before the 'from' date" do - before_from_date = from_date - 5.days + it "excludes issues created before the 'from' date" do + before_from_date = from_date - 5.days - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} - issue.update(milestone: milestone) - issue.update(label_ids: [list_label.id]) + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) - expect(subject.issue).to be_nil - end + expect(subject.issue).to be_nil end end end diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb new file mode 100644 index 00000000000..e3eeb0e505c --- /dev/null +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -0,0 +1,131 @@ +require 'spec_helper' + +describe 'CycleAnalytics#plan', feature: true do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + subject { CycleAnalytics.new(project, from: from_date) } + + def create_commit_referencing_issue(issue, time: Time.now) + sha = Timecop.freeze(time) { project.repository.commit_file(user, FFaker::Product.brand, "content", "Commit for ##{issue.iid}", "master", false) } + commit = project.repository.commit(sha) + commit.create_cross_references! + end + + context "when a milestone is added to the issue" do + context "when the issue is mentioned in a commit" do + it "calculates the median of available durations between the two" do + time_differences = Array.new(5) do + start_time = Time.now + end_time = rand(1..10).days.from_now + + milestone = create(:milestone, project: project) + issue = create(:issue, project: project) + + Timecop.freeze(start_time) { issue.update(milestone: milestone) } + create_commit_referencing_issue(issue, time: end_time) + + end_time - start_time + end + + median_time_difference = time_differences.sort[2] + + # Use `be_within` to account for time lost between Rails invoking CLI git + # and the commit being created, which Timecop can't freeze. + expect(subject.plan).to be_within(2).of(median_time_difference) + end + end + end + + context "when a label is added to the issue" do + context "when the issue is mentioned in a commit" do + context "when the label is a list-label" do + it "calculates the median of available durations between the two" do + time_differences = Array.new(5) do + start_time = Time.now + end_time = rand(1..10).days.from_now + + issue = create(:issue, project: project) + list_label = create(:label, lists: [create(:list)]) + + Timecop.freeze(start_time) { issue.update(label_ids: [list_label.id]) } + create_commit_referencing_issue(issue, time: end_time) + + end_time - start_time + end + + median_time_difference = time_differences.sort[2] + + # Use `be_within` to account for time lost between Rails invoking CLI git + # and the commit being created, which Timecop can't freeze. + expect(subject.plan).to be_within(2).of(median_time_difference) + end + end + + it "does not make a calculation for regular labels" do + 5.times do + regular_label = create(:label) + issue = create(:issue, project: project) + issue.update(label_ids: [regular_label.id]) + + create_commit_referencing_issue(issue) + end + + expect(subject.plan).to be_nil + end + end + end + + context "when a milestone and list-label are both added to the issue" do + context "when the issue is mentioned in a commit" do + it "calculates the median of available durations between the two (using milestone addition as the 'start_time')" do + time_differences = Array.new(5) do + label_addition_time = Time.now + milestone_addition_time = rand(2..12).hours.from_now + end_time = rand(1..10).days.from_now + + issue = create(:issue, project: project) + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + + Timecop.freeze(label_addition_time) { issue.update(label_ids: [list_label.id]) } + Timecop.freeze(milestone_addition_time) { issue.update(milestone: milestone) } + create_commit_referencing_issue(issue, time: end_time) + + end_time - milestone_addition_time + end + + median_time_difference = time_differences.sort[2] + + # Use `be_within` to account for time lost between Rails invoking CLI git + # and the commit being created, which Timecop can't freeze. + expect(subject.plan).to be_within(2).of(median_time_difference) + end + + it "does not include issues from other projects" do + other_project = create(:project) + + list_label = create(:label, lists: [create(:list)]) + issue = create(:issue, project: other_project) + issue.update(milestone: create(:milestone)) + issue.update(label_ids: [list_label.id]) + create_commit_referencing_issue(issue) + + expect(subject.issue).to be_nil + end + + it "excludes issues created before the 'from' date" do + before_from_date = from_date - 5.days + + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) + create_commit_referencing_issue(issue) + + expect(subject.issue).to be_nil + end + end + end +end -- cgit v1.2.1 From 98c9d1207708cd7d9fc37167e65e8a26b668aaa7 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Fri, 2 Sep 2016 17:33:32 +0530 Subject: Refactor cycle analytics specs. 1. Generalise the specs that will be common across all cycle analytics phases. 2. Rewrite specs `issue` and `plan` to use this abstracted testing strategy. 3. Specs that are specific to a given phase, or unwieldy to test in an abstracted manner, are added to each phase's spec. --- spec/models/cycle_analytics/issue_spec.rb | 85 ++++--------------- spec/models/cycle_analytics/plan_spec.rb | 132 +++++------------------------- spec/support/cycle_analytics_helpers.rb | 96 ++++++++++++++++++++++ 3 files changed, 133 insertions(+), 180 deletions(-) create mode 100644 spec/support/cycle_analytics_helpers.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index a176a15b2b7..ef4de184d64 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -5,44 +5,14 @@ describe 'CycleAnalytics#issue', models: true do let(:from_date) { 10.days.ago } subject { CycleAnalytics.new(project, from: from_date) } - context "when a milestone is added to the issue" do - it "calculates the median of available durations (between issue creation and milestone addition)" do - time_differences = Array.new(5) do - start_time = Time.now - end_time = rand(1..10).days.from_now - - milestone = create(:milestone, project: project) - issue = Timecop.freeze(start_time) { create(:issue, project: project) } - Timecop.freeze(end_time) { issue.update(milestone: milestone) } - - end_time - start_time - end - - median_time_difference = time_differences.sort[2] - expect(subject.issue).to eq(median_time_difference) - end - end - - context "when a label is added to the issue" do - context "when the label is a list-label" do - it "calculates the median of available durations (between issue creation and label addition)" do - time_differences = Array.new(5) do - start_time = Time.now - end_time = rand(1..10).days.from_now - - list_label = create(:label, lists: [create(:list)]) - issue = Timecop.freeze(start_time) { create(:issue, project: project) } - Timecop.freeze(end_time) { issue.update(label_ids: [list_label.id]) } - - end_time - start_time - end - - median_time_difference = time_differences.sort[2] - expect(subject.issue).to eq(median_time_difference) - end - end - - it "does not make a calculation for regular labels" do + generate_cycle_analytics_spec(phase: :issue, + data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, + start_time_conditions: [["issue created", -> (context, data) { data[:issue].save }]], + end_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) if data[:issue].persisted? }], + ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) if data[:issue].persisted? }]]) + + 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) @@ -53,39 +23,14 @@ describe 'CycleAnalytics#issue', models: true do end end - context "when a milestone and list-label are both added to the issue" do - it "calculates the median of available durations (between issue creation and milestone addition)" do - start_time = Time.now - milestone_add_time = rand(1..10).days.from_now - list_label_add_time = rand(1..10).days.from_now - - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = Timecop.freeze(start_time) { create(:issue, project: project) } - Timecop.freeze(milestone_add_time) { issue.update(milestone: milestone) } - Timecop.freeze(list_label_add_time) { issue.update(label_ids: [list_label.id]) } - - expect(subject.issue).to eq(milestone_add_time - start_time) - end - - it "does not include issues from other projects" do - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = create(:issue) - issue.update(milestone: milestone) - issue.update(label_ids: [list_label.id]) + context "when the issue belongs to a different project" do + it 'returns nil' do + other_project = create(:project) - expect(subject.issue).to be_nil - end - - it "excludes issues created before the 'from' date" do - before_from_date = from_date - 5.days - - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} - issue.update(milestone: milestone) - issue.update(label_ids: [list_label.id]) + 5.times do + issue = create(:issue, project: other_project) + issue.update(milestone: create(:milestone, project: other_project)) + end expect(subject.issue).to be_nil end diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index e3eeb0e505c..a5d4128d938 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -6,126 +6,38 @@ describe 'CycleAnalytics#plan', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_commit_referencing_issue(issue, time: Time.now) - sha = Timecop.freeze(time) { project.repository.commit_file(user, FFaker::Product.brand, "content", "Commit for ##{issue.iid}", "master", false) } + def create_commit_referencing_issue(issue) + sha = project.repository.commit_file(user, FFaker::Product.brand, "content", "Commit for ##{issue.iid}", "master", false) commit = project.repository.commit(sha) commit.create_cross_references! end - context "when a milestone is added to the issue" do - context "when the issue is mentioned in a commit" do - it "calculates the median of available durations between the two" do - time_differences = Array.new(5) do - start_time = Time.now - end_time = rand(1..10).days.from_now + generate_cycle_analytics_spec(phase: :plan, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) }], + ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) }]], + end_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue]) }]]) - milestone = create(:milestone, project: project) - issue = create(:issue, project: project) + context "when a regular label (instead of a list label) is added to the issue" do + it "returns nil" do + label = create(:label) + issue = create(:issue, project: project) + issue.update(label_ids: [label.id]) + create_commit_referencing_issue(issue) - Timecop.freeze(start_time) { issue.update(milestone: milestone) } - create_commit_referencing_issue(issue, time: end_time) - - end_time - start_time - end - - median_time_difference = time_differences.sort[2] - - # Use `be_within` to account for time lost between Rails invoking CLI git - # and the commit being created, which Timecop can't freeze. - expect(subject.plan).to be_within(2).of(median_time_difference) - end - end - end - - context "when a label is added to the issue" do - context "when the issue is mentioned in a commit" do - context "when the label is a list-label" do - it "calculates the median of available durations between the two" do - time_differences = Array.new(5) do - start_time = Time.now - end_time = rand(1..10).days.from_now - - issue = create(:issue, project: project) - list_label = create(:label, lists: [create(:list)]) - - Timecop.freeze(start_time) { issue.update(label_ids: [list_label.id]) } - create_commit_referencing_issue(issue, time: end_time) - - end_time - start_time - end - - median_time_difference = time_differences.sort[2] - - # Use `be_within` to account for time lost between Rails invoking CLI git - # and the commit being created, which Timecop can't freeze. - expect(subject.plan).to be_within(2).of(median_time_difference) - end - end - - it "does not make a calculation for regular labels" do - 5.times do - regular_label = create(:label) - issue = create(:issue, project: project) - issue.update(label_ids: [regular_label.id]) - - create_commit_referencing_issue(issue) - end - - expect(subject.plan).to be_nil - end + expect(subject.issue).to be_nil end end - context "when a milestone and list-label are both added to the issue" do - context "when the issue is mentioned in a commit" do - it "calculates the median of available durations between the two (using milestone addition as the 'start_time')" do - time_differences = Array.new(5) do - label_addition_time = Time.now - milestone_addition_time = rand(2..12).hours.from_now - end_time = rand(1..10).days.from_now - - issue = create(:issue, project: project) - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - - Timecop.freeze(label_addition_time) { issue.update(label_ids: [list_label.id]) } - Timecop.freeze(milestone_addition_time) { issue.update(milestone: milestone) } - create_commit_referencing_issue(issue, time: end_time) - - end_time - milestone_addition_time - end - - median_time_difference = time_differences.sort[2] + it "does not include issues from other projects" do + other_project = create(:project) - # Use `be_within` to account for time lost between Rails invoking CLI git - # and the commit being created, which Timecop can't freeze. - expect(subject.plan).to be_within(2).of(median_time_difference) - end + list_label = create(:label, lists: [create(:list)]) + issue = create(:issue, project: other_project) + issue.update(milestone: create(:milestone)) + issue.update(label_ids: [list_label.id]) + create_commit_referencing_issue(issue) - it "does not include issues from other projects" do - other_project = create(:project) - - list_label = create(:label, lists: [create(:list)]) - issue = create(:issue, project: other_project) - issue.update(milestone: create(:milestone)) - issue.update(label_ids: [list_label.id]) - create_commit_referencing_issue(issue) - - expect(subject.issue).to be_nil - end - - it "excludes issues created before the 'from' date" do - before_from_date = from_date - 5.days - - milestone = create(:milestone, project: project) - list_label = create(:label, lists: [create(:list)]) - issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} - issue.update(milestone: milestone) - issue.update(label_ids: [list_label.id]) - create_commit_referencing_issue(issue) - - expect(subject.issue).to be_nil - end - end + expect(subject.issue).to be_nil end end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb new file mode 100644 index 00000000000..ba18b390c1a --- /dev/null +++ b/spec/support/cycle_analytics_helpers.rb @@ -0,0 +1,96 @@ +# rubocop:disable Metrics/AbcSize + +# Note: The ABC size is large here because we have a method generating test cases with +# multiple nested contexts. This shouldn't count as a violation. + +module CycleAnalyticsHelpers + # Generate the most common set of specs that all cycle analytics phases need to have. + # + # Arguments: + # + # phase: Which phase are we testing? Will call `CycleAnalytics.new.send(phase)` for the final assertion + # data_fn: A function that returns a hash, constituting initial data for the test case + # start_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with + # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). + # Each `condition_fn` is expected to implement a case which consitutes the start of the given cycle analytics phase. + # end_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with + # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). + # Each `condition_fn` is expected to implement a case which consitutes the end of the given cycle analytics phase. + + def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:) + combinations_of_start_time_conditions = (1..start_time_conditions.size).flat_map { |size| start_time_conditions.combination(size).to_a } + combinations_of_end_time_conditions = (1..end_time_conditions.size).flat_map { |size| end_time_conditions.combination(size).to_a } + + scenarios = combinations_of_start_time_conditions.product(combinations_of_end_time_conditions) + scenarios.each do |start_time_conditions, end_time_conditions| + context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do + context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do + it "finds the median of available durations between the two conditions" do + time_differences = Array.new(5) 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 + + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } + end + + end_time - start_time + end + + median_time_difference = time_differences.sort[2] + expect(subject.send(phase)).to be_within(2).of(median_time_difference) + end + end + end + + 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 + end + + expect(subject.send(phase)).to be_nil + end + end + end + + 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 + end + + expect(subject.send(phase)).to be_nil + end + end + end + end + + context "when none of the start / end conditions are matched" do + it "returns nil" do + expect(subject.send(phase)).to be_nil + end + end + end +end + +RSpec.configure do |config| + config.extend CycleAnalyticsHelpers +end -- cgit v1.2.1 From 69db604e55de2bdf1a28c274be6cc9131534517d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 14:00:57 +0100 Subject: Updated tests --- spec/features/issues/filter_issues_spec.rb | 1 - spec/views/projects/merge_requests/edit.html.haml_spec.rb | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 372ad39676d..24e5491f087 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -110,7 +110,6 @@ describe 'Filter issues', feature: true do end it 'filters by wont fix labels' do - find('.dropdown-menu-labels a', text: label.title).click page.within '.labels-filter' do expect(page).to have_content wontfix.title click_link wontfix.title diff --git a/spec/views/projects/merge_requests/edit.html.haml_spec.rb b/spec/views/projects/merge_requests/edit.html.haml_spec.rb index 31bbb150698..9da05e1721c 100644 --- a/spec/views/projects/merge_requests/edit.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/edit.html.haml_spec.rb @@ -7,12 +7,15 @@ describe 'projects/merge_requests/edit.html.haml' do let(:project) { create(:project) } let(:fork_project) { create(:project, forked_from_project: project) } let(:unlink_project) { Projects::UnlinkForkService.new(fork_project, user) } + let(:milestone) { create(:milestone, project: project) } let(:closed_merge_request) do create(:closed_merge_request, source_project: fork_project, target_project: project, - author: user) + author: user, + assignee: user, + milestone: milestone) end before do -- cgit v1.2.1 From 40c7ba0129b0954802d4045c4b95626166cdfdc4 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sat, 3 Sep 2016 20:24:26 +0100 Subject: Updated spec with next click targets --- spec/features/expand_collapse_diffs_spec.rb | 40 ++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index 688f68d3cff..b9f53cf0fa1 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -68,7 +68,7 @@ feature 'Expand and collapse diffs', js: true, feature: true do context 'expanding a diff for a renamed file' do before do - large_diff_renamed.find('.nothing-here-block').click + large_diff_renamed.find('.click-to-expand').click wait_for_ajax end @@ -87,7 +87,10 @@ feature 'Expand and collapse diffs', js: true, feature: true do context 'expanding a large diff' do before do - click_link('large_diff.md') + # Wait for diffs + find('.file-title', match: :first) + # Click `large_diff.md` title + all('.file-title')[1].click wait_for_ajax end @@ -128,7 +131,10 @@ feature 'Expand and collapse diffs', js: true, feature: true do context 'expanding the diff' do before do - click_link('large_diff.md') + # Wait for diffs + find('.file-title', match: :first) + # Click `large_diff.md` title + all('.file-title')[1].click wait_for_ajax end @@ -146,7 +152,12 @@ feature 'Expand and collapse diffs', js: true, feature: true do end context 'collapsing an expanded diff' do - before { click_link('small_diff.md') } + before do + # Wait for diffs + find('.file-title', match: :first) + # Click `small_diff.md` title + all('.file-title')[3].click + end it 'hides the diff content' do expect(small_diff).not_to have_selector('.code') @@ -154,7 +165,12 @@ feature 'Expand and collapse diffs', js: true, feature: true do end context 're-expanding the same diff' do - before { click_link('small_diff.md') } + before do + # Wait for diffs + find('.file-title', match: :first) + # Click `small_diff.md` title + all('.file-title')[3].click + end it 'shows the diff content' do expect(small_diff).to have_selector('.code') @@ -224,7 +240,12 @@ feature 'Expand and collapse diffs', js: true, feature: true do end context 'collapsing an expanded diff' do - before { click_link('small_diff.md') } + before do + # Wait for diffs + find('.file-title', match: :first) + # Click `small_diff.md` title + all('.file-title')[3].click + end it 'hides the diff content' do expect(small_diff).not_to have_selector('.code') @@ -232,7 +253,12 @@ feature 'Expand and collapse diffs', js: true, feature: true do end context 're-expanding the same diff' do - before { click_link('small_diff.md') } + before do + # Wait for diffs + find('.file-title', match: :first) + # Click `small_diff.md` title + all('.file-title')[3].click + end it 'shows the diff content' do expect(small_diff).to have_selector('.code') -- cgit v1.2.1 From f77c952ae71ec03c9691e44479f0e4a7fc5ef8e8 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 10:35:01 +0530 Subject: Test the `code` cycle analytics phase. - Move the "data belongs to other project" test case into the generated tests, and remove the explicit tests from the `code` and `plan` phases. --- spec/models/cycle_analytics/code_spec.rb | 46 +++++++++++++++++++++++++++++++ spec/models/cycle_analytics/issue_spec.rb | 13 --------- spec/models/cycle_analytics/plan_spec.rb | 12 -------- spec/support/cycle_analytics_helpers.rb | 31 +++++++++++++++++++++ 4 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 spec/models/cycle_analytics/code_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb new file mode 100644 index 00000000000..1eaccb5e937 --- /dev/null +++ b/spec/models/cycle_analytics/code_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe 'CycleAnalytics#code', feature: true do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + subject { CycleAnalytics.new(project, from: from_date) } + + def create_commit_referencing_issue(issue) + sha = project.repository.commit_file(user, FFaker::Product.brand, "content", "Commit for ##{issue.iid}", "master", false) + commit = project.repository.commit(sha) + commit.create_cross_references!(user) + end + + def create_merge_request_closing_issue(issue, message: nil) + source_branch = FFaker::Product.brand + project.repository.add_branch(user, source_branch, 'master') + + opts = { + title: 'Awesome merge_request', + description: message || "Fixes #{issue.to_reference}", + source_branch: source_branch, + target_branch: 'master' + } + + MergeRequests::CreateService.new(project, user, opts).execute + end + + generate_cycle_analytics_spec(phase: :code, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue]) }]], + end_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]]) + + 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) + + create_commit_referencing_issue(issue) + create_merge_request_closing_issue(issue, message: "Closes nothing") + end + + expect(subject.code).to be_nil + end + end +end diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index ef4de184d64..06715498d26 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -22,17 +22,4 @@ describe 'CycleAnalytics#issue', models: true do expect(subject.issue).to be_nil end end - - context "when the issue belongs to a different project" do - it 'returns nil' do - other_project = create(:project) - - 5.times do - issue = create(:issue, project: other_project) - issue.update(milestone: create(:milestone, project: other_project)) - end - - expect(subject.issue).to be_nil - end - end end diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index a5d4128d938..4cae87e9d89 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -28,16 +28,4 @@ describe 'CycleAnalytics#plan', feature: true do expect(subject.issue).to be_nil end end - - it "does not include issues from other projects" do - other_project = create(:project) - - list_label = create(:label, lists: [create(:list)]) - issue = create(:issue, project: other_project) - issue.update(milestone: create(:milestone)) - issue.update(label_ids: [list_label.id]) - create_commit_referencing_issue(issue) - - expect(subject.issue).to be_nil - end end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index ba18b390c1a..b2ca42d7cce 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -45,6 +45,37 @@ module CycleAnalyticsHelpers median_time_difference = time_differences.sort[2] expect(subject.send(phase)).to be_within(2).of(median_time_difference) end + + context "when the data belongs to another project" do + let(:other_project) { create(:project) } + + it "returns nil" do + # Use a stub to "trick" the data/condition functions + # into using another project. This saves us from having to + # define separate data/condition functions for this particular + # 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 + + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } + end + end + + # Turn off the stub before checking assertions + allow(self).to receive(:project).and_call_original + + expect(subject.send(phase)).to be_nil + end + end end end -- cgit v1.2.1 From 71a9bcd3def27a46223ea052e7fe3560869b9d6d Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 10:53:01 +0530 Subject: Test the 'review' cycle analytics phase. --- spec/models/cycle_analytics/review_spec.rb | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 spec/models/cycle_analytics/review_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb new file mode 100644 index 00000000000..5099e502345 --- /dev/null +++ b/spec/models/cycle_analytics/review_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe 'CycleAnalytics#review', feature: true do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + subject { CycleAnalytics.new(project, from: from_date) } + + def create_merge_request_closing_issue(issue) + source_branch = FFaker::Product.brand + project.repository.add_branch(user, source_branch, 'master') + sha = project.repository.commit_file(user, FFaker::Product.brand, "content", "commit message", source_branch, false) + project.repository.commit(sha) + + opts = { + title: 'Awesome merge_request', + description: "Fixes #{issue.to_reference}", + source_branch: source_branch, + target_branch: 'master' + } + + MergeRequests::CreateService.new(project, user, opts).execute + end + + + def merge_merge_requests_closing_issue(issue) + merge_requests = issue.closed_by_merge_requests + merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } + end + + generate_cycle_analytics_spec(phase: :review, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]], + end_time_conditions: [["merge request that closes issue is merged", -> (context, data) { context.merge_merge_requests_closing_issue(data[:issue]) }]]) + + 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 + + expect(subject.review).to be_nil + end + end +end -- cgit v1.2.1 From 0f44c5a56fdc5986797808c508d7b42236cee450 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 10:58:19 +0530 Subject: Generate branch/file names more randomly to avoid failures. - Tests would randomly fail because of naming conflicts. - Use a `random_git_name` method instead of using `FFaker` directly. --- spec/models/cycle_analytics/code_spec.rb | 4 ++-- spec/models/cycle_analytics/plan_spec.rb | 2 +- spec/models/cycle_analytics/review_spec.rb | 5 ++--- spec/support/git_helpers.rb | 9 +++++++++ 4 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 spec/support/git_helpers.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 1eaccb5e937..a81b5cf444d 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -7,13 +7,13 @@ describe 'CycleAnalytics#code', feature: true do subject { CycleAnalytics.new(project, from: from_date) } def create_commit_referencing_issue(issue) - sha = project.repository.commit_file(user, FFaker::Product.brand, "content", "Commit for ##{issue.iid}", "master", false) + sha = project.repository.commit_file(user, random_git_name, "content", "Commit for ##{issue.iid}", "master", false) commit = project.repository.commit(sha) commit.create_cross_references!(user) end def create_merge_request_closing_issue(issue, message: nil) - source_branch = FFaker::Product.brand + source_branch = random_git_name project.repository.add_branch(user, source_branch, 'master') opts = { diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 4cae87e9d89..42984169b28 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -7,7 +7,7 @@ describe 'CycleAnalytics#plan', feature: true do subject { CycleAnalytics.new(project, from: from_date) } def create_commit_referencing_issue(issue) - sha = project.repository.commit_file(user, FFaker::Product.brand, "content", "Commit for ##{issue.iid}", "master", false) + sha = project.repository.commit_file(user, random_git_name, "content", "Commit for ##{issue.iid}", "master", false) commit = project.repository.commit(sha) commit.create_cross_references! end diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 5099e502345..8530d70a38e 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -7,9 +7,9 @@ describe 'CycleAnalytics#review', feature: true do subject { CycleAnalytics.new(project, from: from_date) } def create_merge_request_closing_issue(issue) - source_branch = FFaker::Product.brand + source_branch = random_git_name project.repository.add_branch(user, source_branch, 'master') - sha = project.repository.commit_file(user, FFaker::Product.brand, "content", "commit message", source_branch, false) + sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) project.repository.commit(sha) opts = { @@ -22,7 +22,6 @@ describe 'CycleAnalytics#review', feature: true do MergeRequests::CreateService.new(project, user, opts).execute end - def merge_merge_requests_closing_issue(issue) merge_requests = issue.closed_by_merge_requests merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } diff --git a/spec/support/git_helpers.rb b/spec/support/git_helpers.rb new file mode 100644 index 00000000000..93422390ef7 --- /dev/null +++ b/spec/support/git_helpers.rb @@ -0,0 +1,9 @@ +module GitHelpers + def random_git_name + "#{FFaker::Product.brand}-#{FFaker::Product.brand}-#{rand(1000)}" + end +end + +RSpec.configure do |config| + config.include GitHelpers +end -- cgit v1.2.1 From dd112ef1174b2b0207769a361cddfc44dfe2e6d0 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 11:25:01 +0530 Subject: Test the `staging` cycle analytics phase. Remove overlap from the "start + end" durations in the happy test case. For the `staging` phase, the end time is the _first_ deployment that happens after the MR merge. If we have 5 MRs where the `start_time`s (merge time) are the same, and all the `end_time`s (deploy to production) a few days from now, only the earliest deploy will get picked up, because that consitutes a deploy for _all_ the MRs. We fix this by removing overlap. Every `start_time` is now generated to be _after_ the preceding `end_time`. --- spec/models/cycle_analytics/staging_spec.rb | 79 +++++++++++++++++++++++++++++ spec/support/cycle_analytics_helpers.rb | 8 +-- 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 spec/models/cycle_analytics/staging_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb new file mode 100644 index 00000000000..23e01532500 --- /dev/null +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +describe 'CycleAnalytics#staging', feature: true do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + subject { CycleAnalytics.new(project, from: from_date) } + + def create_merge_request_closing_issue(issue, message: nil) + source_branch = random_git_name + project.repository.add_branch(user, source_branch, 'master') + sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) + project.repository.commit(sha) + + opts = { + title: 'Awesome merge_request', + description: message || "Fixes #{issue.to_reference}", + source_branch: source_branch, + target_branch: 'master' + } + + MergeRequests::CreateService.new(project, user, opts).execute + end + + def merge_merge_requests_closing_issue(issue) + merge_requests = issue.closed_by_merge_requests + merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } + end + + def deploy_master(environment: 'production') + CreateDeploymentService.new(project, user, { + environment: environment, + ref: 'master', + tag: false, + sha: project.repository.commit('master').sha + }).execute + end + + generate_cycle_analytics_spec(phase: :staging, + data_fn: lambda do |context| + issue = context.create(:issue, project: context.project) + { issue: issue, merge_request: context.create_merge_request_closing_issue(issue) } + end, + start_time_conditions: [["merge request that closes issue is merged", -> (context, data) { context.merge_merge_requests_closing_issue(data[:issue])} ]], + end_time_conditions: [["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master }], + ["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) + context.project.repository.commit(sha) + + context.deploy_master + end]]) + + 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 + + expect(subject.staging).to be_nil + end + end + + 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 + + expect(subject.staging).to be_nil + end + end +end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index b2ca42d7cce..4819f8b517a 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -26,10 +26,10 @@ module CycleAnalyticsHelpers context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do it "finds the median of available durations between the two conditions" do - time_differences = Array.new(5) do + time_differences = Array.new(5) do |index| data = data_fn[self] - start_time = Time.now - end_time = rand(1..10).days.from_now + start_time = (index * 10).days.from_now + end_time = start_time + rand(1..5).days start_time_conditions.each do |condition_name, condition_fn| Timecop.freeze(start_time) { condition_fn[self, data] } @@ -43,7 +43,7 @@ module CycleAnalyticsHelpers end median_time_difference = time_differences.sort[2] - expect(subject.send(phase)).to be_within(2).of(median_time_difference) + expect(subject.send(phase)).to be_within(5).of(median_time_difference) end context "when the data belongs to another project" do -- cgit v1.2.1 From de483c6834153b75403633b42f20b0c85eae35e7 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 13:06:58 +0530 Subject: Test the `production` cycle analytics phase. Add a `before_end_fn` option to the code that generates cycle analytics specs. `before_end_fn` is called before the end conditions are. Used for data setup that needs to be called after the start conditions and before the end conditions. --- spec/models/cycle_analytics/production_spec.rb | 81 ++++++++++++++++++++++++++ spec/support/cycle_analytics_helpers.rb | 6 +- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 spec/models/cycle_analytics/production_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb new file mode 100644 index 00000000000..76e42c1c2d4 --- /dev/null +++ b/spec/models/cycle_analytics/production_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' + +describe 'CycleAnalytics#production', feature: true do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + subject { CycleAnalytics.new(project, from: from_date) } + + def create_merge_request_closing_issue(issue, message: nil) + source_branch = random_git_name + project.repository.add_branch(user, source_branch, 'master') + sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) + project.repository.commit(sha) + + opts = { + title: 'Awesome merge_request', + description: message || "Fixes #{issue.to_reference}", + source_branch: source_branch, + target_branch: 'master' + } + + MergeRequests::CreateService.new(project, user, opts).execute + end + + def merge_merge_requests_closing_issue(issue) + merge_requests = issue.closed_by_merge_requests + merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } + end + + def deploy_master(environment: 'production') + CreateDeploymentService.new(project, user, { + environment: environment, + ref: 'master', + tag: false, + sha: project.repository.commit('master').sha + }).execute + end + + generate_cycle_analytics_spec(phase: :production, + data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, + start_time_conditions: [["issue is created", -> (context, data) { data[:issue].save }]], + before_end_fn: lambda do |context, data| + context.create_merge_request_closing_issue(data[:issue]) + context.merge_merge_requests_closing_issue(data[:issue]) + end, + end_time_conditions: + [["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master }], + ["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) + context.project.repository.commit(sha) + + context.deploy_master + end]]) + + 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 + + expect(subject.production).to be_nil + end + end + + 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 + + expect(subject.production).to be_nil + end + end +end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index 4819f8b517a..c369caf8041 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -16,8 +16,9 @@ module CycleAnalyticsHelpers # end_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). # Each `condition_fn` is expected to implement a case which consitutes the end of the given cycle analytics phase. + # before_end_fn: This function is run before calling the end time conditions. Used for setup that needs to be run between the start and end conditions. - def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:) + def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:, before_end_fn: nil) combinations_of_start_time_conditions = (1..start_time_conditions.size).flat_map { |size| start_time_conditions.combination(size).to_a } combinations_of_end_time_conditions = (1..end_time_conditions.size).flat_map { |size| end_time_conditions.combination(size).to_a } @@ -35,6 +36,9 @@ module CycleAnalyticsHelpers Timecop.freeze(start_time) { condition_fn[self, data] } end + # Run `before_end_fn` at the midpoint between `start_time` and `end_time` + Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn + end_time_conditions.each do |condition_name, condition_fn| Timecop.freeze(end_time) { condition_fn[self, data] } end -- cgit v1.2.1 From f849ef792a620164d1e1e231b58f72f17293e9fc Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 17:32:07 +0100 Subject: Fixed issue board label filtering not removing labels Closes #21417 --- spec/features/boards/boards_spec.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index c6c2e2095df..c697dbea131 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -467,6 +467,25 @@ describe 'Issue Boards', feature: true, js: true do end end + it 'removes filtered labels' do + page.within '.labels-filter' do + click_button('Label') + wait_for_ajax + + page.within '.dropdown-menu-labels' do + click_link(testing.title) + end + + expect(page).to have_css('input[name="label_name[]"]', visible: false) + + page.within '.dropdown-menu-labels' do + click_link(testing.title) + end + + expect(page).not_to have_css('input[name="label_name[]"]', visible: false) + end + end + it 'infinite scrolls list with label filter' do 50.times do create(:labeled_issue, project: project, labels: [testing]) -- cgit v1.2.1 From 70451ff0a135b9393a046452f83e8eaa474b9e06 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 09:17:06 +0100 Subject: tests update --- spec/features/boards/boards_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index c697dbea131..62fe2e2e8b6 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -474,12 +474,14 @@ describe 'Issue Boards', feature: true, js: true do page.within '.dropdown-menu-labels' do click_link(testing.title) + wait_for_vue_resource(spinner: false) end expect(page).to have_css('input[name="label_name[]"]', visible: false) page.within '.dropdown-menu-labels' do click_link(testing.title) + wait_for_vue_resource(spinner: false) end expect(page).not_to have_css('input[name="label_name[]"]', visible: false) -- cgit v1.2.1 From 78839ec0fe146564a4a4a2ab339f479e25a13e5e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 10:52:27 +0100 Subject: Tests fix --- spec/features/boards/boards_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 62fe2e2e8b6..dbe81233fcb 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -468,6 +468,8 @@ describe 'Issue Boards', feature: true, js: true do end it 'removes filtered labels' do + wait_for_vue_resource + page.within '.labels-filter' do click_button('Label') wait_for_ajax -- cgit v1.2.1 From 9cff3f8f5282633fd0c5920e3b6d277415ae9000 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 14:11:24 +0530 Subject: Test the `test` cycle analytics phase. --- spec/models/cycle_analytics/test_spec.rb | 90 ++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 spec/models/cycle_analytics/test_spec.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb new file mode 100644 index 00000000000..af4d55f5801 --- /dev/null +++ b/spec/models/cycle_analytics/test_spec.rb @@ -0,0 +1,90 @@ +require 'spec_helper' + +describe 'CycleAnalytics#test', feature: true do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + subject { CycleAnalytics.new(project, from: from_date) } + + def create_merge_request_closing_issue(issue, message: nil) + source_branch = random_git_name + project.repository.add_branch(user, source_branch, 'master') + sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) + project.repository.commit(sha) + + opts = { + title: 'Awesome merge_request', + description: message || "Fixes #{issue.to_reference}", + source_branch: source_branch, + target_branch: 'master' + } + + MergeRequests::CreateService.new(project, user, opts).execute + end + + generate_cycle_analytics_spec(phase: :test, + data_fn: lambda do |context| + issue = context.create(:issue, project: context.project) + merge_request = context.create_merge_request_closing_issue(issue) + { pipeline: context.create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) } + end, + start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]], + end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]]) + + context "when the pipeline is for a regular merge request (that doesn't close an issue)" do + it "returns nil" do + 5.times do + merge_request = create(:merge_request) + pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) + + pipeline.run! + pipeline.succeed! + end + + expect(subject.test).to be_nil + end + end + + 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.run! + pipeline.succeed! + end + + expect(subject.test).to be_nil + end + end + + 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) + + pipeline.run! + pipeline.drop! + end + + expect(subject.test).to be_nil + end + end + + 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) + + pipeline.run! + pipeline.cancel! + end + + expect(subject.test).to be_nil + end + end +end -- cgit v1.2.1 From 32147ddf5412bceaea809dedb028b23f55461a89 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 14:22:03 +0530 Subject: Add a test case for "end condition happens before start condition". - In the cycle analytics specs. --- spec/support/cycle_analytics_helpers.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'spec') diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index c369caf8041..60524624782 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -80,6 +80,27 @@ module CycleAnalyticsHelpers expect(subject.send(phase)).to be_nil end end + + context "when the end condition happens before the start condition" do + it 'returns nil' do + data = data_fn[self] + start_time = Time.now + end_time = start_time + rand(1..5).days + + # Run `before_end_fn` at the midpoint between `start_time` and `end_time` + Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn + + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(start_time) { condition_fn[self, data] } + end + + start_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } + end + + expect(subject.send(phase)).to be_nil + end + end end end -- cgit v1.2.1 From 0a767f7b618161278b66f7e1d842a51c8cab37b3 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 14:29:12 +0530 Subject: Consolidate all cycle analytics helper methods. 1. Move the test generation to `CycleAnalyticsHelpers::TestGeneration` 2. Move all helper methods (previously placed in each individual spec file) to `CycleAnalyticsHelpers` --- spec/models/cycle_analytics/code_spec.rb | 20 --- spec/models/cycle_analytics/plan_spec.rb | 6 - spec/models/cycle_analytics/production_spec.rb | 30 ---- spec/models/cycle_analytics/review_spec.rb | 21 --- spec/models/cycle_analytics/staging_spec.rb | 30 ---- spec/models/cycle_analytics/test_spec.rb | 16 -- spec/support/cycle_analytics_helpers.rb | 171 ++++----------------- .../cycle_analytics_helpers/test_generation.rb | 154 +++++++++++++++++++ 8 files changed, 184 insertions(+), 264 deletions(-) create mode 100644 spec/support/cycle_analytics_helpers/test_generation.rb (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index a81b5cf444d..18dd4d0f1ab 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -6,26 +6,6 @@ describe 'CycleAnalytics#code', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_commit_referencing_issue(issue) - sha = project.repository.commit_file(user, random_git_name, "content", "Commit for ##{issue.iid}", "master", false) - commit = project.repository.commit(sha) - commit.create_cross_references!(user) - end - - def create_merge_request_closing_issue(issue, message: nil) - source_branch = random_git_name - project.repository.add_branch(user, source_branch, 'master') - - opts = { - title: 'Awesome merge_request', - description: message || "Fixes #{issue.to_reference}", - source_branch: source_branch, - target_branch: 'master' - } - - MergeRequests::CreateService.new(project, user, opts).execute - end - generate_cycle_analytics_spec(phase: :code, data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, start_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue]) }]], diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 42984169b28..fa092bf6825 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -6,12 +6,6 @@ describe 'CycleAnalytics#plan', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_commit_referencing_issue(issue) - sha = project.repository.commit_file(user, random_git_name, "content", "Commit for ##{issue.iid}", "master", false) - commit = project.repository.commit(sha) - commit.create_cross_references! - end - generate_cycle_analytics_spec(phase: :plan, data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, start_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) }], diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 76e42c1c2d4..703f8d5f782 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -6,36 +6,6 @@ describe 'CycleAnalytics#production', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_merge_request_closing_issue(issue, message: nil) - source_branch = random_git_name - project.repository.add_branch(user, source_branch, 'master') - sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) - project.repository.commit(sha) - - opts = { - title: 'Awesome merge_request', - description: message || "Fixes #{issue.to_reference}", - source_branch: source_branch, - target_branch: 'master' - } - - MergeRequests::CreateService.new(project, user, opts).execute - end - - def merge_merge_requests_closing_issue(issue) - merge_requests = issue.closed_by_merge_requests - merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } - end - - def deploy_master(environment: 'production') - CreateDeploymentService.new(project, user, { - environment: environment, - ref: 'master', - tag: false, - sha: project.repository.commit('master').sha - }).execute - end - generate_cycle_analytics_spec(phase: :production, data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, start_time_conditions: [["issue is created", -> (context, data) { data[:issue].save }]], diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 8530d70a38e..867a90d6258 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -6,27 +6,6 @@ describe 'CycleAnalytics#review', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_merge_request_closing_issue(issue) - source_branch = random_git_name - project.repository.add_branch(user, source_branch, 'master') - sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) - project.repository.commit(sha) - - opts = { - title: 'Awesome merge_request', - description: "Fixes #{issue.to_reference}", - source_branch: source_branch, - target_branch: 'master' - } - - MergeRequests::CreateService.new(project, user, opts).execute - end - - def merge_merge_requests_closing_issue(issue) - merge_requests = issue.closed_by_merge_requests - merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } - end - generate_cycle_analytics_spec(phase: :review, data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, start_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]], diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index 23e01532500..105f566f41c 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -6,36 +6,6 @@ describe 'CycleAnalytics#staging', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_merge_request_closing_issue(issue, message: nil) - source_branch = random_git_name - project.repository.add_branch(user, source_branch, 'master') - sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) - project.repository.commit(sha) - - opts = { - title: 'Awesome merge_request', - description: message || "Fixes #{issue.to_reference}", - source_branch: source_branch, - target_branch: 'master' - } - - MergeRequests::CreateService.new(project, user, opts).execute - end - - def merge_merge_requests_closing_issue(issue) - merge_requests = issue.closed_by_merge_requests - merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } - end - - def deploy_master(environment: 'production') - CreateDeploymentService.new(project, user, { - environment: environment, - ref: 'master', - tag: false, - sha: project.repository.commit('master').sha - }).execute - end - generate_cycle_analytics_spec(phase: :staging, data_fn: lambda do |context| issue = context.create(:issue, project: context.project) diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index af4d55f5801..aa7faa74d38 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -6,22 +6,6 @@ describe 'CycleAnalytics#test', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - def create_merge_request_closing_issue(issue, message: nil) - source_branch = random_git_name - project.repository.add_branch(user, source_branch, 'master') - sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) - project.repository.commit(sha) - - opts = { - title: 'Awesome merge_request', - description: message || "Fixes #{issue.to_reference}", - source_branch: source_branch, - target_branch: 'master' - } - - MergeRequests::CreateService.new(project, user, opts).execute - end - generate_cycle_analytics_spec(phase: :test, data_fn: lambda do |context| issue = context.create(:issue, project: context.project) diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index 60524624782..c5fe1170423 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -1,152 +1,41 @@ -# rubocop:disable Metrics/AbcSize - -# Note: The ABC size is large here because we have a method generating test cases with -# multiple nested contexts. This shouldn't count as a violation. - module CycleAnalyticsHelpers - # Generate the most common set of specs that all cycle analytics phases need to have. - # - # Arguments: - # - # phase: Which phase are we testing? Will call `CycleAnalytics.new.send(phase)` for the final assertion - # data_fn: A function that returns a hash, constituting initial data for the test case - # start_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with - # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). - # Each `condition_fn` is expected to implement a case which consitutes the start of the given cycle analytics phase. - # end_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with - # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). - # Each `condition_fn` is expected to implement a case which consitutes the end of the given cycle analytics phase. - # before_end_fn: This function is run before calling the end time conditions. Used for setup that needs to be run between the start and end conditions. - - def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:, before_end_fn: nil) - combinations_of_start_time_conditions = (1..start_time_conditions.size).flat_map { |size| start_time_conditions.combination(size).to_a } - combinations_of_end_time_conditions = (1..end_time_conditions.size).flat_map { |size| end_time_conditions.combination(size).to_a } - - scenarios = combinations_of_start_time_conditions.product(combinations_of_end_time_conditions) - scenarios.each do |start_time_conditions, end_time_conditions| - context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do - context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do - it "finds the median of available durations between the two conditions" do - time_differences = Array.new(5) do |index| - data = data_fn[self] - start_time = (index * 10).days.from_now - end_time = start_time + rand(1..5).days - - start_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(start_time) { condition_fn[self, data] } - end - - # Run `before_end_fn` at the midpoint between `start_time` and `end_time` - Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn - - end_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(end_time) { condition_fn[self, data] } - end - - end_time - start_time - end - - median_time_difference = time_differences.sort[2] - expect(subject.send(phase)).to be_within(5).of(median_time_difference) - end - - context "when the data belongs to another project" do - let(:other_project) { create(:project) } - - it "returns nil" do - # Use a stub to "trick" the data/condition functions - # into using another project. This saves us from having to - # define separate data/condition functions for this particular - # 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 - - end_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(end_time) { condition_fn[self, data] } - end - end - - # Turn off the stub before checking assertions - allow(self).to receive(:project).and_call_original - - expect(subject.send(phase)).to be_nil - end - end - - context "when the end condition happens before the start condition" do - it 'returns nil' do - data = data_fn[self] - start_time = Time.now - end_time = start_time + rand(1..5).days - - # Run `before_end_fn` at the midpoint between `start_time` and `end_time` - Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn - - end_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(start_time) { condition_fn[self, data] } - end - - start_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(end_time) { condition_fn[self, data] } - end - - expect(subject.send(phase)).to be_nil - end - end - end - end - - 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 - end + def create_commit_referencing_issue(issue) + sha = project.repository.commit_file(user, random_git_name, "content", "Commit for ##{issue.iid}", "master", false) + commit = project.repository.commit(sha) + commit.create_cross_references!(user) + end - expect(subject.send(phase)).to be_nil - end - end - end + def create_merge_request_closing_issue(issue, message: nil) + source_branch = random_git_name + project.repository.add_branch(user, source_branch, 'master') + sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) + project.repository.commit(sha) - 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 + opts = { + title: 'Awesome merge_request', + description: message || "Fixes #{issue.to_reference}", + source_branch: source_branch, + target_branch: 'master' + } - start_time_conditions.each do |condition_name, condition_fn| - Timecop.freeze(start_time) { condition_fn[self, data] } - end - end + MergeRequests::CreateService.new(project, user, opts).execute + end - expect(subject.send(phase)).to be_nil - end - end - end - end + def merge_merge_requests_closing_issue(issue) + merge_requests = issue.closed_by_merge_requests + merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } + end - context "when none of the start / end conditions are matched" do - it "returns nil" do - expect(subject.send(phase)).to be_nil - end - end + def deploy_master(environment: 'production') + CreateDeploymentService.new(project, user, { + environment: environment, + ref: 'master', + tag: false, + sha: project.repository.commit('master').sha + }).execute end end RSpec.configure do |config| - config.extend CycleAnalyticsHelpers + config.include CycleAnalyticsHelpers end diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb new file mode 100644 index 00000000000..4e386691d78 --- /dev/null +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -0,0 +1,154 @@ +# rubocop:disable Metrics/AbcSize + +# Note: The ABC size is large here because we have a method generating test cases with +# multiple nested contexts. This shouldn't count as a violation. + +module CycleAnalyticsHelpers + module TestGeneration + # Generate the most common set of specs that all cycle analytics phases need to have. + # + # Arguments: + # + # phase: Which phase are we testing? Will call `CycleAnalytics.new.send(phase)` for the final assertion + # data_fn: A function that returns a hash, constituting initial data for the test case + # start_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with + # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). + # Each `condition_fn` is expected to implement a case which consitutes the start of the given cycle analytics phase. + # end_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with + # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). + # Each `condition_fn` is expected to implement a case which consitutes the end of the given cycle analytics phase. + # before_end_fn: This function is run before calling the end time conditions. Used for setup that needs to be run between the start and end conditions. + + def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:, before_end_fn: nil) + combinations_of_start_time_conditions = (1..start_time_conditions.size).flat_map { |size| start_time_conditions.combination(size).to_a } + combinations_of_end_time_conditions = (1..end_time_conditions.size).flat_map { |size| end_time_conditions.combination(size).to_a } + + scenarios = combinations_of_start_time_conditions.product(combinations_of_end_time_conditions) + scenarios.each do |start_time_conditions, end_time_conditions| + context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do + context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do + it "finds the median of available durations between the two conditions" do + time_differences = Array.new(5) do |index| + data = data_fn[self] + start_time = (index * 10).days.from_now + end_time = start_time + rand(1..5).days + + start_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(start_time) { condition_fn[self, data] } + end + + # Run `before_end_fn` at the midpoint between `start_time` and `end_time` + Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn + + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } + end + + end_time - start_time + end + + median_time_difference = time_differences.sort[2] + expect(subject.send(phase)).to be_within(5).of(median_time_difference) + end + + context "when the data belongs to another project" do + let(:other_project) { create(:project) } + + it "returns nil" do + # Use a stub to "trick" the data/condition functions + # into using another project. This saves us from having to + # define separate data/condition functions for this particular + # 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 + + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } + end + end + + # Turn off the stub before checking assertions + allow(self).to receive(:project).and_call_original + + expect(subject.send(phase)).to be_nil + end + end + + context "when the end condition happens before the start condition" do + it 'returns nil' do + data = data_fn[self] + start_time = Time.now + end_time = start_time + rand(1..5).days + + # Run `before_end_fn` at the midpoint between `start_time` and `end_time` + Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn + + end_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(start_time) { condition_fn[self, data] } + end + + start_time_conditions.each do |condition_name, condition_fn| + Timecop.freeze(end_time) { condition_fn[self, data] } + end + + expect(subject.send(phase)).to be_nil + end + end + end + end + + 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 + end + + expect(subject.send(phase)).to be_nil + end + end + end + + 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 + end + + expect(subject.send(phase)).to be_nil + end + end + end + end + + context "when none of the start / end conditions are matched" do + it "returns nil" do + expect(subject.send(phase)).to be_nil + end + end + end + end +end + +RSpec.configure do |config| + config.extend CycleAnalyticsHelpers::TestGeneration +end -- cgit v1.2.1 From 72b9b87ca93615640dcc022f324b2af16ceaa4eb Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 7 Sep 2016 14:51:09 +0530 Subject: Fix rubocop spec. --- spec/support/cycle_analytics_helpers/test_generation.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb index 4e386691d78..52609524564 100644 --- a/spec/support/cycle_analytics_helpers/test_generation.rb +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -38,7 +38,7 @@ module CycleAnalyticsHelpers end # Run `before_end_fn` at the midpoint between `start_time` and `end_time` - Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn + Timecop.freeze(start_time + (end_time - start_time) / 2) { before_end_fn[self, data] } if before_end_fn end_time_conditions.each do |condition_name, condition_fn| Timecop.freeze(end_time) { condition_fn[self, data] } @@ -89,7 +89,7 @@ module CycleAnalyticsHelpers end_time = start_time + rand(1..5).days # Run `before_end_fn` at the midpoint between `start_time` and `end_time` - Timecop.freeze(start_time + (end_time - start_time)/2) { before_end_fn[self, data] } if before_end_fn + Timecop.freeze(start_time + (end_time - start_time) / 2) { before_end_fn[self, data] } if before_end_fn end_time_conditions.each do |condition_name, condition_fn| Timecop.freeze(start_time) { condition_fn[self, data] } -- cgit v1.2.1 From da7c14442cc97e1ecd4c34ab2ef9bf2662ea241d Mon Sep 17 00:00:00 2001 From: Dan Rowden Date: Mon, 25 Jul 2016 22:23:27 +0100 Subject: Updated milestone count helper plus tests --- spec/factories/milestones.rb | 7 ++++++- spec/helpers/milestones_helper_spec.rb | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 spec/helpers/milestones_helper_spec.rb (limited to 'spec') diff --git a/spec/factories/milestones.rb b/spec/factories/milestones.rb index e9e85962fe4..84da71ed6dc 100644 --- a/spec/factories/milestones.rb +++ b/spec/factories/milestones.rb @@ -3,10 +3,15 @@ FactoryGirl.define do title project + trait :active do + state "active" + end + trait :closed do - state :closed + state "closed" end + factory :active_milestone, traits: [:active] factory :closed_milestone, traits: [:closed] end end diff --git a/spec/helpers/milestones_helper_spec.rb b/spec/helpers/milestones_helper_spec.rb new file mode 100644 index 00000000000..8e23415bfe4 --- /dev/null +++ b/spec/helpers/milestones_helper_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe MilestonesHelper do + + describe '#milestone_counts' do + let(:project) { FactoryGirl.create(:project) } + let(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) } + let(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) } + let(:milestone_3) { FactoryGirl.create(:closed_milestone, project: project) } + + let(:counts) { helper.milestone_counts(project.milestones) } + + it 'returns a hash containing three items' do + expect(counts.length).to eq 3 + end + it 'returns a hash containing "opened" key' do + expect(counts.has_key?(:opened)).to eq true + end + it 'returns a hash containing "closed" key' do + expect(counts.has_key?(:closed)).to eq true + end + it 'returns a hash containing "all" key' do + expect(counts.has_key?(:all)).to eq true + end + # This throws a "NoMethodError: undefined method `+' for nil:NilClass" error for line 27; can't figure out why it can't find the keys in the hash + # it 'shows "all" object is the sum of "opened" and "closed" objects' do + # total = counts[:opened] + counts[:closed] + # expect(counts[:all]).to eq total + # end + + end + +end -- cgit v1.2.1 From 19e2bf1c21a853e45db0c18133e5f1b1234ad09f Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 22 Aug 2016 17:58:28 -0500 Subject: Fix failing specs and improve html --- spec/helpers/milestones_helper_spec.rb | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/helpers/milestones_helper_spec.rb b/spec/helpers/milestones_helper_spec.rb index 8e23415bfe4..d65610723b0 100644 --- a/spec/helpers/milestones_helper_spec.rb +++ b/spec/helpers/milestones_helper_spec.rb @@ -1,33 +1,35 @@ require 'spec_helper' describe MilestonesHelper do - describe '#milestone_counts' do let(:project) { FactoryGirl.create(:project) } - let(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) } - let(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) } - let(:milestone_3) { FactoryGirl.create(:closed_milestone, project: project) } + let!(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) } + let!(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) } + let!(:milestone_3) { FactoryGirl.create(:closed_milestone, project: project) } let(:counts) { helper.milestone_counts(project.milestones) } it 'returns a hash containing three items' do expect(counts.length).to eq 3 end + it 'returns a hash containing "opened" key' do expect(counts.has_key?(:opened)).to eq true end + it 'returns a hash containing "closed" key' do expect(counts.has_key?(:closed)).to eq true end + it 'returns a hash containing "all" key' do expect(counts.has_key?(:all)).to eq true end - # This throws a "NoMethodError: undefined method `+' for nil:NilClass" error for line 27; can't figure out why it can't find the keys in the hash - # it 'shows "all" object is the sum of "opened" and "closed" objects' do - # total = counts[:opened] + counts[:closed] - # expect(counts[:all]).to eq total - # end + it 'shows "all" object is the sum of "opened" and "closed" objects' do + puts counts.as_json + total = counts[:opened] + counts[:closed] + expect(counts[:all]).to eq total + end end - end + \ No newline at end of file -- cgit v1.2.1 From 8499de19c9bca4c43378b8a9cf2b6705f9cab647 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 24 Aug 2016 12:29:27 -0500 Subject: Ensure milestone counts work with no data Commit originally written by @smcgivern --- spec/helpers/milestones_helper_spec.rb | 36 ++++++++++++++++------------------ 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'spec') diff --git a/spec/helpers/milestones_helper_spec.rb b/spec/helpers/milestones_helper_spec.rb index d65610723b0..28c2268f8d0 100644 --- a/spec/helpers/milestones_helper_spec.rb +++ b/spec/helpers/milestones_helper_spec.rb @@ -3,33 +3,31 @@ require 'spec_helper' describe MilestonesHelper do describe '#milestone_counts' do let(:project) { FactoryGirl.create(:project) } - let!(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) } - let!(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) } - let!(:milestone_3) { FactoryGirl.create(:closed_milestone, project: project) } - let(:counts) { helper.milestone_counts(project.milestones) } - it 'returns a hash containing three items' do - expect(counts.length).to eq 3 - end + context 'when there are milestones' do + let!(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) } + let!(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) } + let!(:milestone_3) { FactoryGirl.create(:closed_milestone, project: project) } - it 'returns a hash containing "opened" key' do - expect(counts.has_key?(:opened)).to eq true + it 'returns the correct counts' do + expect(counts).to eq(opened: 2, closed: 1, all: 3) + end end - it 'returns a hash containing "closed" key' do - expect(counts.has_key?(:closed)).to eq true - end + context 'when there are only milestones of one type' do + let!(:milestone_1) { FactoryGirl.create(:active_milestone, project: project) } + let!(:milestone_2) { FactoryGirl.create(:active_milestone, project: project) } - it 'returns a hash containing "all" key' do - expect(counts.has_key?(:all)).to eq true + it 'returns the correct counts' do + expect(counts).to eq(opened: 2, closed: 0, all: 2) + end end - it 'shows "all" object is the sum of "opened" and "closed" objects' do - puts counts.as_json - total = counts[:opened] + counts[:closed] - expect(counts[:all]).to eq total + context 'when there are no milestones' do + it 'returns the correct counts' do + expect(counts).to eq(opened: 0, closed: 0, all: 0) + end end end end - \ No newline at end of file -- cgit v1.2.1 From ad5f835ceefb4b05f9373381b1581a5f142adf2d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 8 Sep 2016 09:59:20 +0100 Subject: Fixed list issues not loading with spaces in filtered values Vue resource is kindly encoding our URL params but Rails sadly doesn't seem to understand them. Closes #21920 --- spec/features/boards/boards_spec.rb | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index c6c2e2095df..c6ed5ade440 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -61,6 +61,7 @@ describe 'Issue Boards', feature: true, js: true do let(:bug) { create(:label, project: project, name: 'Bug') } let!(:backlog) { create(:label, project: project, name: 'Backlog') } let!(:done) { create(:label, project: project, name: 'Done') } + let!(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') } let!(:list1) { create(:list, board: project.board, label: planning, position: 0) } let!(:list2) { create(:list, board: project.board, label: development, position: 1) } @@ -74,7 +75,7 @@ describe 'Issue Boards', feature: true, js: true do let!(:issue6) { create(:labeled_issue, project: project, labels: [planning, development]) } let!(:issue7) { create(:labeled_issue, project: project, labels: [development]) } let!(:issue8) { create(:closed_issue, project: project) } - let!(:issue9) { create(:labeled_issue, project: project, labels: [testing, bug]) } + let!(:issue9) { create(:labeled_issue, project: project, labels: [testing, bug, accepting]) } before do visit namespace_project_board_path(project.namespace, project) @@ -467,6 +468,34 @@ describe 'Issue Boards', feature: true, js: true do end end + it 'filters by label with space after reload' do + page.within '.issues-filters' do + click_button('Label') + wait_for_ajax + + page.within '.dropdown-menu-labels' do + click_link(accepting.title) + wait_for_vue_resource(spinner: false) + find('.dropdown-menu-close').click + end + end + + # Test after reload + page.evaluate_script 'window.location.reload()' + + wait_for_vue_resource + + page.within(find('.board', match: :first)) do + expect(page.find('.board-header')).to have_content('1') + expect(page).to have_selector('.card', count: 1) + end + + page.within(find('.board:nth-child(2)')) do + expect(page.find('.board-header')).to have_content('0') + expect(page).to have_selector('.card', count: 0) + end + end + it 'infinite scrolls list with label filter' do 50.times do create(:labeled_issue, project: project, labels: [testing]) -- cgit v1.2.1 From ff1d6477dade1564d8d8f366375607ce57f3592f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 16 Aug 2016 17:32:58 +0200 Subject: Export integration test and attribute change spec - squashed Export file integration test that checks for sensitive info. Also added spec to check new added attributes to models that can be exported. --- .../projects/import_export/export_file_spec.rb | 162 +++++++++++++++++++++ .../import_export/attribute_configuration_spec.rb | 83 +++++++++++ 2 files changed, 245 insertions(+) create mode 100644 spec/features/projects/import_export/export_file_spec.rb create mode 100644 spec/lib/gitlab/import_export/attribute_configuration_spec.rb (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb new file mode 100644 index 00000000000..eea0f595eb0 --- /dev/null +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -0,0 +1,162 @@ +require 'spec_helper' + +feature 'project export', feature: true, js: true do + include Select2Helper + + let(:user) { create(:admin) } + let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } + + let(:sensitive_words) { %w[pass secret token key] } + let(:safe_hashes) do + { + token: [ + { # Triggers + "id" => 1, + "token" => "token", + "project_id" => nil, + "deleted_at" => nil, + "gl_project_id" => 4 + }, + { # Project hooks + "id" => 1, + "project_id" => 4, + "service_id" => nil, + "push_events" => true, + "issues_events" => false, + "merge_requests_events" => false, + "tag_push_events" => false, + "note_events" => false, + "enable_ssl_verification" => true, + "build_events" => false, + "wiki_page_events" => false, + "pipeline_events" => false, + "token" => "token" + } + ] + } + end + + let(:project) { setup_project } + + background do + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) + end + + after do + FileUtils.rm_rf(export_path, secure: true) + end + + context 'admin user' do + before do + login_as(user) + end + + scenario 'user imports an exported project successfully' do + visit edit_namespace_project_path(project.namespace, project) + + expect(page).to have_content('Export project') + + click_link 'Export project' + + visit edit_namespace_project_path(project.namespace, project) + + expect(page).to have_content('Download export') + + in_directory_with_expanded_export(project) do |exit_status, tmpdir| + expect(exit_status).to eq(0) + + project_json_path = File.join(tmpdir, 'project.json') + expect(File).to exist(project_json_path) + + project_hash = JSON.parse(IO.read(project_json_path)) + + sensitive_words.each do |sensitive_word| + expect(has_sensitive_attributes?(sensitive_word, project_hash)).to be false + end + end + end + end + + def setup_project + issue = create(:issue, assignee: user) + snippet = create(:project_snippet) + release = create(:release) + + project = create(:project, + :public, + issues: [issue], + snippets: [snippet], + releases: [release] + ) + label = create(:label, project: project) + create(:label_link, label: label, target: issue) + milestone = create(:milestone, project: project) + merge_request = create(:merge_request, source_project: project, milestone: milestone) + commit_status = create(:commit_status, project: project) + + ci_pipeline = create(:ci_pipeline, + project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch, + statuses: [commit_status]) + + create(:ci_build, pipeline: ci_pipeline, project: project) + create(:milestone, project: project) + create(:note, noteable: issue, project: project) + create(:note, noteable: merge_request, project: project) + create(:note, noteable: snippet, project: project) + create(:note_on_commit, + author: user, + project: project, + commit_id: ci_pipeline.sha) + + create(:event, target: milestone, project: project, action: Event::CREATED, author: user) + create(:project_member, :master, user: user, project: project) + create(:ci_variable, project: project) + create(:ci_trigger, project: project) + key = create(:deploy_key) + key.projects << project + create(:service, project: project) + create(:project_hook, project: project, token: 'token') + create(:protected_branch, project: project) + + project + end + + # Expands the compressed file for an exported project into +tmpdir+ + def in_directory_with_expanded_export(project) + Dir.mktmpdir do |tmpdir| + export_file = project.export_project_path + _output, exit_status = Gitlab::Popen.popen(%W{tar -zxf #{export_file} -C #{tmpdir}}) + + yield(exit_status, tmpdir) + end + end + + # Recursively finds key/values including +key+ as part of the key, inside a nested hash + def deep_find_with_parent(key, object, found = nil) + if object.respond_to?(:key?) && object.keys.any? { |k| k.include?(key) } + [object[key], object] if object[key] + elsif object.is_a? Enumerable + object.find { |*a| found, object = deep_find_with_parent(key, a.last, found) } + [found, object] if found + end + end + + # Returns true if a sensitive word is found inside a hash, excluding safe hashes + def has_sensitive_attributes?(sensitive_word, project_hash) + loop do + object, parent = deep_find_with_parent(sensitive_word, project_hash) + parent.except!('created_at', 'updated_at', 'url') if parent + + if object && safe_hashes[sensitive_word.to_sym].include?(parent) + # It's in the safe list, remove hash and keep looking + parent.delete(object) + elsif object + return true + else + return false + end + end + end +end diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb new file mode 100644 index 00000000000..7872f0c2257 --- /dev/null +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -0,0 +1,83 @@ +require 'spec_helper' + +# Checks whether there are new attributes in models that are currently being exported as part of the +# project Import/Export feature. +# If there are new attributes, these will have to either be added to this spec in case we want them +# to be included as part of the export, or blacklist them using the import_export.yml configuration file. +# Likewise, new models added to import_export.yml, will need to be added with their correspondent attributes +# to this spec. +describe 'Attribute configuration', lib: true do + let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } + let(:relation_names) do + names = config_hash['project_tree'].to_s.gsub(/[\[{}\]=>\"\:]/, ',').split(',').delete_if(&:blank?) + names.uniq - ['author', 'milestones', 'labels'] + ['project'] # Remove duplicated or add missing models + end + + let(:safe_model_attributes) do + { + 'Issue' => %w[id title assignee_id author_id project_id created_at updated_at position branch_name description state iid updated_by_id confidential deleted_at due_date moved_to_id lock_version], + 'Event' => %w[id target_type target_id title data project_id created_at updated_at action author_id], + 'Note' => %w[id note noteable_type author_id created_at updated_at project_id attachment line_code commit_id noteable_id system st_diff updated_by_id type position original_position], + 'LabelLink' => %w[id label_id target_id target_type created_at updated_at], + 'Label' => %w[id title color project_id created_at updated_at template description priority], + 'Milestone' => %w[id title project_id description due_date created_at updated_at state iid], + 'ProjectSnippet' => %w[id title content author_id project_id created_at updated_at file_name type visibility_level], + 'Release' => %w[id tag description project_id created_at updated_at], + 'ProjectMember' => %w[id access_level source_id source_type user_id notification_level type created_at updated_at created_by_id invite_email invite_token invite_accepted_at requested_at], + 'User' => %w[id username email], + 'MergeRequest' => %w[id target_branch source_branch source_project_id author_id assignee_id title created_at updated_at state merge_status target_project_id iid description position locked_at updated_by_id merge_error merge_params merge_when_build_succeeds merge_user_id merge_commit_sha deleted_at in_progress_merge_commit_sha lock_version], + 'MergeRequestDiff' => %w[id state st_commits merge_request_id created_at updated_at base_commit_sha real_size head_commit_sha start_commit_sha], + 'Ci::Pipeline' => %w[id project_id ref sha before_sha push_data created_at updated_at tag yaml_errors committed_at gl_project_id status started_at finished_at duration user_id], + 'CommitStatus' => %w[id project_id status finished_at trace created_at updated_at started_at runner_id coverage commit_id commands job_id name deploy options allow_failure stage trigger_request_id stage_idx tag ref user_id type target_url description artifacts_file gl_project_id artifacts_metadata erased_by_id erased_at artifacts_expire_at environment artifacts_size when yaml_variables queued_at], + 'Ci::Variable' => %w[id project_id key value encrypted_value encrypted_value_salt encrypted_value_iv gl_project_id], + 'Ci::Trigger' => %w[id token project_id deleted_at created_at updated_at gl_project_id], + 'DeployKey' => %w[id user_id created_at updated_at key title type fingerprint public], + 'Service' => %w[id type title project_id created_at updated_at active properties template push_events issues_events merge_requests_events tag_push_events note_events pipeline_events build_events category default wiki_page_events], + 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token], + 'ProtectedBranch' => %w[id project_id name created_at updated_at], + 'Project' => %w[description issues_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived] + } + end + + it 'has no new columns' do + relation_names.each do |relation_name| + relation_class = relation_class_for_name(relation_name) + + expect(safe_model_attributes[relation_class.to_s]).not_to be_nil + + current_attributes = parsed_attributes(relation_name, relation_class.attribute_names) + safe_attributes = safe_model_attributes[relation_class.to_s] + new_attributes = current_attributes - safe_attributes + + expect(new_attributes).to be_empty, failure_message(relation_class.to_s, new_attributes) + end + end + + def relation_class_for_name(relation_name) + relation_name = Gitlab::ImportExport::RelationFactory::OVERRIDES[relation_name.to_sym] || relation_name + relation_name.to_s.classify.constantize + end + + def failure_message(relation_class, new_attributes) + <<-MSG + It looks like #{relation_class}, which is exported using the project Import/Export, has new attributes: #{new_attributes.join(',')} + + Please add the attribute(s) to +safe_model_attributes+ in CURRENT_SPEC if you consider this can be exported. + Otherwise, please blacklist the attribute(s) in IMPORT_EXPORT_CONFIG by adding it to its correspondent + model in the +excluded_attributes+ section. + + CURRENT_SPEC: #{__FILE__} + IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file} + MSG + end + + def parsed_attributes(relation_name, attributes) + excluded_attributes = config_hash['excluded_attributes'][relation_name] + included_attributes = config_hash['included_attributes'][relation_name] + + attributes = attributes - JSON[excluded_attributes.to_json] if excluded_attributes + attributes = attributes & JSON[included_attributes.to_json] if included_attributes + + attributes + end +end -- cgit v1.2.1 From ad14944be717884dba9e11187a81fde281ac2237 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 19 Aug 2016 17:22:02 +0200 Subject: fix specs so they work in EE straight away --- spec/features/projects/import_export/export_file_spec.rb | 2 +- spec/lib/gitlab/import_export/attribute_configuration_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index eea0f595eb0..8188403f18f 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -147,7 +147,7 @@ feature 'project export', feature: true, js: true do def has_sensitive_attributes?(sensitive_word, project_hash) loop do object, parent = deep_find_with_parent(sensitive_word, project_hash) - parent.except!('created_at', 'updated_at', 'url') if parent + parent.except!('created_at', 'updated_at', 'url', 'group_id') if parent if object && safe_hashes[sensitive_word.to_sym].include?(parent) # It's in the safe list, remove hash and keep looking diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 7872f0c2257..968a2eb6d42 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -15,9 +15,9 @@ describe 'Attribute configuration', lib: true do let(:safe_model_attributes) do { - 'Issue' => %w[id title assignee_id author_id project_id created_at updated_at position branch_name description state iid updated_by_id confidential deleted_at due_date moved_to_id lock_version], + 'Issue' => %w[id title assignee_id author_id project_id created_at updated_at position branch_name description state iid updated_by_id confidential deleted_at due_date moved_to_id lock_version milestone_id weight], 'Event' => %w[id target_type target_id title data project_id created_at updated_at action author_id], - 'Note' => %w[id note noteable_type author_id created_at updated_at project_id attachment line_code commit_id noteable_id system st_diff updated_by_id type position original_position], + 'Note' => %w[id note noteable_type author_id created_at updated_at project_id attachment line_code commit_id noteable_id system st_diff updated_by_id type position original_position resolved_at resolved_by_id discussion_id original_discussion_id], 'LabelLink' => %w[id label_id target_id target_type created_at updated_at], 'Label' => %w[id title color project_id created_at updated_at template description priority], 'Milestone' => %w[id title project_id description due_date created_at updated_at state iid], @@ -25,7 +25,7 @@ describe 'Attribute configuration', lib: true do 'Release' => %w[id tag description project_id created_at updated_at], 'ProjectMember' => %w[id access_level source_id source_type user_id notification_level type created_at updated_at created_by_id invite_email invite_token invite_accepted_at requested_at], 'User' => %w[id username email], - 'MergeRequest' => %w[id target_branch source_branch source_project_id author_id assignee_id title created_at updated_at state merge_status target_project_id iid description position locked_at updated_by_id merge_error merge_params merge_when_build_succeeds merge_user_id merge_commit_sha deleted_at in_progress_merge_commit_sha lock_version], + 'MergeRequest' => %w[id target_branch source_branch source_project_id author_id assignee_id title created_at updated_at state merge_status target_project_id iid description position locked_at updated_by_id merge_error merge_params merge_when_build_succeeds merge_user_id merge_commit_sha deleted_at in_progress_merge_commit_sha lock_version milestone_id approvals_before_merge rebase_commit_sha], 'MergeRequestDiff' => %w[id state st_commits merge_request_id created_at updated_at base_commit_sha real_size head_commit_sha start_commit_sha], 'Ci::Pipeline' => %w[id project_id ref sha before_sha push_data created_at updated_at tag yaml_errors committed_at gl_project_id status started_at finished_at duration user_id], 'CommitStatus' => %w[id project_id status finished_at trace created_at updated_at started_at runner_id coverage commit_id commands job_id name deploy options allow_failure stage trigger_request_id stage_idx tag ref user_id type target_url description artifacts_file gl_project_id artifacts_metadata erased_by_id erased_at artifacts_expire_at environment artifacts_size when yaml_variables queued_at], @@ -33,7 +33,7 @@ describe 'Attribute configuration', lib: true do 'Ci::Trigger' => %w[id token project_id deleted_at created_at updated_at gl_project_id], 'DeployKey' => %w[id user_id created_at updated_at key title type fingerprint public], 'Service' => %w[id type title project_id created_at updated_at active properties template push_events issues_events merge_requests_events tag_push_events note_events pipeline_events build_events category default wiki_page_events], - 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token], + 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token group_id], 'ProtectedBranch' => %w[id project_id name created_at updated_at], 'Project' => %w[description issues_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived] } -- cgit v1.2.1 From c71ed6291027ed5593087c980ceb6376ac3a09d4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 29 Aug 2016 15:55:10 +0200 Subject: fixed failing spec --- spec/lib/gitlab/import_export/attribute_configuration_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 968a2eb6d42..9f95b46229a 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -23,7 +23,7 @@ describe 'Attribute configuration', lib: true do 'Milestone' => %w[id title project_id description due_date created_at updated_at state iid], 'ProjectSnippet' => %w[id title content author_id project_id created_at updated_at file_name type visibility_level], 'Release' => %w[id tag description project_id created_at updated_at], - 'ProjectMember' => %w[id access_level source_id source_type user_id notification_level type created_at updated_at created_by_id invite_email invite_token invite_accepted_at requested_at], + 'ProjectMember' => %w[id access_level source_id source_type user_id notification_level type created_at updated_at created_by_id invite_email invite_token invite_accepted_at requested_at expires_at], 'User' => %w[id username email], 'MergeRequest' => %w[id target_branch source_branch source_project_id author_id assignee_id title created_at updated_at state merge_status target_project_id iid description position locked_at updated_by_id merge_error merge_params merge_when_build_succeeds merge_user_id merge_commit_sha deleted_at in_progress_merge_commit_sha lock_version milestone_id approvals_before_merge rebase_commit_sha], 'MergeRequestDiff' => %w[id state st_commits merge_request_id created_at updated_at base_commit_sha real_size head_commit_sha start_commit_sha], -- cgit v1.2.1 From 7323d30f44eaabbd8aad66a18ded233261a74718 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 31 Aug 2016 09:48:20 +0200 Subject: refactored specs based on feedback --- .../projects/import_export/export_file_spec.rb | 90 +--------------------- .../import_export/attribute_configuration_spec.rb | 10 ++- spec/support/import_export/export_file_helper.rb | 81 +++++++++++++++++++ 3 files changed, 92 insertions(+), 89 deletions(-) create mode 100644 spec/support/import_export/export_file_helper.rb (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 8188403f18f..0fff533eb2e 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' feature 'project export', feature: true, js: true do include Select2Helper + include ExportFileHelper let(:user) { create(:admin) } let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } @@ -15,11 +16,11 @@ feature 'project export', feature: true, js: true do "token" => "token", "project_id" => nil, "deleted_at" => nil, - "gl_project_id" => 4 + "gl_project_id" => project.id }, { # Project hooks "id" => 1, - "project_id" => 4, + "project_id" => project.id, "service_id" => nil, "push_events" => true, "issues_events" => false, @@ -51,7 +52,7 @@ feature 'project export', feature: true, js: true do login_as(user) end - scenario 'user imports an exported project successfully' do + scenario 'exports a project successfully' do visit edit_namespace_project_path(project.namespace, project) expect(page).to have_content('Export project') @@ -76,87 +77,4 @@ feature 'project export', feature: true, js: true do end end end - - def setup_project - issue = create(:issue, assignee: user) - snippet = create(:project_snippet) - release = create(:release) - - project = create(:project, - :public, - issues: [issue], - snippets: [snippet], - releases: [release] - ) - label = create(:label, project: project) - create(:label_link, label: label, target: issue) - milestone = create(:milestone, project: project) - merge_request = create(:merge_request, source_project: project, milestone: milestone) - commit_status = create(:commit_status, project: project) - - ci_pipeline = create(:ci_pipeline, - project: project, - sha: merge_request.diff_head_sha, - ref: merge_request.source_branch, - statuses: [commit_status]) - - create(:ci_build, pipeline: ci_pipeline, project: project) - create(:milestone, project: project) - create(:note, noteable: issue, project: project) - create(:note, noteable: merge_request, project: project) - create(:note, noteable: snippet, project: project) - create(:note_on_commit, - author: user, - project: project, - commit_id: ci_pipeline.sha) - - create(:event, target: milestone, project: project, action: Event::CREATED, author: user) - create(:project_member, :master, user: user, project: project) - create(:ci_variable, project: project) - create(:ci_trigger, project: project) - key = create(:deploy_key) - key.projects << project - create(:service, project: project) - create(:project_hook, project: project, token: 'token') - create(:protected_branch, project: project) - - project - end - - # Expands the compressed file for an exported project into +tmpdir+ - def in_directory_with_expanded_export(project) - Dir.mktmpdir do |tmpdir| - export_file = project.export_project_path - _output, exit_status = Gitlab::Popen.popen(%W{tar -zxf #{export_file} -C #{tmpdir}}) - - yield(exit_status, tmpdir) - end - end - - # Recursively finds key/values including +key+ as part of the key, inside a nested hash - def deep_find_with_parent(key, object, found = nil) - if object.respond_to?(:key?) && object.keys.any? { |k| k.include?(key) } - [object[key], object] if object[key] - elsif object.is_a? Enumerable - object.find { |*a| found, object = deep_find_with_parent(key, a.last, found) } - [found, object] if found - end - end - - # Returns true if a sensitive word is found inside a hash, excluding safe hashes - def has_sensitive_attributes?(sensitive_word, project_hash) - loop do - object, parent = deep_find_with_parent(sensitive_word, project_hash) - parent.except!('created_at', 'updated_at', 'url', 'group_id') if parent - - if object && safe_hashes[sensitive_word.to_sym].include?(parent) - # It's in the safe list, remove hash and keep looking - parent.delete(object) - elsif object - return true - else - return false - end - end - end end diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 9f95b46229a..b098e913a11 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -10,7 +10,7 @@ describe 'Attribute configuration', lib: true do let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } let(:relation_names) do names = config_hash['project_tree'].to_s.gsub(/[\[{}\]=>\"\:]/, ',').split(',').delete_if(&:blank?) - names.uniq - ['author', 'milestones', 'labels'] + ['project'] # Remove duplicated or add missing models + names.uniq - ['milestones', 'labels'] + ['project'] # Remove duplicated or add missing models end let(:safe_model_attributes) do @@ -35,7 +35,8 @@ describe 'Attribute configuration', lib: true do 'Service' => %w[id type title project_id created_at updated_at active properties template push_events issues_events merge_requests_events tag_push_events note_events pipeline_events build_events category default wiki_page_events], 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token group_id], 'ProtectedBranch' => %w[id project_id name created_at updated_at], - 'Project' => %w[description issues_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived] + 'Project' => %w[description issues_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived], + 'Author' => %w[name] } end @@ -43,7 +44,7 @@ describe 'Attribute configuration', lib: true do relation_names.each do |relation_name| relation_class = relation_class_for_name(relation_name) - expect(safe_model_attributes[relation_class.to_s]).not_to be_nil + expect(safe_model_attributes[relation_class.to_s]).not_to be_nil, "Expected exported class #{relation_class.to_s} to exist in safe_model_attributes" current_attributes = parsed_attributes(relation_name, relation_class.attribute_names) safe_attributes = safe_model_attributes[relation_class.to_s] @@ -80,4 +81,7 @@ describe 'Attribute configuration', lib: true do attributes end + + class Author < User + end end diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb new file mode 100644 index 00000000000..a2ff15c7bc5 --- /dev/null +++ b/spec/support/import_export/export_file_helper.rb @@ -0,0 +1,81 @@ +module ExportFileHelper + def setup_project + project = create(:project, :public) + + create(:release, project: project) + + issue = create(:issue, assignee: user, project: project) + snippet = create(:project_snippet, project: project) + label = create(:label, project: project) + milestone = create(:milestone, project: project) + merge_request = create(:merge_request, source_project: project, milestone: milestone) + commit_status = create(:commit_status, project: project) + + create(:label_link, label: label, target: issue) + + ci_pipeline = create(:ci_pipeline, + project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch, + statuses: [commit_status]) + + create(:ci_build, pipeline: ci_pipeline, project: project) + create(:milestone, project: project) + create(:note, noteable: issue, project: project) + create(:note, noteable: merge_request, project: project) + create(:note, noteable: snippet, project: project) + create(:note_on_commit, + author: user, + project: project, + commit_id: ci_pipeline.sha) + + create(:event, target: milestone, project: project, action: Event::CREATED, author: user) + create(:project_member, :master, user: user, project: project) + create(:ci_variable, project: project) + create(:ci_trigger, project: project) + key = create(:deploy_key) + key.projects << project + create(:service, project: project) + create(:project_hook, project: project, token: 'token') + create(:protected_branch, project: project) + + project + end + + # Expands the compressed file for an exported project into +tmpdir+ + def in_directory_with_expanded_export(project) + Dir.mktmpdir do |tmpdir| + export_file = project.export_project_path + _output, exit_status = Gitlab::Popen.popen(%W{tar -zxf #{export_file} -C #{tmpdir}}) + + yield(exit_status, tmpdir) + end + end + + # Recursively finds key/values including +key+ as part of the key, inside a nested hash + def deep_find_with_parent(key, object, found = nil) + if object.respond_to?(:key?) && object.keys.any? { |k| k.include?(key) } + [object[key], object] if object[key] + elsif object.is_a? Enumerable + object.find { |*a| found, object = deep_find_with_parent(key, a.last, found) } + [found, object] if found + end + end + + # Returns true if a sensitive word is found inside a hash, excluding safe hashes + def has_sensitive_attributes?(sensitive_word, project_hash) + loop do + object, parent = deep_find_with_parent(sensitive_word, project_hash) + parent.except!('created_at', 'updated_at', 'url', 'group_id') if parent + + if object && safe_hashes[sensitive_word.to_sym].include?(parent) + # It's in the safe list, remove hash and keep looking + parent.delete(object) + elsif object + return true + else + return false + end + end + end +end -- cgit v1.2.1 From 8ca963bd96a47411f390360fbe3e85766dce00db Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 1 Sep 2016 11:49:55 +0200 Subject: more refactoring of the specs --- .../projects/import_export/export_file_spec.rb | 27 ++-------------- .../import_export/attribute_configuration_spec.rb | 17 ++++++++-- spec/support/import_export/export_file_helper.rb | 36 +++++++++++++++++----- 3 files changed, 46 insertions(+), 34 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 0fff533eb2e..1a04c25012b 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -8,32 +8,9 @@ feature 'project export', feature: true, js: true do let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } let(:sensitive_words) { %w[pass secret token key] } - let(:safe_hashes) do + let(:safe_models) do { - token: [ - { # Triggers - "id" => 1, - "token" => "token", - "project_id" => nil, - "deleted_at" => nil, - "gl_project_id" => project.id - }, - { # Project hooks - "id" => 1, - "project_id" => project.id, - "service_id" => nil, - "push_events" => true, - "issues_events" => false, - "merge_requests_events" => false, - "tag_push_events" => false, - "note_events" => false, - "enable_ssl_verification" => true, - "build_events" => false, - "wiki_page_events" => false, - "pipeline_events" => false, - "token" => "token" - } - ] + token: [ProjectHook, Ci::Trigger] } end diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index b098e913a11..336da93c782 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -9,8 +9,12 @@ require 'spec_helper' describe 'Attribute configuration', lib: true do let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } let(:relation_names) do - names = config_hash['project_tree'].to_s.gsub(/[\[{}\]=>\"\:]/, ',').split(',').delete_if(&:blank?) - names.uniq - ['milestones', 'labels'] + ['project'] # Remove duplicated or add missing models + names = names_from_tree(config_hash['project_tree']) + + # Remove duplicated or add missing models + # - project is not part of the tree, so it has to be added manually. + # - milestone, labels have both singular and plural versions in the tree, so remove the duplicates. + names.flatten.uniq - ['milestones', 'labels'] + ['project'] end let(:safe_model_attributes) do @@ -54,6 +58,15 @@ describe 'Attribute configuration', lib: true do end end + # Returns a list of models from hashes/arrays contained in +project_tree+ + def names_from_tree(project_tree) + project_tree.map do |branch_or_model| + branch_or_model = branch_or_model.to_s if branch_or_model.is_a?(Symbol) + + branch_or_model.is_a?(String) ? branch_or_model : names_from_tree(branch_or_model) + end + end + def relation_class_for_name(relation_name) relation_name = Gitlab::ImportExport::RelationFactory::OVERRIDES[relation_name.to_sym] || relation_name relation_name.to_s.classify.constantize diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index a2ff15c7bc5..791863b8d16 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -1,4 +1,6 @@ module ExportFileHelper + IGNORED_ATTRIBUTES = %w[created_at updated_at url group_id] + def setup_project project = create(:project, :public) @@ -53,22 +55,28 @@ module ExportFileHelper end # Recursively finds key/values including +key+ as part of the key, inside a nested hash - def deep_find_with_parent(key, object, found = nil) - if object.respond_to?(:key?) && object.keys.any? { |k| k.include?(key) } - [object[key], object] if object[key] - elsif object.is_a? Enumerable - object.find { |*a| found, object = deep_find_with_parent(key, a.last, found) } + def deep_find_with_parent(sensitive_key_word, object, found = nil) + # Returns the parent object and the object found containing a sensitive word as part of the key + if object_contains_key?(object, sensitive_key_word) + [object[sensitive_key_word], object] if object[sensitive_key_word] + elsif object.is_a?(Enumerable) + # Recursively lookup for keys containing sensitive words in a Hash or Array + object.find { |*hash_or_array| found, object = deep_find_with_parent(sensitive_key_word, hash_or_array.last, found) } [found, object] if found end end + #Return true if the hash has a key containing a sensitive word + def object_contains_key?(object, sensitive_key_word) + object.is_a?(Hash) && object.keys.any? { |key| key.include?(sensitive_key_word) } + end + # Returns true if a sensitive word is found inside a hash, excluding safe hashes def has_sensitive_attributes?(sensitive_word, project_hash) loop do object, parent = deep_find_with_parent(sensitive_word, project_hash) - parent.except!('created_at', 'updated_at', 'url', 'group_id') if parent - if object && safe_hashes[sensitive_word.to_sym].include?(parent) + if object && is_safe_hash?(parent, sensitive_word) # It's in the safe list, remove hash and keep looking parent.delete(object) elsif object @@ -78,4 +86,18 @@ module ExportFileHelper end end end + + # Returns true if it's one of the excluded models in +safe_models+ + def is_safe_hash?(parent, sensitive_word) + return false unless parent + + # Extra attributes that appear in a model but not in the exported hash. + excluded_attributes = ['type'] + + safe_models[sensitive_word.to_sym].each do |safe_model| + return true if (safe_model.attribute_names - parent.keys - excluded_attributes).empty? + end + + false + end end -- cgit v1.2.1 From cb4ec41fd37a6d01d03a60487c9f6c84441b4eea Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 1 Sep 2016 11:57:01 +0200 Subject: remove IGNORED_ATTRIBUTES no longer required --- spec/support/import_export/export_file_helper.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'spec') diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index 791863b8d16..5235a859d9b 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -1,6 +1,4 @@ module ExportFileHelper - IGNORED_ATTRIBUTES = %w[created_at updated_at url group_id] - def setup_project project = create(:project, :public) -- cgit v1.2.1 From 74cefffd067a90fc25f8c64c40f57c484785c5d0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 1 Sep 2016 12:06:13 +0200 Subject: fixed spacing --- spec/support/import_export/export_file_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index 5235a859d9b..8e56bca21a3 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -64,7 +64,7 @@ module ExportFileHelper end end - #Return true if the hash has a key containing a sensitive word + # Return true if the hash has a key containing a sensitive word def object_contains_key?(object, sensitive_key_word) object.is_a?(Hash) && object.keys.any? { |key| key.include?(sensitive_key_word) } end -- cgit v1.2.1 From 13a977475aa813636c31f606e93ee2cc1a9e8d75 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 1 Sep 2016 17:59:36 +0200 Subject: add model configuration spec to check for new models. Also refactored attribute_configuration spec --- spec/lib/gitlab/import_export/all_models.json | 196 +++++++++++++++++++++ .../import_export/attribute_configuration_spec.rb | 16 +- .../import_export/model_configuration_spec.rb | 58 ++++++ spec/support/import_export/configuration_helper.rb | 15 ++ 4 files changed, 271 insertions(+), 14 deletions(-) create mode 100644 spec/lib/gitlab/import_export/all_models.json create mode 100644 spec/lib/gitlab/import_export/model_configuration_spec.rb create mode 100644 spec/support/import_export/configuration_helper.rb (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.json b/spec/lib/gitlab/import_export/all_models.json new file mode 100644 index 00000000000..81ebeeb64f9 --- /dev/null +++ b/spec/lib/gitlab/import_export/all_models.json @@ -0,0 +1,196 @@ +{ + "issues": [ + "subscriptions", + "award_emoji", + "author", + "assignee", + "updated_by", + "milestone", + "notes", + "label_links", + "labels", + "todos", + "user_agent_detail", + "project", + "moved_to", + "events" + ], + "events": [ + "author", + "project", + "target" + ], + "notes": [ + "award_emoji", + "project", + "noteable", + "author", + "updated_by", + "resolved_by", + "todos", + "events" + ], + "label_links": [ + "target", + "label" + ], + "label": [ + "subscriptions", + "project", + "lists", + "label_links", + "issues", + "merge_requests" + ], + "milestone": [ + "project", + "issues", + "labels", + "merge_requests", + "participants", + "events" + ], + "snippets": [ + "author", + "project", + "notes" + ], + "releases": [ + "project" + ], + "project_members": [ + "created_by", + "user", + "source", + "project" + ], + "merge_requests": [ + "subscriptions", + "award_emoji", + "author", + "assignee", + "updated_by", + "milestone", + "notes", + "label_links", + "labels", + "todos", + "target_project", + "source_project", + "merge_user", + "merge_request_diffs", + "merge_request_diff", + "events" + ], + "merge_request_diff": [ + "merge_request" + ], + "pipelines": [ + "project", + "user", + "statuses", + "builds", + "trigger_requests" + ], + "statuses": [ + "project", + "pipeline", + "user" + ], + "variables": [ + "project" + ], + "triggers": [ + "project", + "trigger_requests" + ], + "deploy_keys": [ + "user", + "deploy_keys_projects", + "projects" + ], + "services": [ + "project", + "service_hook" + ], + "hooks": [ + "project" + ], + "protected_branches": [ + "project", + "merge_access_levels", + "push_access_levels" + ], + "project": [ + "taggings", + "base_tags", + "tag_taggings", + "tags", + "creator", + "group", + "namespace", + "board", + "last_event", + "services", + "campfire_service", + "drone_ci_service", + "emails_on_push_service", + "builds_email_service", + "irker_service", + "pivotaltracker_service", + "hipchat_service", + "flowdock_service", + "assembla_service", + "asana_service", + "gemnasium_service", + "slack_service", + "buildkite_service", + "bamboo_service", + "teamcity_service", + "pushover_service", + "jira_service", + "redmine_service", + "custom_issue_tracker_service", + "bugzilla_service", + "gitlab_issue_tracker_service", + "external_wiki_service", + "forked_project_link", + "forked_from_project", + "forked_project_links", + "forks", + "merge_requests", + "fork_merge_requests", + "issues", + "labels", + "events", + "milestones", + "notes", + "snippets", + "hooks", + "protected_branches", + "project_members", + "users", + "requesters", + "deploy_keys_projects", + "deploy_keys", + "users_star_projects", + "starrers", + "releases", + "lfs_objects_projects", + "lfs_objects", + "project_group_links", + "invited_groups", + "todos", + "notification_settings", + "import_data", + "commit_statuses", + "pipelines", + "builds", + "runner_projects", + "runners", + "variables", + "triggers", + "environments", + "deployments" + ] +} \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 336da93c782..931b27ffb24 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -7,6 +7,8 @@ require 'spec_helper' # Likewise, new models added to import_export.yml, will need to be added with their correspondent attributes # to this spec. describe 'Attribute configuration', lib: true do + include ConfigurationHelper + let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } let(:relation_names) do names = names_from_tree(config_hash['project_tree']) @@ -58,20 +60,6 @@ describe 'Attribute configuration', lib: true do end end - # Returns a list of models from hashes/arrays contained in +project_tree+ - def names_from_tree(project_tree) - project_tree.map do |branch_or_model| - branch_or_model = branch_or_model.to_s if branch_or_model.is_a?(Symbol) - - branch_or_model.is_a?(String) ? branch_or_model : names_from_tree(branch_or_model) - end - end - - def relation_class_for_name(relation_name) - relation_name = Gitlab::ImportExport::RelationFactory::OVERRIDES[relation_name.to_sym] || relation_name - relation_name.to_s.classify.constantize - end - def failure_message(relation_class, new_attributes) <<-MSG It looks like #{relation_class}, which is exported using the project Import/Export, has new attributes: #{new_attributes.join(',')} diff --git a/spec/lib/gitlab/import_export/model_configuration_spec.rb b/spec/lib/gitlab/import_export/model_configuration_spec.rb new file mode 100644 index 00000000000..82bab7ac164 --- /dev/null +++ b/spec/lib/gitlab/import_export/model_configuration_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +# Finds if a new model has been added that can potentially be part of the Import/Export +# If it finds a new model, it will show a +failure_message+ with the options available. +describe 'Model configuration', lib: true do + include ConfigurationHelper + + let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } + let(:relation_names) do + names = names_from_tree(config_hash['project_tree']) + + # Remove duplicated or add missing models + # - project is not part of the tree, so it has to be added manually. + # - milestone, labels have both singular and plural versions in the tree, so remove the duplicates. + # - User, Author... Models we don not care about for checking relations + names.flatten.uniq - ['milestones', 'labels', 'user', 'author'] + ['project'] + end + + let(:all_models_json) { 'spec/lib/gitlab/import_export/all_models.json' } + let(:all_models) { JSON.parse(File.read(all_models_json)) } + let(:current_models) { setup_models } + + it 'has no new models' do + relation_names.each do |relation_name| + new_models = current_models[relation_name] - all_models[relation_name] + expect(new_models).to be_empty, failure_message(relation_name.classify, new_models) + end + end + + # List of current relations between models, in the format of + # {model: [model_2, model3], ...} + def setup_models + all_models_hash = {} + + relation_names.each do |relation_name| + relation_class = relation_class_for_name(relation_name) + + all_models_hash[relation_name] = relation_class.reflect_on_all_associations.map do |association| + association.name.to_s + end + end + + all_models_hash + end + + def failure_message(relation_name, new_models) + <<-MSG + New model(s) <#{new_models.join(',')}> have been added, related to #{relation_name}, which is exported by + the Import/Export feature. + + If you don't think this should be exported, please add it to MODELS_JSON, inside the #{relation_name} hash. + If you think we should export this new model, please add it to IMPORT_EXPORT_CONFIG. + + MODELS_JSON: #{File.expand_path(all_models_json)} + IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file} + MSG + end +end diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb new file mode 100644 index 00000000000..fec83765253 --- /dev/null +++ b/spec/support/import_export/configuration_helper.rb @@ -0,0 +1,15 @@ +module ConfigurationHelper + # Returns a list of models from hashes/arrays contained in +project_tree+ + def names_from_tree(project_tree) + project_tree.map do |branch_or_model| + branch_or_model = branch_or_model.to_s if branch_or_model.is_a?(Symbol) + + branch_or_model.is_a?(String) ? branch_or_model : names_from_tree(branch_or_model) + end + end + + def relation_class_for_name(relation_name) + relation_name = Gitlab::ImportExport::RelationFactory::OVERRIDES[relation_name.to_sym] || relation_name + relation_name.to_s.classify.constantize + end +end -- cgit v1.2.1 From 621b4eaf22ea92d89c8612293fad4f6b9d322efe Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 2 Sep 2016 14:26:13 +0200 Subject: fixing a couple of bugs and lots of refactoring of the export file spec --- .../projects/import_export/export_file_spec.rb | 15 +- spec/lib/gitlab/import_export/all_models.json | 196 --------------------- spec/lib/gitlab/import_export/all_models.yml | 175 ++++++++++++++++++ .../import_export/attribute_configuration_spec.rb | 12 +- .../import_export/model_configuration_spec.rb | 17 +- spec/support/import_export/configuration_helper.rb | 10 ++ spec/support/import_export/export_file_helper.rb | 68 +++++-- 7 files changed, 259 insertions(+), 234 deletions(-) delete mode 100644 spec/lib/gitlab/import_export/all_models.json create mode 100644 spec/lib/gitlab/import_export/all_models.yml (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 1a04c25012b..0311edfa133 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -1,18 +1,25 @@ require 'spec_helper' +# Integration test that exports a file using the Import/EXport feature +# It looks up for any sensitive word inside the JSON, so if a sensitive word is found +# we''l have to either include it adding the model containing it to the +safe_list+ +# or make sure the attribute is blacklisted in the +import_export.yml+ configuration feature 'project export', feature: true, js: true do include Select2Helper include ExportFileHelper let(:user) { create(:admin) } let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } + let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } let(:sensitive_words) { %w[pass secret token key] } - let(:safe_models) do + let(:safe_list) do { - token: [ProjectHook, Ci::Trigger] + token: [ProjectHook, Ci::Trigger], + key: [Project, Ci::Variable, :yaml_variables] } end + let(:safe_hashes) { { yaml_variables: %w[key value public] } } let(:project) { setup_project } @@ -49,7 +56,9 @@ feature 'project export', feature: true, js: true do project_hash = JSON.parse(IO.read(project_json_path)) sensitive_words.each do |sensitive_word| - expect(has_sensitive_attributes?(sensitive_word, project_hash)).to be false + found = find_sensitive_attributes(sensitive_word, project_hash) + + expect(found).to be_nil, "Found a new sensitive word <#{found.try(:key_found)}>, which is part of the hash #{found.try(:parent)}" end end end diff --git a/spec/lib/gitlab/import_export/all_models.json b/spec/lib/gitlab/import_export/all_models.json deleted file mode 100644 index 81ebeeb64f9..00000000000 --- a/spec/lib/gitlab/import_export/all_models.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "issues": [ - "subscriptions", - "award_emoji", - "author", - "assignee", - "updated_by", - "milestone", - "notes", - "label_links", - "labels", - "todos", - "user_agent_detail", - "project", - "moved_to", - "events" - ], - "events": [ - "author", - "project", - "target" - ], - "notes": [ - "award_emoji", - "project", - "noteable", - "author", - "updated_by", - "resolved_by", - "todos", - "events" - ], - "label_links": [ - "target", - "label" - ], - "label": [ - "subscriptions", - "project", - "lists", - "label_links", - "issues", - "merge_requests" - ], - "milestone": [ - "project", - "issues", - "labels", - "merge_requests", - "participants", - "events" - ], - "snippets": [ - "author", - "project", - "notes" - ], - "releases": [ - "project" - ], - "project_members": [ - "created_by", - "user", - "source", - "project" - ], - "merge_requests": [ - "subscriptions", - "award_emoji", - "author", - "assignee", - "updated_by", - "milestone", - "notes", - "label_links", - "labels", - "todos", - "target_project", - "source_project", - "merge_user", - "merge_request_diffs", - "merge_request_diff", - "events" - ], - "merge_request_diff": [ - "merge_request" - ], - "pipelines": [ - "project", - "user", - "statuses", - "builds", - "trigger_requests" - ], - "statuses": [ - "project", - "pipeline", - "user" - ], - "variables": [ - "project" - ], - "triggers": [ - "project", - "trigger_requests" - ], - "deploy_keys": [ - "user", - "deploy_keys_projects", - "projects" - ], - "services": [ - "project", - "service_hook" - ], - "hooks": [ - "project" - ], - "protected_branches": [ - "project", - "merge_access_levels", - "push_access_levels" - ], - "project": [ - "taggings", - "base_tags", - "tag_taggings", - "tags", - "creator", - "group", - "namespace", - "board", - "last_event", - "services", - "campfire_service", - "drone_ci_service", - "emails_on_push_service", - "builds_email_service", - "irker_service", - "pivotaltracker_service", - "hipchat_service", - "flowdock_service", - "assembla_service", - "asana_service", - "gemnasium_service", - "slack_service", - "buildkite_service", - "bamboo_service", - "teamcity_service", - "pushover_service", - "jira_service", - "redmine_service", - "custom_issue_tracker_service", - "bugzilla_service", - "gitlab_issue_tracker_service", - "external_wiki_service", - "forked_project_link", - "forked_from_project", - "forked_project_links", - "forks", - "merge_requests", - "fork_merge_requests", - "issues", - "labels", - "events", - "milestones", - "notes", - "snippets", - "hooks", - "protected_branches", - "project_members", - "users", - "requesters", - "deploy_keys_projects", - "deploy_keys", - "users_star_projects", - "starrers", - "releases", - "lfs_objects_projects", - "lfs_objects", - "project_group_links", - "invited_groups", - "todos", - "notification_settings", - "import_data", - "commit_statuses", - "pipelines", - "builds", - "runner_projects", - "runners", - "variables", - "triggers", - "environments", - "deployments" - ] -} \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml new file mode 100644 index 00000000000..16ad3e1e599 --- /dev/null +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -0,0 +1,175 @@ +--- +issues: +- subscriptions +- award_emoji +- author +- assignee +- updated_by +- milestone +- notes +- label_links +- labels +- todos +- user_agent_detail +- project +- moved_to +- events +events: +- author +- project +- target +notes: +- award_emoji +- project +- noteable +- author +- updated_by +- resolved_by +- todos +- events +label_links: +- target +- label +label: +- subscriptions +- project +- lists +- label_links +- issues +- merge_requests +milestone: +- project +- issues +- labels +- merge_requests +- participants +- events +snippets: +- author +- project +- notes +releases: +- project +project_members: +- created_by +- user +- source +- project +merge_requests: +- subscriptions +- award_emoji +- author +- assignee +- updated_by +- milestone +- notes +- label_links +- labels +- todos +- target_project +- source_project +- merge_user +- merge_request_diffs +- merge_request_diff +- events +merge_request_diff: +- merge_request +pipelines: +- project +- user +- statuses +- builds +- trigger_requests +statuses: +- project +- pipeline +- user +variables: +- project +triggers: +- project +- trigger_requests +deploy_keys: +- user +- deploy_keys_projects +- projects +services: +- project +- service_hook +hooks: +- project +protected_branches: +- project +- merge_access_levels +- push_access_levels +project: +- taggings +- base_tags +- tag_taggings +- tags +- creator +- group +- namespace +- board +- last_event +- services +- campfire_service +- drone_ci_service +- emails_on_push_service +- builds_email_service +- irker_service +- pivotaltracker_service +- hipchat_service +- flowdock_service +- assembla_service +- asana_service +- gemnasium_service +- slack_service +- buildkite_service +- bamboo_service +- teamcity_service +- pushover_service +- jira_service +- redmine_service +- custom_issue_tracker_service +- bugzilla_service +- gitlab_issue_tracker_service +- external_wiki_service +- forked_project_link +- forked_from_project +- forked_project_links +- forks +- merge_requests +- fork_merge_requests +- issues +- labels +- events +- milestones +- notes +- snippets +- hooks +- protected_branches +- project_members +- users +- requesters +- deploy_keys_projects +- deploy_keys +- users_star_projects +- starrers +- releases +- lfs_objects_projects +- lfs_objects +- project_group_links +- invited_groups +- todos +- notification_settings +- import_data +- commit_statuses +- pipelines +- builds +- runner_projects +- runners +- variables +- triggers +- environments +- deployments diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 931b27ffb24..ba923a24cdd 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -1,5 +1,7 @@ require 'spec_helper' + +# Part of the Import/Export feature security testing # Checks whether there are new attributes in models that are currently being exported as part of the # project Import/Export feature. # If there are new attributes, these will have to either be added to this spec in case we want them @@ -73,16 +75,6 @@ describe 'Attribute configuration', lib: true do MSG end - def parsed_attributes(relation_name, attributes) - excluded_attributes = config_hash['excluded_attributes'][relation_name] - included_attributes = config_hash['included_attributes'][relation_name] - - attributes = attributes - JSON[excluded_attributes.to_json] if excluded_attributes - attributes = attributes & JSON[included_attributes.to_json] if included_attributes - - attributes - end - class Author < User end end diff --git a/spec/lib/gitlab/import_export/model_configuration_spec.rb b/spec/lib/gitlab/import_export/model_configuration_spec.rb index 82bab7ac164..1805a9b3324 100644 --- a/spec/lib/gitlab/import_export/model_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/model_configuration_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' +# Part of the Import/Export feature security testing # Finds if a new model has been added that can potentially be part of the Import/Export # If it finds a new model, it will show a +failure_message+ with the options available. describe 'Model configuration', lib: true do @@ -12,12 +13,12 @@ describe 'Model configuration', lib: true do # Remove duplicated or add missing models # - project is not part of the tree, so it has to be added manually. # - milestone, labels have both singular and plural versions in the tree, so remove the duplicates. - # - User, Author... Models we don not care about for checking relations + # - User, Author... Models we do not care about for checking relations names.flatten.uniq - ['milestones', 'labels', 'user', 'author'] + ['project'] end - let(:all_models_json) { 'spec/lib/gitlab/import_export/all_models.json' } - let(:all_models) { JSON.parse(File.read(all_models_json)) } + let(:all_models_yml) { 'spec/lib/gitlab/import_export/all_models.yml' } + let(:all_models) { YAML.load_file(all_models_yml) } let(:current_models) { setup_models } it 'has no new models' do @@ -43,15 +44,15 @@ describe 'Model configuration', lib: true do all_models_hash end - def failure_message(relation_name, new_models) + def failure_message(parent_model_name, new_models) <<-MSG - New model(s) <#{new_models.join(',')}> have been added, related to #{relation_name}, which is exported by + New model(s) <#{new_models.join(',')}> have been added, related to #{parent_model_name}, which is exported by the Import/Export feature. - If you don't think this should be exported, please add it to MODELS_JSON, inside the #{relation_name} hash. - If you think we should export this new model, please add it to IMPORT_EXPORT_CONFIG. + If you don't think this should be exported, please add it to MODELS_JSON, inside the #{parent_model_name} hash. + If you think we should export this new model, please add it to IMPORT_EXPORT_CONFIG and to MODELS_JSON. - MODELS_JSON: #{File.expand_path(all_models_json)} + MODELS_JSON: #{File.expand_path(all_models_yml)} IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file} MSG end diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb index fec83765253..d7582057c83 100644 --- a/spec/support/import_export/configuration_helper.rb +++ b/spec/support/import_export/configuration_helper.rb @@ -12,4 +12,14 @@ module ConfigurationHelper relation_name = Gitlab::ImportExport::RelationFactory::OVERRIDES[relation_name.to_sym] || relation_name relation_name.to_s.classify.constantize end + + def parsed_attributes(relation_name, attributes) + excluded_attributes = config_hash['excluded_attributes'][relation_name] + included_attributes = config_hash['included_attributes'][relation_name] + + attributes = attributes - JSON[excluded_attributes.to_json] if excluded_attributes + attributes = attributes & JSON[included_attributes.to_json] if included_attributes + + attributes + end end diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index 8e56bca21a3..de066f1cd66 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -1,4 +1,8 @@ module ExportFileHelper + include ConfigurationHelper + + ObjectWithParent = Struct.new(:object, :parent, :key_found) + def setup_project project = create(:project, :public) @@ -54,48 +58,78 @@ module ExportFileHelper # Recursively finds key/values including +key+ as part of the key, inside a nested hash def deep_find_with_parent(sensitive_key_word, object, found = nil) + sensitive_key_found = object_contains_key?(object, sensitive_key_word) + # Returns the parent object and the object found containing a sensitive word as part of the key - if object_contains_key?(object, sensitive_key_word) - [object[sensitive_key_word], object] if object[sensitive_key_word] + if sensitive_key_found && object[sensitive_key_found] + ObjectWithParent.new(object[sensitive_key_found], object, sensitive_key_found) elsif object.is_a?(Enumerable) # Recursively lookup for keys containing sensitive words in a Hash or Array - object.find { |*hash_or_array| found, object = deep_find_with_parent(sensitive_key_word, hash_or_array.last, found) } - [found, object] if found + object_with_parent = nil + + object.find do |*hash_or_array| + object_with_parent = deep_find_with_parent(sensitive_key_word, hash_or_array.last, found) + end + + object_with_parent end end # Return true if the hash has a key containing a sensitive word def object_contains_key?(object, sensitive_key_word) - object.is_a?(Hash) && object.keys.any? { |key| key.include?(sensitive_key_word) } + return false unless object.is_a?(Hash) + + object.keys.find { |key| key.include?(sensitive_key_word) } end - # Returns true if a sensitive word is found inside a hash, excluding safe hashes - def has_sensitive_attributes?(sensitive_word, project_hash) + # Returns the offended ObjectWithParent object if a sensitive word is found inside a hash, + # excluding the whitelisted safe hashes. + def find_sensitive_attributes(sensitive_word, project_hash) loop do - object, parent = deep_find_with_parent(sensitive_word, project_hash) + object_with_parent = deep_find_with_parent(sensitive_word, project_hash) + + return nil unless object_with_parent && object_with_parent.object - if object && is_safe_hash?(parent, sensitive_word) + if is_safe_hash?(object_with_parent.parent, sensitive_word) # It's in the safe list, remove hash and keep looking - parent.delete(object) - elsif object - return true + object_with_parent.parent.delete(object_with_parent.key_found) else - return false + return object_with_parent end + + nil end end - # Returns true if it's one of the excluded models in +safe_models+ + # Returns true if it's one of the excluded models in +safe_list+ def is_safe_hash?(parent, sensitive_word) - return false unless parent + return false unless parent && safe_list[sensitive_word.to_sym] # Extra attributes that appear in a model but not in the exported hash. excluded_attributes = ['type'] - safe_models[sensitive_word.to_sym].each do |safe_model| - return true if (safe_model.attribute_names - parent.keys - excluded_attributes).empty? + safe_list[sensitive_word.to_sym].each do |model| + # Check whether this is a hash attribute inside a model + if model.is_a?(Symbol) + return true if (safe_hashes[model] - parent.keys).empty? + else + return true if safe_model?(model, excluded_attributes, parent) + end end false end + + def associations_for(safe_model) + safe_model.reflect_on_all_associations.map { |assoc| assoc.name.to_s } + end + + # Compares model attributes with those those found in the hash + # and returns true if there is a match, ignoring some excluded attributes. + def safe_model?(model, excluded_attributes, parent) + excluded_attributes += associations_for(model) + parsed_model_attributes = parsed_attributes(model.name.underscore, model.attribute_names) + + (parsed_model_attributes - parent.keys - excluded_attributes).empty? + end end -- cgit v1.2.1 From 668ebfcaaefba297b29dcda82c5348377633c47c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 2 Sep 2016 14:35:33 +0200 Subject: fix wording --- spec/features/projects/import_export/export_file_spec.rb | 4 ++-- spec/lib/gitlab/import_export/attribute_configuration_spec.rb | 2 +- spec/lib/gitlab/import_export/model_configuration_spec.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 0311edfa133..ba1f0970a32 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -# Integration test that exports a file using the Import/EXport feature +# Integration test that exports a file using the Import/Export feature # It looks up for any sensitive word inside the JSON, so if a sensitive word is found -# we''l have to either include it adding the model containing it to the +safe_list+ +# we''l have to either include it adding the model that includes it to the +safe_list+ # or make sure the attribute is blacklisted in the +import_export.yml+ configuration feature 'project export', feature: true, js: true do include Select2Helper diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index ba923a24cdd..2680425f02b 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' -# Part of the Import/Export feature security testing +# Part of the test security suite for the Import/Export feature # Checks whether there are new attributes in models that are currently being exported as part of the # project Import/Export feature. # If there are new attributes, these will have to either be added to this spec in case we want them diff --git a/spec/lib/gitlab/import_export/model_configuration_spec.rb b/spec/lib/gitlab/import_export/model_configuration_spec.rb index 1805a9b3324..238b610825a 100644 --- a/spec/lib/gitlab/import_export/model_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/model_configuration_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -# Part of the Import/Export feature security testing +# Part of the test security suite for the Import/Export feature # Finds if a new model has been added that can potentially be part of the Import/Export # If it finds a new model, it will show a +failure_message+ with the options available. describe 'Model configuration', lib: true do -- cgit v1.2.1 From e2827250c3617602a0ca89ee4d974cbd17a53892 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 2 Sep 2016 14:47:16 +0200 Subject: remove extra line --- spec/lib/gitlab/import_export/attribute_configuration_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 2680425f02b..d0f19cf323a 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' - # Part of the test security suite for the Import/Export feature # Checks whether there are new attributes in models that are currently being exported as part of the # project Import/Export feature. -- cgit v1.2.1 From 1631ceff19025714d71ef0f91bf247d1d12cefdb Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 2 Sep 2016 15:23:53 +0200 Subject: fix attributes missing in spec after rebase with master --- spec/lib/gitlab/import_export/attribute_configuration_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index d0f19cf323a..526919fb93b 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -39,8 +39,8 @@ describe 'Attribute configuration', lib: true do 'Ci::Variable' => %w[id project_id key value encrypted_value encrypted_value_salt encrypted_value_iv gl_project_id], 'Ci::Trigger' => %w[id token project_id deleted_at created_at updated_at gl_project_id], 'DeployKey' => %w[id user_id created_at updated_at key title type fingerprint public], - 'Service' => %w[id type title project_id created_at updated_at active properties template push_events issues_events merge_requests_events tag_push_events note_events pipeline_events build_events category default wiki_page_events], - 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token group_id], + 'Service' => %w[id type title project_id created_at updated_at active properties template push_events issues_events merge_requests_events tag_push_events note_events pipeline_events build_events category default wiki_page_events confidential_issues_events], + 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token group_id confidential_issues_events], 'ProtectedBranch' => %w[id project_id name created_at updated_at], 'Project' => %w[description issues_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived], 'Author' => %w[name] -- cgit v1.2.1 From 0f15e971fc8c06a4c76eaaad16abe4229816a676 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 7 Sep 2016 09:14:47 +0200 Subject: more spec refactoring based on feedback --- .../projects/import_export/export_file_spec.rb | 18 +- .../projects/import_export/import_file_spec.rb | 2 +- .../import_export/attribute_configuration_spec.rb | 34 +-- .../import_export/model_configuration_spec.rb | 26 +- .../gitlab/import_export/safe_model_attributes.yml | 300 +++++++++++++++++++++ spec/support/import_export/configuration_helper.rb | 6 + 6 files changed, 340 insertions(+), 46 deletions(-) create mode 100644 spec/lib/gitlab/import_export/safe_model_attributes.yml (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index ba1f0970a32..7e2c701e401 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' # It looks up for any sensitive word inside the JSON, so if a sensitive word is found # we''l have to either include it adding the model that includes it to the +safe_list+ # or make sure the attribute is blacklisted in the +import_export.yml+ configuration -feature 'project export', feature: true, js: true do +feature 'Import/Export - project export integration test', feature: true, js: true do include Select2Helper include ExportFileHelper @@ -58,9 +58,23 @@ feature 'project export', feature: true, js: true do sensitive_words.each do |sensitive_word| found = find_sensitive_attributes(sensitive_word, project_hash) - expect(found).to be_nil, "Found a new sensitive word <#{found.try(:key_found)}>, which is part of the hash #{found.try(:parent)}" + expect(found).to be_nil, failure_message(found.try(:key_found), found.try(:parent), sensitive_word) end end end + + def failure_message(key_found, parent, sensitive_word) + <<-MSG + Found a new sensitive word <#{key_found}>, which is part of the hash #{parent.inspect} + + If you think this information shouldn't get exported, please exclude the model or attribute in IMPORT_EXPORT_CONFIG. + + Otherwise, please add the exception to +safe_list+ in CURRENT_SPEC using #{sensitive_word} as the key and the + correspondent hash or model as the value. + + IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file} + CURRENT_SPEC: #{__FILE__} + MSG + end end end diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index f707ccf4e93..09cd6369881 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'project import', feature: true, js: true do +feature 'Import/Export - project import integration test', feature: true, js: true do include Select2Helper let(:admin) { create(:admin) } diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 526919fb93b..2ba344092ce 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' # to be included as part of the export, or blacklist them using the import_export.yml configuration file. # Likewise, new models added to import_export.yml, will need to be added with their correspondent attributes # to this spec. -describe 'Attribute configuration', lib: true do +describe 'Import/Export attribute configuration', lib: true do include ConfigurationHelper let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } @@ -20,32 +20,8 @@ describe 'Attribute configuration', lib: true do names.flatten.uniq - ['milestones', 'labels'] + ['project'] end - let(:safe_model_attributes) do - { - 'Issue' => %w[id title assignee_id author_id project_id created_at updated_at position branch_name description state iid updated_by_id confidential deleted_at due_date moved_to_id lock_version milestone_id weight], - 'Event' => %w[id target_type target_id title data project_id created_at updated_at action author_id], - 'Note' => %w[id note noteable_type author_id created_at updated_at project_id attachment line_code commit_id noteable_id system st_diff updated_by_id type position original_position resolved_at resolved_by_id discussion_id original_discussion_id], - 'LabelLink' => %w[id label_id target_id target_type created_at updated_at], - 'Label' => %w[id title color project_id created_at updated_at template description priority], - 'Milestone' => %w[id title project_id description due_date created_at updated_at state iid], - 'ProjectSnippet' => %w[id title content author_id project_id created_at updated_at file_name type visibility_level], - 'Release' => %w[id tag description project_id created_at updated_at], - 'ProjectMember' => %w[id access_level source_id source_type user_id notification_level type created_at updated_at created_by_id invite_email invite_token invite_accepted_at requested_at expires_at], - 'User' => %w[id username email], - 'MergeRequest' => %w[id target_branch source_branch source_project_id author_id assignee_id title created_at updated_at state merge_status target_project_id iid description position locked_at updated_by_id merge_error merge_params merge_when_build_succeeds merge_user_id merge_commit_sha deleted_at in_progress_merge_commit_sha lock_version milestone_id approvals_before_merge rebase_commit_sha], - 'MergeRequestDiff' => %w[id state st_commits merge_request_id created_at updated_at base_commit_sha real_size head_commit_sha start_commit_sha], - 'Ci::Pipeline' => %w[id project_id ref sha before_sha push_data created_at updated_at tag yaml_errors committed_at gl_project_id status started_at finished_at duration user_id], - 'CommitStatus' => %w[id project_id status finished_at trace created_at updated_at started_at runner_id coverage commit_id commands job_id name deploy options allow_failure stage trigger_request_id stage_idx tag ref user_id type target_url description artifacts_file gl_project_id artifacts_metadata erased_by_id erased_at artifacts_expire_at environment artifacts_size when yaml_variables queued_at], - 'Ci::Variable' => %w[id project_id key value encrypted_value encrypted_value_salt encrypted_value_iv gl_project_id], - 'Ci::Trigger' => %w[id token project_id deleted_at created_at updated_at gl_project_id], - 'DeployKey' => %w[id user_id created_at updated_at key title type fingerprint public], - 'Service' => %w[id type title project_id created_at updated_at active properties template push_events issues_events merge_requests_events tag_push_events note_events pipeline_events build_events category default wiki_page_events confidential_issues_events], - 'ProjectHook' => %w[id url project_id created_at updated_at type service_id push_events issues_events merge_requests_events tag_push_events note_events pipeline_events enable_ssl_verification build_events wiki_page_events token group_id confidential_issues_events], - 'ProtectedBranch' => %w[id project_id name created_at updated_at], - 'Project' => %w[description issues_enabled merge_requests_enabled wiki_enabled snippets_enabled visibility_level archived], - 'Author' => %w[name] - } - end + let(:safe_attributes_file) { 'spec/lib/gitlab/import_export/safe_model_attributes.yml' } + let(:safe_model_attributes) { YAML.load_file(safe_attributes_file) } it 'has no new columns' do relation_names.each do |relation_name| @@ -65,11 +41,11 @@ describe 'Attribute configuration', lib: true do <<-MSG It looks like #{relation_class}, which is exported using the project Import/Export, has new attributes: #{new_attributes.join(',')} - Please add the attribute(s) to +safe_model_attributes+ in CURRENT_SPEC if you consider this can be exported. + Please add the attribute(s) to SAFE_MODEL_ATTRIBUTES if you consider this can be exported. Otherwise, please blacklist the attribute(s) in IMPORT_EXPORT_CONFIG by adding it to its correspondent model in the +excluded_attributes+ section. - CURRENT_SPEC: #{__FILE__} + SAFE_MODEL_ATTRIBUTES: #{File.expand_path(safe_attributes_file)} IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file} MSG end diff --git a/spec/lib/gitlab/import_export/model_configuration_spec.rb b/spec/lib/gitlab/import_export/model_configuration_spec.rb index 238b610825a..38e9edc4aab 100644 --- a/spec/lib/gitlab/import_export/model_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/model_configuration_spec.rb @@ -3,17 +3,17 @@ require 'spec_helper' # Part of the test security suite for the Import/Export feature # Finds if a new model has been added that can potentially be part of the Import/Export # If it finds a new model, it will show a +failure_message+ with the options available. -describe 'Model configuration', lib: true do +describe 'Import/Export model configuration', lib: true do include ConfigurationHelper let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys } - let(:relation_names) do + let(:model_names) do names = names_from_tree(config_hash['project_tree']) # Remove duplicated or add missing models # - project is not part of the tree, so it has to be added manually. # - milestone, labels have both singular and plural versions in the tree, so remove the duplicates. - # - User, Author... Models we do not care about for checking relations + # - User, Author... Models we do not care about for checking models names.flatten.uniq - ['milestones', 'labels', 'user', 'author'] + ['project'] end @@ -22,23 +22,21 @@ describe 'Model configuration', lib: true do let(:current_models) { setup_models } it 'has no new models' do - relation_names.each do |relation_name| - new_models = current_models[relation_name] - all_models[relation_name] - expect(new_models).to be_empty, failure_message(relation_name.classify, new_models) + model_names.each do |model_name| + new_models = current_models[model_name] - all_models[model_name] + expect(new_models).to be_empty, failure_message(model_name.classify, new_models) end end - # List of current relations between models, in the format of + # List of current models between models, in the format of # {model: [model_2, model3], ...} def setup_models all_models_hash = {} - relation_names.each do |relation_name| - relation_class = relation_class_for_name(relation_name) + model_names.each do |model_name| + model_class = relation_class_for_name(model_name) - all_models_hash[relation_name] = relation_class.reflect_on_all_associations.map do |association| - association.name.to_s - end + all_models_hash[model_name] = associations_for(model_class) end all_models_hash @@ -49,8 +47,8 @@ describe 'Model configuration', lib: true do New model(s) <#{new_models.join(',')}> have been added, related to #{parent_model_name}, which is exported by the Import/Export feature. - If you don't think this should be exported, please add it to MODELS_JSON, inside the #{parent_model_name} hash. - If you think we should export this new model, please add it to IMPORT_EXPORT_CONFIG and to MODELS_JSON. + If you think this model should be included in the export, please add it to IMPORT_EXPORT_CONFIG. + Definitely add it to MODELS_JSON to signal that you've handled this error and to prevent it from showing up in the future. MODELS_JSON: #{File.expand_path(all_models_yml)} IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file} diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml new file mode 100644 index 00000000000..f7baf6a19cc --- /dev/null +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -0,0 +1,300 @@ +--- +Issue: +- id +- title +- assignee_id +- author_id +- project_id +- created_at +- updated_at +- position +- branch_name +- description +- state +- iid +- updated_by_id +- confidential +- deleted_at +- due_date +- moved_to_id +- lock_version +- milestone_id +- weight +Event: +- id +- target_type +- target_id +- title +- data +- project_id +- created_at +- updated_at +- action +- author_id +Note: +- id +- note +- noteable_type +- author_id +- created_at +- updated_at +- project_id +- attachment +- line_code +- commit_id +- noteable_id +- system +- st_diff +- updated_by_id +- type +- position +- original_position +- resolved_at +- resolved_by_id +- discussion_id +- original_discussion_id +LabelLink: +- id +- label_id +- target_id +- target_type +- created_at +- updated_at +Label: +- id +- title +- color +- project_id +- created_at +- updated_at +- template +- description +- priority +Milestone: +- id +- title +- project_id +- description +- due_date +- created_at +- updated_at +- state +- iid +ProjectSnippet: +- id +- title +- content +- author_id +- project_id +- created_at +- updated_at +- file_name +- type +- visibility_level +Release: +- id +- tag +- description +- project_id +- created_at +- updated_at +ProjectMember: +- id +- access_level +- source_id +- source_type +- user_id +- notification_level +- type +- created_at +- updated_at +- created_by_id +- invite_email +- invite_token +- invite_accepted_at +- requested_at +- expires_at +User: +- id +- username +- email +MergeRequest: +- id +- target_branch +- source_branch +- source_project_id +- author_id +- assignee_id +- title +- created_at +- updated_at +- state +- merge_status +- target_project_id +- iid +- description +- position +- locked_at +- updated_by_id +- merge_error +- merge_params +- merge_when_build_succeeds +- merge_user_id +- merge_commit_sha +- deleted_at +- in_progress_merge_commit_sha +- lock_version +- milestone_id +- approvals_before_merge +- rebase_commit_sha +MergeRequestDiff: +- id +- state +- st_commits +- merge_request_id +- created_at +- updated_at +- base_commit_sha +- real_size +- head_commit_sha +- start_commit_sha +Ci::Pipeline: +- id +- project_id +- ref +- sha +- before_sha +- push_data +- created_at +- updated_at +- tag +- yaml_errors +- committed_at +- gl_project_id +- status +- started_at +- finished_at +- duration +- user_id +CommitStatus: +- id +- project_id +- status +- finished_at +- trace +- created_at +- updated_at +- started_at +- runner_id +- coverage +- commit_id +- commands +- job_id +- name +- deploy +- options +- allow_failure +- stage +- trigger_request_id +- stage_idx +- tag +- ref +- user_id +- type +- target_url +- description +- artifacts_file +- gl_project_id +- artifacts_metadata +- erased_by_id +- erased_at +- artifacts_expire_at +- environment +- artifacts_size +- when +- yaml_variables +- queued_at +Ci::Variable: +- id +- project_id +- key +- value +- encrypted_value +- encrypted_value_salt +- encrypted_value_iv +- gl_project_id +Ci::Trigger: +- id +- token +- project_id +- deleted_at +- created_at +- updated_at +- gl_project_id +DeployKey: +- id +- user_id +- created_at +- updated_at +- key +- title +- type +- fingerprint +- public +Service: +- id +- type +- title +- project_id +- created_at +- updated_at +- active +- properties +- template +- push_events +- issues_events +- merge_requests_events +- tag_push_events +- note_events +- pipeline_events +- build_events +- category +- default +- wiki_page_events +- confidential_issues_events +ProjectHook: +- id +- url +- project_id +- created_at +- updated_at +- type +- service_id +- push_events +- issues_events +- merge_requests_events +- tag_push_events +- note_events +- pipeline_events +- enable_ssl_verification +- build_events +- wiki_page_events +- token +- group_id +- confidential_issues_events +ProtectedBranch: +- id +- project_id +- name +- created_at +- updated_at +Project: +- description +- issues_enabled +- merge_requests_enabled +- wiki_enabled +- snippets_enabled +- visibility_level +- archived +Author: +- name diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb index d7582057c83..3276313df51 100644 --- a/spec/support/import_export/configuration_helper.rb +++ b/spec/support/import_export/configuration_helper.rb @@ -22,4 +22,10 @@ module ConfigurationHelper attributes end + + def associations_for(model_class) + model_class.reflect_on_all_associations.map do |association| + association.name.to_s + end + end end -- cgit v1.2.1 From 37fbb15a2967523d41887f55b6f38e6d74bd6d7f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 7 Sep 2016 10:04:20 +0200 Subject: refactored some stuff and added new models / attributes after rebase --- spec/lib/gitlab/import_export/all_models.yml | 2 +- spec/lib/gitlab/import_export/model_configuration_spec.rb | 4 ++-- spec/lib/gitlab/import_export/safe_model_attributes.yml | 10 ++++++++++ spec/support/import_export/configuration_helper.rb | 6 ++---- spec/support/import_export/export_file_helper.rb | 4 ---- 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 16ad3e1e599..30968ba2d5f 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -11,7 +11,6 @@ issues: - labels - todos - user_agent_detail -- project - moved_to - events events: @@ -173,3 +172,4 @@ project: - triggers - environments - deployments +- project_feature \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/model_configuration_spec.rb b/spec/lib/gitlab/import_export/model_configuration_spec.rb index 38e9edc4aab..9b492d1b9c7 100644 --- a/spec/lib/gitlab/import_export/model_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/model_configuration_spec.rb @@ -23,7 +23,7 @@ describe 'Import/Export model configuration', lib: true do it 'has no new models' do model_names.each do |model_name| - new_models = current_models[model_name] - all_models[model_name] + new_models = Array(current_models[model_name]) - Array(all_models[model_name]) expect(new_models).to be_empty, failure_message(model_name.classify, new_models) end end @@ -36,7 +36,7 @@ describe 'Import/Export model configuration', lib: true do model_names.each do |model_name| model_class = relation_class_for_name(model_name) - all_models_hash[model_name] = associations_for(model_class) + all_models_hash[model_name] = associations_for(model_class) - ['project'] end all_models_hash diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index f7baf6a19cc..f2d272ca7e2 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -298,3 +298,13 @@ Project: - archived Author: - name +ProjectFeature: +- id +- project_id +- merge_requests_access_level +- issues_access_level +- wiki_access_level +- snippets_access_level +- builds_access_level +- created_at +- updated_at \ No newline at end of file diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb index 3276313df51..f752508d48c 100644 --- a/spec/support/import_export/configuration_helper.rb +++ b/spec/support/import_export/configuration_helper.rb @@ -23,9 +23,7 @@ module ConfigurationHelper attributes end - def associations_for(model_class) - model_class.reflect_on_all_associations.map do |association| - association.name.to_s - end + def associations_for(safe_model) + safe_model.reflect_on_all_associations.map { |assoc| assoc.name.to_s } end end diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index de066f1cd66..7e75ed9793b 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -120,10 +120,6 @@ module ExportFileHelper false end - def associations_for(safe_model) - safe_model.reflect_on_all_associations.map { |assoc| assoc.name.to_s } - end - # Compares model attributes with those those found in the hash # and returns true if there is a match, ignoring some excluded attributes. def safe_model?(model, excluded_attributes, parent) -- cgit v1.2.1 From c4d2cacac77fc47b112d30fc135219a4a27452fd Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 9 Sep 2016 18:08:30 +0200 Subject: attempt to fix random error in remote build --- spec/support/import_export/export_file_helper.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index 7e75ed9793b..be0772d6a4a 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -1,3 +1,5 @@ +require './spec/support/import_export/configuration_helper' + module ExportFileHelper include ConfigurationHelper -- cgit v1.2.1 From 47b49624b1caff3db026c69ac219aa48507eedaa Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 9 Sep 2016 12:08:49 +0100 Subject: Fixed search dropdown labels not displaying This would only happen when the search term was empty because the method was returning before the controller could find the group or project for the toggle Closes #21783 --- spec/features/search_spec.rb | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'spec') diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index dcd3a2f17b0..1806200c82c 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe "Search", feature: true do + include WaitForAjax + let(:user) { create(:user) } let(:project) { create(:project, namespace: user.namespace) } let!(:issue) { create(:issue, project: project, assignee: user) } @@ -16,6 +18,36 @@ describe "Search", feature: true do expect(page).not_to have_selector('.search') end + context 'search filters', js: true do + let(:group) { create(:group) } + + before do + group.add_owner(user) + end + + it 'shows group name after filtering' do + find('.js-search-group-dropdown').click + wait_for_ajax + + page.within '.search-holder' do + click_link group.name + end + + expect(find('.js-search-group-dropdown')).to have_content(group.name) + end + + it 'shows project name after filtering' do + page.within('.project-filter') do + find('.js-search-project-dropdown').click + wait_for_ajax + + click_link project.name_with_namespace + end + + expect(find('.js-search-project-dropdown')).to have_content(project.name_with_namespace) + end + end + describe 'searching for Projects' do it 'finds a project' do page.within '.search-holder' do -- cgit v1.2.1 From 999f18480511d81b1499b502cbc89a5b34e54544 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 13:35:43 +0100 Subject: Tests update --- spec/features/groups/members/owner_manages_access_requests_spec.rb | 2 +- spec/features/projects/members/master_manages_access_requests_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/groups/members/owner_manages_access_requests_spec.rb b/spec/features/groups/members/owner_manages_access_requests_spec.rb index 10d3713f19f..d811b05b0c3 100644 --- a/spec/features/groups/members/owner_manages_access_requests_spec.rb +++ b/spec/features/groups/members/owner_manages_access_requests_spec.rb @@ -41,7 +41,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do def expect_visible_access_request(group, user) expect(group.requesters.exists?(user_id: user)).to be_truthy - expect(page).to have_content "#{group.name} access requests 1" + expect(page).to have_content "Users requesting access to #{group.name} 1" expect(page).to have_content user.name end end diff --git a/spec/features/projects/members/master_manages_access_requests_spec.rb b/spec/features/projects/members/master_manages_access_requests_spec.rb index f7fcd9b6731..d15376931c3 100644 --- a/spec/features/projects/members/master_manages_access_requests_spec.rb +++ b/spec/features/projects/members/master_manages_access_requests_spec.rb @@ -41,7 +41,7 @@ feature 'Projects > Members > Master manages access requests', feature: true do def expect_visible_access_request(project, user) expect(project.requesters.exists?(user_id: user)).to be_truthy - expect(page).to have_content "#{project.name} access requests 1" + expect(page).to have_content "Users requesting access to #{project.name} 1" expect(page).to have_content user.name end end -- cgit v1.2.1 From 2c3fa33ca2e75792d1027eb73e2f69fed67bc435 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 15:10:22 +0100 Subject: Updated some specs Fixed issue with group name not showing --- .../members/master_adds_member_with_expiration_date_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb index 430c384ac2e..27a83fdcd1f 100644 --- a/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb +++ b/spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' feature 'Projects > Members > Master adds member with expiration date', feature: true, js: true do + include WaitForAjax include Select2Helper include ActiveSupport::Testing::TimeHelpers @@ -20,7 +21,7 @@ feature 'Projects > Members > Master adds member with expiration date', feature: page.within '.users-project-form' do select2(new_member.id, from: '#user_ids', multiple: true) fill_in 'expires_at', with: '2016-08-10' - click_on 'Add users to project' + click_on 'Add to project' end page.within '.project_member:first-child' do @@ -35,9 +36,8 @@ feature 'Projects > Members > Master adds member with expiration date', feature: visit namespace_project_project_members_path(project.namespace, project) page.within '.project_member:first-child' do - click_on 'Edit' - fill_in 'Access expiration date', with: '2016-08-09' - click_on 'Save' + find('.js-access-expiration-date').set '2016-08-09' + wait_for_ajax expect(page).to have_content('Expires in 3 days') end end -- cgit v1.2.1 From e747626fad5c0e675d6a5cd5b6fcd482f10dad90 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 09:24:47 +0100 Subject: Added test for updating groups permissions --- spec/features/projects/members/group_links_spec.rb | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 spec/features/projects/members/group_links_spec.rb (limited to 'spec') diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb new file mode 100644 index 00000000000..3d59df20197 --- /dev/null +++ b/spec/features/projects/members/group_links_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +feature 'Projects > Members > Anonymous user sees members', feature: true, js: true do + include WaitForAjax + + let(:user) { create(:user) } + let(:group) { create(:group, :public) } + let(:project) { create(:empty_project, :public) } + + background do + project.team << [user, :master] + @group_link = create(:project_group_link, project: project, group: group) + + login_as(user) + visit namespace_project_project_members_path(project.namespace, project) + end + + it 'updates group access level' do + select 'Guest', from: "member_access_level_#{group.id}" + wait_for_ajax + + visit namespace_project_project_members_path(project.namespace, project) + + expect(page).to have_select("member_access_level_#{group.id}", selected: 'Guest') + end + + it 'updates expiry date' do + tomorrow = Date.today + 3 + + fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F") + wait_for_ajax + + page.within(first('li.member')) do + expect(page).to have_content('Expires in 3 days') + end + end +end -- cgit v1.2.1 From 11c0c6509251a280f46c6be74da64a1cd7a5e190 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 10:06:13 +0100 Subject: Expires in test update --- spec/features/projects/members/group_links_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 3d59df20197..2085e875f12 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -31,7 +31,7 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t wait_for_ajax page.within(first('li.member')) do - expect(page).to have_content('Expires in 3 days') + expect(page).to have_content('Expires in') end end end -- cgit v1.2.1 From 73c4da1780c5086543eb998d5bc9cbd632ef6576 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 16:20:20 +0100 Subject: Fixed removing groups --- spec/features/projects/members/group_links_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 2085e875f12..7870bc663b1 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -34,4 +34,13 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t expect(page).to have_content('Expires in') end end + + it 'deletes group link' do + page.within(first('.group_member')) do + find('.btn-remove').click + end + wait_for_ajax + + expect(page).not_to have_selector('.group_member') + end end -- cgit v1.2.1 From 2b41db9215f322ba61113a7bef2f49da157bbd53 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 6 Sep 2016 16:48:48 +0100 Subject: Search project groups --- spec/features/projects/members/group_links_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'spec') diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 7870bc663b1..14ab7541fad 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -43,4 +43,24 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t expect(page).not_to have_selector('.group_member') end + + context 'search' do + it 'finds no results' do + page.within '.member-search-form' do + fill_in 'search', with: 'testing 123' + find('.member-search-btn').click + end + + expect(page).not_to have_selector('.group_member') + end + + it 'finds results' do + page.within '.member-search-form' do + fill_in 'search', with: group.name + find('.member-search-btn').click + end + + expect(page).to have_selector('.group_member', count: 1) + end + end end -- cgit v1.2.1 From ecf7640b28562468880dda97ba42e5fd18c0859f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 10:58:52 +0100 Subject: Fixed group_links expire date not updating in view --- spec/features/projects/members/group_links_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/projects/members/group_links_spec.rb b/spec/features/projects/members/group_links_spec.rb index 14ab7541fad..cc2f695211c 100644 --- a/spec/features/projects/members/group_links_spec.rb +++ b/spec/features/projects/members/group_links_spec.rb @@ -30,7 +30,7 @@ feature 'Projects > Members > Anonymous user sees members', feature: true, js: t fill_in "member_expires_at_#{group.id}", with: tomorrow.strftime("%F") wait_for_ajax - page.within(first('li.member')) do + page.within(find('li.group_member')) do expect(page).to have_content('Expires in') end end -- cgit v1.2.1 From 9d9c2d314c10347da4a0929db429c2c2bc24a64d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 01:10:58 +0800 Subject: Fix pipeline emails and add tests --- .../pipeline_email_service_spec.rb | 130 +++++++++++++++++++++ .../ci/send_pipeline_notification_service_spec.rb | 35 ++++++ 2 files changed, 165 insertions(+) create mode 100644 spec/models/project_services/pipeline_email_service_spec.rb create mode 100644 spec/services/ci/send_pipeline_notification_service_spec.rb (limited to 'spec') diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb new file mode 100644 index 00000000000..38c2b25c88c --- /dev/null +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -0,0 +1,130 @@ +require 'spec_helper' + +describe PipelinesEmailService do + let(:data) do + Gitlab::DataBuilder::Pipeline.build(create(:ci_pipeline)) + end + + let(:recipient) { 'test@gitlab.com' } + + def expect_pipeline_service + expect_any_instance_of(Ci::SendPipelineNotificationService) + end + + def receive_execute + receive(:execute).with([recipient]) + end + + describe 'Validations' do + context 'when service is active' do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of(:recipients) } + + context 'when pusher is added' do + before do + subject.add_pusher = true + end + + it { is_expected.not_to validate_presence_of(:recipients) } + end + end + + context 'when service is inactive' do + before do + subject.active = false + end + + it { is_expected.not_to validate_presence_of(:recipients) } + end + end + + describe '#test_data' do + let(:build) { create(:ci_build) } + let(:project) { build.project } + let(:user) { create(:user) } + + before do + project.team << [user, :developer] + end + + it 'builds test data' do + data = subject.test_data(project, user) + + expect(data[:object_kind]).to eq('pipeline') + end + end + + describe '#test' do + before do + subject.recipients = recipient + end + + shared_examples 'sending email' do + it 'sends email' do + expect_pipeline_service.to receive_execute + + subject.test(data) + end + end + + it_behaves_like 'sending email' + + context 'when pipeline is succeeded' do + before do + data[:object_attributes][:status] = 'success' + end + + it_behaves_like 'sending email' + end + end + + describe '#execute' do + context 'with recipients' do + before do + subject.recipients = recipient + end + + it 'sends email for failed pipeline' do + data[:object_attributes][:status] = 'failed' + + expect_pipeline_service.to receive_execute + + subject.execute(data) + end + + it 'does not send email for succeeded pipeline' do + data[:object_attributes][:status] = 'success' + + expect_pipeline_service.not_to receive_execute + + subject.execute(data) + end + + context 'with notify_only_broken_pipelines on' do + before do + subject.notify_only_broken_pipelines = true + end + + it 'sends email for failed pipeline' do + data[:object_attributes][:status] = 'failed' + + expect_pipeline_service.to receive_execute + + subject.execute(data) + end + end + end + + it 'does not send email when recipients list is empty' do + subject.recipients = ' ,, ' + data[:object_attributes][:status] = 'failed' + + expect_pipeline_service.not_to receive_execute + + subject.execute(data) + end + end +end diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb new file mode 100644 index 00000000000..ba588ed8ef5 --- /dev/null +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Ci::SendPipelineNotificationService, services: true do + let(:user) { create(:user) } + let(:pipeline) { create(:ci_pipeline, user: user, status: status) } + subject{ described_class.new(pipeline) } + + describe '#execute' do + shared_examples 'sending emails' do + it 'sends an email to pipeline user' do + perform_enqueued_jobs do + subject.execute + end + + email = ActionMailer::Base.deliveries.last + expect(email.subject).to include(email_subject) + expect(email.to).to eq([user.email]) + end + end + + context 'with success pipeline' do + let(:status) { 'success' } + let(:email_subject) { 'Pipeline succeeded for' } + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline' do + let(:status) { 'failed' } + let(:email_subject) { 'Pipeline failed for' } + + it_behaves_like 'sending emails' + end + end +end -- cgit v1.2.1 From 32979803f232c43c7b87e30bec275b79182b06ad Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Mon, 12 Sep 2016 21:02:09 +0100 Subject: Replace single quotes with escaped single quotes and write spec to test multiple lable selection over a page load Added spec for removing label with space and single quote Fixed removing label with single quote --- spec/features/issues/filter_issues_spec.rb | 31 ++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 0e9f814044e..69fda27cc61 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -101,7 +101,7 @@ describe 'Filter issues', feature: true do expect(find('.js-label-select .dropdown-toggle-text')).to have_content('No Label') end - it 'filters by no label' do + it 'filters by a label' do find('.dropdown-menu-labels a', text: label.title).click page.within '.labels-filter' do expect(page).to have_content label.title @@ -109,7 +109,7 @@ describe 'Filter issues', feature: true do expect(find('.js-label-select .dropdown-toggle-text')).to have_content(label.title) end - it 'filters by wont fix labels' do + it "filters by `won't fix` and another label" do find('.dropdown-menu-labels a', text: label.title).click page.within '.labels-filter' do expect(page).to have_content wontfix.title @@ -117,6 +117,33 @@ describe 'Filter issues', feature: true do end expect(find('.js-label-select .dropdown-toggle-text')).to have_content(wontfix.title) end + + it "filters by `won't fix` label followed by another label after page load" do + find('.dropdown-menu-labels a', text: wontfix.title).click + # Close label dropdown to load + find('body').click + expect(find('.filtered-labels')).to have_content(wontfix.title) + + find('.js-label-select').click + wait_for_ajax + find('.dropdown-menu-labels a', text: label.title).click + # Close label dropdown to load + find('body').click + expect(find('.filtered-labels')).to have_content(label.title) + + find('.js-label-select').click + wait_for_ajax + expect(find('.dropdown-menu-labels li', text: wontfix.title)).to have_css('.is-active') + expect(find('.dropdown-menu-labels li', text: label.title)).to have_css('.is-active') + end + + it "selects and unselects `won't fix`" do + find('.dropdown-menu-labels a', text: wontfix.title).click + find('.dropdown-menu-labels a', text: wontfix.title).click + # Close label dropdown to load + find('body').click + expect(page).not_to have_css('.filtered-labels') + end end describe 'Filter issues for assignee and label from issues#index' do -- cgit v1.2.1 From 1404aa8677969a03ed56e8f8350257f317f576d8 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 19:34:24 +0800 Subject: Split notification integration into another branch --- spec/services/ci/send_pipeline_notification_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index ba588ed8ef5..cb53ba8b051 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -9,7 +9,7 @@ describe Ci::SendPipelineNotificationService, services: true do shared_examples 'sending emails' do it 'sends an email to pipeline user' do perform_enqueued_jobs do - subject.execute + subject.execute([user.email]) end email = ActionMailer::Base.deliveries.last -- cgit v1.2.1 From 15bb44fc6357ca57e344d7b4818ac74ffb0a4dea Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 20:38:20 +0800 Subject: test for real --- .../pipeline_email_service_spec.rb | 116 +++++++++++++++------ 1 file changed, 82 insertions(+), 34 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 38c2b25c88c..c352ddc00c3 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -1,18 +1,15 @@ require 'spec_helper' describe PipelinesEmailService do - let(:data) do - Gitlab::DataBuilder::Pipeline.build(create(:ci_pipeline)) - end - + let(:pipeline) { create(:ci_pipeline) } let(:recipient) { 'test@gitlab.com' } - def expect_pipeline_service - expect_any_instance_of(Ci::SendPipelineNotificationService) + let(:data) do + Gitlab::DataBuilder::Pipeline.build(pipeline) end - def receive_execute - receive(:execute).with([recipient]) + before do + ActionMailer::Base.deliveries.clear end describe 'Validations' do @@ -57,24 +54,53 @@ describe PipelinesEmailService do end end - describe '#test' do + shared_examples 'sending email' do before do - subject.recipients = recipient + perform_enqueued_jobs do + run + end end - shared_examples 'sending email' do - it 'sends email' do - expect_pipeline_service.to receive_execute + it 'sends email' do + sent_to = ActionMailer::Base.deliveries.flat_map(&:to) + expect(sent_to).to contain_exactly(recipient) + end + end - subject.test(data) + shared_examples 'not sending email' do + before do + perform_enqueued_jobs do + run end end - it_behaves_like 'sending email' + it 'does not send email' do + expect(ActionMailer::Base.deliveries).to be_empty + end + end + + describe '#test' do + def run + subject.test(data) + end + + before do + subject.recipients = recipient + end + + context 'when pipeline is failed' do + before do + data[:object_attributes][:status] = 'failed' + pipeline.update(status: 'failed') + end + + it_behaves_like 'sending email' + end context 'when pipeline is succeeded' do before do data[:object_attributes][:status] = 'success' + pipeline.update(status: 'success') end it_behaves_like 'sending email' @@ -82,25 +108,31 @@ describe PipelinesEmailService do end describe '#execute' do + def run + subject.execute(data) + end + context 'with recipients' do before do subject.recipients = recipient end - it 'sends email for failed pipeline' do - data[:object_attributes][:status] = 'failed' - - expect_pipeline_service.to receive_execute + context 'with failed pipeline' do + before do + data[:object_attributes][:status] = 'failed' + pipeline.update(status: 'failed') + end - subject.execute(data) + it_behaves_like 'sending email' end - it 'does not send email for succeeded pipeline' do - data[:object_attributes][:status] = 'success' - - expect_pipeline_service.not_to receive_execute + context 'with succeeded pipeline' do + before do + data[:object_attributes][:status] = 'success' + pipeline.update(status: 'success') + end - subject.execute(data) + it_behaves_like 'not sending email' end context 'with notify_only_broken_pipelines on' do @@ -108,23 +140,39 @@ describe PipelinesEmailService do subject.notify_only_broken_pipelines = true end - it 'sends email for failed pipeline' do - data[:object_attributes][:status] = 'failed' + context 'with failed pipeline' do + before do + data[:object_attributes][:status] = 'failed' + pipeline.update(status: 'failed') + end - expect_pipeline_service.to receive_execute + it_behaves_like 'sending email' + end + + context 'with succeeded pipeline' do + before do + data[:object_attributes][:status] = 'success' + pipeline.update(status: 'success') + end - subject.execute(data) + it_behaves_like 'not sending email' end end end - it 'does not send email when recipients list is empty' do - subject.recipients = ' ,, ' - data[:object_attributes][:status] = 'failed' + context 'with empty recipients list' do + before do + subject.recipients = ' ,, ' + end - expect_pipeline_service.not_to receive_execute + context 'with failed pipeline' do + before do + data[:object_attributes][:status] = 'failed' + pipeline.update(status: 'failed') + end - subject.execute(data) + it_behaves_like 'not sending email' + end end end end -- cgit v1.2.1 From 11f87700e8bceeec96440809682406ae24334ed8 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 11:57:09 +0200 Subject: Add access specs --- spec/lib/gitlab/auth_spec.rb | 76 +++++++++++++++++++++++++--- spec/lib/gitlab/git_access_spec.rb | 101 ++++++++++++++++++++++++++++--------- 2 files changed, 147 insertions(+), 30 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 7c23e02d05a..b665517bbb0 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -4,15 +4,51 @@ describe Gitlab::Auth, lib: true do let(:gl_auth) { described_class } describe 'find_for_git_client' do - it 'recognizes CI' do - token = '123' + context 'build token' do + subject { gl_auth.find_for_git_client('gitlab-ci-token', build.token, project: project, ip: 'ip') } + + context 'for running build' do + let!(:build) { create(:ci_build, :running) } + let(:project) { build.project } + + before do + expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'gitlab-ci-token') + end + + it 'recognises user-less build' do + expect(subject).to eq(Gitlab::Auth::Result.new(nil, build.project, :ci, build_capabilities)) + end + + it 'recognises user token' do + build.update(user: create(:user)) + + expect(subject).to eq(Gitlab::Auth::Result.new(build.user, build.project, :build, build_capabilities)) + end + end + + context 'for non-running build' do + let!(:build) { create(:ci_build, :pending) } + let(:project) { build.project } + + before do + expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'gitlab-ci-token') + end + + it 'denies authentication' do + expect(subject).to eq(Gitlab::Auth::Result.new) + end + end + end + + it 'recognizes other ci services' do project = create(:empty_project) - project.update_attributes(runners_token: token) + project.create_drone_ci_service(active: true) + project.drone_ci_service.update(token: 'token') ip = 'ip' - expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'gitlab-ci-token') - expect(gl_auth.find_for_git_client('gitlab-ci-token', token, project: project, ip: ip)).to eq(Gitlab::Auth::Result.new(nil, :ci)) + expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'drone-ci-token') + expect(gl_auth.find_for_git_client('drone-ci-token', 'token', project: project, ip: ip)).to eq(Gitlab::Auth::Result.new(nil, project, :ci, build_capabilities)) end it 'recognizes master passwords' do @@ -20,7 +56,7 @@ describe Gitlab::Auth, lib: true do ip = 'ip' expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username) - expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :gitlab_or_ldap)) + 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_capabilities)) end it 'recognizes OAuth tokens' do @@ -30,7 +66,7 @@ describe Gitlab::Auth, lib: true do ip = 'ip' 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, :oauth)) + expect(gl_auth.find_for_git_client("oauth2", token.token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, nil, :oauth, read_capabilities)) end it 'returns double nil for invalid credentials' do @@ -92,4 +128,30 @@ describe Gitlab::Auth, lib: true do end end end + + private + + def build_capabilities + [ + :read_project, + :build_download_code, + :build_read_container_image, + :build_create_container_image + ] + end + + def read_capabilities + [ + :read_project, + :download_code, + :read_container_image + ] + end + + def full_capabilities + read_capabilities + [ + :push_code, + :update_container_image + ] + end end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index f12c9a370f7..77dce676cdb 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -1,10 +1,17 @@ require 'spec_helper' describe Gitlab::GitAccess, lib: true do - let(:access) { Gitlab::GitAccess.new(actor, project, 'web') } + let(:access) { Gitlab::GitAccess.new(actor, project, 'web', capabilities: capabilities) } let(:project) { create(:project) } let(:user) { create(:user) } let(:actor) { user } + let(:capabilities) do + [ + :read_project, + :download_code, + :push_code + ] + end describe '#check with single protocols allowed' do def disable_protocol(protocol) @@ -111,6 +118,36 @@ describe Gitlab::GitAccess, lib: true do end end end + + describe 'build capabilities permissions' do + let(:capabilities) { build_capabilities } + + describe 'reporter user' do + before { project.team << [user, :reporter] } + + context 'pull code' do + it { expect(subject).to be_allowed } + end + end + + describe 'admin user' do + let(:user) { create(:admin) } + + context 'when member of the project' do + before { project.team << [user, :reporter] } + + context 'pull code' do + it { expect(subject).to be_allowed } + end + end + + context 'when is not member of the project' do + context 'pull code' do + it { expect(subject).not_to be_allowed } + end + end + end + end end describe 'push_access_check' do @@ -281,40 +318,58 @@ describe Gitlab::GitAccess, lib: true do admin: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false })) end end + end - describe 'deploy key permissions' do - let(:key) { create(:deploy_key) } - let(:actor) { key } + shared_examples 'can not push code' do + subject { access.check('git-receive-pack', '_any') } - context 'push code' do - subject { access.check('git-receive-pack', '_any') } + context 'when project is authorized' do + before { key.projects << project } - context 'when project is authorized' do - before { key.projects << project } + it { expect(subject).not_to be_allowed } + end + + context 'when unauthorized' do + context 'to public project' do + let(:project) { create(:project, :public) } it { expect(subject).not_to be_allowed } end - context 'when unauthorized' do - context 'to public project' do - let(:project) { create(:project, :public) } - - it { expect(subject).not_to be_allowed } - end - - context 'to internal project' do - let(:project) { create(:project, :internal) } + context 'to internal project' do + let(:project) { create(:project, :internal) } - it { expect(subject).not_to be_allowed } - end + it { expect(subject).not_to be_allowed } + end - context 'to private project' do - let(:project) { create(:project, :internal) } + context 'to private project' do + let(:project) { create(:project, :internal) } - it { expect(subject).not_to be_allowed } - end + it { expect(subject).not_to be_allowed } end end end + + describe 'build capabilities permissions' do + let(:capabilities) { build_capabilities } + + it_behaves_like 'cannot push code' + end + + describe 'deploy key permissions' do + let(:key) { create(:deploy_key) } + let(:actor) { key } + + it_behaves_like 'cannot push code' + end + + private + + def build_capabilities + [ + :read_project, + :build_download_code + ] + end end -- cgit v1.2.1 From 9d1ccd2ad3af37139649100476b568d219343a57 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 13:49:11 +0200 Subject: Fix existing authorization specs --- spec/lib/gitlab/git_access_spec.rb | 17 ++++++++++++----- spec/requests/git_http_spec.rb | 9 ++++----- spec/requests/jwt_controller_spec.rb | 6 ++++-- .../container_registry_authentication_service_spec.rb | 14 +++++++++++++- 4 files changed, 33 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 77dce676cdb..d418b0be0ed 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::GitAccess, lib: true do context 'ssh disabled' do before do disable_protocol('ssh') - @acc = Gitlab::GitAccess.new(actor, project, 'ssh') + @acc = Gitlab::GitAccess.new(actor, project, 'ssh', capabilities: capabilities) end it 'blocks ssh git push' do @@ -37,7 +37,7 @@ describe Gitlab::GitAccess, lib: true do context 'http disabled' do before do disable_protocol('http') - @acc = Gitlab::GitAccess.new(actor, project, 'http') + @acc = Gitlab::GitAccess.new(actor, project, 'http', capabilities: capabilities) end it 'blocks http push' do @@ -318,7 +318,6 @@ describe Gitlab::GitAccess, lib: true do admin: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false })) end end - end shared_examples 'can not push code' do @@ -354,14 +353,14 @@ describe Gitlab::GitAccess, lib: true do describe 'build capabilities permissions' do let(:capabilities) { build_capabilities } - it_behaves_like 'cannot push code' + it_behaves_like 'can not push code' end describe 'deploy key permissions' do let(:key) { create(:deploy_key) } let(:actor) { key } - it_behaves_like 'cannot push code' + it_behaves_like 'can not push code' end private @@ -372,4 +371,12 @@ describe Gitlab::GitAccess, lib: true do :build_download_code ] end + + def full_capabilities + [ + :read_project, + :download_code, + :push_code + ] + end end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index b7001fede40..5977ee04524 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -300,23 +300,22 @@ describe 'Git HTTP requests', lib: true do end context "when a gitlab ci token is provided" do - let(:token) { 123 } - let(:project) { FactoryGirl.create :empty_project } + let(:build) { create(:ci_build, :running) } + let(:project) { build.project } before do - project.update_attributes(runners_token: token) project.project_feature.update_attributes(builds_access_level: ProjectFeature::ENABLED) end it "downloads get status 200" do - clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: token + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token expect(response).to have_http_status(200) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) end it "uploads get status 401 (no project existence information leak)" do - push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: token + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token expect(response).to have_http_status(401) end diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index fc42b534dca..93b9cfaf33d 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -22,11 +22,13 @@ describe JwtController do context 'when using authorized request' do context 'using CI token' do - let(:project) { create(:empty_project, runners_token: 'token') } - let(:headers) { { authorization: credentials('gitlab-ci-token', project.runners_token) } } + let(:build) { create(:ci_build, :running) } + let(:project) { build.project } + let(:headers) { { authorization: credentials('gitlab-ci-token', build.token) } } context 'project with enabled CI' do subject! { get '/jwt/auth', parameters, headers } + it { expect(service_class).to have_received(:new).with(project, nil, parameters) } end diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index 7cc71f706ce..c82deb7d423 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -6,8 +6,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do let(:current_params) { {} } let(:rsa_key) { OpenSSL::PKey::RSA.generate(512) } let(:payload) { JWT.decode(subject[:token], rsa_key).first } + let(:capabilities) do + [ + :read_container_image, + :create_container_image + ] + end - subject { described_class.new(current_project, current_user, current_params).execute } + subject { described_class.new(current_project, current_user, current_params).execute(capabilities: capabilities) } before do allow(Gitlab.config.registry).to receive_messages(enabled: true, issuer: 'rspec', key: nil) @@ -42,6 +48,12 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do 'actions' => actions, }] end + let(:capabilities) do + [ + :build_read_container_image, + :build_create_container_image + ] + end it_behaves_like 'a valid token' it { expect(payload).to include('access' => access) } -- cgit v1.2.1 From 548169cfb57b27cca911d947e2aa6f4f7e6df004 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 15:40:53 +0200 Subject: Fix most of specs --- spec/lib/gitlab/git_access_spec.rb | 14 +++++++++++--- spec/lib/gitlab/git_access_wiki_spec.rb | 9 ++++++++- spec/requests/lfs_http_spec.rb | 10 ++++++---- .../auth/container_registry_authentication_service_spec.rb | 12 ++++++------ 4 files changed, 31 insertions(+), 14 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index d418b0be0ed..c6fe56aac1c 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -324,7 +324,7 @@ describe Gitlab::GitAccess, lib: true do subject { access.check('git-receive-pack', '_any') } context 'when project is authorized' do - before { key.projects << project } + before { authorize } it { expect(subject).not_to be_allowed } end @@ -353,14 +353,22 @@ describe Gitlab::GitAccess, lib: true do describe 'build capabilities permissions' do let(:capabilities) { build_capabilities } - it_behaves_like 'can not push code' + it_behaves_like 'can not push code' do + def authorize + project.team << [user, :reporter] + end + end end describe 'deploy key permissions' do let(:key) { create(:deploy_key) } let(:actor) { key } - it_behaves_like 'can not push code' + it_behaves_like 'can not push code' do + def authorize + key.projects << project + end + end end private diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 4244b807d41..860e701c1a1 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -1,9 +1,16 @@ require 'spec_helper' describe Gitlab::GitAccessWiki, lib: true do - let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web') } + let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web', capabilities: capabilities) } let(:project) { create(:project) } let(:user) { create(:user) } + let(:capabilities) do + [ + :read_project, + :download_code, + :push_code + ] + end describe 'push_allowed?' do before do diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 6e551bb65fa..85290ec05c2 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -586,8 +586,8 @@ describe 'Git LFS API and storage' do context 'when CI is authorized' do let(:authorization) { authorize_ci_project } - it 'responds with 401' do - expect(response).to have_http_status(401) + it 'responds with 403' do + expect(response).to have_http_status(403) end end end @@ -614,7 +614,7 @@ describe 'Git LFS API and storage' do let(:authorization) { authorize_ci_project } it 'responds with status 403' do - expect(response).to have_http_status(401) + expect(response).to have_http_status(403) end end end @@ -897,7 +897,9 @@ describe 'Git LFS API and storage' do end def authorize_ci_project - ActionController::HttpAuthentication::Basic.encode_credentials('gitlab-ci-token', project.runners_token) + pipeline = create(:ci_empty_pipeline, project: project) + build = create(:ci_build, :running, pipeline: pipeline) + ActionController::HttpAuthentication::Basic.encode_credentials('gitlab-ci-token', build.token) end def authorize_user diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index c82deb7d423..5f82fee43c6 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -48,12 +48,6 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do 'actions' => actions, }] end - let(:capabilities) do - [ - :build_read_container_image, - :build_create_container_image - ] - end it_behaves_like 'a valid token' it { expect(payload).to include('access' => access) } @@ -203,6 +197,12 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do context 'project authorization' do let(:current_project) { create(:empty_project) } + let(:capabilities) do + [ + :build_read_container_image, + :build_create_container_image + ] + end context 'allow to use scope-less authentication' do it_behaves_like 'a valid token' -- cgit v1.2.1 From e3a422c2672096a819291c395623619c8c669e74 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 16:17:57 +0200 Subject: Fix LFS specs --- spec/requests/lfs_http_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 85290ec05c2..1ee3881b839 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -586,8 +586,8 @@ describe 'Git LFS API and storage' do context 'when CI is authorized' do let(:authorization) { authorize_ci_project } - it 'responds with 403' do - expect(response).to have_http_status(403) + it 'responds with 401' do + expect(response).to have_http_status(401) end end end @@ -613,8 +613,8 @@ describe 'Git LFS API and storage' do context 'when CI is authorized' do let(:authorization) { authorize_ci_project } - it 'responds with status 403' do - expect(response).to have_http_status(403) + it 'responds with status 401' do + expect(response).to have_http_status(401) end end end -- cgit v1.2.1 From eed5c58d8542cef8cc4012a303c9bb963b7f5f20 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 16:36:39 +0200 Subject: Verify permission of build in context of dependent project --- spec/requests/lfs_http_spec.rb | 6 ++-- ...ntainer_registry_authentication_service_spec.rb | 40 +++++++++++++++++++--- 2 files changed, 38 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 1ee3881b839..7bf43a03f23 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -14,6 +14,8 @@ describe 'Git LFS API and storage' do end let(:authorization) { } let(:sendfile) { } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let(:build) { create(:ci_build, :running, pipeline: pipeline) } let(:sample_oid) { lfs_object.oid } let(:sample_size) { lfs_object.size } @@ -244,7 +246,7 @@ describe 'Git LFS API and storage' do end end - context 'when CI is authorized' do + context 'when build is authorized' do let(:authorization) { authorize_ci_project } let(:update_permissions) do @@ -897,8 +899,6 @@ describe 'Git LFS API and storage' do end def authorize_ci_project - pipeline = create(:ci_empty_pipeline, project: project) - build = create(:ci_build, :running, pipeline: pipeline) ActionController::HttpAuthentication::Basic.encode_credentials('gitlab-ci-token', build.token) end diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index 5f82fee43c6..2d39bd61b8f 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -195,8 +195,9 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do end end - context 'project authorization' do + context 'build authorized as user' do let(:current_project) { create(:empty_project) } + let(:current_user) { create(:user) } let(:capabilities) do [ :build_read_container_image, @@ -204,10 +205,12 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ] end - context 'allow to use scope-less authentication' do - it_behaves_like 'a valid token' + before do + current_project.team << [current_user, :developer] end + it_behaves_like 'a valid token' + context 'allow to pull and push images' do let(:current_params) do { scope: "repository:#{current_project.path_with_namespace}:pull,push" } @@ -226,12 +229,34 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do context 'allow for public' do let(:project) { create(:empty_project, :public) } + it_behaves_like 'a pullable' end - context 'disallow for private' do + shared_examples 'pullable for being team member' do + context 'when you are not member' do + it_behaves_like 'an inaccessible' + end + + context 'when you are member' do + before do + project.team << [current_user, :developer] + end + + it_behaves_like 'a pullable' + end + end + + context 'for private' do let(:project) { create(:empty_project, :private) } - it_behaves_like 'an inaccessible' + + it_behaves_like 'pullable for being team member' + + context 'when you are admin' do + let(:current_user) { create(:admin) } + + it_behaves_like 'pullable for being team member' + end end end @@ -242,6 +267,11 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do context 'disallow for all' do let(:project) { create(:empty_project, :public) } + + before do + project.team << [current_user, :developer] + end + it_behaves_like 'an inaccessible' end end -- cgit v1.2.1 From e40e3fdc8271d1becf7952c7e30546c5abecb79b Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Thu, 25 Aug 2016 17:26:20 -0500 Subject: Added LFS support to SSH - Required on the GitLab Rails side is mostly authentication and API related. --- spec/lib/gitlab/auth_spec.rb | 16 +++++++++++++ spec/models/concerns/token_authenticatable_spec.rb | 20 +++++++++++++++++ spec/requests/api/internal_spec.rb | 26 ++++++++++++++++++---- spec/requests/lfs_http_spec.rb | 16 +++++++++++++ 4 files changed, 74 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 7c23e02d05a..cd00a15be3b 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -23,6 +23,22 @@ 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, :gitlab_or_ldap)) end + it 'recognizes user lfs tokens' do + user = create(:user) + ip = 'ip' + + expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username) + expect(gl_auth.find_for_git_client(user.username, user.lfs_token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :lfs_token)) + end + + it 'recognizes deploy key lfs tokens' do + key = create(:deploy_key) + ip = 'ip' + + expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'lfs-deploy-key') + expect(gl_auth.find_for_git_client('lfs-deploy-key', key.lfs_token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(key, :lfs_deploy_token)) + end + it 'recognizes OAuth tokens' do user = create(:user) application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb index eb64f3d0c83..82076600f3b 100644 --- a/spec/models/concerns/token_authenticatable_spec.rb +++ b/spec/models/concerns/token_authenticatable_spec.rb @@ -18,6 +18,26 @@ describe User, 'TokenAuthenticatable' do subject { create(:user).send(token_field) } it { is_expected.to be_a String } end + + describe 'lfs token' do + let(:token_field) { :lfs_token } + it_behaves_like 'TokenAuthenticatable' + + describe 'ensure it' do + subject { create(:user).send(token_field) } + it { is_expected.to be_a String } + end + end +end + +describe DeployKey, 'TokenAuthenticatable' do + let(:token_field) { :lfs_token } + it_behaves_like 'TokenAuthenticatable' + + describe 'ensures authentication token' do + subject { create(:deploy_key).send(token_field) } + it { is_expected.to be_a String } + end end describe ApplicationSetting, 'TokenAuthenticatable' do diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 46d1b868782..95fc5f790e8 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -101,12 +101,28 @@ describe API::API, api: true do end describe "GET /internal/discover" do - it do - get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) + context 'user key' do + it 'returns the correct information about the key' do + get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) - expect(response).to have_http_status(200) + expect(response).to have_http_status(200) + + expect(json_response['name']).to eq(user.name) + expect(json_response['lfs_token']).to eq(user.lfs_token) + end + end - expect(json_response['name']).to eq(user.name) + context 'deploy key' do + let(:key) { create(:deploy_key) } + + it 'returns the correct information about the key' do + get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) + + expect(response).to have_http_status(200) + + expect(json_response['username']).to eq('lfs-deploy-key') + expect(json_response['lfs_token']).to eq(key.lfs_token) + end end end @@ -143,6 +159,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) + expect(json_response["repository_http_path"]).to eq(project.http_url_to_repo) end end @@ -153,6 +170,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) + expect(json_response["repository_http_path"]).to eq(project.http_url_to_repo) end end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 6e551bb65fa..58f8515c0e2 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -244,6 +244,18 @@ describe 'Git LFS API and storage' do end end + context 'when deploy key is authorized' do + let(:key) { create(:deploy_key) } + let(:authorization) { authorize_deploy_key } + + let(:update_permissions) do + project.deploy_keys << key + project.lfs_objects << lfs_object + end + + it_behaves_like 'responds with a file' + end + context 'when CI is authorized' do let(:authorization) { authorize_ci_project } @@ -904,6 +916,10 @@ describe 'Git LFS API and storage' do ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) end + def authorize_deploy_key + ActionController::HttpAuthentication::Basic.encode_credentials('lfs-deploy-key', key.lfs_token) + end + def fork_project(project, user, object = nil) allow(RepositoryForkWorker).to receive(:perform_async).and_return(true) Projects::ForkService.new(project, user, {}).execute -- cgit v1.2.1 From cb85cf1f0a7047c485d7b29b2792b8965e270898 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Mon, 29 Aug 2016 13:05:07 -0500 Subject: Refactor LFS token logic to use a Redis key instead of a DB field, making it a 1 use only token. --- spec/lib/gitlab/auth_spec.rb | 8 +++-- spec/lib/gitlab/lfs_token_spec.rb | 35 ++++++++++++++++++++++ spec/models/concerns/token_authenticatable_spec.rb | 20 ------------- spec/requests/api/internal_spec.rb | 6 ++-- spec/requests/lfs_http_spec.rb | 2 +- 5 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 spec/lib/gitlab/lfs_token_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index cd00a15be3b..6ce680e3c26 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -26,17 +26,19 @@ describe Gitlab::Auth, lib: true do it 'recognizes user lfs tokens' do user = create(:user) ip = 'ip' + token = Gitlab::LfsToken.new(user).set_token expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username) - expect(gl_auth.find_for_git_client(user.username, user.lfs_token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :lfs_token)) + expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :lfs_token)) end it 'recognizes deploy key lfs tokens' do key = create(:deploy_key) ip = 'ip' + token = Gitlab::LfsToken.new(key).set_token - expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'lfs-deploy-key') - expect(gl_auth.find_for_git_client('lfs-deploy-key', key.lfs_token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(key, :lfs_deploy_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, :lfs_deploy_token)) end it 'recognizes OAuth tokens' do diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb new file mode 100644 index 00000000000..76b348637c7 --- /dev/null +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Gitlab::LfsToken, lib: true do + describe '#set_token and #get_value' do + shared_examples 'an LFS token generator' do + it 'returns a randomly generated token' do + token = handler.set_token + + expect(token).not_to be_nil + expect(token).to be_a String + expect(token.length).to eq 50 + end + + it 'returns the correct token based on the key' do + token = handler.set_token + + expect(handler.get_value).to eq(token) + end + end + + context 'when the actor is a user' do + let(:actor) { create(:user) } + let(:handler) { described_class.new(actor) } + + it_behaves_like 'an LFS token generator' + end + + context 'when the actor is a deploy key' do + let(:actor) { create(:deploy_key) } + let(:handler) { described_class.new(actor) } + + it_behaves_like 'an LFS token generator' + end + end +end diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb index 82076600f3b..eb64f3d0c83 100644 --- a/spec/models/concerns/token_authenticatable_spec.rb +++ b/spec/models/concerns/token_authenticatable_spec.rb @@ -18,26 +18,6 @@ describe User, 'TokenAuthenticatable' do subject { create(:user).send(token_field) } it { is_expected.to be_a String } end - - describe 'lfs token' do - let(:token_field) { :lfs_token } - it_behaves_like 'TokenAuthenticatable' - - describe 'ensure it' do - subject { create(:user).send(token_field) } - it { is_expected.to be_a String } - end - end -end - -describe DeployKey, 'TokenAuthenticatable' do - let(:token_field) { :lfs_token } - it_behaves_like 'TokenAuthenticatable' - - describe 'ensures authentication token' do - subject { create(:deploy_key).send(token_field) } - it { is_expected.to be_a String } - end end describe ApplicationSetting, 'TokenAuthenticatable' do diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 95fc5f790e8..59df5af770b 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -108,7 +108,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response['name']).to eq(user.name) - expect(json_response['lfs_token']).to eq(user.lfs_token) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(user).get_value) end end @@ -120,8 +120,8 @@ describe API::API, api: true do expect(response).to have_http_status(200) - expect(json_response['username']).to eq('lfs-deploy-key') - expect(json_response['lfs_token']).to eq(key.lfs_token) + expect(json_response['username']).to eq("lfs-deploy-key-#{key.id}") + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).get_value) end end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 58f8515c0e2..d15e72b2570 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -917,7 +917,7 @@ describe 'Git LFS API and storage' do end def authorize_deploy_key - ActionController::HttpAuthentication::Basic.encode_credentials('lfs-deploy-key', key.lfs_token) + ActionController::HttpAuthentication::Basic.encode_credentials("lfs-deploy-key-#{key.id}", Gitlab::LfsToken.new(key).set_token) end def fork_project(project, user, object = nil) -- cgit v1.2.1 From 48f1a61fd5c6aac395be0ce5d59aee61bbb69fe9 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 30 Aug 2016 13:38:22 -0500 Subject: Refactored LFS auth logic when using SSH to use its own API endpoint `/lfs_authenticate` and added tests. --- spec/lib/gitlab/auth_spec.rb | 4 ++-- spec/lib/gitlab/lfs_token_spec.rb | 6 +++--- spec/requests/api/internal_spec.rb | 40 +++++++++++++++++++++++++++++--------- spec/requests/lfs_http_spec.rb | 2 +- 4 files changed, 37 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 6ce680e3c26..4c8e09cd904 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -26,7 +26,7 @@ describe Gitlab::Auth, lib: true do it 'recognizes user lfs tokens' do user = create(:user) ip = 'ip' - token = Gitlab::LfsToken.new(user).set_token + token = Gitlab::LfsToken.new(user).generate 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, :lfs_token)) @@ -35,7 +35,7 @@ describe Gitlab::Auth, lib: true do it 'recognizes deploy key lfs tokens' do key = create(:deploy_key) ip = 'ip' - token = Gitlab::LfsToken.new(key).set_token + token = Gitlab::LfsToken.new(key).generate 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, :lfs_deploy_token)) diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb index 76b348637c7..1d2e4fd9566 100644 --- a/spec/lib/gitlab/lfs_token_spec.rb +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -4,7 +4,7 @@ describe Gitlab::LfsToken, lib: true do describe '#set_token and #get_value' do shared_examples 'an LFS token generator' do it 'returns a randomly generated token' do - token = handler.set_token + token = handler.generate expect(token).not_to be_nil expect(token).to be_a String @@ -12,9 +12,9 @@ describe Gitlab::LfsToken, lib: true do end it 'returns the correct token based on the key' do - token = handler.set_token + token = handler.generate - expect(handler.get_value).to eq(token) + expect(handler.value).to eq(token) end end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 59df5af770b..ff697286927 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -100,15 +100,20 @@ describe API::API, api: true do end end - describe "GET /internal/discover" do + describe "POST /internal/lfs_authenticate" do + before do + project.team << [user, :developer] + end + context 'user key' do it 'returns the correct information about the key' do - get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) + lfs_auth(key, project) expect(response).to have_http_status(200) + expect(json_response['username']).to eq(user.username) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(user).value) - expect(json_response['name']).to eq(user.name) - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(user).get_value) + expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end end @@ -116,16 +121,26 @@ describe API::API, api: true do let(:key) { create(:deploy_key) } it 'returns the correct information about the key' do - get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) + lfs_auth(key, project) expect(response).to have_http_status(200) - expect(json_response['username']).to eq("lfs-deploy-key-#{key.id}") - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).get_value) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) + expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end end end + describe "GET /internal/discover" do + it do + get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) + + expect(response).to have_http_status(200) + + expect(json_response['name']).to eq(user.name) + end + end + describe "POST /internal/allowed" do context "access granted" do before do @@ -159,7 +174,6 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) - expect(json_response["repository_http_path"]).to eq(project.http_url_to_repo) end end @@ -170,7 +184,6 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response["status"]).to be_truthy expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) - expect(json_response["repository_http_path"]).to eq(project.http_url_to_repo) end end end @@ -407,4 +420,13 @@ describe API::API, api: true do protocol: 'ssh' ) end + + def lfs_auth(key, project) + post( + api("/internal/lfs_authenticate"), + key_id: key.id, + secret_token: secret_token, + project: project.path_with_namespace + ) + end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index d15e72b2570..e61502400ff 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -917,7 +917,7 @@ describe 'Git LFS API and storage' do end def authorize_deploy_key - ActionController::HttpAuthentication::Basic.encode_credentials("lfs-deploy-key-#{key.id}", Gitlab::LfsToken.new(key).set_token) + ActionController::HttpAuthentication::Basic.encode_credentials("lfs-deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) end def fork_project(project, user, object = nil) -- cgit v1.2.1 From c25630ee2c2804e351a2c3ae4fd9224434e4698a Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 30 Aug 2016 18:43:24 -0500 Subject: Refactored handling of the `LfsToken` and added functionality to it to simplify external code. --- spec/lib/gitlab/lfs_token_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb index 1d2e4fd9566..f9812664e3b 100644 --- a/spec/lib/gitlab/lfs_token_spec.rb +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -23,6 +23,14 @@ describe Gitlab::LfsToken, lib: true do let(:handler) { described_class.new(actor) } it_behaves_like 'an LFS token generator' + + it 'returns the correct username' do + expect(handler.actor_name).to eq(actor.username) + end + + it 'returns the correct token type' do + expect(handler.type).to eq(:lfs_token) + end end context 'when the actor is a deploy key' do @@ -30,6 +38,14 @@ describe Gitlab::LfsToken, lib: true do let(:handler) { described_class.new(actor) } it_behaves_like 'an LFS token generator' + + it 'returns the correct username' do + expect(handler.actor_name).to eq("lfs-deploy-key-#{actor.id}") + end + + it 'returns the correct token type' do + expect(handler.type).to eq(:lfs_deploy_token) + end end end end -- cgit v1.2.1 From c144db2935f0f71c7f282a3015d126526bc16b57 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 6 Sep 2016 16:32:39 -0500 Subject: Better authentication handling, syntax fixes and better actor handling for LFS Tokens --- spec/requests/api/internal_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index ff697286927..1ee390e0a19 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -111,7 +111,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response['username']).to eq(user.username) - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(user).value) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end -- cgit v1.2.1 From 71aff7f6a3ab63f1395bfab6ea49f0175fe08167 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 7 Sep 2016 11:55:54 -0500 Subject: Use special characters for `lfs+deploy-key` to prevent a someone from creating a user with this username, and method name refactoring. --- spec/lib/gitlab/auth_spec.rb | 4 ++-- spec/lib/gitlab/lfs_token_spec.rb | 2 +- spec/requests/api/internal_spec.rb | 2 +- spec/requests/lfs_http_spec.rb | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 4c8e09cd904..56f349f5d92 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -37,8 +37,8 @@ describe Gitlab::Auth, lib: true do ip = 'ip' token = Gitlab::LfsToken.new(key).generate - 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, :lfs_deploy_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, :lfs_deploy_token)) end it 'recognizes OAuth tokens' do diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb index f9812664e3b..184f235c1b2 100644 --- a/spec/lib/gitlab/lfs_token_spec.rb +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -40,7 +40,7 @@ describe Gitlab::LfsToken, lib: true do it_behaves_like 'an LFS token generator' it 'returns the correct username' do - expect(handler.actor_name).to eq("lfs-deploy-key-#{actor.id}") + expect(handler.actor_name).to eq("lfs+deploy-key-#{actor.id}") end it 'returns the correct token type' do diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 1ee390e0a19..2e1e6a11b53 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -124,7 +124,7 @@ describe API::API, api: true do lfs_auth(key, project) expect(response).to have_http_status(200) - expect(json_response['username']).to eq("lfs-deploy-key-#{key.id}") + expect(json_response['username']).to eq("lfs+deploy-key-#{key.id}") expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index e61502400ff..54ecb793729 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -917,7 +917,7 @@ describe 'Git LFS API and storage' do end def authorize_deploy_key - ActionController::HttpAuthentication::Basic.encode_credentials("lfs-deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) + ActionController::HttpAuthentication::Basic.encode_credentials("lfs+deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) end def fork_project(project, user, object = nil) -- cgit v1.2.1 From be09bcf074e6048aa9ba5f8dfb99754e6afbe156 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Thu, 15 Sep 2016 11:54:24 -0500 Subject: Refactored authentication code to make it a bit clearer, added test for wrong SSH key. --- spec/lib/gitlab/auth_spec.rb | 2 +- spec/lib/gitlab/lfs_token_spec.rb | 2 +- spec/requests/api/internal_spec.rb | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 56f349f5d92..13c5a7156f5 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -55,7 +55,7 @@ describe Gitlab::Auth, lib: true do login = 'foo' ip = 'ip' - expect(gl_auth).to receive(:rate_limit!).with(ip, success: false, login: login) + expect(gl_auth).to receive(:rate_limit!).with(ip, success: nil, login: login) expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new) end end diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb index 184f235c1b2..9f04f67e0a8 100644 --- a/spec/lib/gitlab/lfs_token_spec.rb +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::LfsToken, lib: true do - describe '#set_token and #get_value' do + describe '#generate and #value' do shared_examples 'an LFS token generator' do it 'returns a randomly generated token' do token = handler.generate diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 2e1e6a11b53..46e8e6f1169 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -107,7 +107,7 @@ describe API::API, api: true do context 'user key' do it 'returns the correct information about the key' do - lfs_auth(key, project) + lfs_auth(key.id, project) expect(response).to have_http_status(200) expect(json_response['username']).to eq(user.username) @@ -115,13 +115,19 @@ describe API::API, api: true do expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end + + it 'returns a 404 when the wrong key is provided' do + lfs_auth(nil, project) + + expect(response).to have_http_status(404) + end end context 'deploy key' do let(:key) { create(:deploy_key) } it 'returns the correct information about the key' do - lfs_auth(key, project) + lfs_auth(key.id, project) expect(response).to have_http_status(200) expect(json_response['username']).to eq("lfs+deploy-key-#{key.id}") @@ -421,10 +427,10 @@ describe API::API, api: true do ) end - def lfs_auth(key, project) + def lfs_auth(key_id, project) post( api("/internal/lfs_authenticate"), - key_id: key.id, + key_id: key_id, secret_token: secret_token, project: project.path_with_namespace ) -- cgit v1.2.1 From 5f45ddc54577fb65db00636a05408b00636544f5 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 22:17:12 +0200 Subject: Fix specs after merging LFS changes --- spec/lib/gitlab/auth_spec.rb | 6 +++--- spec/requests/jwt_controller_spec.rb | 24 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index c09ab1dbd57..e24ad530904 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -65,7 +65,7 @@ describe Gitlab::Auth, lib: true do token = Gitlab::LfsToken.new(user).generate 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, :lfs_token)) + expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, nil, :lfs_token, read_capabilities)) end it 'recognizes deploy key lfs tokens' do @@ -74,7 +74,7 @@ describe Gitlab::Auth, lib: true do token = Gitlab::LfsToken.new(key).generate 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, :lfs_deploy_token)) + 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_capabilities)) end it 'recognizes OAuth tokens' do @@ -91,7 +91,7 @@ describe Gitlab::Auth, lib: true do login = 'foo' ip = 'ip' - expect(gl_auth).to receive(:rate_limit!).with(ip, success: nil, login: login) + expect(gl_auth).to receive(:rate_limit!).with(ip, success: false, login: login) expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new) end end diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 93b9cfaf33d..1ca4541dbde 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -45,13 +45,31 @@ describe JwtController do context 'using User login' do let(:user) { create(:user) } - let(:headers) { { authorization: credentials('user', 'password') } } - - before { expect(Gitlab::Auth).to receive(:find_with_user_password).with('user', 'password').and_return(user) } + let(:headers) { { authorization: credentials(user.username , user.password) } } subject! { get '/jwt/auth', parameters, headers } it { expect(service_class).to have_received(:new).with(nil, user, parameters) } + + context 'when user has 2FA enabled' do + let(:user) { create(:user, :two_factor) } + + context 'without personal token' do + it 'rejects the authorization attempt' do + expect(response).to have_http_status(401) + expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + end + end + + context 'with personal token' do + let(:access_token) { create(:personal_access_token, user: user) } + let(:headers) { { authorization: credentials(user.username, access_token.token) } } + + it 'rejects the authorization attempt' do + expect(response).to have_http_status(200) + end + end + end end context 'using invalid login' do -- cgit v1.2.1 From ac6412d0766fbc090a3aa8272cfd4cc2d9a26c16 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 23:27:01 +0200 Subject: Added builds_spec and git_http_specs --- spec/requests/ci/api/builds_spec.rb | 77 ++++++++++++++++++++++++++++++------ spec/requests/git_http_spec.rb | 69 ++++++++++++++++++++++++++++---- spec/requests/jwt_controller_spec.rb | 2 +- 3 files changed, 129 insertions(+), 19 deletions(-) (limited to 'spec') diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 780bd7f2859..09d72fe0a0e 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -254,7 +254,8 @@ describe Ci::API::API do let(:get_url) { ci_api("/builds/#{build.id}/artifacts") } let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') } let(:headers) { { "GitLab-Workhorse" => "1.0", Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } } - let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => build.token) } + let(:token) { build.token } + let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => token) } before { build.run! } @@ -274,6 +275,13 @@ describe Ci::API::API do expect(json_response["TempPath"]).not_to be_nil end + it "using runners token" do + post authorize_url, { token: build.project.runners_token }, headers + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(json_response["TempPath"]).not_to be_nil + end + it "reject requests that did not go through gitlab-workhorse" do headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER) post authorize_url, { token: build.token }, headers @@ -358,6 +366,16 @@ describe Ci::API::API do it_behaves_like 'successful artifacts upload' end + + context 'when using runners token' do + let(:token) { build.project.runners_token } + + before do + upload_artifacts(file_upload, headers_with_token) + end + + it_behaves_like 'successful artifacts upload' + end end context 'posts artifacts file and metadata file' do @@ -497,19 +515,40 @@ describe Ci::API::API do before do delete delete_url, token: build.token - build.reload end - it 'removes build artifacts' do - expect(response).to have_http_status(200) - expect(build.artifacts_file.exists?).to be_falsy - expect(build.artifacts_metadata.exists?).to be_falsy - expect(build.artifacts_size).to be_nil + shared_examples 'having removable artifacts' do + it 'removes build artifacts' do + build.reload + + expect(response).to have_http_status(200) + expect(build.artifacts_file.exists?).to be_falsy + expect(build.artifacts_metadata.exists?).to be_falsy + expect(build.artifacts_size).to be_nil + end + end + + context 'when using build token' do + before do + delete delete_url, token: build.token + end + + it_behaves_like 'having removable artifacts' + end + + context 'when using runnners token' do + before do + delete delete_url, token: build.project.runners_token + end + + it_behaves_like 'having removable artifacts' end end describe 'GET /builds/:id/artifacts' do - before { get get_url, token: build.token } + before do + get get_url, token: token + end context 'build has artifacts' do let(:build) { create(:ci_build, :artifacts) } @@ -518,13 +557,29 @@ describe Ci::API::API do 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' } end - it 'downloads artifact' do - expect(response).to have_http_status(200) - expect(response.headers).to include download_headers + shared_examples 'having downloadable artifacts' do + it 'download artifacts' do + expect(response).to have_http_status(200) + expect(response.headers).to include download_headers + end + end + + context 'when using build token' do + let(:token) { build.token } + + it_behaves_like 'having downloadable artifacts' + end + + context 'when using runnners token' do + let(:token) { build.project.runners_token } + + it_behaves_like 'having downloadable artifacts' end end context 'build does not has artifacts' do + let(:token) { build.token } + it 'responds with not found' do expect(response).to have_http_status(404) end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 5977ee04524..0311755dd06 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -302,22 +302,77 @@ describe 'Git HTTP requests', lib: true do context "when a gitlab ci token is provided" do let(:build) { create(:ci_build, :running) } let(:project) { build.project } + let(:other_project) { create(:empty_project) } before do project.project_feature.update_attributes(builds_access_level: ProjectFeature::ENABLED) end - it "downloads get status 200" do - clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + context 'when build created by system is authenticated' do + it "downloads get status 200" do + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - expect(response).to have_http_status(200) - expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end + + it "uploads get status 401 (no project existence information leak)" do + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(401) + end + + it "downloads from other project get status 401" do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(401) + end end - it "uploads get status 401 (no project existence information leak)" do - push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + context 'and build created by' do + before do + build.update(user: user) + project.team << [user, :reporter] + end - expect(response).to have_http_status(401) + shared_examples 'can download code only from own projects' do + it 'downloads get status 200' do + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end + + it 'uploads get status 403' do + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(403) + end + end + + context 'administrator' do + let(:user) { create(:admin) } + + it_behaves_like 'can download code only from own projects' + + it 'downloads from other project get status 403' do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(403) + end + end + + context 'regular user' do + let(:user) { create(:user) } + + it_behaves_like 'can download code only from own projects' + + it 'downloads from other project get status 404' do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(404) + end + end end end end diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 1ca4541dbde..6b956e63004 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -45,7 +45,7 @@ describe JwtController do context 'using User login' do let(:user) { create(:user) } - let(:headers) { { authorization: credentials(user.username , user.password) } } + let(:headers) { { authorization: credentials(user.username, user.password) } } subject! { get '/jwt/auth', parameters, headers } -- cgit v1.2.1 From e000f02bd3b7c13f7f3a95b855fea6b3dd277417 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Tue, 13 Sep 2016 17:15:14 -0500 Subject: Add support for column limits in add_column_with_default --- spec/lib/gitlab/database/migration_helpers_spec.rb | 106 +++++++++++++-------- 1 file changed, 64 insertions(+), 42 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 4ec3f19e03f..21d90e29cdb 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -91,63 +91,85 @@ describe Gitlab::Database::MigrationHelpers, lib: true do describe '#add_column_with_default' do context 'outside of a transaction' do - before do - expect(model).to receive(:transaction_open?).and_return(false) + context 'when a column limit is not set' do + before do + expect(model).to receive(:transaction_open?).and_return(false) - expect(model).to receive(:transaction).and_yield + expect(model).to receive(:transaction).and_yield - expect(model).to receive(:add_column). - with(:projects, :foo, :integer, default: nil) + expect(model).to receive(:add_column). + with(:projects, :foo, :integer, default: nil) - expect(model).to receive(:change_column_default). - with(:projects, :foo, 10) - end + expect(model).to receive(:change_column_default). + with(:projects, :foo, 10) + end - it 'adds the column while allowing NULL values' do - expect(model).to receive(:update_column_in_batches). - with(:projects, :foo, 10) + it 'adds the column while allowing NULL values' do + expect(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10) - expect(model).not_to receive(:change_column_null) + expect(model).not_to receive(:change_column_null) - model.add_column_with_default(:projects, :foo, :integer, - default: 10, - allow_null: true) - end + model.add_column_with_default(:projects, :foo, :integer, + default: 10, + allow_null: true) + end - it 'adds the column while not allowing NULL values' do - expect(model).to receive(:update_column_in_batches). - with(:projects, :foo, 10) + it 'adds the column while not allowing NULL values' do + expect(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10) - expect(model).to receive(:change_column_null). - with(:projects, :foo, false) + expect(model).to receive(:change_column_null). + with(:projects, :foo, false) - model.add_column_with_default(:projects, :foo, :integer, default: 10) - end + model.add_column_with_default(:projects, :foo, :integer, default: 10) + end - it 'removes the added column whenever updating the rows fails' do - expect(model).to receive(:update_column_in_batches). - with(:projects, :foo, 10). - and_raise(RuntimeError) + it 'removes the added column whenever updating the rows fails' do + expect(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10). + and_raise(RuntimeError) - expect(model).to receive(:remove_column). - with(:projects, :foo) + expect(model).to receive(:remove_column). + with(:projects, :foo) - expect do - model.add_column_with_default(:projects, :foo, :integer, default: 10) - end.to raise_error(RuntimeError) - end + expect do + model.add_column_with_default(:projects, :foo, :integer, default: 10) + end.to raise_error(RuntimeError) + end - it 'removes the added column whenever changing a column NULL constraint fails' do - expect(model).to receive(:change_column_null). - with(:projects, :foo, false). - and_raise(RuntimeError) + it 'removes the added column whenever changing a column NULL constraint fails' do + expect(model).to receive(:change_column_null). + with(:projects, :foo, false). + and_raise(RuntimeError) - expect(model).to receive(:remove_column). - with(:projects, :foo) + expect(model).to receive(:remove_column). + with(:projects, :foo) - expect do - model.add_column_with_default(:projects, :foo, :integer, default: 10) - end.to raise_error(RuntimeError) + expect do + model.add_column_with_default(:projects, :foo, :integer, default: 10) + end.to raise_error(RuntimeError) + end + end + + context 'when a column limit is set' do + it 'adds the column with a limit' do + allow(model).to receive(:transaction_open?).and_return(false) + allow(model).to receive(:transaction).and_yield + expect(model).to receive(:add_column). + with(:projects, :foo, :integer, default: nil, limit: 8) + allow(model).to receive(:update_column_in_batches). + with(:projects, :foo, 10) + allow(model).to receive(:change_column_null). + with(:projects, :foo, false) + allow(model).to receive(:change_column_default). + with(:projects, :foo, 10) + + expect(model).to receive(:add_column). + with(:projects, :foo, :integer, default: nil, limit: 8) + + model.add_column_with_default(:projects, :foo, :integer, default: 10, limit: 8) + end end end -- cgit v1.2.1 From 1f399fe437abc67e3f6d4812bab17f0ef0aab77b Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Thu, 15 Sep 2016 21:59:55 -0500 Subject: fix --- spec/lib/gitlab/database/migration_helpers_spec.rb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 21d90e29cdb..7fd25b9e5bf 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -156,14 +156,9 @@ describe Gitlab::Database::MigrationHelpers, lib: true do it 'adds the column with a limit' do allow(model).to receive(:transaction_open?).and_return(false) allow(model).to receive(:transaction).and_yield - expect(model).to receive(:add_column). - with(:projects, :foo, :integer, default: nil, limit: 8) - allow(model).to receive(:update_column_in_batches). - with(:projects, :foo, 10) - allow(model).to receive(:change_column_null). - with(:projects, :foo, false) - allow(model).to receive(:change_column_default). - with(:projects, :foo, 10) + allow(model).to receive(:update_column_in_batches).with(:projects, :foo, 10) + allow(model).to receive(:change_column_null).with(:projects, :foo, false) + allow(model).to receive(:change_column_default).with(:projects, :foo, 10) expect(model).to receive(:add_column). with(:projects, :foo, :integer, default: nil, limit: 8) -- cgit v1.2.1 From 73269b587cb3542a99a356984b3803d232d4b161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 16 Sep 2016 10:16:21 +0200 Subject: MergeRequest#environments now returns an empty array when diff_head_commit is nil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/models/merge_request_spec.rb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 3b815ded2d3..06feeb1bbba 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -703,16 +703,24 @@ describe MergeRequest, models: true do describe "#environments" do let(:project) { create(:project) } - let!(:environment) { create(:environment, project: project) } - let!(:environment1) { create(:environment, project: project) } - let!(:environment2) { create(:environment, project: project) } let(:merge_request) { create(:merge_request, source_project: project) } it 'selects deployed environments' do - create(:deployment, environment: environment, sha: project.commit('master').id) - create(:deployment, environment: environment1, sha: project.commit('feature').id) + environments = create_list(:environment, 3, project: project) + create(:deployment, environment: environments.first, sha: project.commit('master').id) + create(:deployment, environment: environments.second, sha: project.commit('feature').id) - expect(merge_request.environments).to eq [environment] + expect(merge_request.environments).to eq [environments.first] + end + + context 'without a diff_head_commit' do + before do + expect(merge_request).to receive(:diff_head_commit).and_return(nil) + end + + it 'returns an empty array' do + expect(merge_request.environments).to be_empty + end end end -- cgit v1.2.1 From e941365f3be88cebd57e9b08ba8702c1b688cb94 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Sep 2016 09:59:10 +0200 Subject: Rename capabilities to authentication_abilities --- spec/lib/gitlab/auth_spec.rb | 22 +++++++++++----------- spec/lib/gitlab/git_access_spec.rb | 20 ++++++++++---------- spec/lib/gitlab/git_access_wiki_spec.rb | 4 ++-- ...ntainer_registry_authentication_service_spec.rb | 18 ++++++++++++++---- 4 files changed, 37 insertions(+), 27 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index e24ad530904..744282b2afa 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -16,13 +16,13 @@ describe Gitlab::Auth, lib: true do end it 'recognises user-less build' do - expect(subject).to eq(Gitlab::Auth::Result.new(nil, build.project, :ci, build_capabilities)) + expect(subject).to eq(Gitlab::Auth::Result.new(nil, build.project, :ci, build_authentication_abilities)) end it 'recognises user token' do build.update(user: create(:user)) - expect(subject).to eq(Gitlab::Auth::Result.new(build.user, build.project, :build, build_capabilities)) + expect(subject).to eq(Gitlab::Auth::Result.new(build.user, build.project, :build, build_authentication_abilities)) end end @@ -48,7 +48,7 @@ describe Gitlab::Auth, lib: true do ip = 'ip' expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: 'drone-ci-token') - expect(gl_auth.find_for_git_client('drone-ci-token', 'token', project: project, ip: ip)).to eq(Gitlab::Auth::Result.new(nil, project, :ci, build_capabilities)) + expect(gl_auth.find_for_git_client('drone-ci-token', 'token', project: project, ip: ip)).to eq(Gitlab::Auth::Result.new(nil, project, :ci, build_authentication_abilities)) end it 'recognizes master passwords' do @@ -56,7 +56,7 @@ describe Gitlab::Auth, lib: true do ip = 'ip' expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username) - 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_capabilities)) + 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 @@ -65,7 +65,7 @@ describe Gitlab::Auth, lib: true do token = Gitlab::LfsToken.new(user).generate 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, read_capabilities)) + expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, nil, :lfs_token, read_authentication_abilities)) end it 'recognizes deploy key lfs tokens' do @@ -74,7 +74,7 @@ describe Gitlab::Auth, lib: true do token = Gitlab::LfsToken.new(key).generate 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_capabilities)) + 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 it 'recognizes OAuth tokens' do @@ -84,7 +84,7 @@ describe Gitlab::Auth, lib: true do ip = 'ip' 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_capabilities)) + 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)) end it 'returns double nil for invalid credentials' do @@ -149,7 +149,7 @@ describe Gitlab::Auth, lib: true do private - def build_capabilities + def build_authentication_abilities [ :read_project, :build_download_code, @@ -158,7 +158,7 @@ describe Gitlab::Auth, lib: true do ] end - def read_capabilities + def read_authentication_abilities [ :read_project, :download_code, @@ -166,8 +166,8 @@ describe Gitlab::Auth, lib: true do ] end - def full_capabilities - read_capabilities + [ + def full_authentication_abilities + read_authentication_abilities + [ :push_code, :update_container_image ] diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index c6fe56aac1c..ed43646330f 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper' describe Gitlab::GitAccess, lib: true do - let(:access) { Gitlab::GitAccess.new(actor, project, 'web', capabilities: capabilities) } + let(:access) { Gitlab::GitAccess.new(actor, project, 'web', authentication_abilities: authentication_abilities) } let(:project) { create(:project) } let(:user) { create(:user) } let(:actor) { user } - let(:capabilities) do + let(:authentication_abilities) do [ :read_project, :download_code, @@ -22,7 +22,7 @@ describe Gitlab::GitAccess, lib: true do context 'ssh disabled' do before do disable_protocol('ssh') - @acc = Gitlab::GitAccess.new(actor, project, 'ssh', capabilities: capabilities) + @acc = Gitlab::GitAccess.new(actor, project, 'ssh', authentication_abilities: authentication_abilities) end it 'blocks ssh git push' do @@ -37,7 +37,7 @@ describe Gitlab::GitAccess, lib: true do context 'http disabled' do before do disable_protocol('http') - @acc = Gitlab::GitAccess.new(actor, project, 'http', capabilities: capabilities) + @acc = Gitlab::GitAccess.new(actor, project, 'http', authentication_abilities: authentication_abilities) end it 'blocks http push' do @@ -119,8 +119,8 @@ describe Gitlab::GitAccess, lib: true do end end - describe 'build capabilities permissions' do - let(:capabilities) { build_capabilities } + describe 'build authentication_abilities permissions' do + let(:authentication_abilities) { build_authentication_abilities } describe 'reporter user' do before { project.team << [user, :reporter] } @@ -350,8 +350,8 @@ describe Gitlab::GitAccess, lib: true do end end - describe 'build capabilities permissions' do - let(:capabilities) { build_capabilities } + describe 'build authentication abilities' do + let(:authentication_abilities) { build_authentication_abilities } it_behaves_like 'can not push code' do def authorize @@ -373,14 +373,14 @@ describe Gitlab::GitAccess, lib: true do private - def build_capabilities + def build_authentication_abilities [ :read_project, :build_download_code ] end - def full_capabilities + def full_authentication_abilities [ :read_project, :download_code, diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 860e701c1a1..d05f0beb080 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' describe Gitlab::GitAccessWiki, lib: true do - let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web', capabilities: capabilities) } + let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web', authentication_abilities) } let(:project) { create(:project) } let(:user) { create(:user) } - let(:capabilities) do + let(:authentication_abilities) do [ :read_project, :download_code, diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index 2d39bd61b8f..c64df4979b0 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -6,14 +6,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do let(:current_params) { {} } let(:rsa_key) { OpenSSL::PKey::RSA.generate(512) } let(:payload) { JWT.decode(subject[:token], rsa_key).first } - let(:capabilities) do + let(:authentication_abilities) do [ :read_container_image, :create_container_image ] end - subject { described_class.new(current_project, current_user, current_params).execute(capabilities: capabilities) } + subject { described_class.new(current_project, current_user, current_params).execute(authentication_abilities: authentication_abilities) } before do allow(Gitlab.config.registry).to receive_messages(enabled: true, issuer: 'rspec', key: nil) @@ -198,7 +198,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do context 'build authorized as user' do let(:current_project) { create(:empty_project) } let(:current_user) { create(:user) } - let(:capabilities) do + let(:authentication_abilities) do [ :build_read_container_image, :build_create_container_image @@ -255,7 +255,17 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do context 'when you are admin' do let(:current_user) { create(:admin) } - it_behaves_like 'pullable for being team member' + context 'when you are not member' do + it_behaves_like 'an inaccessible' + end + + context 'when you are member' do + before do + project.team << [current_user, :developer] + end + + it_behaves_like 'a pullable' + end end end end -- cgit v1.2.1 From a387ff7ba85dc75608ae5347aa405ea30b4e8c8c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Sep 2016 11:06:31 +0200 Subject: Fix specs after renaming authentication_capabilities --- spec/lib/gitlab/auth_spec.rb | 22 ++++++++++++---------- spec/lib/gitlab/git_access_wiki_spec.rb | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 744282b2afa..d3707005a0e 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -26,16 +26,18 @@ describe Gitlab::Auth, lib: true do end end - context 'for non-running build' do - let!(:build) { create(:ci_build, :pending) } - let(:project) { build.project } - - before do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'gitlab-ci-token') - end - - it 'denies authentication' do - expect(subject).to eq(Gitlab::Auth::Result.new) + (HasStatus::AVAILABLE_STATUSES - [:running]).each do |build_status| + context "for #{build_status} build" do + let!(:build) { create(:ci_build, status: build_status) } + let(:project) { build.project } + + before do + expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'gitlab-ci-token') + end + + it 'denies authentication' do + expect(subject).not_to eq(Gitlab::Auth::Result.new) + end end end end diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index d05f0beb080..576cda595bb 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::GitAccessWiki, lib: true do - let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web', authentication_abilities) } + let(:access) { Gitlab::GitAccessWiki.new(user, project, 'web', authentication_abilities: authentication_abilities) } let(:project) { create(:project) } let(:user) { create(:user) } let(:authentication_abilities) do -- cgit v1.2.1 From 1954cb80fd168b7d7cd3a446782fdaf30d0b3f08 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Sep 2016 11:06:57 +0200 Subject: Added missing LFS specs --- spec/requests/lfs_http_spec.rb | 235 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 213 insertions(+), 22 deletions(-) (limited to 'spec') diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 8ead97efb01..cad8b914668 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -15,7 +15,6 @@ describe 'Git LFS API and storage' do let(:authorization) { } let(:sendfile) { } let(:pipeline) { create(:ci_empty_pipeline, project: project) } - let(:build) { create(:ci_build, :running, pipeline: pipeline) } let(:sample_oid) { lfs_object.oid } let(:sample_size) { lfs_object.size } @@ -258,14 +257,63 @@ describe 'Git LFS API and storage' do it_behaves_like 'responds with a file' end - context 'when build is authorized' do + context 'when build is authorized as' do let(:authorization) { authorize_ci_project } - let(:update_permissions) do - project.lfs_objects << lfs_object + shared_examples 'can download LFS only from own projects' do + context 'for own project' do + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + + let(:update_permissions) do + project.team << [user, :reporter] + project.lfs_objects << lfs_object + end + + it_behaves_like 'responds with a file' + end + + context 'for other project' do + let(:other_project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } + + let(:update_permissions) do + project.lfs_objects << lfs_object + end + + it 'rejects downloading code' do + expect(response).to have_http_status(other_project_status) + end + end end - it_behaves_like 'responds with a file' + context 'administrator' do + let(:user) { create(:admin) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it_behaves_like 'can download LFS only from own projects' do + # We render 403, because administrator does have normally access + let(:other_project_status) { 403 } + end + end + + context 'regular user' do + let(:user) { create(:user) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it_behaves_like 'can download LFS only from own projects' do + # We render 404, to prevent data leakage about existence of the project + let(:other_project_status) { 404 } + end + end + + context 'does not have user' do + let(:build) { create(:ci_build, :running, pipeline: pipeline) } + + it_behaves_like 'can download LFS only from own projects' do + # We render 401, to prevent data leakage about existence of the project + let(:other_project_status) { 401 } + end + end end end @@ -445,10 +493,62 @@ describe 'Git LFS API and storage' do end end - context 'when CI is authorized' do + context 'when build is authorized as' do let(:authorization) { authorize_ci_project } - it_behaves_like 'an authorized requests' + let(:update_lfs_permissions) do + project.lfs_objects << lfs_object + end + + shared_examples 'can download LFS only from own projects' do + context 'for own project' do + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + + let(:update_user_permissions) do + project.team << [user, :reporter] + end + + it_behaves_like 'an authorized requests' + end + + context 'for other project' do + let(:other_project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } + + it 'rejects downloading code' do + expect(response).to have_http_status(other_project_status) + end + end + end + + context 'administrator' do + let(:user) { create(:admin) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it_behaves_like 'can download LFS only from own projects' do + # We render 403, because administrator does have normally access + let(:other_project_status) { 403 } + end + end + + context 'regular user' do + let(:user) { create(:user) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it_behaves_like 'can download LFS only from own projects' do + # We render 404, to prevent data leakage about existence of the project + let(:other_project_status) { 404 } + end + end + + context 'does not have user' do + let(:build) { create(:ci_build, :running, pipeline: pipeline) } + + it_behaves_like 'can download LFS only from own projects' do + # We render 401, to prevent data leakage about existence of the project + let(:other_project_status) { 401 } + end + end end context 'when user is not authenticated' do @@ -597,11 +697,37 @@ describe 'Git LFS API and storage' do end end - context 'when CI is authorized' do + context 'when build is authorized' do let(:authorization) { authorize_ci_project } - it 'responds with 401' do - expect(response).to have_http_status(401) + context 'build has an user' do + let(:user) { create(:user) } + + context 'tries to push to own project' do + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it 'responds with 403' do + expect(response).to have_http_status(403) + end + end + + context 'tries to push to other project' do + let(:other_project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it 'responds with 403' do + expect(response).to have_http_status(403) + end + end + end + + context 'does not have user' do + let(:build) { create(:ci_build, :running, pipeline: pipeline) } + + it 'responds with 401' do + expect(response).to have_http_status(401) + end end end end @@ -623,14 +749,6 @@ describe 'Git LFS API and storage' do end end end - - context 'when CI is authorized' do - let(:authorization) { authorize_ci_project } - - it 'responds with status 401' do - expect(response).to have_http_status(401) - end - end end describe 'unsupported' do @@ -793,10 +911,51 @@ describe 'Git LFS API and storage' do end end - context 'when CI is authenticated' do + context 'when build is authorized' do let(:authorization) { authorize_ci_project } - it_behaves_like 'unauthorized' + context 'build has an user' do + let(:user) { create(:user) } + + context 'tries to push to own project' do + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + before do + project.team << [user, :developer] + put_authorize + end + + it 'responds with 403' do + expect(response).to have_http_status(403) + end + end + + context 'tries to push to other project' do + let(:other_project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + before do + put_authorize + end + + it 'responds with 404' do + expect(response).to have_http_status(404) + end + end + end + + context 'does not have user' do + let(:build) { create(:ci_build, :running, pipeline: pipeline) } + + before do + put_authorize + end + + it 'responds with 401' do + expect(response).to have_http_status(401) + end + end end context 'for unauthenticated' do @@ -853,10 +1012,42 @@ describe 'Git LFS API and storage' do end end - context 'when CI is authenticated' do + context 'when build is authorized' do let(:authorization) { authorize_ci_project } - it_behaves_like 'unauthorized' + before do + put_authorize + end + + context 'build has an user' do + let(:user) { create(:user) } + + context 'tries to push to own project' do + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it 'responds with 403' do + expect(response).to have_http_status(403) + end + end + + context 'tries to push to other project' do + let(:other_project) { create(:empty_project) } + let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } + let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } + + it 'responds with 403' do + expect(response).to have_http_status(403) + end + end + end + + context 'does not have user' do + let(:build) { create(:ci_build, :running, pipeline: pipeline) } + + it 'responds with 401' do + expect(response).to have_http_status(401) + end + end end context 'for unauthenticated' do -- cgit v1.2.1 From 67ec96e3e0ea9d25356ed3de0be12c0d92ed6d16 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 16 Sep 2016 11:43:05 +0200 Subject: Strip comments before sending keys to gitlab-shell Avoid issues with text encoding by not sending out non-7-bit ASCII text. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/22167 --- spec/lib/gitlab/backend/shell_spec.rb | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index 6e5ba211382..07407f212aa 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'stringio' describe Gitlab::Shell, lib: true do let(:project) { double('Project', id: 7, path: 'diaspora') } @@ -44,15 +45,38 @@ describe Gitlab::Shell, lib: true do end end + describe '#add_key' do + it 'removes trailing garbage' do + allow(gitlab_shell).to receive(:gitlab_shell_keys_path).and_return(:gitlab_shell_keys_path) + expect(Gitlab::Utils).to receive(:system_silent).with( + [:gitlab_shell_keys_path, 'add-key', 'key-123', 'ssh-rsa foobar'] + ) + + gitlab_shell.add_key('key-123', 'ssh-rsa foobar trailing garbage') + end + end + describe Gitlab::Shell::KeyAdder, lib: true do describe '#add_key' do - it 'normalizes space characters in the key' do - io = spy + it 'removes trailing garbage' do + io = spy(:io) adder = described_class.new(io) - adder.add_key('key-42', "sha-rsa foo\tbar\tbaz") + adder.add_key('key-42', "ssh-rsa foo bar\tbaz") + + expect(io).to have_received(:puts).with("key-42\tssh-rsa foo") + end + + it 'raises an exception if the key contains a tab' do + expect do + described_class.new(StringIO.new).add_key('key-42', "ssh-rsa\tfoobar") + end.to raise_error(Gitlab::Shell::Error) + end - expect(io).to have_received(:puts).with("key-42\tsha-rsa foo bar baz") + it 'raises an exception if the key contains a newline' do + expect do + described_class.new(StringIO.new).add_key('key-42', "ssh-rsa foobar\nssh-rsa pawned") + end.to raise_error(Gitlab::Shell::Error) end end end -- cgit v1.2.1 From a5035ed3108e4c335382c44b24470e4a564270e4 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 5 Sep 2016 16:38:19 +0100 Subject: Correctly loads gfm autocomplete source on pages where it is required --- .../projects/gfm_autocomplete_load_spec.rb | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spec/features/projects/gfm_autocomplete_load_spec.rb (limited to 'spec') diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb new file mode 100644 index 00000000000..18cf2f9d1fb --- /dev/null +++ b/spec/features/projects/gfm_autocomplete_load_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe 'GFM autocomplete loading', feature: true, js: true do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + project.team << [user, :master] + login_as user + + visit namespace_project_path(project.namespace, project) + end + + it 'does not load on project#show' do + expect(evaluate_script('GitLab.GfmAutoComplete.dataSource')).to eq('') + end + + it 'loads on new issue page' do + visit new_namespace_project_issue_path(project.namespace, project) + + expect(evaluate_script('GitLab.GfmAutoComplete.dataSource')).not_to eq('') + end +end -- cgit v1.2.1 From 9c5638fb5b5d28e081d5859baa0e926cf92599d7 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 7 Sep 2016 09:13:40 +0100 Subject: Use admin user in tests --- spec/features/projects/gfm_autocomplete_load_spec.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/gfm_autocomplete_load_spec.rb b/spec/features/projects/gfm_autocomplete_load_spec.rb index 18cf2f9d1fb..1921ea6d8ae 100644 --- a/spec/features/projects/gfm_autocomplete_load_spec.rb +++ b/spec/features/projects/gfm_autocomplete_load_spec.rb @@ -1,12 +1,10 @@ require 'spec_helper' describe 'GFM autocomplete loading', feature: true, js: true do - let(:user) { create(:user) } let(:project) { create(:project) } before do - project.team << [user, :master] - login_as user + login_as :admin visit namespace_project_path(project.namespace, project) end -- cgit v1.2.1 From f7ae37c1d092f89cd9b9dc24be95670abed16ffc Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Sep 2016 13:34:05 +0200 Subject: Simplify checking of allowed abilities in git_http_client_controller --- spec/requests/git_http_spec.rb | 2 +- spec/requests/lfs_http_spec.rb | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'spec') diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 0311755dd06..f828e898740 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -346,7 +346,7 @@ describe 'Git HTTP requests', lib: true do it 'uploads get status 403' do push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - expect(response).to have_http_status(403) + expect(response).to have_http_status(401) end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index cad8b914668..09e4e265dd1 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -310,8 +310,8 @@ describe 'Git LFS API and storage' do let(:build) { create(:ci_build, :running, pipeline: pipeline) } it_behaves_like 'can download LFS only from own projects' do - # We render 401, to prevent data leakage about existence of the project - let(:other_project_status) { 401 } + # We render 404, to prevent data leakage about existence of the project + let(:other_project_status) { 404 } end end end @@ -545,8 +545,8 @@ describe 'Git LFS API and storage' do let(:build) { create(:ci_build, :running, pipeline: pipeline) } it_behaves_like 'can download LFS only from own projects' do - # We render 401, to prevent data leakage about existence of the project - let(:other_project_status) { 401 } + # We render 404, to prevent data leakage about existence of the project + let(:other_project_status) { 404 } end end end @@ -706,8 +706,8 @@ describe 'Git LFS API and storage' do context 'tries to push to own project' do let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } - it 'responds with 403' do - expect(response).to have_http_status(403) + it 'responds with 401' do + expect(response).to have_http_status(401) end end @@ -716,8 +716,8 @@ describe 'Git LFS API and storage' do let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } - it 'responds with 403' do - expect(response).to have_http_status(403) + it 'responds with 401' do + expect(response).to have_http_status(401) end end end @@ -925,8 +925,8 @@ describe 'Git LFS API and storage' do put_authorize end - it 'responds with 403' do - expect(response).to have_http_status(403) + it 'responds with 401' do + expect(response).to have_http_status(401) end end @@ -939,8 +939,8 @@ describe 'Git LFS API and storage' do put_authorize end - it 'responds with 404' do - expect(response).to have_http_status(404) + it 'responds with 401' do + expect(response).to have_http_status(401) end end end @@ -1025,8 +1025,8 @@ describe 'Git LFS API and storage' do context 'tries to push to own project' do let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } - it 'responds with 403' do - expect(response).to have_http_status(403) + it 'responds with 401' do + expect(response).to have_http_status(401) end end @@ -1035,8 +1035,8 @@ describe 'Git LFS API and storage' do let(:pipeline) { create(:ci_empty_pipeline, project: other_project) } let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) } - it 'responds with 403' do - expect(response).to have_http_status(403) + it 'responds with 401' do + expect(response).to have_http_status(401) end end end -- cgit v1.2.1 From 8b2dbe8997636a57ed6cf02a3be7f113d7a29f04 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 16 Sep 2016 14:37:48 +0300 Subject: Remove schema annotations completely --- spec/factories/ci/runner_projects.rb | 11 ----------- spec/factories/ci/runners.rb | 19 ------------------- spec/factories/ci/variables.rb | 14 -------------- spec/factories/group_members.rb | 13 ------------- spec/models/hooks/project_hook_spec.rb | 18 ------------------ spec/models/hooks/service_hook_spec.rb | 18 ------------------ spec/models/hooks/system_hook_spec.rb | 20 +------------------- spec/models/hooks/web_hook_spec.rb | 18 ------------------ spec/models/members/group_member_spec.rb | 19 ------------------- spec/models/members/project_member_spec.rb | 19 ------------------- spec/models/project_services/asana_service_spec.rb | 20 -------------------- .../project_services/assembla_service_spec.rb | 20 -------------------- spec/models/project_services/bamboo_service_spec.rb | 20 -------------------- .../project_services/bugzilla_service_spec.rb | 20 -------------------- .../project_services/buildkite_service_spec.rb | 20 -------------------- .../project_services/campfire_service_spec.rb | 20 -------------------- .../custom_issue_tracker_service_spec.rb | 20 -------------------- .../project_services/drone_ci_service_spec.rb | 20 -------------------- .../project_services/external_wiki_service_spec.rb | 21 --------------------- .../project_services/flowdock_service_spec.rb | 20 -------------------- .../project_services/gemnasium_service_spec.rb | 20 -------------------- .../gitlab_issue_tracker_service_spec.rb | 20 -------------------- .../models/project_services/hipchat_service_spec.rb | 20 -------------------- spec/models/project_services/irker_service_spec.rb | 20 -------------------- spec/models/project_services/jira_service_spec.rb | 20 -------------------- .../project_services/pivotaltracker_service_spec.rb | 20 -------------------- .../project_services/pushover_service_spec.rb | 20 -------------------- .../models/project_services/redmine_service_spec.rb | 20 -------------------- spec/models/project_services/slack_service_spec.rb | 20 -------------------- .../project_services/teamcity_service_spec.rb | 20 -------------------- 30 files changed, 1 insertion(+), 569 deletions(-) (limited to 'spec') diff --git a/spec/factories/ci/runner_projects.rb b/spec/factories/ci/runner_projects.rb index 83fccad679f..3372e5ab685 100644 --- a/spec/factories/ci/runner_projects.rb +++ b/spec/factories/ci/runner_projects.rb @@ -1,14 +1,3 @@ -# == Schema Information -# -# Table name: runner_projects -# -# id :integer not null, primary key -# runner_id :integer not null -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# - FactoryGirl.define do factory :ci_runner_project, class: Ci::RunnerProject do runner_id 1 diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb index 45eaebb2576..e3b73e29987 100644 --- a/spec/factories/ci/runners.rb +++ b/spec/factories/ci/runners.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: runners -# -# id :integer not null, primary key -# token :string(255) -# created_at :datetime -# updated_at :datetime -# description :string(255) -# contacted_at :datetime -# active :boolean default(TRUE), not null -# is_shared :boolean default(FALSE) -# name :string(255) -# version :string(255) -# revision :string(255) -# platform :string(255) -# architecture :string(255) -# - FactoryGirl.define do factory :ci_runner, class: Ci::Runner do sequence :description do |n| diff --git a/spec/factories/ci/variables.rb b/spec/factories/ci/variables.rb index 856a8e725eb..6653f0bb5c3 100644 --- a/spec/factories/ci/variables.rb +++ b/spec/factories/ci/variables.rb @@ -1,17 +1,3 @@ -# == Schema Information -# -# Table name: ci_variables -# -# id :integer not null, primary key -# project_id :integer not null -# key :string(255) -# value :text -# encrypted_value :text -# encrypted_value_salt :string(255) -# encrypted_value_iv :string(255) -# gl_project_id :integer -# - FactoryGirl.define do factory :ci_variable, class: Ci::Variable do sequence(:key) { |n| "VARIABLE_#{n}" } diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb index debb86d997f..2044ebec09a 100644 --- a/spec/factories/group_members.rb +++ b/spec/factories/group_members.rb @@ -1,16 +1,3 @@ -# == Schema Information -# -# Table name: group_members -# -# id :integer not null, primary key -# group_access :integer not null -# group_id :integer not null -# user_id :integer not null -# created_at :datetime -# updated_at :datetime -# notification_level :integer default(3), not null -# - FactoryGirl.define do factory :group_member do access_level { GroupMember::OWNER } diff --git a/spec/models/hooks/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb index 4a457997a4f..474ae62ccec 100644 --- a/spec/models/hooks/project_hook_spec.rb +++ b/spec/models/hooks/project_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require 'spec_helper' describe ProjectHook, models: true do diff --git a/spec/models/hooks/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb index 534e1b4f128..1a83c836652 100644 --- a/spec/models/hooks/service_hook_spec.rb +++ b/spec/models/hooks/service_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require "spec_helper" describe ServiceHook, models: true do diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index cbdf7eec082..ad2b710041a 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require "spec_helper" describe SystemHook, models: true do @@ -48,7 +30,7 @@ describe SystemHook, models: true do it "user_create hook" do create(:user) - + expect(WebMock).to have_requested(:post, system_hook.url).with( body: /user_create/, headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index f9bab487b96..e52b9d75cef 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -1,21 +1,3 @@ -# == Schema Information -# -# Table name: web_hooks -# -# id :integer not null, primary key -# url :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# type :string(255) default("ProjectHook") -# service_id :integer -# push_events :boolean default(TRUE), not null -# issues_events :boolean default(FALSE), not null -# merge_requests_events :boolean default(FALSE), not null -# tag_push_events :boolean default(FALSE) -# note_events :boolean default(FALSE), not null -# - require 'spec_helper' describe WebHook, models: true do diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index 4f875fd257a..56fa7fa6134 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string(255) not null -# user_id :integer -# notification_level :integer not null -# type :string(255) -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string(255) -# invite_token :string(255) -# invite_accepted_at :datetime -# - require 'spec_helper' describe GroupMember, models: true do diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index be57957b569..805c15a4e5e 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -1,22 +1,3 @@ -# == Schema Information -# -# Table name: members -# -# id :integer not null, primary key -# access_level :integer not null -# source_id :integer not null -# source_type :string(255) not null -# user_id :integer -# notification_level :integer not null -# type :string(255) -# created_at :datetime -# updated_at :datetime -# created_by_id :integer -# invite_email :string(255) -# invite_token :string(255) -# invite_accepted_at :datetime -# - require 'spec_helper' describe ProjectMember, models: true do diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb index dc702cfc42c..8e5145e824b 100644 --- a/spec/models/project_services/asana_service_spec.rb +++ b/spec/models/project_services/asana_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe AsanaService, models: true do diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb index d672d80156c..4c5acb7990b 100644 --- a/spec/models/project_services/assembla_service_spec.rb +++ b/spec/models/project_services/assembla_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe AssemblaService, models: true do diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb index 9ae461f8c2d..d7e1a4e3b6c 100644 --- a/spec/models/project_services/bamboo_service_spec.rb +++ b/spec/models/project_services/bamboo_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe BambooService, models: true do diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb index a6d9717ccb5..739cc72b2ff 100644 --- a/spec/models/project_services/bugzilla_service_spec.rb +++ b/spec/models/project_services/bugzilla_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe BugzillaService, models: true do diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb index 0866e1532dd..6f65beb79d0 100644 --- a/spec/models/project_services/buildkite_service_spec.rb +++ b/spec/models/project_services/buildkite_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe BuildkiteService, models: true do diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb index c76ae21421b..a3b9d084a75 100644 --- a/spec/models/project_services/campfire_service_spec.rb +++ b/spec/models/project_services/campfire_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe CampfireService, models: true do diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb index ff976f8ec59..7020667ea58 100644 --- a/spec/models/project_services/custom_issue_tracker_service_spec.rb +++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe CustomIssueTrackerService, models: true do diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb index 8ef892259f2..f13bb1e8adf 100644 --- a/spec/models/project_services/drone_ci_service_spec.rb +++ b/spec/models/project_services/drone_ci_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe DroneCiService, models: true do diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb index d7c5ea95d71..342d86aeca9 100644 --- a/spec/models/project_services/external_wiki_service_spec.rb +++ b/spec/models/project_services/external_wiki_service_spec.rb @@ -1,24 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# build_events :boolean default(FALSE), not null -# - require 'spec_helper' describe ExternalWikiService, models: true do diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb index d2557019756..d6db02d6e76 100644 --- a/spec/models/project_services/flowdock_service_spec.rb +++ b/spec/models/project_services/flowdock_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe FlowdockService, models: true do diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb index 3d0b6c9816b..529044d1d8b 100644 --- a/spec/models/project_services/gemnasium_service_spec.rb +++ b/spec/models/project_services/gemnasium_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe GemnasiumService, models: true do diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index 8ef79a17d50..652804fb444 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe GitlabIssueTrackerService, models: true do diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 34eafbe555d..cf713684463 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe HipchatService, models: true do diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb index ffb17fd3259..f8c45b37561 100644 --- a/spec/models/project_services/irker_service_spec.rb +++ b/spec/models/project_services/irker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' require 'socket' require 'json' diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 9037ca5cc20..b48a3176007 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe JiraService, models: true do diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb index d098d988521..45b2f1068bf 100644 --- a/spec/models/project_services/pivotaltracker_service_spec.rb +++ b/spec/models/project_services/pivotaltracker_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe PivotaltrackerService, models: true do diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb index 5959c81577d..8fc92a9ab51 100644 --- a/spec/models/project_services/pushover_service_spec.rb +++ b/spec/models/project_services/pushover_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe PushoverService, models: true do diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb index 7d14f6e8280..b8679cd2563 100644 --- a/spec/models/project_services/redmine_service_spec.rb +++ b/spec/models/project_services/redmine_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe RedmineService, models: true do diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index 5afdc4b2f7b..c07a70a8069 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe SlackService, models: true do diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb index 474715d24c3..f7e878844dc 100644 --- a/spec/models/project_services/teamcity_service_spec.rb +++ b/spec/models/project_services/teamcity_service_spec.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - require 'spec_helper' describe TeamcityService, models: true do -- cgit v1.2.1 From b0195d5c55d913dd62cb01b553b045f2681e7eb7 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Sep 2016 13:47:54 +0200 Subject: Fix specs for available statuses --- spec/lib/gitlab/auth_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index d3707005a0e..1af5abe9f15 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -26,7 +26,7 @@ describe Gitlab::Auth, lib: true do end end - (HasStatus::AVAILABLE_STATUSES - [:running]).each do |build_status| + (HasStatus::AVAILABLE_STATUSES - ['running']).each do |build_status| context "for #{build_status} build" do let!(:build) { create(:ci_build, status: build_status) } let(:project) { build.project } @@ -36,7 +36,7 @@ describe Gitlab::Auth, lib: true do end it 'denies authentication' do - expect(subject).not_to eq(Gitlab::Auth::Result.new) + expect(subject).to eq(Gitlab::Auth::Result.new) end end end -- cgit v1.2.1 From 2742f9fb98babc0009e446d291757ae43c54c101 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 16 Sep 2016 16:07:21 +0200 Subject: Improve authentication_result usage --- spec/requests/git_http_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index f828e898740..e3922bec689 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -322,10 +322,10 @@ describe 'Git HTTP requests', lib: true do expect(response).to have_http_status(401) end - it "downloads from other project get status 401" do + it "downloads from other project get status 404" do clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - expect(response).to have_http_status(401) + expect(response).to have_http_status(404) end end -- cgit v1.2.1 From cf00fbecc544dfd2d597ae89c5ecbae1b6842932 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 16 Sep 2016 14:30:28 +0200 Subject: Fix API notes endpoint when posting only emoji --- spec/requests/api/notes_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 223444ea39f..063a8706e76 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -220,6 +220,15 @@ describe API::API, api: true do expect(Time.parse(json_response['created_at'])).to be_within(1.second).of(creation_time) end end + + context 'when the user is posting an award emoji' do + it 'returns an award emoji' do + post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: ':+1:' + + expect(response).to have_http_status(201) + expect(json_response['awardable_id']).to eq issue.id + end + end end context "when noteable is a Snippet" do -- cgit v1.2.1 From d8dd1c1940c929eab324951e3c302d197c5f0dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 15 Sep 2016 18:34:57 +0200 Subject: Ensure invitees are not returned in Members API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/members_spec.rb | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index 1e365bf353a..b9cf348bbf0 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -30,20 +30,27 @@ describe API::Members, api: true do let(:route) { get api("/#{source_type.pluralize}/#{source.id}/members", stranger) } end - context 'when authenticated as a non-member' do - %i[access_requester stranger].each do |type| - context "as a #{type}" do - it 'returns 200' do - user = public_send(type) - get api("/#{source_type.pluralize}/#{source.id}/members", user) + %i[master developer access_requester stranger].each do |type| + context "when authenticated as a #{type}" do + it 'returns 200' do + user = public_send(type) + get api("/#{source_type.pluralize}/#{source.id}/members", user) - expect(response).to have_http_status(200) - expect(json_response.size).to eq(2) - end + expect(response).to have_http_status(200) + expect(json_response.size).to eq(2) end end end + it 'does not return invitees' do + invitee = create(:"#{source_type}_member", invite_token: '123', invite_email: 'test@abc.com', source: source, user: nil) + + get api("/#{source_type.pluralize}/#{source.id}/members", developer) + + expect(response).to have_http_status(200) + expect(json_response.size).to eq(2) + end + it 'finds members with query string' do get api("/#{source_type.pluralize}/#{source.id}/members", developer), query: master.username -- cgit v1.2.1 From c054254f1e5038f85e407317e63a7bcb45368125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 16 Sep 2016 10:30:16 +0200 Subject: Better assertion in API members specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/members_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index b9cf348bbf0..92032f09b17 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -38,17 +38,19 @@ describe API::Members, api: true do expect(response).to have_http_status(200) expect(json_response.size).to eq(2) + expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id] end end end it 'does not return invitees' do - invitee = create(:"#{source_type}_member", invite_token: '123', invite_email: 'test@abc.com', source: source, user: nil) + create(:"#{source_type}_member", invite_token: '123', invite_email: 'test@abc.com', source: source, user: nil) get api("/#{source_type.pluralize}/#{source.id}/members", developer) expect(response).to have_http_status(200) expect(json_response.size).to eq(2) + expect(json_response.map { |u| u['id'] }).to match_array [master.id, developer.id] end it 'finds members with query string' do -- cgit v1.2.1 From a147b43dcce7da64512efed392041c37ef45851c Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 13 Sep 2016 21:43:25 -0500 Subject: Replace contributions calendar timezone payload with dates --- spec/features/calendar_spec.rb | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 spec/features/calendar_spec.rb (limited to 'spec') diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb new file mode 100644 index 00000000000..fd5fbaf2af4 --- /dev/null +++ b/spec/features/calendar_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +feature 'Contributions Calendar', js: true, feature: true do + include WaitForAjax + + let(:contributed_project) { create(:project, :public) } + + before do + login_as :user + + issue_params = { title: 'Bug in old browser' } + Issues::CreateService.new(contributed_project, @user, issue_params).execute + + # Push code contribution + push_params = { + project: contributed_project, + action: Event::PUSHED, + author_id: @user.id, + data: { commit_count: 3 } + } + + Event.create(push_params) + + visit @user.username + wait_for_ajax + end + + it 'displays calendar', js: true do + expect(page).to have_css('.js-contrib-calendar') + end + + it 'displays calendar activity log', js: true do + expect(find('.content_list .event-note')).to have_content "Bug in old browser" + end + + it 'displays calendar activity square color', js: true do + expect(page).to have_selector('.user-contrib-cell[fill=\'#acd5f2\']', count: 1) + end +end -- cgit v1.2.1 From c0a7eb3809ba8031ee8afc84fd1b66f8ed68a5af Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 4 Sep 2016 11:05:26 -0700 Subject: Refactor boards_spec.rb to avoid code duplication Originally created to address #21197, but !6224 solved the intermittent spec failures. --- spec/features/boards/boards_spec.rb | 177 +++++++++++++++--------------------- 1 file changed, 72 insertions(+), 105 deletions(-) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index e51586d32ec..19941978c5f 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -94,15 +94,8 @@ describe 'Issue Boards', feature: true, js: true do end it 'shows issues in lists' do - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('2') - expect(page).to have_selector('.card', count: 2) - end - - page.within(find('.board:nth-child(3)')) do - expect(page.find('.board-header')).to have_content('2') - expect(page).to have_selector('.card', count: 2) - end + wait_for_board_cards(2, 2) + wait_for_board_cards(3, 2) end it 'shows confidential issues with icon' do @@ -203,37 +196,33 @@ describe 'Issue Boards', feature: true, js: true do context 'backlog' do it 'shows issues in backlog with no labels' do - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('6') - expect(page).to have_selector('.card', count: 6) - end + wait_for_board_cards(1, 6) end it 'moves issue from backlog into list' do drag_to(list_to_index: 1) - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('5') - expect(page).to have_selector('.card', count: 5) - end - wait_for_vue_resource - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('3') - expect(page).to have_selector('.card', count: 3) - end + wait_for_board_cards(1, 5) + wait_for_board_cards(2, 3) end end context 'done' do it 'shows list of done issues' do - expect(find('.board:nth-child(4)')).to have_selector('.card', count: 1) + wait_for_board_cards(4, 1) + wait_for_ajax end it 'moves issue to done' do drag_to(list_from_index: 0, list_to_index: 3) + wait_for_board_cards(1, 5) + wait_for_board_cards(2, 2) + wait_for_board_cards(3, 2) + wait_for_board_cards(4, 2) + + expect(find('.board:nth-child(1)')).not_to have_content(issue9.title) expect(find('.board:nth-child(4)')).to have_selector('.card', count: 2) expect(find('.board:nth-child(4)')).to have_content(issue9.title) expect(find('.board:nth-child(4)')).not_to have_content(planning.title) @@ -242,8 +231,12 @@ describe 'Issue Boards', feature: true, js: true do it 'removes all of the same issue to done' do drag_to(list_from_index: 1, list_to_index: 3) - expect(find('.board:nth-child(2)')).to have_selector('.card', count: 1) - expect(find('.board:nth-child(3)')).to have_selector('.card', count: 1) + wait_for_board_cards(1, 6) + wait_for_board_cards(2, 1) + wait_for_board_cards(3, 1) + wait_for_board_cards(4, 2) + + expect(find('.board:nth-child(2)')).not_to have_content(issue6.title) expect(find('.board:nth-child(4)')).to have_content(issue6.title) expect(find('.board:nth-child(4)')).not_to have_content(planning.title) end @@ -253,6 +246,11 @@ describe 'Issue Boards', feature: true, js: true do it 'changes position of list' do drag_to(list_from_index: 1, list_to_index: 2, selector: '.board-header') + wait_for_board_cards(1, 6) + wait_for_board_cards(2, 2) + wait_for_board_cards(3, 2) + wait_for_board_cards(4, 1) + expect(find('.board:nth-child(2)')).to have_content(development.title) expect(find('.board:nth-child(2)')).to have_content(planning.title) end @@ -260,8 +258,11 @@ describe 'Issue Boards', feature: true, js: true do it 'issue moves between lists' do drag_to(list_from_index: 1, card_index: 1, list_to_index: 2) - expect(find('.board:nth-child(2)')).to have_selector('.card', count: 1) - expect(find('.board:nth-child(3)')).to have_selector('.card', count: 3) + wait_for_board_cards(1, 6) + wait_for_board_cards(2, 1) + wait_for_board_cards(3, 3) + wait_for_board_cards(4, 1) + expect(find('.board:nth-child(3)')).to have_content(issue6.title) expect(find('.board:nth-child(3)').all('.card').last).not_to have_content(development.title) end @@ -269,8 +270,11 @@ describe 'Issue Boards', feature: true, js: true do it 'issue moves between lists' do drag_to(list_from_index: 2, list_to_index: 1) - expect(find('.board:nth-child(2)')).to have_selector('.card', count: 3) - expect(find('.board:nth-child(3)')).to have_selector('.card', count: 1) + wait_for_board_cards(1, 6) + wait_for_board_cards(2, 3) + wait_for_board_cards(3, 1) + wait_for_board_cards(4, 1) + expect(find('.board:nth-child(2)')).to have_content(issue7.title) expect(find('.board:nth-child(2)').all('.card').first).not_to have_content(planning.title) end @@ -278,8 +282,12 @@ describe 'Issue Boards', feature: true, js: true do it 'issue moves from done' do drag_to(list_from_index: 3, list_to_index: 1) - expect(find('.board:nth-child(2)')).to have_selector('.card', count: 3) expect(find('.board:nth-child(2)')).to have_content(issue8.title) + + wait_for_board_cards(1, 6) + wait_for_board_cards(2, 3) + wait_for_board_cards(3, 2) + wait_for_board_cards(4, 0) end context 'issue card' do @@ -342,10 +350,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'moves issues from backlog into new list' do - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('6') - expect(page).to have_selector('.card', count: 6) - end + wait_for_board_cards(1, 6) click_button 'Create new list' wait_for_ajax @@ -356,10 +361,7 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('5') - expect(page).to have_selector('.card', count: 5) - end + wait_for_board_cards(1, 5) end end end @@ -379,16 +381,8 @@ describe 'Issue Boards', feature: true, js: true do end wait_for_vue_resource - - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('1') - expect(page).to have_selector('.card', count: 1) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end + wait_for_board_cards(1, 1) + wait_for_empty_boards((2..4)) end it 'filters by assignee' do @@ -406,15 +400,8 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('1') - expect(page).to have_selector('.card', count: 1) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end + wait_for_board_cards(1, 1) + wait_for_empty_boards((2..4)) end it 'filters by milestone' do @@ -431,16 +418,10 @@ describe 'Issue Boards', feature: true, js: true do end wait_for_vue_resource - - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('1') - expect(page).to have_selector('.card', count: 1) - end + wait_for_board_cards(1, 0) + wait_for_board_cards(2, 1) + wait_for_board_cards(3, 0) + wait_for_board_cards(4, 0) end it 'filters by label' do @@ -456,16 +437,8 @@ describe 'Issue Boards', feature: true, js: true do end wait_for_vue_resource - - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('1') - expect(page).to have_selector('.card', count: 1) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end + wait_for_board_cards(1, 1) + wait_for_empty_boards((2..4)) end it 'infinite scrolls list with label filter' do @@ -519,15 +492,8 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('1') - expect(page).to have_selector('.card', count: 1) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end + wait_for_board_cards(1, 1) + wait_for_empty_boards((2..4)) end it 'filters by no label' do @@ -544,15 +510,10 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('5') - expect(page).to have_selector('.card', count: 5) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end + wait_for_board_cards(1, 5) + wait_for_board_cards(2, 0) + wait_for_board_cards(3, 0) + wait_for_board_cards(4, 1) end it 'filters by clicking label button on issue' do @@ -565,15 +526,8 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource - page.within(find('.board', match: :first)) do - expect(page.find('.board-header')).to have_content('1') - expect(page).to have_selector('.card', count: 1) - end - - page.within(find('.board:nth-child(2)')) do - expect(page.find('.board-header')).to have_content('0') - expect(page).to have_selector('.card', count: 0) - end + wait_for_board_cards(1, 1) + wait_for_empty_boards((2..4)) page.within('.labels-filter') do expect(find('.dropdown-toggle-text')).to have_content(bug.title) @@ -648,4 +602,17 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource end + + def wait_for_board_cards(board_number, expected_cards) + page.within(find(".board:nth-child(#{board_number})")) do + expect(page.find('.board-header')).to have_content(expected_cards.to_s) + expect(page).to have_selector('.card', count: expected_cards) + end + end + + def wait_for_empty_boards(board_numbers) + board_numbers.each do |board| + wait_for_board_cards(board, 0) + end + end end -- cgit v1.2.1 From b1a4d94091b87ca0a8d36a7b75095f7ae5d7ccef Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 17 Sep 2016 20:33:41 -0700 Subject: Only create a protected branch upon a push to a new branch if a rule for that branch doesn't exist A customer ran into an issue where a Sidekiq task retried over and over, leading to duplicate master branches in their protected branch list. Closes #22177 --- spec/services/git_push_service_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 6ac1fa8f182..22724434a7f 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -253,6 +253,21 @@ describe GitPushService, services: true do expect(project.protected_branches.last.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER]) end + it "when pushing a branch for the first time with an existing branch permission configured" do + stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH) + + create(:protected_branch, :no_one_can_push, :developers_can_merge, project: project, name: 'master') + expect(project).to receive(:execute_hooks) + expect(project.default_branch).to eq("master") + expect_any_instance_of(ProtectedBranches::CreateService).not_to receive(:execute) + + execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' ) + + expect(project.protected_branches).not_to be_empty + expect(project.protected_branches.last.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::NO_ACCESS]) + expect(project.protected_branches.last.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::DEVELOPER]) + end + it "when pushing a branch for the first time with default branch protection set to 'developers can merge'" do stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE) -- cgit v1.2.1 From bf41ab2640d215dccd890cc9ba3dd4f3f72cf84a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Sun, 18 Sep 2016 21:41:45 +0200 Subject: Add specs that target status failure --- spec/requests/api/commits_spec.rb | 2 +- spec/views/projects/pipelines/show.html.haml_spec.rb | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 5b3dc60aba2..10f772c5b1a 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -110,7 +110,7 @@ describe API::API, api: true do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user) expect(response).to have_http_status(200) - expect(json_response['status']).to be_nil + expect(json_response['status']).to eq("created") end end diff --git a/spec/views/projects/pipelines/show.html.haml_spec.rb b/spec/views/projects/pipelines/show.html.haml_spec.rb index c5b16c1c304..ac7f3ffb157 100644 --- a/spec/views/projects/pipelines/show.html.haml_spec.rb +++ b/spec/views/projects/pipelines/show.html.haml_spec.rb @@ -9,11 +9,13 @@ describe 'projects/pipelines/show' do before do controller.prepend_view_path('app/views/projects') - create_build('build', 0, 'build') - create_build('test', 1, 'rspec 0:2') - create_build('test', 1, 'rspec 1:2') - create_build('test', 1, 'audit') - create_build('deploy', 2, 'production') + create_build('build', 0, 'build', :success) + create_build('test', 1, 'rspec 0:2', :pending) + create_build('test', 1, 'rspec 1:2', :running) + create_build('test', 1, 'spinach 0:2', :created) + create_build('test', 1, 'spinach 1:2', :created) + create_build('test', 1, 'audit', :created) + create_build('deploy', 2, 'production', :created) create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3) @@ -37,6 +39,7 @@ describe 'projects/pipelines/show' do # builds expect(rendered).to have_text('rspec') + expect(rendered).to have_text('spinach') expect(rendered).to have_text('rspec 0:2') expect(rendered).to have_text('production') expect(rendered).to have_text('jenkins') @@ -44,7 +47,7 @@ describe 'projects/pipelines/show' do private - def create_build(stage, stage_idx, name) - create(:ci_build, pipeline: pipeline, stage: stage, stage_idx: stage_idx, name: name) + def create_build(stage, stage_idx, name, status) + create(:ci_build, pipeline: pipeline, stage: stage, stage_idx: stage_idx, name: name, status: status) end end -- cgit v1.2.1 From 73f5a8eb88383563802952f53e2bc4f074016744 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 18 Sep 2016 13:44:34 -0700 Subject: Add missing spec for ProtectedBranches::CreateService --- .../protected_branches/create_service_spec.rb | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spec/services/protected_branches/create_service_spec.rb (limited to 'spec') diff --git a/spec/services/protected_branches/create_service_spec.rb b/spec/services/protected_branches/create_service_spec.rb new file mode 100644 index 00000000000..7d4eff3b6ef --- /dev/null +++ b/spec/services/protected_branches/create_service_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe ProtectedBranches::CreateService, services: true do + let(:project) { create(:empty_project) } + let(:user) { project.owner } + let(:params) do + { + name: 'master', + merge_access_levels_attributes: [ { access_level: Gitlab::Access::MASTER } ], + push_access_levels_attributes: [ { access_level: Gitlab::Access::MASTER } ] + } + end + + describe '#execute' do + subject(:service) { described_class.new(project, user, params) } + + it 'creates a new protected branch' do + expect { service.execute }.to change(ProtectedBranch, :count).by(1) + expect(project.protected_branches.last.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER]) + expect(project.protected_branches.last.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MASTER]) + end + end +end -- cgit v1.2.1 From 282c325d024e115b52c2ebfe394096b7e4cc68ed Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 18 Sep 2016 21:21:43 -0700 Subject: Reset pushes_since_gc counter before specs run to ensure starting point is 0 --- spec/services/projects/housekeeping_service_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb index c6160f4fa57..cf90b33dfb4 100644 --- a/spec/services/projects/housekeeping_service_spec.rb +++ b/spec/services/projects/housekeeping_service_spec.rb @@ -4,6 +4,10 @@ describe Projects::HousekeepingService do subject { Projects::HousekeepingService.new(project) } let(:project) { create :project } + before do + project.reset_pushes_since_gc + end + after do project.reset_pushes_since_gc end -- cgit v1.2.1 From 31e592647aaab8923922a316e442c404ef70b8df Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:12:45 +0800 Subject: Fix download artifacts button link: Rails ignored unused arguments and ref_name_and_path is the last path argument, therefore we need to concatenate that parts ourselves. Otherwise, 'download' won't be shown at all. --- spec/features/projects/branches/download_buttons_spec.rb | 6 +++++- spec/features/projects/files/download_buttons_spec.rb | 6 +++++- spec/features/projects/main/download_buttons_spec.rb | 6 +++++- spec/features/projects/tags/download_buttons_spec.rb | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/branches/download_buttons_spec.rb b/spec/features/projects/branches/download_buttons_spec.rb index 04058300570..92028c19361 100644 --- a/spec/features/projects/branches/download_buttons_spec.rb +++ b/spec/features/projects/branches/download_buttons_spec.rb @@ -33,7 +33,11 @@ feature 'Download buttons in branches page', feature: true do end scenario 'shows download artifacts button' do - expect(page).to have_link "Download '#{build.name}'" + href = latest_succeeded_namespace_project_artifacts_path( + project.namespace, project, 'binary-encoding/download', + job: 'build') + + expect(page).to have_link "Download '#{build.name}'", href: href end end end diff --git a/spec/features/projects/files/download_buttons_spec.rb b/spec/features/projects/files/download_buttons_spec.rb index be5cebcd7c9..d7c29a7e074 100644 --- a/spec/features/projects/files/download_buttons_spec.rb +++ b/spec/features/projects/files/download_buttons_spec.rb @@ -34,7 +34,11 @@ feature 'Download buttons in files tree', feature: true do end scenario 'shows download artifacts button' do - expect(page).to have_link "Download '#{build.name}'" + href = latest_succeeded_namespace_project_artifacts_path( + project.namespace, project, "#{project.default_branch}/download", + job: 'build') + + expect(page).to have_link "Download '#{build.name}'", href: href end end end diff --git a/spec/features/projects/main/download_buttons_spec.rb b/spec/features/projects/main/download_buttons_spec.rb index b26c0ea7a14..227ccf9459c 100644 --- a/spec/features/projects/main/download_buttons_spec.rb +++ b/spec/features/projects/main/download_buttons_spec.rb @@ -33,7 +33,11 @@ feature 'Download buttons in project main page', feature: true do end scenario 'shows download artifacts button' do - expect(page).to have_link "Download '#{build.name}'" + href = latest_succeeded_namespace_project_artifacts_path( + project.namespace, project, "#{project.default_branch}/download", + job: 'build') + + expect(page).to have_link "Download '#{build.name}'", href: href end end end diff --git a/spec/features/projects/tags/download_buttons_spec.rb b/spec/features/projects/tags/download_buttons_spec.rb index 6e0022c179f..dd93d25c2c6 100644 --- a/spec/features/projects/tags/download_buttons_spec.rb +++ b/spec/features/projects/tags/download_buttons_spec.rb @@ -34,7 +34,11 @@ feature 'Download buttons in tags page', feature: true do end scenario 'shows download artifacts button' do - expect(page).to have_link "Download '#{build.name}'" + href = latest_succeeded_namespace_project_artifacts_path( + project.namespace, project, "#{tag}/download", + job: 'build') + + expect(page).to have_link "Download '#{build.name}'", href: href end end end -- cgit v1.2.1 From e74b7d665b80525c894bd3743ed7c4dc8810b4af Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 30 Aug 2016 10:09:41 +0200 Subject: squashed - Fix DB exceptions raised importing some specific projects. Better import of labels, milestones and protected branches. Updated relevant specs. Loose pipeline validation on importing, so it does not fail when there are missing fields, which are not validated at DB level. Also, updated spec with relevant test. --- .../import_export/test_project_export.tar.gz | Bin 676870 -> 1363770 bytes spec/lib/gitlab/import_export/project.json | 80 +++++++++++++++++++-- .../import_export/project_tree_restorer_spec.rb | 36 ++++++++-- .../gitlab/import_export/version_checker_spec.rb | 2 +- 4 files changed, 106 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz index e14b2705704..d04bdea0fe4 100644 Binary files a/spec/features/projects/import_export/test_project_export.tar.gz and b/spec/features/projects/import_export/test_project_export.tar.gz differ diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 5114f9c55e1..281f6cf1177 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -24,7 +24,7 @@ "test_ee_field": "test", "milestone": { "id": 1, - "title": "v0.0", + "title": "test milestone", "project_id": 8, "description": "test milestone", "due_date": null, @@ -51,7 +51,7 @@ { "id": 2, "label_id": 2, - "target_id": 3, + "target_id": 40, "target_type": "Issue", "created_at": "2016-07-22T08:57:02.840Z", "updated_at": "2016-07-22T08:57:02.840Z", @@ -281,6 +281,31 @@ "deleted_at": null, "due_date": null, "moved_to_id": null, + "milestone": { + "id": 1, + "title": "test milestone", + "project_id": 8, + "description": "test milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "events": [ + { + "id": 487, + "target_type": "Milestone", + "target_id": 1, + "title": null, + "data": null, + "project_id": 46, + "created_at": "2016-06-14T15:02:04.418Z", + "updated_at": "2016-06-14T15:02:04.418Z", + "action": 1, + "author_id": 18 + } + ] + }, "notes": [ { "id": 359, @@ -494,6 +519,27 @@ "deleted_at": null, "due_date": null, "moved_to_id": null, + "label_links": [ + { + "id": 99, + "label_id": 2, + "target_id": 38, + "target_type": "Issue", + "created_at": "2016-07-22T08:57:02.840Z", + "updated_at": "2016-07-22T08:57:02.840Z", + "label": { + "id": 2, + "title": "test2", + "color": "#428bca", + "project_id": 8, + "created_at": "2016-07-22T08:55:44.161Z", + "updated_at": "2016-07-22T08:55:44.161Z", + "template": false, + "description": "", + "priority": null + } + } + ], "notes": [ { "id": 367, @@ -6478,7 +6524,7 @@ { "id": 37, "project_id": 5, - "ref": "master", + "ref": null, "sha": "048721d90c449b244b7b4c53a9186b04330174ec", "before_sha": null, "push_data": null, @@ -7301,6 +7347,30 @@ ], "protected_branches": [ - + { + "id": 1, + "project_id": 9, + "name": "master", + "created_at": "2016-08-30T07:32:52.426Z", + "updated_at": "2016-08-30T07:32:52.426Z", + "merge_access_levels": [ + { + "id": 1, + "protected_branch_id": 1, + "access_level": 40, + "created_at": "2016-08-30T07:32:52.458Z", + "updated_at": "2016-08-30T07:32:52.458Z" + } + ], + "push_access_levels": [ + { + "id": 1, + "protected_branch_id": 1, + "access_level": 40, + "created_at": "2016-08-30T07:32:52.490Z", + "updated_at": "2016-08-30T07:32:52.490Z" + } + ] + } ] -} +} \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index a07ef279e68..feacb295231 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -29,12 +29,30 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::ENABLED) end + it 'has the same label associated to two issues' do + restored_project_json + + expect(Label.first.issues.count).to eq(2) + end + + it 'has milestones associated to two separate issues' do + restored_project_json + + expect(Milestone.find_by_description('test milestone').issues.count).to eq(2) + end + it 'creates a valid pipeline note' do restored_project_json expect(Ci::Pipeline.first.notes).not_to be_empty end + it 'restores pipelines with missing ref' do + restored_project_json + + expect(Ci::Pipeline.where(ref: nil)).not_to be_empty + end + it 'restores the correct event with symbolised data' do restored_project_json @@ -49,6 +67,18 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(issue.reload.updated_at.to_s).to eq('2016-06-14 15:02:47 UTC') end + it 'contains the merge access levels on a protected branch' do + restored_project_json + + expect(ProtectedBranch.first.merge_access_levels).not_to be_empty + end + + it 'contains the push access levels on a protected branch' do + restored_project_json + + expect(ProtectedBranch.first.push_access_levels).not_to be_empty + end + context 'event at forth level of the tree' do let(:event) { Event.where(title: 'test levels').first } @@ -77,12 +107,6 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(Label.first.label_links.first.target).not_to be_nil end - it 'has milestones associated to issues' do - restored_project_json - - expect(Milestone.find_by_description('test milestone').issues).not_to be_empty - end - context 'Merge requests' do before do restored_project_json diff --git a/spec/lib/gitlab/import_export/version_checker_spec.rb b/spec/lib/gitlab/import_export/version_checker_spec.rb index 90c6d1c67f6..c680e712b59 100644 --- a/spec/lib/gitlab/import_export/version_checker_spec.rb +++ b/spec/lib/gitlab/import_export/version_checker_spec.rb @@ -23,7 +23,7 @@ describe Gitlab::ImportExport::VersionChecker, services: true do it 'shows the correct error message' do described_class.check!(shared: shared) - expect(shared.errors.first).to eq("Import version mismatch: Required <= #{Gitlab::ImportExport.version} but was #{version}") + expect(shared.errors.first).to eq("Import version mismatch: Required #{Gitlab::ImportExport.version} but was #{version}") end end end -- cgit v1.2.1 From 8f6208513a98b33d7edd6ecf1ae6062f266c279f Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 19 Sep 2016 12:56:25 +0530 Subject: Test all cycle analytics pre-calculation code. All the code that pre-calculates metrics for use in the cycle analytics page. - Ci::Pipeline -> build start/finish - Ci::Pipeline#merge_requests - Issue -> record default metrics after save - MergeRequest -> record default metrics after save - Deployment -> Update "first_deployed_to_production_at" for MR metrics - Git Push -> Update "first commit mention" for issue metrics - Merge request create/update/refresh -> Update "merge requests closing issues" --- spec/models/ci/pipeline_spec.rb | 55 ++++++++++++++++ spec/models/issue/metrics_spec.rb | 55 ++++++++++++++++ spec/models/merge_request/metrics_spec.rb | 18 +++++ spec/services/create_deployment_service_spec.rb | 76 ++++++++++++++++++++++ spec/services/git_push_service_spec.rb | 37 +++++++++++ .../services/merge_requests/create_service_spec.rb | 28 ++++++++ .../merge_requests/refresh_service_spec.rb | 30 +++++++++ .../services/merge_requests/update_service_spec.rb | 34 ++++++++++ 8 files changed, 333 insertions(+) create mode 100644 spec/models/issue/metrics_spec.rb create mode 100644 spec/models/merge_request/metrics_spec.rb (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 598df576001..5bafcc13f61 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -169,6 +169,37 @@ describe Ci::Pipeline, models: true do expect(pipeline.reload.finished_at).to be_nil end end + + describe "merge request metrics" do + let(:project) { FactoryGirl.create :project } + let(:pipeline) { FactoryGirl.create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: project.repository.commit('master').id) } + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref) } + + context 'when transitioning to running' do + it 'records the build start time' do + time = Time.now + Timecop.freeze(time) { build.run } + + expect(merge_request.metrics.latest_build_started_at).to eq(time) + end + + it 'clears the build end time' do + build.run + + expect(merge_request.metrics.latest_build_finished_at).to be_nil + end + end + + context 'when transitioning to success' do + it 'records the build end time' do + build.run + time = Time.now + Timecop.freeze(time) { build.success } + + expect(merge_request.metrics.latest_build_finished_at).to eq(time) + end + end + end end describe '#branch?' do @@ -429,4 +460,28 @@ describe Ci::Pipeline, models: true do create(:ci_build, :created, pipeline: pipeline, name: name) end end + + describe "#merge_requests" do + let(:project) { FactoryGirl.create :project } + let(:pipeline) { FactoryGirl.create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: project.repository.commit('master').id) } + + it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do + merge_request = create(:merge_request, source_project: project, source_branch: pipeline.ref) + + expect(pipeline.merge_requests).to eq([merge_request]) + end + + it "doesn't return merge requests whose source branch doesn't match the pipeline's ref" do + create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') + + expect(pipeline.merge_requests).to be_empty + end + + it "doesn't return merge requests whose `diff_head_sha` doesn't match the pipeline's SHA" do + create(:merge_request, source_project: project, source_branch: pipeline.ref) + allow_any_instance_of(MergeRequest).to receive(:diff_head_sha) { '97de212e80737a608d939f648d959671fb0a0142b' } + + expect(pipeline.merge_requests).to be_empty + end + end end diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb new file mode 100644 index 00000000000..df977486943 --- /dev/null +++ b/spec/models/issue/metrics_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Issue::Metrics, models: true do + let(:project) { create(:project) } + + subject { create(:issue, project: project) } + + describe "when recording the default set of issue metrics on issue save" do + context "milestones" do + it "records the first time an issue is associated with a milestone" do + time = Time.now + Timecop.freeze(time) { subject.update(milestone: create(:milestone)) } + metrics = subject.metrics + + expect(metrics).to be_present + expect(metrics.first_associated_with_milestone_at).to eq(time) + end + + it "does not record the second time an issue is associated with a milestone" do + time = Time.now + Timecop.freeze(time) { subject.update(milestone: create(:milestone)) } + Timecop.freeze(time + 2.hours) { subject.update(milestone: nil) } + Timecop.freeze(time + 6.hours) { subject.update(milestone: create(:milestone)) } + metrics = subject.metrics + + expect(metrics).to be_present + expect(metrics.first_associated_with_milestone_at).to eq(time) + end + end + + context "list labels" do + it "records the first time an issue is associated with a list label" do + list_label = create(:label, lists: [create(:list)]) + time = Time.now + Timecop.freeze(time) { subject.update(label_ids: [list_label.id]) } + metrics = subject.metrics + + expect(metrics).to be_present + expect(metrics.first_added_to_board_at).to eq(time) + end + + it "does not record the second time an issue is associated with a list label" do + time = Time.now + first_list_label = create(:label, lists: [create(:list)]) + Timecop.freeze(time) { subject.update(label_ids: [first_list_label.id]) } + second_list_label = create(:label, lists: [create(:list)]) + Timecop.freeze(time + 5.hours) { subject.update(label_ids: [second_list_label.id]) } + metrics = subject.metrics + + expect(metrics).to be_present + expect(metrics.first_added_to_board_at).to eq(time) + end + end + end +end diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb new file mode 100644 index 00000000000..718b50642ad --- /dev/null +++ b/spec/models/merge_request/metrics_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe MergeRequest::Metrics, models: true do + let(:project) { create(:project) } + + subject { create(:merge_request, source_project: project) } + + describe "when recording the default set of metrics on merge request save" do + it "records the merge time" do + time = Time.now + Timecop.freeze(time) { subject.mark_as_merged } + metrics = subject.metrics + + expect(metrics).to be_present + expect(metrics.merged_at).to eq(time) + end + end +end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 8da2a2b3c1b..5cc0f2ab974 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -132,4 +132,80 @@ describe CreateDeploymentService, services: true do end end end + + describe "merge request metrics" do + let(:params) do + { + environment: 'production', + ref: 'master', + tag: false, + sha: '97de212e80737a608d939f648d959671fb0a0142b', + } + end + + let(:merge_request) { create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: project) } + + context "while updating the 'first_deployed_to_production_at' time" do + before { merge_request.mark_as_merged } + + context "for merge requests merged before the current deploy" do + it "sets the time if the deploy's environment is 'production'" do + time = Time.now + Timecop.freeze(time) { service.execute } + + expect(merge_request.metrics.first_deployed_to_production_at).to eq(time) + end + + it "doesn't set the time if the deploy's environment is not 'production'" do + staging_params = params.merge(environment: 'staging') + service = described_class.new(project, user, staging_params) + service.execute + + expect(merge_request.metrics.first_deployed_to_production_at).to be_nil + end + + it 'does not raise errors if the merge request does not have a metrics record' do + merge_request.metrics.destroy + + expect(merge_request.reload.metrics).to be_nil + expect { service.execute }.not_to raise_error + end + end + + context "for merge requests merged before the previous deploy" do + context "if the 'first_deployed_to_production_at' time is already set" do + it "does not overwrite the older 'first_deployed_to_production_at' time" do + # Previous deploy + time = Time.now + Timecop.freeze(time) { service.execute } + + expect(merge_request.reload.metrics.first_deployed_to_production_at).to eq(time) + + # Current deploy + service = described_class.new(project, user, params) + Timecop.freeze(time + 12.hours) { service.execute } + + expect(merge_request.reload.metrics.first_deployed_to_production_at).to eq(time) + end + end + + context "if the 'first_deployed_to_production_at' time is not already set" do + it "does not overwrite the older 'first_deployed_to_production_at' time" do + # Previous deploy + time = Time.now + Timecop.freeze(time) { service.execute } + merge_request.metrics.update(first_deployed_to_production_at: nil) + + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil + + # Current deploy + service = described_class.new(project, user, params) + Timecop.freeze(time + 12.hours) { service.execute } + + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil + end + end + end + end + end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 6ac1fa8f182..125110e0c37 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -324,6 +324,43 @@ describe GitPushService, services: true do end end + describe "issue metrics" do + let(:issue) { create :issue, project: project } + let(:commit_author) { create :user } + let(:commit) { project.commit } + let(:commit_time) { Time.now } + + before do + project.team << [commit_author, :developer] + project.team << [user, :developer] + + allow(commit).to receive_messages( + safe_message: "this commit \n mentions #{issue.to_reference}", + references: [issue], + author_name: commit_author.name, + author_email: commit_author.email, + committed_date: commit_time + ) + + allow(project.repository).to receive(:commits_between).and_return([commit]) + end + + context "while saving the 'first_mentioned_in_commit_at' metric for an issue" do + it 'sets the metric for referenced issues' do + execute_service(project, user, @oldrev, @newrev, @ref) + + expect(issue.metrics.first_mentioned_in_commit_at).to eq(commit_time) + end + + it 'does not set the metric for non-referenced issues' do + non_referenced_issue = create(:issue, project: project) + execute_service(project, user, @oldrev, @newrev, @ref) + + expect(non_referenced_issue.metrics.first_mentioned_in_commit_at).to be_nil + end + end + end + describe "closing issues from pushed commits containing a closing reference" do let(:issue) { create :issue, project: project } let(:other_issue) { create :issue, project: project } diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index c1e4f8bd96b..a0614abcf62 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -83,5 +83,33 @@ describe MergeRequests::CreateService, services: true do } end end + + context 'while saving references to issues that the created merge request closes' do + let(:first_issue) { create(:issue, project: project) } + let(:second_issue) { create(:issue, project: project) } + + let(:opts) do + { + title: 'Awesome merge_request', + source_branch: 'feature', + target_branch: 'master', + force_remove_source_branch: '1' + } + end + + before do + project.team << [user, :master] + project.team << [assignee, :developer] + end + + it 'creates a `MergeRequestsClosingIssues` record for each issue' do + issue_closing_opts = opts.merge(description: "Closes #{first_issue.to_reference} and #{second_issue.to_reference}") + service = described_class.new(project, user, issue_closing_opts) + allow(service).to receive(:execute_hooks) + merge_request = service.execute + + expect(merge_request.issues_closed).to match_array([first_issue, second_issue]) + end + end end end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index fff86480c6d..7ecad8d6bad 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -174,6 +174,36 @@ describe MergeRequests::RefreshService, services: true do end end + context 'push commits closing issues' do + let(:issue) { create :issue, project: @project } + let(:commit_author) { create :user } + let(:commit) { project.commit } + let!(:merge_request) { create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: @project) } + + before do + project.team << [commit_author, :developer] + project.team << [user, :developer] + + allow(commit).to receive_messages( + safe_message: "Closes #{issue.to_reference}", + references: [issue], + author_name: commit_author.name, + author_email: commit_author.email, + committed_date: Time.now + ) + + allow_any_instance_of(MergeRequest).to receive(:commits).and_return([commit]) + end + + it 'creates a `MergeRequestsClosingIssues` record for each closed issue' do + refresh_service = service.new(@project, @user) + allow(refresh_service).to receive(:execute_hooks) + refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature') + + expect(merge_request.reload.issues_closed).to eq([issue]) + end + end + def reload_mrs @merge_request.reload @fork_merge_request.reload diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 6dfeb581975..cfd506707de 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -263,5 +263,39 @@ describe MergeRequests::UpdateService, services: true do end end end + + context 'while saving references to issues that the updated merge request closes' do + let(:first_issue) { create(:issue, project: project) } + let(:second_issue) { create(:issue, project: project) } + + it 'creates a `MergeRequestsClosingIssues` record for each issue' do + issue_closing_opts = { description: "Closes #{first_issue.to_reference} and #{second_issue.to_reference}" } + service = described_class.new(project, user, issue_closing_opts) + allow(service).to receive(:execute_hooks) + service.execute(merge_request) + + expect(merge_request.reload.issues_closed).to match_array([first_issue, second_issue]) + end + end + + it 'removes `MergeRequestsClosingIssues` records when issues are not closed anymore' do + opts = { + title: 'Awesome merge_request', + description: "Closes #{first_issue.to_reference} and #{second_issue.to_reference}", + source_branch: 'feature', + target_branch: 'master', + force_remove_source_branch: '1' + } + + merge_request = MergeRequests::CreateService.new(project, user, opts).execute + + expect(merge_request.issues_closed).to match_array([first_issue, second_issue]) + + service = described_class.new(project, user, description: "not closing any issues") + allow(service).to receive(:execute_hooks) + service.execute(merge_request.reload) + + expect(merge_request.reload.issues_closed).to be_empty + end end end -- cgit v1.2.1 From ba5bd3d1d64b1f56c39e4ddd03270de6820b2f7b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 14 Sep 2016 19:52:28 +0200 Subject: Add new CI configuration entry for the environment --- spec/lib/gitlab/ci/config/node/environment_spec.rb | 125 +++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 spec/lib/gitlab/ci/config/node/environment_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/node/environment_spec.rb b/spec/lib/gitlab/ci/config/node/environment_spec.rb new file mode 100644 index 00000000000..27238f9c887 --- /dev/null +++ b/spec/lib/gitlab/ci/config/node/environment_spec.rb @@ -0,0 +1,125 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Node::Environment do + let(:entry) { described_class.new(config) } + + before { entry.compose! } + + context 'when configuration is a string' do + let(:config) { 'production' } + + describe '#string?' do + it 'is string configuration' do + expect(entry).to be_string + end + end + + describe '#hash?' do + it 'is not hash configuration' do + expect(entry).not_to be_hash + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to eq(name: 'production') + end + end + + describe '#name' do + it 'returns environment name' do + expect(entry.name).to eq 'production' + end + end + + describe '#url' do + it 'returns environment url' do + expect(entry.url).to be_nil + end + end + end + + context 'when configuration is a hash' do + let(:config) do + { name: 'development', url: 'https://example.gitlab.com' } + end + + describe '#string?' do + it 'is not string configuration' do + expect(entry).not_to be_string + end + end + + describe '#hash?' do + it 'is hash configuration' do + expect(entry).to be_hash + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to eq config + end + end + + describe '#name' do + it 'returns environment name' do + expect(entry.name).to eq 'development' + end + end + + describe '#url' do + it 'returns environment url' do + expect(entry.url).to eq 'https://example.gitlab.com' + end + end + end + + context 'when configuration is invalid' do + context 'when configuration is an array' do + let(:config) { ['env'] } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'contains error about invalid type' do + expect(entry.errors) + .to include 'environment config should be a hash or a string' + end + end + end + + context 'when environment name is not present' do + let(:config) { { url: 'https://example.gitlab.com' } } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors?' do + it 'contains error about missing environment name' do + expect(entry.errors) + .to include "environment name can't be blank" + end + end + end + end +end -- cgit v1.2.1 From 08272ec1513cbd565e5db5995a681c25e1f4544f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 14 Sep 2016 22:14:26 +0200 Subject: Add validation of URL and validation of name --- spec/lib/gitlab/ci/config/node/environment_spec.rb | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/node/environment_spec.rb b/spec/lib/gitlab/ci/config/node/environment_spec.rb index 27238f9c887..df453223da7 100644 --- a/spec/lib/gitlab/ci/config/node/environment_spec.rb +++ b/spec/lib/gitlab/ci/config/node/environment_spec.rb @@ -87,6 +87,19 @@ describe Gitlab::Ci::Config::Node::Environment do end end + context 'when variables are used for environment' do + let(:config) do + { name: 'review/$CI_BUILD_REF_NAME', + url: 'https://$CI_BUILD_REF_NAME.review.gitlab.com' } + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + context 'when configuration is invalid' do context 'when configuration is an array' do let(:config) { ['env'] } @@ -121,5 +134,22 @@ describe Gitlab::Ci::Config::Node::Environment do end end end + + context 'when invalid URL is used' do + let(:config) { { name: 'test', url: 'invalid-example.gitlab.com' } } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors?' do + it 'contains error about invalid URL' do + expect(entry.errors) + .to include "environment url must be a valid url" + end + end + end end end -- cgit v1.2.1 From e1b3ab5af290f6d2eeb56c4b72e341324414a6d2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 14 Sep 2016 22:32:11 +0200 Subject: Verify expandability of variables defined as part of environment --- spec/lib/expand_variables_spec.rb | 73 +++++++++++++++++++++++++ spec/models/environment_spec.rb | 16 ++++++ spec/services/create_deployment_service_spec.rb | 32 ++++++++++- 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 spec/lib/expand_variables_spec.rb (limited to 'spec') diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb new file mode 100644 index 00000000000..90bc7dad379 --- /dev/null +++ b/spec/lib/expand_variables_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe ExpandVariables do + describe '#expand' do + subject { described_class.expand(value, variables) } + + tests = [ + { value: 'key', + result: 'key', + variables: [] + }, + { value: 'key$variable', + result: 'key', + variables: [] + }, + { value: 'key$variable', + result: 'keyvalue', + variables: [ + { key: 'variable', value: 'value' } + ] + }, + { value: 'key${variable}', + result: 'keyvalue', + variables: [ + { key: 'variable', value: 'value' } + ] + }, + { value: 'key$variable$variable2', + result: 'keyvalueresult', + variables: [ + { key: 'variable', value: 'value' }, + { key: 'variable2', value: 'result' }, + ] + }, + { value: 'key${variable}${variable2}', + result: 'keyvalueresult', + variables: [ + { key: 'variable', value: 'value' }, + { key: 'variable2', value: 'result' } + ] + }, + { value: 'key$variable2$variable', + result: 'keyresultvalue', + variables: [ + { key: 'variable', value: 'value' }, + { key: 'variable2', value: 'result' }, + ] + }, + { value: 'key${variable2}${variable}', + result: 'keyresultvalue', + variables: [ + { key: 'variable', value: 'value' }, + { key: 'variable2', value: 'result' } + ] + }, + { value: 'review/$CI_BUILD_REF_NAME', + result: 'review/feature/add-review-apps', + variables: [ + { key: 'CI_BUILD_REF_NAME', value: 'feature/add-review-apps' } + ] + }, + ] + + tests.each do |test| + context "#{test[:value]} resolves to #{test[:result]}" do + let(:value) { test[:value] } + let(:variables) { test[:variables] } + + it { is_expected.to eq(test[:result]) } + end + end + end +end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index c881897926e..7afc7ec5ca1 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -63,4 +63,20 @@ describe Environment, models: true do end end end + + describe '#environment_type' do + subject { environment.environment_type } + + it 'sets a environment type if name has multiple segments' do + environment.update(name: 'production/worker.gitlab.com') + + is_expected.to eq('production') + end + + it 'nullifies a type if it\'s a simple name' do + environment.update(name: 'production') + + is_expected.to be_nil + end + end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 8da2a2b3c1b..c8c741c0e88 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -56,8 +56,38 @@ describe CreateDeploymentService, services: true do expect(subject).not_to be_persisted end end + + context 'when variables are used' do + let(:params) do + { environment: 'review-apps/$CI_BUILD_REF_NAME', + ref: 'master', + tag: false, + sha: '97de212e80737a608d939f648d959671fb0a0142', + options: { + environment: { + name: 'review-apps/$CI_BUILD_REF_NAME', + url: 'http://$CI_BUILD_REF_NAME.review-apps.gitlab.com' + } + }, + variables: [ + { key: 'CI_BUILD_REF_NAME', value: 'feature-review-apps' } + ] + } + end + + it 'does create a new environment' do + expect { subject }.to change { Environment.count }.by(1) + + expect(subject.environment.name).to eq('review-apps/feature-review-apps') + expect(subject.environment.external_url).to eq('http://feature-review-apps.review-apps.gitlab.com') + end + + it 'does create a new deployment' do + expect(subject).not_to be_persisted + end + end end - + describe 'processing of builds' do let(:environment) { nil } -- cgit v1.2.1 From 6b979687459ad1ab5f1953bf451ee80fdb899b96 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 14 Sep 2016 23:00:15 +0200 Subject: Update support for dynamic environments --- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 14 ++++++++++++++ spec/services/create_deployment_service_spec.rb | 21 ++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index af192664b33..2ad33007b8a 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -754,6 +754,20 @@ module Ci it 'does return production' do expect(builds.size).to eq(1) expect(builds.first[:environment]).to eq(environment) + expect(builds.first[:options]).to include(environment: { name: environment }) + end + end + + context 'when hash is specified' do + let(:environment) do + { name: 'production', + url: 'http://production.gitlab.com' } + end + + it 'does return production and URL' do + expect(builds.size).to eq(1) + expect(builds.first[:environment]).to eq(environment[:name]) + expect(builds.first[:options]).to include(environment) end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index c8c741c0e88..7ebfddc45d5 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -41,7 +41,7 @@ describe CreateDeploymentService, services: true do context 'for environment with invalid name' do let(:params) do - { environment: 'name with spaces', + { environment: '..', ref: 'master', tag: false, sha: '97de212e80737a608d939f648d959671fb0a0142', @@ -64,10 +64,8 @@ describe CreateDeploymentService, services: true do tag: false, sha: '97de212e80737a608d939f648d959671fb0a0142', options: { - environment: { - name: 'review-apps/$CI_BUILD_REF_NAME', - url: 'http://$CI_BUILD_REF_NAME.review-apps.gitlab.com' - } + name: 'review-apps/$CI_BUILD_REF_NAME', + url: 'http://$CI_BUILD_REF_NAME.review-apps.gitlab.com' }, variables: [ { key: 'CI_BUILD_REF_NAME', value: 'feature-review-apps' } @@ -83,7 +81,7 @@ describe CreateDeploymentService, services: true do end it 'does create a new deployment' do - expect(subject).not_to be_persisted + expect(subject).to be_persisted end end end @@ -125,6 +123,12 @@ describe CreateDeploymentService, services: true do expect(Deployment.last.deployable).to eq(deployable) end + + it 'create environment has URL set' do + subject + + expect(Deployment.last.environment.external_url).not_to be_nil + end end context 'without environment specified' do @@ -137,7 +141,10 @@ describe CreateDeploymentService, services: true do context 'when environment is specified' do let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, pipeline: pipeline, environment: 'production') } + let(:build) { create(:ci_build, pipeline: pipeline, environment: 'production', options: options) } + let(:options) do + { environment: { name: 'production', url: 'http://gitlab.com' } } + end context 'when build succeeds' do it_behaves_like 'does create environment and deployment' do -- cgit v1.2.1 From 2ad7753d34a963abfcadfa42e5d5b4cd59afc221 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 16 Sep 2016 11:25:37 +0200 Subject: Fix CI job environment configuration attributes --- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 2ad33007b8a..c139ef36a9a 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -767,7 +767,7 @@ module Ci it 'does return production and URL' do expect(builds.size).to eq(1) expect(builds.first[:environment]).to eq(environment[:name]) - expect(builds.first[:options]).to include(environment) + expect(builds.first[:options]).to include(environment: environment) end end @@ -784,7 +784,8 @@ module Ci let(:environment) { 1 } it 'raises error' do - expect { builds }.to raise_error("jobs:deploy_to_production environment #{Gitlab::Regex.environment_name_regex_message}") + expect { builds }.to raise_error( + 'jobs:deploy_to_production:environment config should be a hash or a string') end end -- cgit v1.2.1 From 8fe05d83ac259bf8a0fa4ca344d330a1c0cea8bb Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 09:01:04 +0200 Subject: Fix validation regexs (+1 squashed commit) Squashed commits: [f9a9315] Use : to test invalid environment name --- spec/features/environments_spec.rb | 2 +- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 4 ++-- spec/models/environment_spec.rb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index fcd41b38413..4309a726917 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -150,7 +150,7 @@ feature 'Environments', feature: true do context 'for invalid name' do before do - fill_in('Name', with: 'name with spaces') + fill_in('Name', with: 'name,with,commas') click_on 'Save' end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index c139ef36a9a..6dedd25e9d3 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -790,10 +790,10 @@ module Ci end context 'is not a valid string' do - let(:environment) { 'production staging' } + let(:environment) { 'production:staging' } it 'raises error' do - expect { builds }.to raise_error("jobs:deploy_to_production environment #{Gitlab::Regex.environment_name_regex_message}") + expect { builds }.to raise_error("jobs:deploy_to_production:environment name #{Gitlab::Regex.environment_name_regex_message}") end end end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 7afc7ec5ca1..6b1867a44e1 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -68,13 +68,13 @@ describe Environment, models: true do subject { environment.environment_type } it 'sets a environment type if name has multiple segments' do - environment.update(name: 'production/worker.gitlab.com') + environment.update!(name: 'production/worker.gitlab.com') is_expected.to eq('production') end it 'nullifies a type if it\'s a simple name' do - environment.update(name: 'production') + environment.update!(name: 'production') is_expected.to be_nil end -- cgit v1.2.1 From 58d02520b037255f9948de4386ab6cd970586445 Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Mon, 12 Sep 2016 20:14:26 +0100 Subject: Ensure validation messages are shown within the milestone form * Remove call to Milestone#save! instead just Milestone#save * Add safety specs to stop a regression Fixes #22033 --- spec/features/milestone_spec.rb | 21 ++++++++++++++++++--- spec/requests/api/milestones_spec.rb | 23 +++++++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index c43661e5681..b8c838bf7ab 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -3,9 +3,8 @@ require 'rails_helper' feature 'Milestone', feature: true do include WaitForAjax - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public) } let(:user) { create(:user) } - let(:milestone) { create(:milestone, project: project, title: 8.7) } before do project.team << [user, :master] @@ -13,7 +12,7 @@ feature 'Milestone', feature: true do end feature 'Create a milestone' do - scenario 'shows an informative message for a new issue' do + scenario 'shows an informative message for a new milestone' do visit new_namespace_project_milestone_path(project.namespace, project) page.within '.milestone-form' do fill_in "milestone_title", with: '8.7' @@ -26,10 +25,26 @@ feature 'Milestone', feature: true do feature 'Open a milestone with closed issues' do scenario 'shows an informative message' do + milestone = create(:milestone, project: project, title: 8.7) + create(:issue, title: "Bugfix1", project: project, milestone: milestone, state: "closed") visit namespace_project_milestone_path(project.namespace, project, milestone) expect(find('.alert-success')).to have_content('All issues for this milestone are closed. You may close this milestone now.') end end + + feature 'Open a milestone with an existing title' do + scenario 'displays validation message' do + milestone = create(:milestone, project: project, title: 8.7) + + visit new_namespace_project_milestone_path(project.namespace, project) + page.within '.milestone-form' do + fill_in "milestone_title", with: milestone.title + end + find('input[name="commit"]').click + + expect(find('.alert-danger')).to have_content('Title has already been taken') + end + end end diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index d6a0c656e74..b89dac01040 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } - let!(:project) { create(:project, namespace: user.namespace ) } + let!(:project) { create(:empty_project, namespace: user.namespace ) } let!(:closed_milestone) { create(:closed_milestone, project: project) } let!(:milestone) { create(:milestone, project: project) } @@ -12,6 +12,7 @@ describe API::API, api: true do describe 'GET /projects/:id/milestones' do it 'returns project milestones' do get api("/projects/#{project.id}/milestones", user) + expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.first['title']).to eq(milestone.title) @@ -19,6 +20,7 @@ describe API::API, api: true do it 'returns a 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones") + expect(response).to have_http_status(401) end @@ -44,6 +46,7 @@ describe API::API, api: true do describe 'GET /projects/:id/milestones/:milestone_id' do it 'returns a project milestone by id' do get api("/projects/#{project.id}/milestones/#{milestone.id}", user) + expect(response).to have_http_status(200) expect(json_response['title']).to eq(milestone.title) expect(json_response['iid']).to eq(milestone.iid) @@ -60,11 +63,13 @@ describe API::API, api: true do it 'returns 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones/#{milestone.id}") + expect(response).to have_http_status(401) end it 'returns a 404 error if milestone id not found' do get api("/projects/#{project.id}/milestones/1234", user) + expect(response).to have_http_status(404) end end @@ -72,6 +77,7 @@ describe API::API, api: true do describe 'POST /projects/:id/milestones' do it 'creates a new project milestone' do post api("/projects/#{project.id}/milestones", user), title: 'new milestone' + expect(response).to have_http_status(201) expect(json_response['title']).to eq('new milestone') expect(json_response['description']).to be_nil @@ -80,6 +86,7 @@ describe API::API, api: true do it 'creates a new project milestone with description and due date' do post api("/projects/#{project.id}/milestones", user), title: 'new milestone', description: 'release', due_date: '2013-03-02' + expect(response).to have_http_status(201) expect(json_response['description']).to eq('release') expect(json_response['due_date']).to eq('2013-03-02') @@ -87,6 +94,14 @@ describe API::API, api: true do it 'returns a 400 error if title is missing' do post api("/projects/#{project.id}/milestones", user) + + expect(response).to have_http_status(400) + end + + it 'returns a 400 error if params are invalid (duplicate title)' do + post api("/projects/#{project.id}/milestones", user), + title: milestone.title, description: 'release', due_date: '2013-03-02' + expect(response).to have_http_status(400) end end @@ -95,6 +110,7 @@ describe API::API, api: true do it 'updates a project milestone' do put api("/projects/#{project.id}/milestones/#{milestone.id}", user), title: 'updated title' + expect(response).to have_http_status(200) expect(json_response['title']).to eq('updated title') end @@ -102,6 +118,7 @@ describe API::API, api: true do it 'returns a 404 error if milestone id not found' do put api("/projects/#{project.id}/milestones/1234", user), title: 'updated title' + expect(response).to have_http_status(404) end end @@ -131,6 +148,7 @@ describe API::API, api: true do end it 'returns project issues for a particular milestone' do get api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user) + expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.first['milestone']['title']).to eq(milestone.title) @@ -138,11 +156,12 @@ describe API::API, api: true do it 'returns a 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones/#{milestone.id}/issues") + expect(response).to have_http_status(401) end describe 'confidential issues' do - let(:public_project) { create(:project, :public) } + let(:public_project) { create(:empty_project, :public) } let(:milestone) { create(:milestone, project: public_project) } let(:issue) { create(:issue, project: public_project) } let(:confidential_issue) { create(:issue, confidential: true, project: public_project) } -- cgit v1.2.1 From b51ededc5fef05f94a632aa7651b5a1f7395bd4e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 12:38:03 +0200 Subject: Don't leak build tokens in build logs --- spec/lib/ci/mask_secret_spec.rb | 19 ++++++++++ spec/models/build_spec.rb | 78 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 spec/lib/ci/mask_secret_spec.rb (limited to 'spec') diff --git a/spec/lib/ci/mask_secret_spec.rb b/spec/lib/ci/mask_secret_spec.rb new file mode 100644 index 00000000000..518de76911c --- /dev/null +++ b/spec/lib/ci/mask_secret_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe Ci::MaskSecret, lib: true do + subject { described_class } + + describe '#mask' do + it 'masks exact number of characters' do + expect(subject.mask('token', 'oke')).to eq('txxxn') + end + + it 'masks multiple occurrences' do + expect(subject.mask('token token token', 'oke')).to eq('txxxn txxxn txxxn') + end + + it 'does not mask if not found' do + expect(subject.mask('token', 'not')).to eq('token') + end + end +end diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index 8eab4281bc7..e7864b7ad33 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -88,9 +88,7 @@ describe Ci::Build, models: true do end describe '#trace' do - subject { build.trace_html } - - it { is_expected.to be_empty } + it { expect(build.trace).to be_nil } context 'when build.trace contains text' do let(:text) { 'example output' } @@ -98,16 +96,80 @@ describe Ci::Build, models: true do build.trace = text end - it { is_expected.to include(text) } - it { expect(subject.length).to be >= text.length } + it { expect(build.trace).to eq(text) } + end + + context 'when build.trace hides runners token' do + let(:token) { 'my_secret_token' } + + before do + build.update(trace: token) + build.project.update(runners_token: token) + end + + it { expect(build.trace).not_to include(token) } + it { expect(build.raw_trace).to include(token) } + end + + context 'when build.trace hides build token' do + let(:token) { 'my_secret_token' } + + before do + build.update(trace: token) + build.update(token: token) + end + + it { expect(build.trace).not_to include(token) } + it { expect(build.raw_trace).to include(token) } + end + end + + describe '#raw_trace' do + subject { build.raw_trace } + + context 'when build.trace hides runners token' do + let(:token) { 'my_secret_token' } + + before do + build.project.update(runners_token: token) + build.update(trace: token) + end + + it { is_expected.not_to include(token) } + end + + context 'when build.trace hides build token' do + let(:token) { 'my_secret_token' } + + before do + build.update(token: token) + build.update(trace: token) + end + + it { is_expected.not_to include(token) } + end + end + + context '#append_trace' do + subject { build.trace_html } + + context 'when build.trace hides runners token' do + let(:token) { 'my_secret_token' } + + before do + build.project.update(runners_token: token) + build.append_trace(token, 0) + end + + it { is_expected.not_to include(token) } end - context 'when build.trace hides token' do + context 'when build.trace hides build token' do let(:token) { 'my_secret_token' } before do - build.project.update_attributes(runners_token: token) - build.update_attributes(trace: token) + build.update(token: token) + build.append_trace(token, 0) end it { is_expected.not_to include(token) } -- cgit v1.2.1 From 4939911e96297aa6ed9fb60f635d7d16a360876f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 12:44:10 +0200 Subject: Fix specs failures --- spec/services/create_deployment_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 7ebfddc45d5..41b897f36cd 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -41,7 +41,7 @@ describe CreateDeploymentService, services: true do context 'for environment with invalid name' do let(:params) do - { environment: '..', + { environment: 'name,with,commas', ref: 'master', tag: false, sha: '97de212e80737a608d939f648d959671fb0a0142', -- cgit v1.2.1 From 10c072263b2568a64321439860da039a4f572e31 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 16 Sep 2016 18:38:07 +0100 Subject: Enable Warden for the Grape API The practical effect of this commit is to make the API check the Rails session cookie for authentication details. If the cookie is present and valid, it will be used to authenticate. The API now has several authentication options for users. They follow in this order of precedence: * Authentication token * Personal access token * OAuth2 Bearer token (Doorkeeper - application access) * Rails session cookie --- spec/requests/api/api_helpers_spec.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index bbdf8f03c2b..e66faeed705 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -36,11 +36,36 @@ describe API::Helpers, api: true do params.delete(API::Helpers::SUDO_PARAM) end + def warden_authenticate_returns(value) + warden = double("warden", authenticate: value) + env['warden'] = warden + end + + def doorkeeper_guard_returns(value) + allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ value } + end + def error!(message, status) raise Exception end describe ".current_user" do + subject { current_user } + + describe "when authenticating via Warden" do + before { doorkeeper_guard_returns false } + + context "fails" do + it { is_expected.to be_nil } + end + + context "succeeds" do + before { warden_authenticate_returns user } + + it { is_expected.to eq(user) } + end + end + describe "when authenticating using a user's private token" do it "returns nil for an invalid token" do env[API::Helpers::PRIVATE_TOKEN_HEADER] = 'invalid token' -- cgit v1.2.1 From 748dd35c65b0a7f3fbb0832fd18933ff8c19ef7d Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 13:29:48 +0200 Subject: Fix spec failures --- spec/lib/gitlab/auth_spec.rb | 2 +- spec/models/ci/build_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 1af5abe9f15..21f0d46100e 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -171,7 +171,7 @@ describe Gitlab::Auth, lib: true do def full_authentication_abilities read_authentication_abilities + [ :push_code, - :update_container_image + :create_container_image ] end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index bce18b4e99e..a37a00f461a 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -8,7 +8,7 @@ describe Ci::Build, models: true do it 'obfuscates project runners token' do allow(build).to receive(:raw_trace).and_return("Test: #{build.project.runners_token}") - expect(build.trace).to eq("Test: xxxxxx") + expect(build.trace).to eq("Test: xxxxxxxxxxxxxxxxxxxx") end it 'empty project runners token' do -- cgit v1.2.1 From 6d43c95b7011ec7ec4600e00bdc8df76bb39813c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 13:38:58 +0200 Subject: Revert all changes introduced by https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6043 --- spec/lib/gitlab/auth_spec.rb | 18 -------------- spec/lib/gitlab/lfs_token_spec.rb | 51 -------------------------------------- spec/requests/api/internal_spec.rb | 46 ---------------------------------- spec/requests/lfs_http_spec.rb | 16 ------------ 4 files changed, 131 deletions(-) delete mode 100644 spec/lib/gitlab/lfs_token_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 21f0d46100e..8807a68a0a2 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -61,24 +61,6 @@ 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) - ip = 'ip' - token = Gitlab::LfsToken.new(user).generate - - 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, read_authentication_abilities)) - end - - it 'recognizes deploy key lfs tokens' do - key = create(:deploy_key) - ip = 'ip' - token = Gitlab::LfsToken.new(key).generate - - 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 - it 'recognizes OAuth tokens' do user = create(:user) application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb deleted file mode 100644 index 9f04f67e0a8..00000000000 --- a/spec/lib/gitlab/lfs_token_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'spec_helper' - -describe Gitlab::LfsToken, lib: true do - describe '#generate and #value' do - shared_examples 'an LFS token generator' do - it 'returns a randomly generated token' do - token = handler.generate - - expect(token).not_to be_nil - expect(token).to be_a String - expect(token.length).to eq 50 - end - - it 'returns the correct token based on the key' do - token = handler.generate - - expect(handler.value).to eq(token) - end - end - - context 'when the actor is a user' do - let(:actor) { create(:user) } - let(:handler) { described_class.new(actor) } - - it_behaves_like 'an LFS token generator' - - it 'returns the correct username' do - expect(handler.actor_name).to eq(actor.username) - end - - it 'returns the correct token type' do - expect(handler.type).to eq(:lfs_token) - end - end - - context 'when the actor is a deploy key' do - let(:actor) { create(:deploy_key) } - let(:handler) { described_class.new(actor) } - - it_behaves_like 'an LFS token generator' - - it 'returns the correct username' do - expect(handler.actor_name).to eq("lfs+deploy-key-#{actor.id}") - end - - it 'returns the correct token type' do - expect(handler.type).to eq(:lfs_deploy_token) - end - end - end -end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 46e8e6f1169..46d1b868782 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -100,43 +100,6 @@ describe API::API, api: true do end end - describe "POST /internal/lfs_authenticate" do - before do - project.team << [user, :developer] - end - - context 'user key' do - it 'returns the correct information about the key' do - lfs_auth(key.id, project) - - expect(response).to have_http_status(200) - expect(json_response['username']).to eq(user.username) - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) - - expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) - end - - it 'returns a 404 when the wrong key is provided' do - lfs_auth(nil, project) - - expect(response).to have_http_status(404) - end - end - - context 'deploy key' do - let(:key) { create(:deploy_key) } - - it 'returns the correct information about the key' do - lfs_auth(key.id, project) - - expect(response).to have_http_status(200) - expect(json_response['username']).to eq("lfs+deploy-key-#{key.id}") - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) - expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) - end - end - end - describe "GET /internal/discover" do it do get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) @@ -426,13 +389,4 @@ describe API::API, api: true do protocol: 'ssh' ) end - - def lfs_auth(key_id, project) - post( - api("/internal/lfs_authenticate"), - key_id: key_id, - secret_token: secret_token, - project: project.path_with_namespace - ) - end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 09e4e265dd1..b58d410b7a3 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -245,18 +245,6 @@ describe 'Git LFS API and storage' do end end - context 'when deploy key is authorized' do - let(:key) { create(:deploy_key) } - let(:authorization) { authorize_deploy_key } - - let(:update_permissions) do - project.deploy_keys << key - project.lfs_objects << lfs_object - end - - it_behaves_like 'responds with a file' - end - context 'when build is authorized as' do let(:authorization) { authorize_ci_project } @@ -1109,10 +1097,6 @@ describe 'Git LFS API and storage' do ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) end - def authorize_deploy_key - ActionController::HttpAuthentication::Basic.encode_credentials("lfs+deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) - end - def fork_project(project, user, object = nil) allow(RepositoryForkWorker).to receive(:perform_async).and_return(true) Projects::ForkService.new(project, user, {}).execute -- cgit v1.2.1 From 135be3cabb01ca3c825829f18ede4e8720383d7b Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 14:23:18 +0200 Subject: Solve code review comments --- spec/requests/ci/api/builds_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 09d72fe0a0e..df97f1bf7b6 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -263,6 +263,7 @@ describe Ci::API::API do context "should authorize posting artifact to running build" do it "using token as parameter" do post authorize_url, { token: build.token }, headers + expect(response).to have_http_status(200) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) expect(json_response["TempPath"]).not_to be_nil @@ -270,6 +271,7 @@ describe Ci::API::API do it "using token as header" do post authorize_url, {}, headers_with_token + expect(response).to have_http_status(200) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) expect(json_response["TempPath"]).not_to be_nil @@ -277,6 +279,7 @@ describe Ci::API::API do it "using runners token" do post authorize_url, { token: build.project.runners_token }, headers + expect(response).to have_http_status(200) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) expect(json_response["TempPath"]).not_to be_nil @@ -284,7 +287,9 @@ describe Ci::API::API do it "reject requests that did not go through gitlab-workhorse" do headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER) + post authorize_url, { token: build.token }, headers + expect(response).to have_http_status(500) end end @@ -292,13 +297,17 @@ describe Ci::API::API do context "should fail to post too large artifact" do it "using token as parameter" do stub_application_setting(max_artifacts_size: 0) + post authorize_url, { token: build.token, filesize: 100 }, headers + expect(response).to have_http_status(413) end it "using token as header" do stub_application_setting(max_artifacts_size: 0) + post authorize_url, { filesize: 100 }, headers_with_token + expect(response).to have_http_status(413) end end -- cgit v1.2.1 From 3c1bb3432b0b8448262ec9a9a3468641c82db5c1 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 16:34:32 +0200 Subject: Revert "Revert all changes introduced by https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6043" This reverts commit 6d43c95b7011ec7ec4600e00bdc8df76bb39813c. --- spec/lib/gitlab/auth_spec.rb | 18 ++++++++++++++ spec/lib/gitlab/lfs_token_spec.rb | 51 ++++++++++++++++++++++++++++++++++++++ spec/requests/api/internal_spec.rb | 46 ++++++++++++++++++++++++++++++++++ spec/requests/lfs_http_spec.rb | 16 ++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 spec/lib/gitlab/lfs_token_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 8807a68a0a2..21f0d46100e 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -61,6 +61,24 @@ 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) + ip = 'ip' + token = Gitlab::LfsToken.new(user).generate + + 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, read_authentication_abilities)) + end + + it 'recognizes deploy key lfs tokens' do + key = create(:deploy_key) + ip = 'ip' + token = Gitlab::LfsToken.new(key).generate + + 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 + it 'recognizes OAuth tokens' do user = create(:user) application = Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb new file mode 100644 index 00000000000..9f04f67e0a8 --- /dev/null +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe Gitlab::LfsToken, lib: true do + describe '#generate and #value' do + shared_examples 'an LFS token generator' do + it 'returns a randomly generated token' do + token = handler.generate + + expect(token).not_to be_nil + expect(token).to be_a String + expect(token.length).to eq 50 + end + + it 'returns the correct token based on the key' do + token = handler.generate + + expect(handler.value).to eq(token) + end + end + + context 'when the actor is a user' do + let(:actor) { create(:user) } + let(:handler) { described_class.new(actor) } + + it_behaves_like 'an LFS token generator' + + it 'returns the correct username' do + expect(handler.actor_name).to eq(actor.username) + end + + it 'returns the correct token type' do + expect(handler.type).to eq(:lfs_token) + end + end + + context 'when the actor is a deploy key' do + let(:actor) { create(:deploy_key) } + let(:handler) { described_class.new(actor) } + + it_behaves_like 'an LFS token generator' + + it 'returns the correct username' do + expect(handler.actor_name).to eq("lfs+deploy-key-#{actor.id}") + end + + it 'returns the correct token type' do + expect(handler.type).to eq(:lfs_deploy_token) + end + end + end +end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 46d1b868782..46e8e6f1169 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -100,6 +100,43 @@ describe API::API, api: true do end end + describe "POST /internal/lfs_authenticate" do + before do + project.team << [user, :developer] + end + + context 'user key' do + it 'returns the correct information about the key' do + lfs_auth(key.id, project) + + expect(response).to have_http_status(200) + expect(json_response['username']).to eq(user.username) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) + + expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) + end + + it 'returns a 404 when the wrong key is provided' do + lfs_auth(nil, project) + + expect(response).to have_http_status(404) + end + end + + context 'deploy key' do + let(:key) { create(:deploy_key) } + + it 'returns the correct information about the key' do + lfs_auth(key.id, project) + + expect(response).to have_http_status(200) + expect(json_response['username']).to eq("lfs+deploy-key-#{key.id}") + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) + expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) + end + end + end + describe "GET /internal/discover" do it do get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) @@ -389,4 +426,13 @@ describe API::API, api: true do protocol: 'ssh' ) end + + def lfs_auth(key_id, project) + post( + api("/internal/lfs_authenticate"), + key_id: key_id, + secret_token: secret_token, + project: project.path_with_namespace + ) + end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index b58d410b7a3..09e4e265dd1 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -245,6 +245,18 @@ describe 'Git LFS API and storage' do end end + context 'when deploy key is authorized' do + let(:key) { create(:deploy_key) } + let(:authorization) { authorize_deploy_key } + + let(:update_permissions) do + project.deploy_keys << key + project.lfs_objects << lfs_object + end + + it_behaves_like 'responds with a file' + end + context 'when build is authorized as' do let(:authorization) { authorize_ci_project } @@ -1097,6 +1109,10 @@ describe 'Git LFS API and storage' do ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) end + def authorize_deploy_key + ActionController::HttpAuthentication::Basic.encode_credentials("lfs+deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) + end + def fork_project(project, user, object = nil) allow(RepositoryForkWorker).to receive(:perform_async).and_return(true) Projects::ForkService.new(project, user, {}).execute -- cgit v1.2.1 From 028c086f902f56e26db6382caa6131404ce74dcd Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 16 Sep 2016 16:05:12 +0200 Subject: Restrict last_activity_at updates to one per hour The lock in turn is only obtained when actually needed, reducing some load on Redis. Fixes gitlab-org/gitlab-ce#22213 --- spec/models/event_spec.rb | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index b5d0d79e14e..8600eb4d2c4 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -16,18 +16,12 @@ describe Event, models: true do describe 'Callbacks' do describe 'after_create :reset_project_activity' do - let(:project) { create(:project) } + let(:project) { create(:empty_project) } - context "project's last activity was less than 5 minutes ago" do - it 'does not update project.last_activity_at if it has been touched less than 5 minutes ago' do - create_event(project, project.owner) - project.update_column(:last_activity_at, 5.minutes.ago) - project_last_activity_at = project.last_activity_at + it 'calls the reset_project_activity method' do + expect_any_instance_of(Event).to receive(:reset_project_activity) - create_event(project, project.owner) - - expect(project.last_activity_at).to eq(project_last_activity_at) - end + create_event(project, project.owner) end end end @@ -161,6 +155,35 @@ describe Event, models: true do end end + describe '#reset_project_activity' do + let(:project) { create(:empty_project) } + + context 'when a project was updated less than 1 hour ago' do + it 'does not update the project' do + project.update(last_activity_at: Time.now) + + expect(project).not_to receive(:update_column). + with(:last_activity_at, a_kind_of(Time)) + + create_event(project, project.owner) + end + end + + context 'when a project was updated more than 1 hour ago' do + it 'updates the project' do + project.update(last_activity_at: 1.year.ago) + + expect_any_instance_of(Gitlab::ExclusiveLease). + to receive(:try_obtain).and_return(true) + + expect(project).to receive(:update_column). + with(:last_activity_at, a_kind_of(Time)) + + create_event(project, project.owner) + end + end + end + def create_event(project, user, attrs = {}) data = { before: Gitlab::Git::BLANK_SHA, -- cgit v1.2.1 From e0067d185005f563b0f8dad9e150d922419c0ea2 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 14 Sep 2016 19:04:27 -0300 Subject: Allow to set request_access_enabled for groups and projects using API --- spec/requests/api/groups_spec.rb | 11 +++++++++-- spec/requests/api/projects_spec.rb | 18 +++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 4860b23c2ed..1f68ef1af8f 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -120,10 +120,11 @@ describe API::API, api: true do context 'when authenticated as the group owner' do it 'updates the group' do - put api("/groups/#{group1.id}", user1), name: new_group_name + put api("/groups/#{group1.id}", user1), name: new_group_name, request_access_enabled: true expect(response).to have_http_status(200) expect(json_response['name']).to eq(new_group_name) + expect(json_response['request_access_enabled']).to eq(true) end it 'returns 404 for a non existing group' do @@ -238,8 +239,14 @@ describe API::API, api: true do context "when authenticated as user with group permissions" do it "creates group" do - post api("/groups", user3), attributes_for(:group) + group = attributes_for(:group, { request_access_enabled: false }) + + post api("/groups", user3), group expect(response).to have_http_status(201) + + expect(json_response["name"]).to eq(group[:name]) + expect(json_response["path"]).to eq(group[:path]) + expect(json_response["request_access_enabled"]).to eq(group[:request_access_enabled]) end it "does not create group, duplicate" do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 28aa56e8644..192c7d14c13 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -225,7 +225,8 @@ describe API::API, api: true do issues_enabled: false, merge_requests_enabled: false, wiki_enabled: false, - only_allow_merge_if_build_succeeds: false + only_allow_merge_if_build_succeeds: false, + request_access_enabled: true }) post api('/projects', user), project @@ -352,7 +353,8 @@ describe API::API, api: true do description: FFaker::Lorem.sentence, issues_enabled: false, merge_requests_enabled: false, - wiki_enabled: false + wiki_enabled: false, + request_access_enabled: true }) post api("/projects/user/#{user.id}", admin), project @@ -887,6 +889,15 @@ describe API::API, api: true do expect(json_response['message']['name']).to eq(['has already been taken']) end + it 'updates request_access_enabled' do + project_param = { request_access_enabled: false } + + put api("/projects/#{project.id}", user), project_param + + expect(response).to have_http_status(200) + expect(json_response['request_access_enabled']).to eq(false) + end + it 'updates path & name to existing path & name in different namespace' do project_param = { path: project4.path, name: project4.name } put api("/projects/#{project3.id}", user), project_param @@ -948,7 +959,8 @@ describe API::API, api: true do wiki_enabled: true, snippets_enabled: true, merge_requests_enabled: true, - description: 'new description' } + description: 'new description', + request_access_enabled: true } put api("/projects/#{project.id}", user3), project_param expect(response).to have_http_status(403) end -- cgit v1.2.1 From e0f596c99debe880dfcaed66220a9483d0c81e7b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 23:51:27 +0800 Subject: Show all pipelines from all merge_request_diffs: This way we could also show pipelines from commits which were discarded due to a force push. --- spec/models/merge_request_spec.rb | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 06feeb1bbba..fb599e1207d 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -495,15 +495,34 @@ describe MergeRequest, models: true do end describe '#all_pipelines' do - let!(:pipelines) do - subject.merge_request_diff.commits.map do |commit| - create(:ci_empty_pipeline, project: subject.source_project, sha: commit.id, ref: subject.source_branch) + shared_examples 'returning pipelines with proper ordering' do + let!(:pipelines) do + subject.merge_request_diffs.flat_map do |diff| + diff.commits.map do |commit| + create(:ci_empty_pipeline, + project: subject.source_project, + sha: commit.id, + ref: subject.source_branch) + end + end + end + + it 'returns all pipelines' do + expect(subject.all_pipelines).not_to be_empty + expect(subject.all_pipelines).to eq(pipelines.reverse) end end - it 'returns a pipelines from source projects with proper ordering' do - expect(subject.all_pipelines).not_to be_empty - expect(subject.all_pipelines).to eq(pipelines.reverse) + context 'with single merge_request_diffs' do + it_behaves_like 'returning pipelines with proper ordering' + end + + context 'with multiple irrelevant merge_request_diffs' do + before do + subject.update(target_branch: 'markdown') + end + + it_behaves_like 'returning pipelines with proper ordering' end end -- cgit v1.2.1 From 25004cbc32432d989a05532925c5c4c591cca1b5 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 3 Jun 2016 11:44:04 +0200 Subject: Snippets get award emoji! :thumbsup: --- spec/controllers/snippets_controller_spec.rb | 31 ++++++++++++++++++++++++++-- spec/models/snippet_spec.rb | 2 ++ spec/requests/api/award_emoji_spec.rb | 7 +++++++ 3 files changed, 38 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index 2a89159c070..2ea57e50e76 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' describe SnippetsController do - describe 'GET #show' do - let(:user) { create(:user) } + let(:user) { create(:user) } + describe 'GET #show' do context 'when the personal snippet is private' do let(:personal_snippet) { create(:personal_snippet, :private, author: user) } @@ -230,4 +230,31 @@ describe SnippetsController do end end end + + context 'award emoji on snippets' do + let(:personal_snippet) { create(:personal_snippet, :private, author: user) } + + before do + sign_in(user) + end + + describe 'POST #toggle_award_emoji' do + it "toggles the award emoji" do + expect do + post(:toggle_award_emoji, id: personal_snippet.to_param, name: "thumbsup") + end.to change { personal_snippet.award_emoji.count }.by(1) + + expect(response.status).to eq(200) + end + + it "removes the already awarded emoji" do + post(:toggle_award_emoji, id: personal_snippet.to_param, name: "thumbsup") + expect do + post(:toggle_award_emoji, id: personal_snippet.to_param, name: "thumbsup") + end.to change { personal_snippet.award_emoji.count }.by(-1) + + expect(response.status).to eq(200) + end + end + end end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 0621c6a06ce..e6bc5296398 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -9,12 +9,14 @@ describe Snippet, models: true do it { is_expected.to include_module(Participable) } it { is_expected.to include_module(Referable) } it { is_expected.to include_module(Sortable) } + it { is_expected.to include_module(Awardable) } end describe 'associations' do it { is_expected.to belong_to(:author).class_name('User') } it { is_expected.to belong_to(:project) } it { is_expected.to have_many(:notes).dependent(:destroy) } + it { is_expected.to have_many(:award_emoji).dependent(:destroy) } end describe 'validation' do diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index 981a6791881..f55702794f6 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -14,6 +14,9 @@ describe API::API, api: true do describe "GET /projects/:id/awardable/:awardable_id/award_emoji" do context 'on an issue' do + let(:issue) { create(:issue, project: project, author: user) } + let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) } + it "returns an array of award_emoji" do get api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user) @@ -39,6 +42,10 @@ describe API::API, api: true do end end + context 'on a snippet' do + it 'returns the awarded ' + end + context 'when the user has no access' do it 'returns a status code 404' do user1 = create(:user) -- cgit v1.2.1 From 7475f9d175482254b9b3097226b95a14c5325cff Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 30 Jun 2016 10:56:56 +0200 Subject: API support for Award Emoji on Snippets --- spec/requests/api/award_emoji_spec.rb | 55 +++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index f55702794f6..f94ed37ddbc 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -4,7 +4,7 @@ describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } let!(:project) { create(:project) } - let(:issue) { create(:issue, project: project) } + let(:issue) { create(:issue, project: project, author: user) } let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) } @@ -14,9 +14,6 @@ describe API::API, api: true do describe "GET /projects/:id/awardable/:awardable_id/award_emoji" do context 'on an issue' do - let(:issue) { create(:issue, project: project, author: user) } - let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) } - it "returns an array of award_emoji" do get api("/projects/#{project.id}/issues/#{issue.id}/award_emoji", user) @@ -43,7 +40,16 @@ describe API::API, api: true do end context 'on a snippet' do - it 'returns the awarded ' + let(:snippet) { create(:project_snippet, :public, project: project) } + let!(:award) { create(:award_emoji, awardable: snippet) } + + it 'returns the awarded emoji' do + get api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq(award.name) + end end context 'when the user has no access' do @@ -98,6 +104,20 @@ describe API::API, api: true do end end + context 'on a snippet' do + let(:snippet) { create(:project_snippet, :public, project: project) } + let!(:award) { create(:award_emoji, awardable: snippet) } + + it 'returns the awarded emoji' do + get api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user) + + expect(response).to have_http_status(200) + expect(json_response['name']).to eq(award.name) + expect(json_response['awardable_id']).to eq(snippet.id) + expect(json_response['awardable_type']).to eq("Snippet") + end + end + context 'when the user has no access' do it 'returns a status code 404' do user1 = create(:user) @@ -167,6 +187,18 @@ describe API::API, api: true do end end end + + context 'on a snippet' do + it 'creates a new award emoji' do + snippet = create(:project_snippet, :public, project: project) + + post api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji", user), name: 'blowfish' + + expect(response).to have_http_status(201) + expect(json_response['name']).to eq('blowfish') + expect(json_response['user']['username']).to eq(user.username) + end + end end describe "POST /projects/:id/awardable/:awardable_id/notes/:note_id/award_emoji" do @@ -236,6 +268,19 @@ describe API::API, api: true do expect(response).to have_http_status(404) end end + + context 'when the awardable is a Snippet' do + let(:snippet) { create(:project_snippet, :public, project: project) } + let!(:award) { create(:award_emoji, awardable: snippet, user: user) } + + it 'deletes the award' do + expect do + delete api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user) + end.to change { snippet.award_emoji.count }.from(1).to(0) + + expect(response).to have_http_status(200) + end + end end describe 'DELETE /projects/:id/awardable/:awardable_id/award_emoji/:award_emoji_id' do -- cgit v1.2.1 From e8dd0d54cb1e82d142978224a4e062a705cae2cf Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 7 Sep 2016 14:48:43 +0200 Subject: Fix tests for Snippets toggling awards Also incorporate feedback --- spec/controllers/snippets_controller_spec.rb | 10 ++++++---- spec/requests/api/award_emoji_spec.rb | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index 2ea57e50e76..41d263a46a4 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -232,26 +232,28 @@ describe SnippetsController do end context 'award emoji on snippets' do - let(:personal_snippet) { create(:personal_snippet, :private, author: user) } + let(:personal_snippet) { create(:personal_snippet, :public, author: user) } + let(:another_user) { create(:user) } before do - sign_in(user) + sign_in(another_user) end describe 'POST #toggle_award_emoji' do it "toggles the award emoji" do expect do post(:toggle_award_emoji, id: personal_snippet.to_param, name: "thumbsup") - end.to change { personal_snippet.award_emoji.count }.by(1) + end.to change { personal_snippet.award_emoji.count }.from(0).to(1) expect(response.status).to eq(200) end it "removes the already awarded emoji" do post(:toggle_award_emoji, id: personal_snippet.to_param, name: "thumbsup") + expect do post(:toggle_award_emoji, id: personal_snippet.to_param, name: "thumbsup") - end.to change { personal_snippet.award_emoji.count }.by(-1) + end.to change { personal_snippet.award_emoji.count }.from(1).to(0) expect(response.status).to eq(200) end diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb index f94ed37ddbc..5ad4fc4865a 100644 --- a/spec/requests/api/award_emoji_spec.rb +++ b/spec/requests/api/award_emoji_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } - let!(:project) { create(:project) } - let(:issue) { create(:issue, project: project, author: user) } + let!(:project) { create(:empty_project) } + let(:issue) { create(:issue, project: project) } let!(:award_emoji) { create(:award_emoji, awardable: issue, user: user) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) } -- cgit v1.2.1 From ace11553966cc7c313e666672de8c45418139429 Mon Sep 17 00:00:00 2001 From: Dan Dunckel Date: Thu, 8 Sep 2016 08:40:07 -0700 Subject: Add optional 'author' param when making commits --- spec/models/repository_spec.rb | 136 +++++++++++++++++++++++++++++++++++++++- spec/requests/api/files_spec.rb | 75 ++++++++++++++++++++++ 2 files changed, 209 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 94681004c96..db29f4d353b 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -16,6 +16,21 @@ describe Repository, models: true do merge_commit_id = repository.merge(user, merge_request, commit_options) repository.commit(merge_commit_id) end + let(:author_email) { FFaker::Internet.email } + + # I have to remove periods from the end of the name + # This happened when the user's name had a suffix (i.e. "Sr.") + # This seems to be what git does under the hood. For example, this commit: + # + # $ git commit --author='Foo Sr. ' -m 'Where's my trailing period?' + # + # results in this: + # + # $ git show --pretty + # ... + # Author: Foo Sr + # ... + let(:author_name) { FFaker::Name.name.chomp("\.") } describe '#branch_names_contains' do subject { repository.branch_names_contains(sample_commit.id) } @@ -132,7 +147,31 @@ describe Repository, models: true do end end - describe :commit_file 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') + end.to change { repository.commits('master').count }.by(1) + + newdir = repository.tree('master', 'newdir') + expect(newdir.path).to eq('newdir') + 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) + end.to change { repository.commits('master').count }.by(1) + + last_commit = repository.commit + + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end + end + + describe "#commit_file" do it 'commits change to a file successfully' do expect do repository.commit_file(user, 'CHANGELOG', 'Changelog!', @@ -144,9 +183,23 @@ describe Repository, models: true do expect(blob.data).to eq('Changelog!') 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_file(user, "README", 'README!', 'Add README', + 'master', true, author_email: author_email, author_name: author_name) + end.to change { repository.commits('master').count }.by(1) + + last_commit = repository.commit + + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end end - describe :update_file do + describe "#update_file" do it 'updates filename successfully' do expect do repository.update_file(user, 'NEWLICENSE', 'Copyright!', @@ -160,6 +213,85 @@ describe Repository, models: true do expect(files).not_to include('LICENSE') expect(files).to include('NEWLICENSE') end + + 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) + + 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) + end.to change { repository.commits('master').count }.by(1) + + last_commit = repository.commit + + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end + end + + describe "#remove_file" do + it 'removes file successfully' do + repository.commit_file(user, "README", 'README!', 'Add README', 'master', true) + + expect do + repository.remove_file(user, "README", "Remove README", 'master') + end.to change { repository.commits('master').count }.by(1) + + expect(repository.blob_at('master', 'README')).to be_nil + end + + 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) + + expect do + repository.remove_file(user, "README", "Remove README", 'master', author_email: author_email, author_name: author_name) + end.to change { repository.commits('master').count }.by(1) + + last_commit = repository.commit + + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end + end + + describe '#get_committer_and_author' do + it 'returns the committer and author data' do + options = repository.get_committer_and_author(user) + expect(options[:committer][:email]).to eq(user.email) + expect(options[:author][:email]).to eq(user.email) + end + + context 'when the email/name are given' do + it 'returns an object containing the email/name' do + options = repository.get_committer_and_author(user, email: author_email, name: author_name) + expect(options[:author][:email]).to eq(author_email) + expect(options[:author][:name]).to eq(author_name) + end + end + + context 'when the email is given but the name is not' do + it 'returns the committer as the author' do + options = repository.get_committer_and_author(user, email: author_email) + expect(options[:author][:email]).to eq(user.email) + expect(options[:author][:name]).to eq(user.name) + end + end + + context 'when the name is given but the email is not' do + it 'returns nil' do + options = repository.get_committer_and_author(user, name: author_name) + expect(options[:author][:email]).to eq(user.email) + expect(options[:author][:name]).to eq(user.name) + end + end end describe "search_files" do diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 2d1213df8a7..050d0dd082d 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -5,6 +5,21 @@ describe API::API, api: true do let(:user) { create(:user) } let!(:project) { create(:project, namespace: user.namespace ) } let(:file_path) { 'files/ruby/popen.rb' } + let(:author_email) { FFaker::Internet.email } + + # I have to remove periods from the end of the name + # This happened when the user's name had a suffix (i.e. "Sr.") + # This seems to be what git does under the hood. For example, this commit: + # + # $ git commit --author='Foo Sr. ' -m 'Where's my trailing period?' + # + # results in this: + # + # $ git show --pretty + # ... + # Author: Foo Sr + # ... + let(:author_name) { FFaker::Name.name.chomp("\.") } before { project.team << [user, :developer] } @@ -16,6 +31,7 @@ describe API::API, api: true do } get api("/projects/#{project.id}/repository/files", user), params + expect(response).to have_http_status(200) expect(json_response['file_path']).to eq(file_path) expect(json_response['file_name']).to eq('popen.rb') @@ -25,6 +41,7 @@ describe API::API, api: true do it "returns a 400 bad request if no params given" do get api("/projects/#{project.id}/repository/files", user) + expect(response).to have_http_status(400) end @@ -35,6 +52,7 @@ describe API::API, api: true do } get api("/projects/#{project.id}/repository/files", user), params + expect(response).to have_http_status(404) end end @@ -51,12 +69,17 @@ describe API::API, api: true do it "creates a new file in project repo" do post api("/projects/#{project.id}/repository/files", user), valid_params + expect(response).to have_http_status(201) expect(json_response['file_path']).to eq('newfile.rb') + last_commit = project.repository.commit.raw + expect(last_commit.author_email).to eq(user.email) + expect(last_commit.author_name).to eq(user.name) end it "returns a 400 bad request if no params given" do post api("/projects/#{project.id}/repository/files", user) + expect(response).to have_http_status(400) end @@ -65,8 +88,22 @@ describe API::API, api: true do and_return(false) post api("/projects/#{project.id}/repository/files", user), valid_params + expect(response).to have_http_status(400) end + + context "when specifying an author" do + it "creates a new file with the specified author" do + valid_params.merge!(author_email: author_email, author_name: author_name) + + post api("/projects/#{project.id}/repository/files", user), valid_params + + expect(response).to have_http_status(201) + last_commit = project.repository.commit.raw + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end end describe "PUT /projects/:id/repository/files" do @@ -81,14 +118,32 @@ describe API::API, api: true do it "updates existing file in project repo" do put api("/projects/#{project.id}/repository/files", user), valid_params + expect(response).to have_http_status(200) expect(json_response['file_path']).to eq(file_path) + last_commit = project.repository.commit.raw + expect(last_commit.author_email).to eq(user.email) + expect(last_commit.author_name).to eq(user.name) end it "returns a 400 bad request if no params given" do put api("/projects/#{project.id}/repository/files", user) + expect(response).to have_http_status(400) end + + context "when specifying an author" do + it "updates a file with the specified author" do + valid_params.merge!(author_email: author_email, author_name: author_name, content: "New content") + + put api("/projects/#{project.id}/repository/files", user), valid_params + + expect(response).to have_http_status(200) + last_commit = project.repository.commit.raw + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end end describe "DELETE /projects/:id/repository/files" do @@ -102,12 +157,17 @@ describe API::API, api: true do it "deletes existing file in project repo" do delete api("/projects/#{project.id}/repository/files", user), valid_params + expect(response).to have_http_status(200) expect(json_response['file_path']).to eq(file_path) + last_commit = project.repository.commit.raw + expect(last_commit.author_email).to eq(user.email) + expect(last_commit.author_name).to eq(user.name) end it "returns a 400 bad request if no params given" do delete api("/projects/#{project.id}/repository/files", user) + expect(response).to have_http_status(400) end @@ -115,8 +175,22 @@ describe API::API, api: true do allow_any_instance_of(Repository).to receive(:remove_file).and_return(false) delete api("/projects/#{project.id}/repository/files", user), valid_params + expect(response).to have_http_status(400) end + + context "when specifying an author" do + it "removes a file with the specified author" do + valid_params.merge!(author_email: author_email, author_name: author_name) + + delete api("/projects/#{project.id}/repository/files", user), valid_params + + expect(response).to have_http_status(200) + last_commit = project.repository.commit.raw + expect(last_commit.author_email).to eq(author_email) + expect(last_commit.author_name).to eq(author_name) + end + end end describe "POST /projects/:id/repository/files with binary file" do @@ -143,6 +217,7 @@ describe API::API, api: true do it "remains unchanged" do get api("/projects/#{project.id}/repository/files", user), get_params + expect(response).to have_http_status(200) expect(json_response['file_path']).to eq(file_path) expect(json_response['file_name']).to eq(file_path) -- cgit v1.2.1 From dba227da88357ee47126e5a8565fc67bdbddc255 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 19 Sep 2016 20:22:10 +0200 Subject: Fix test failure --- spec/lib/gitlab/auth_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 21f0d46100e..745fbc0df45 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -67,7 +67,7 @@ describe Gitlab::Auth, lib: true do token = Gitlab::LfsToken.new(user).generate 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, read_authentication_abilities)) + 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 -- cgit v1.2.1 From 97dc1b24d34b718b57a9e4dbf5c05c6218315eca Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 14 Sep 2016 13:55:07 +0200 Subject: Style merge request diff dropdowns & disable comments. --- .../merge_requests/merge_request_versions_spec.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_request_versions_spec.rb b/spec/features/merge_requests/merge_request_versions_spec.rb index 9e759de3752..c2ea3d8b954 100644 --- a/spec/features/merge_requests/merge_request_versions_spec.rb +++ b/spec/features/merge_requests/merge_request_versions_spec.rb @@ -21,7 +21,7 @@ feature 'Merge Request versions', js: true, feature: true do describe 'switch between versions' do before do page.within '.mr-version-dropdown' do - find('.btn-link').click + find('.btn-default').click click_link 'version 1' end end @@ -37,17 +37,18 @@ feature 'Merge Request versions', js: true, feature: true do it 'show the message about disabled comments' do expect(page).to have_content 'Comments are disabled' end + end describe 'compare with older version' do before do page.within '.mr-version-compare-dropdown' do - find('.btn-link').click + find('.btn-default').click click_link 'version 1' end end - it 'should has correct value in the compare dropdown' do + it 'should have correct value in the compare dropdown' do page.within '.mr-version-compare-dropdown' do expect(page).to have_content 'version 1' end @@ -64,5 +65,13 @@ feature 'Merge Request versions', js: true, feature: true do it 'show diff between new and old version' do expect(page).to have_content '4 changed files with 15 additions and 6 deletions' end + + it 'should return to latest version when "Show latest version" button is clicked' do + click_link 'Show latest version' + page.within '.mr-version-dropdown' do + expect(page).to have_content 'latest version' + end + expect(page).to have_content '8 changed files' + end end end -- cgit v1.2.1 From d20d7c98857c60c9e64628e04cdd7edc977a6aad Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 14 Sep 2016 22:18:02 +0200 Subject: Shush rubocop. --- spec/features/merge_requests/merge_request_versions_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_request_versions_spec.rb b/spec/features/merge_requests/merge_request_versions_spec.rb index c2ea3d8b954..22d9e42119d 100644 --- a/spec/features/merge_requests/merge_request_versions_spec.rb +++ b/spec/features/merge_requests/merge_request_versions_spec.rb @@ -37,7 +37,6 @@ feature 'Merge Request versions', js: true, feature: true do it 'show the message about disabled comments' do expect(page).to have_content 'Comments are disabled' end - end describe 'compare with older version' do -- cgit v1.2.1 From cf9ee8fda7dbb42f388f0044b22bd3ff2b30048c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 19 Sep 2016 19:59:29 -0700 Subject: Fix broken spec due to last_activity_at updates being throttled In https://gitlab.com/gitlab-org/gitlab-ce/builds/4218398, the build failed because the last_activity_at column was only being updated once per hour. We can fix this spec by stubbing out the throttling and adjusting the spec to test the right event timestamp. --- spec/factories/events.rb | 5 +++-- spec/models/project_spec.rb | 13 ++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/factories/events.rb b/spec/factories/events.rb index 90788f30ac9..8820d527c61 100644 --- a/spec/factories/events.rb +++ b/spec/factories/events.rb @@ -1,10 +1,11 @@ FactoryGirl.define do factory :event do + project + author factory: :user + factory :closed_issue_event do - project action { Event::CLOSED } target factory: :closed_issue - author factory: :user end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 7ca1bd1e5c9..a388ff703a6 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -308,20 +308,23 @@ describe Project, models: true do end describe 'last_activity methods' do - let(:project) { create(:project) } - let(:last_event) { double(created_at: Time.now) } + let(:timestamp) { Time.now - 2.hours } + let(:project) { create(:project, created_at: timestamp, updated_at: timestamp) } describe 'last_activity' do it 'alias last_activity to last_event' do - allow(project).to receive(:last_event).and_return(last_event) + last_event = create(:event, project: project) + expect(project.last_activity).to eq(last_event) end end describe 'last_activity_date' do it 'returns the creation date of the project\'s last event if present' do - create(:event, project: project) - expect(project.last_activity_at.to_i).to eq(last_event.created_at.to_i) + expect_any_instance_of(Event).to receive(:try_obtain_lease).and_return(true) + new_event = create(:event, project: project, created_at: Time.now) + + expect(project.last_activity_at.to_i).to eq(new_event.created_at.to_i) end it 'returns the project\'s last update date if it has no events' do -- cgit v1.2.1 From b335730817e096bb4c68e5e4a4a2a3ec29b25243 Mon Sep 17 00:00:00 2001 From: Maximiliano Perez Coto Date: Wed, 13 Jul 2016 20:56:54 -0300 Subject: Fix "Unsubscribe" link in notification emails that is triggered by anti-virus * Created a force=true param that will continue with the previous behaviour of the unsubscribe method * Created a filter for not-logged users so they see a unsubsribe confirmation page * Added the List-Unsubscribe header on emails so the email client can display it on top --- .../sent_notifications_controller_spec.rb | 103 ++++++++++++++++++--- spec/features/unsubscribe_links_spec.rb | 54 +++++++++++ spec/mailers/notify_spec.rb | 10 +- spec/mailers/shared/notify.rb | 8 ++ 4 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 spec/features/unsubscribe_links_spec.rb (limited to 'spec') diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb index 9ced397bd4a..4e75372ffb2 100644 --- a/spec/controllers/sent_notifications_controller_spec.rb +++ b/spec/controllers/sent_notifications_controller_spec.rb @@ -1,25 +1,102 @@ require 'rails_helper' describe SentNotificationsController, type: :controller do - let(:user) { create(:user) } - let(:issue) { create(:issue, author: user) } - let(:sent_notification) { create(:sent_notification, noteable: issue) } + let(:user) { create(:user) } + let(:project) { create(:empty_project) } + let(:sent_notification) { create(:sent_notification, noteable: issue, recipient: user) } - describe 'GET #unsubscribe' do - it 'returns a 404 when calling without existing id' do - get(:unsubscribe, id: '0' * 32) + let(:issue) do + create(:issue, project: project, author: user) do |issue| + issue.subscriptions.create(user: user, subscribed: true) + end + end + + describe 'GET unsubscribe' do + context 'when the user is not logged in' do + context 'when the force param is passed' do + before { get(:unsubscribe, id: sent_notification.reply_key, force: true) } + + it 'unsubscribes the user' do + expect(issue.subscribed?(user)).to be_falsey + end + + it 'sets the flash message' do + expect(controller).to set_flash[:notice].to(/unsubscribed/).now + end + + it 'redirects to the login page' do + expect(response).to redirect_to(new_user_session_path) + end + end + + context 'when the force param is not passed' do + before { get(:unsubscribe, id: sent_notification.reply_key) } + + it 'does not unsubscribe the user' do + expect(issue.subscribed?(user)).to be_truthy + end - expect(response.status).to be 404 + it 'does not set the flash message' do + expect(controller).not_to set_flash[:notice] + end + + it 'redirects to the login page' do + expect(response).to redirect_to(new_user_session_path) + end + end end - context 'calling with id' do - it 'shows a flash message to the user' do - get(:unsubscribe, id: sent_notification.reply_key) + context 'when the user is logged in' do + before { sign_in(user) } + + context 'when the ID passed does not exist' do + before { get(:unsubscribe, id: sent_notification.reply_key.reverse) } + + it 'does not unsubscribe the user' do + expect(issue.subscribed?(user)).to be_truthy + end + + it 'does not set the flash message' do + expect(controller).not_to set_flash[:notice] + end + + it 'returns a 404' do + expect(response).to have_http_status(:not_found) + end + end + + context 'when the force param is passed' do + before { get(:unsubscribe, id: sent_notification.reply_key, force: true) } + + it 'unsubscribes the user' do + expect(issue.subscribed?(user)).to be_falsey + end + + it 'sets the flash message' do + expect(controller).to set_flash[:notice].to(/unsubscribed/).now + end + + it 'redirects to the issue page' do + expect(response). + to redirect_to(namespace_project_issue_path(project.namespace, project, issue)) + end + end + + context 'when the force param is not passed' do + before { get(:unsubscribe, id: sent_notification.reply_key) } + + it 'unsubscribes the user' do + expect(issue.subscribed?(user)).to be_falsey + end - expect(response.status).to be 302 + it 'sets the flash message' do + expect(controller).to set_flash[:notice].to(/unsubscribed/).now + end - expect(response).to redirect_to new_user_session_path - expect(controller).to set_flash[:notice].to(/unsubscribed/).now + it 'redirects to the issue page' do + expect(response). + to redirect_to(namespace_project_issue_path(project.namespace, project, issue)) + end end end end diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb new file mode 100644 index 00000000000..eafad1a726d --- /dev/null +++ b/spec/features/unsubscribe_links_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe 'Unsubscribe links', feature: true do + include Warden::Test::Helpers + + let(:recipient) { create(:user) } + let(:author) { create(:user) } + let(:project) { create(:empty_project, :public) } + let(:params) { { title: 'A bug!', description: 'Fix it!', assignee: recipient } } + let(:issue) { Issues::CreateService.new(project, author, params).execute } + + let(:mail) { ActionMailer::Base.deliveries.last } + let(:body) { Capybara::Node::Simple.new(mail.default_part_body.to_s) } + let(:header_link) { mail.header['List-Unsubscribe'] } + let(:body_link) { body.find_link('unsubscribe')['href'] } + + before do + perform_enqueued_jobs { issue } + end + + context 'when logged out' do + it 'redirects to the login page when visiting the link from the body' do + visit body_link + + expect(current_path).to eq new_user_session_path + expect(issue.subscribed?(recipient)).to be_truthy + end + + it 'unsubscribes from the issue when visiting the link from the header' do + visit header_link + + expect(page).to have_text('unsubscribed') + expect(issue.subscribed?(recipient)).to be_falsey + end + end + + context 'when logged in' do + before { login_as(recipient) } + + it 'unsubscribes from the issue when visiting the link from the email body' do + visit body_link + + expect(page).to have_text('unsubscribed') + expect(issue.subscribed?(recipient)).to be_falsey + end + + it 'unsubscribes from the issue when visiting the link from the header' do + visit header_link + + expect(page).to have_text('unsubscribed') + expect(issue.subscribed?(recipient)).to be_falsey + end + end +end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index eae9c060c38..0363bc74939 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -861,7 +861,7 @@ describe Notify do subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :create) } it_behaves_like 'it should not have Gmail Actions links' - it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'a user cannot unsubscribe through footer link' it_behaves_like 'an email with X-GitLab headers containing project details' it_behaves_like 'an email that contains a header with author username' @@ -914,7 +914,7 @@ describe Notify do subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :delete) } it_behaves_like 'it should not have Gmail Actions links' - it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'a user cannot unsubscribe through footer link' it_behaves_like 'an email with X-GitLab headers containing project details' it_behaves_like 'an email that contains a header with author username' @@ -936,7 +936,7 @@ describe Notify do subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) } it_behaves_like 'it should not have Gmail Actions links' - it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'a user cannot unsubscribe through footer link' it_behaves_like 'an email with X-GitLab headers containing project details' it_behaves_like 'an email that contains a header with author username' @@ -964,7 +964,7 @@ describe Notify do subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, diff_refs: diff_refs, send_from_committer_email: send_from_committer_email) } it_behaves_like 'it should not have Gmail Actions links' - it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'a user cannot unsubscribe through footer link' it_behaves_like 'an email with X-GitLab headers containing project details' it_behaves_like 'an email that contains a header with author username' @@ -1066,7 +1066,7 @@ describe Notify do subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, diff_refs: diff_refs) } it_behaves_like 'it should show Gmail Actions View Commit link' - it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'a user cannot unsubscribe through footer link' it_behaves_like 'an email with X-GitLab headers containing project details' it_behaves_like 'an email that contains a header with author username' diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 93de5850ba2..56872da9a8f 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -169,10 +169,18 @@ shared_examples 'it should show Gmail Actions View Commit link' do end shared_examples 'an unsubscribeable thread' do + it 'has a List-Unsubscribe header' do + is_expected.to have_header 'List-Unsubscribe', /unsubscribe/ + end + it { is_expected.to have_body_text /unsubscribe/ } end shared_examples 'a user cannot unsubscribe through footer link' do + it 'does not have a List-Unsubscribe header' do + is_expected.not_to have_header 'List-Unsubscribe', /unsubscribe/ + end + it { is_expected.not_to have_body_text /unsubscribe/ } end -- cgit v1.2.1 From c61a54f7fe932b9b76ce930aaccb04f897c4093b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 16 Sep 2016 17:08:09 +0200 Subject: Fix initial implementation to actually render the unsubscribe page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../sent_notifications_controller_spec.rb | 14 ++++++++--- spec/features/unsubscribe_links_spec.rb | 29 +++++++++++++++++++--- 2 files changed, 35 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb index 4e75372ffb2..191e290a118 100644 --- a/spec/controllers/sent_notifications_controller_spec.rb +++ b/spec/controllers/sent_notifications_controller_spec.rb @@ -41,7 +41,7 @@ describe SentNotificationsController, type: :controller do end it 'redirects to the login page' do - expect(response).to redirect_to(new_user_session_path) + expect(response).to render_template :unsubscribe end end end @@ -83,19 +83,25 @@ describe SentNotificationsController, type: :controller do end context 'when the force param is not passed' do + let(:merge_request) do + create(:merge_request, source_project: project, author: user) do |merge_request| + merge_request.subscriptions.create(user: user, subscribed: true) + end + end + let(:sent_notification) { create(:sent_notification, noteable: merge_request, recipient: user) } before { get(:unsubscribe, id: sent_notification.reply_key) } it 'unsubscribes the user' do - expect(issue.subscribed?(user)).to be_falsey + expect(merge_request.subscribed?(user)).to be_falsey end it 'sets the flash message' do expect(controller).to set_flash[:notice].to(/unsubscribed/).now end - it 'redirects to the issue page' do + it 'redirects to the merge request page' do expect(response). - to redirect_to(namespace_project_issue_path(project.namespace, project, issue)) + to redirect_to(namespace_project_merge_request_path(project.namespace, project, merge_request)) end end end diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index eafad1a726d..3802f5f1335 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -19,11 +19,32 @@ describe 'Unsubscribe links', feature: true do end context 'when logged out' do - it 'redirects to the login page when visiting the link from the body' do - visit body_link + context 'when visiting the link from the body' do + it 'shows the unsubscribe confirmation page and redirects to root path when confirming' do + visit body_link + + expect(current_path).to eq unsubscribe_sent_notification_path(SentNotification.last) + expect(page).to have_text(%(Unsubscribe from issue "#{issue.title}" (#{issue.to_reference}))) + expect(page).to have_text(%(Are you sure you want to unsubscribe from issue "#{issue.title}" (#{issue.to_reference})?)) + expect(issue.subscribed?(recipient)).to be_truthy + + click_link 'Unsubscribe' + + expect(issue.subscribed?(recipient)).to be_falsey + expect(current_path).to eq new_user_session_path + end + + it 'shows the unsubscribe confirmation page and redirects to root path when canceling' do + visit body_link + + expect(current_path).to eq unsubscribe_sent_notification_path(SentNotification.last) + expect(issue.subscribed?(recipient)).to be_truthy + + click_link 'Cancel' - expect(current_path).to eq new_user_session_path - expect(issue.subscribed?(recipient)).to be_truthy + expect(issue.subscribed?(recipient)).to be_truthy + expect(current_path).to eq new_user_session_path + end end it 'unsubscribes from the issue when visiting the link from the header' do -- cgit v1.2.1 From 204419e9e9b01977cbeac34b1a8385239b1455aa Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 20 Sep 2016 09:54:42 +0530 Subject: Test the `CycleAnalytics::Summary` model. --- spec/factories/deployments.rb | 3 +- spec/models/cycle_analytics/summary_spec.rb | 53 +++++++++++++++++++++++++++++ spec/support/cycle_analytics_helpers.rb | 26 ++++++++++++-- 3 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 spec/models/cycle_analytics/summary_spec.rb (limited to 'spec') diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 82591604fcb..6f24bf58d14 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -3,11 +3,12 @@ FactoryGirl.define do sha '97de212e80737a608d939f648d959671fb0a0142' ref 'master' tag false + project nil environment factory: :environment after(:build) do |deployment, evaluator| - deployment.project = deployment.environment.project + deployment.project ||= deployment.environment.project end end end diff --git a/spec/models/cycle_analytics/summary_spec.rb b/spec/models/cycle_analytics/summary_spec.rb new file mode 100644 index 00000000000..743bc2da33f --- /dev/null +++ b/spec/models/cycle_analytics/summary_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe CycleAnalytics::Summary, models: true do + let(:project) { create(:project) } + let(:from) { Time.now } + let(:user) { create(:user, :admin) } + subject { described_class.new(project, from: from) } + + describe "#new_issues" do + it "finds the number of issues created after the 'from date'" do + Timecop.freeze(5.days.ago) { create(:issue, project: project) } + Timecop.freeze(5.days.from_now) { create(:issue, project: project) } + + expect(subject.new_issues).to eq(1) + end + + it "doesn't find issues from other projects" do + Timecop.freeze(5.days.from_now) { create(:issue, project: create(:project)) } + + expect(subject.new_issues).to eq(0) + end + end + + describe "#commits" do + it "finds the number of commits created after the 'from date'" do + Timecop.freeze(5.days.ago) { create_commit("Test message", project, user, 'master') } + Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master') } + + expect(subject.commits).to eq(1) + end + + it "doesn't find commits from other projects" do + Timecop.freeze(5.days.from_now) { create_commit("Test message", create(:project), user, 'master') } + + expect(subject.commits).to eq(0) + end + end + + describe "#deploys" do + it "finds the number of deploys made created after the 'from date'" do + Timecop.freeze(5.days.ago) { create(:deployment, project: project) } + Timecop.freeze(5.days.from_now) { create(:deployment, project: project) } + + expect(subject.deploys).to eq(1) + end + + it "doesn't find commits from other projects" do + Timecop.freeze(5.days.from_now) { create(:deployment, project: create(:project)) } + + expect(subject.deploys).to eq(0) + end + end +end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index c5fe1170423..ffd3eb60b80 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -1,8 +1,28 @@ module CycleAnalyticsHelpers def create_commit_referencing_issue(issue) - sha = project.repository.commit_file(user, random_git_name, "content", "Commit for ##{issue.iid}", "master", false) - commit = project.repository.commit(sha) - commit.create_cross_references!(user) + branch_name = random_git_name + project.repository.add_branch(user, branch_name, 'master') + create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name) + end + + def create_commit(message, project, user, branch_name) + filename = random_git_name + + options = { + committer: project.repository.user_to_committer(user), + author: project.repository.user_to_committer(user), + commit: { message: message, branch: branch_name, update_ref: true }, + file: { content: "content", path: filename, update: false } + } + + commit_sha = Gitlab::Git::Blob.commit(project.repository, options) + project.repository.commit(commit_sha) + + GitPushService.new(project, + user, + oldrev: project.repository.commit(branch_name).sha, + newrev: commit_sha, + ref: 'refs/heads/master').execute end def create_merge_request_closing_issue(issue, message: nil) -- cgit v1.2.1 From d0e101e997347b0b52d4ef3a945a0f26571546a2 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 20 Sep 2016 11:17:36 +0530 Subject: Fix all cycle analytics specs. A number of failures were introduced due to performance improvements (like pre-calculating metrics). --- spec/models/cycle_analytics/code_spec.rb | 9 +++++++- spec/models/cycle_analytics/issue_spec.rb | 14 +++++++++++- spec/models/cycle_analytics/plan_spec.rb | 17 ++++++++++++--- spec/models/cycle_analytics/review_spec.rb | 5 ++++- spec/models/cycle_analytics/test_spec.rb | 25 +++++++++++++++++++--- spec/support/cycle_analytics_helpers.rb | 15 +++++++------ .../cycle_analytics_helpers/test_generation.rb | 13 ++++++++++- 7 files changed, 82 insertions(+), 16 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 18dd4d0f1ab..e81c78df8f0 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -9,7 +9,11 @@ describe 'CycleAnalytics#code', feature: true do generate_cycle_analytics_spec(phase: :code, data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, start_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue]) }]], - end_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]]) + end_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]], + post_fn: -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) context "when a regular merge request (that doesn't close the issue) is created" do it "returns nil" do @@ -18,6 +22,9 @@ describe 'CycleAnalytics#code', feature: true do create_commit_referencing_issue(issue) create_merge_request_closing_issue(issue, message: "Closes nothing") + + merge_merge_requests_closing_issue(issue) + deploy_master end expect(subject.code).to be_nil diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 06715498d26..8d7d03193f0 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -3,13 +3,21 @@ require 'spec_helper' describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec(phase: :issue, data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, start_time_conditions: [["issue created", -> (context, data) { data[:issue].save }]], end_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) if data[:issue].persisted? }], - ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) if data[:issue].persisted? }]]) + ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) if data[:issue].persisted? }]], + post_fn: -> (context, data) do + if data[:issue].persisted? + context.create_merge_request_closing_issue(data[:issue].reload) + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end + end) context "when a regular label (instead of a list label) is added to the issue" do it "returns nil" do @@ -17,6 +25,10 @@ describe 'CycleAnalytics#issue', models: true do 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) + deploy_master end expect(subject.issue).to be_nil diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index fa092bf6825..aa779e5050f 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -7,17 +7,28 @@ describe 'CycleAnalytics#plan', feature: true do subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec(phase: :plan, - data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project), + branch_name: context.random_git_name } }, start_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) }], ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) }]], - end_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue]) }]]) + end_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue], branch_name: data[:branch_name]) }]], + post_fn: -> (context, data) do + context.create_merge_request_closing_issue(data[:issue], source_branch: data[:branch_name]) + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) context "when a regular label (instead of a list label) is added to the issue" do it "returns nil" do + branch_name = random_git_name label = create(:label) issue = create(:issue, project: project) issue.update(label_ids: [label.id]) - create_commit_referencing_issue(issue) + create_commit_referencing_issue(issue, branch_name: branch_name) + + create_merge_request_closing_issue(issue, source_branch: branch_name) + merge_merge_requests_closing_issue(issue) + deploy_master expect(subject.issue).to be_nil end diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 867a90d6258..100ce11299a 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -9,12 +9,15 @@ describe 'CycleAnalytics#review', feature: true do generate_cycle_analytics_spec(phase: :review, data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, start_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]], - end_time_conditions: [["merge request that closes issue is merged", -> (context, data) { context.merge_merge_requests_closing_issue(data[:issue]) }]]) + end_time_conditions: [["merge request that closes issue is merged", -> (context, data) { context.merge_merge_requests_closing_issue(data[:issue]) }]], + post_fn: -> (context, data) { context.deploy_master }) 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)) + + deploy_master end expect(subject.review).to be_nil diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index aa7faa74d38..79edc29c173 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -10,19 +10,30 @@ describe 'CycleAnalytics#test', feature: true do data_fn: lambda do |context| issue = context.create(:issue, project: context.project) merge_request = context.create_merge_request_closing_issue(issue) - { pipeline: context.create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha) } + { + pipeline: context.create(:ci_pipeline, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, project: context.project), + issue: issue + } end, start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]], - end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]]) + end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]], + post_fn: -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) context "when the pipeline is for a regular merge request (that doesn't close an issue)" do it "returns nil" do 5.times do - merge_request = create(:merge_request) + 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! + + merge_merge_requests_closing_issue(issue) + deploy_master end expect(subject.test).to be_nil @@ -36,6 +47,8 @@ describe 'CycleAnalytics#test', feature: true do pipeline.run! pipeline.succeed! + + deploy_master end expect(subject.test).to be_nil @@ -51,6 +64,9 @@ describe 'CycleAnalytics#test', feature: true do pipeline.run! pipeline.drop! + + merge_merge_requests_closing_issue(issue) + deploy_master end expect(subject.test).to be_nil @@ -66,6 +82,9 @@ describe 'CycleAnalytics#test', feature: true do pipeline.run! pipeline.cancel! + + merge_merge_requests_closing_issue(issue) + deploy_master end expect(subject.test).to be_nil diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index ffd3eb60b80..e8e760a6187 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -1,12 +1,12 @@ module CycleAnalyticsHelpers - def create_commit_referencing_issue(issue) - branch_name = random_git_name + def create_commit_referencing_issue(issue, branch_name: random_git_name) project.repository.add_branch(user, branch_name, 'master') create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name) end def create_commit(message, project, user, branch_name) filename = random_git_name + oldrev = project.repository.commit(branch_name).sha options = { committer: project.repository.user_to_committer(user), @@ -20,14 +20,17 @@ module CycleAnalyticsHelpers GitPushService.new(project, user, - oldrev: project.repository.commit(branch_name).sha, + oldrev: oldrev, newrev: commit_sha, ref: 'refs/heads/master').execute end - def create_merge_request_closing_issue(issue, message: nil) - source_branch = random_git_name - project.repository.add_branch(user, source_branch, 'master') + def create_merge_request_closing_issue(issue, message: nil, source_branch: nil) + if !source_branch || project.repository.commit(source_branch).blank? + source_branch = random_git_name + project.repository.add_branch(user, source_branch, 'master') + end + sha = project.repository.commit_file(user, random_git_name, "content", "commit message", source_branch, false) project.repository.commit(sha) diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb index 52609524564..4d5ce86691f 100644 --- a/spec/support/cycle_analytics_helpers/test_generation.rb +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -18,8 +18,9 @@ module CycleAnalyticsHelpers # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`). # Each `condition_fn` is expected to implement a case which consitutes the end of the given cycle analytics phase. # before_end_fn: This function is run before calling the end time conditions. Used for setup that needs to be run between the start and end conditions. + # post_fn: Code that needs to be run after running the end time conditions. - def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:, before_end_fn: nil) + def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:, before_end_fn: nil, post_fn: nil) combinations_of_start_time_conditions = (1..start_time_conditions.size).flat_map { |size| start_time_conditions.combination(size).to_a } combinations_of_end_time_conditions = (1..end_time_conditions.size).flat_map { |size| end_time_conditions.combination(size).to_a } @@ -44,6 +45,8 @@ module CycleAnalyticsHelpers Timecop.freeze(end_time) { condition_fn[self, data] } end + Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn + end_time - start_time end @@ -73,6 +76,8 @@ module CycleAnalyticsHelpers 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 end # Turn off the stub before checking assertions @@ -99,6 +104,8 @@ module CycleAnalyticsHelpers Timecop.freeze(end_time) { condition_fn[self, data] } end + Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn + expect(subject.send(phase)).to be_nil end end @@ -115,6 +122,8 @@ module CycleAnalyticsHelpers 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 end expect(subject.send(phase)).to be_nil @@ -132,6 +141,8 @@ module CycleAnalyticsHelpers 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 end expect(subject.send(phase)).to be_nil -- cgit v1.2.1 From 0c65112da79e177da3574458c3bb5befc349fd30 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 8 Aug 2016 15:05:58 +0200 Subject: modify github import JS and controller so we can now specify a namespace and/or name for a project. - Fixed and added specs. - Added different namespace options depending on user privilages - Updated docs. --- spec/controllers/import/github_controller_spec.rb | 46 ++++++++++++++++------ .../gitlab/github_import/project_creator_spec.rb | 2 +- 2 files changed, 35 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb index ebfbf54182b..4f96567192d 100644 --- a/spec/controllers/import/github_controller_spec.rb +++ b/spec/controllers/import/github_controller_spec.rb @@ -124,8 +124,8 @@ describe Import::GithubController do context "when the GitHub user and GitLab user's usernames match" do it "takes the current user's namespace" do expect(Gitlab::GithubImport::ProjectCreator). - to receive(:new).with(github_repo, user.namespace, user, access_params). - and_return(double(execute: true)) + to receive(:new).with(github_repo, github_repo.name, user.namespace, user, access_params). + and_return(double(execute: true)) post :create, format: :js end @@ -136,8 +136,8 @@ describe Import::GithubController do it "takes the current user's namespace" do expect(Gitlab::GithubImport::ProjectCreator). - to receive(:new).with(github_repo, user.namespace, user, access_params). - and_return(double(execute: true)) + to receive(:new).with(github_repo, github_repo.name, user.namespace, user, access_params). + and_return(double(execute: true)) post :create, format: :js end @@ -158,8 +158,8 @@ describe Import::GithubController do context "when the namespace is owned by the GitLab user" do it "takes the existing namespace" do expect(Gitlab::GithubImport::ProjectCreator). - to receive(:new).with(github_repo, existing_namespace, user, access_params). - and_return(double(execute: true)) + to receive(:new).with(github_repo, github_repo.name, existing_namespace, user, access_params). + and_return(double(execute: true)) post :create, format: :js end @@ -171,9 +171,10 @@ describe Import::GithubController do existing_namespace.save end - it "doesn't create a project" do + it "creates a project using user's namespace" do expect(Gitlab::GithubImport::ProjectCreator). - not_to receive(:new) + to receive(:new).with(github_repo, github_repo.name, user.namespace, user, access_params). + and_return(double(execute: true)) post :create, format: :js end @@ -186,15 +187,15 @@ describe Import::GithubController do expect(Gitlab::GithubImport::ProjectCreator). to receive(:new).and_return(double(execute: true)) - expect { post :create, format: :js }.to change(Namespace, :count).by(1) + expect { post :create, target_namespace: github_repo.name, format: :js }.to change(Namespace, :count).by(1) end it "takes the new namespace" do expect(Gitlab::GithubImport::ProjectCreator). - to receive(:new).with(github_repo, an_instance_of(Group), user, access_params). + to receive(:new).with(github_repo, github_repo.name, an_instance_of(Group), user, access_params). and_return(double(execute: true)) - post :create, format: :js + post :create, target_namespace: github_repo.name, format: :js end end @@ -212,13 +213,34 @@ describe Import::GithubController do it "takes the current user's namespace" do expect(Gitlab::GithubImport::ProjectCreator). - to receive(:new).with(github_repo, user.namespace, user, access_params). + to receive(:new).with(github_repo, github_repo.name, user.namespace, user, access_params). and_return(double(execute: true)) post :create, format: :js end end end + + context 'user has chosen a namespace and name for the project' do + let(:test_namespace) { create(:namespace, name: 'test_namespace', owner: user) } + let(:test_name) { 'test_name' } + + it 'takes the selected namespace and name' do + expect(Gitlab::GithubImport::ProjectCreator). + to receive(:new).with(github_repo, test_name, test_namespace, user, access_params). + and_return(double(execute: true)) + + post :create, { target_namespace: test_namespace.name, new_name: test_name, format: :js } + end + + it 'takes the selected name and default namespace' do + expect(Gitlab::GithubImport::ProjectCreator). + to receive(:new).with(github_repo, test_name, user.namespace, user, access_params). + and_return(double(execute: true)) + + post :create, { new_name: test_name, format: :js } + end + end end end end diff --git a/spec/lib/gitlab/github_import/project_creator_spec.rb b/spec/lib/gitlab/github_import/project_creator_spec.rb index 014ee462e5c..ab06b7bc5bb 100644 --- a/spec/lib/gitlab/github_import/project_creator_spec.rb +++ b/spec/lib/gitlab/github_import/project_creator_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::GithubImport::ProjectCreator, lib: true do ) end - subject(:service) { described_class.new(repo, namespace, user, github_access_token: 'asdffg') } + subject(:service) { described_class.new(repo, repo.name, namespace, user, github_access_token: 'asdffg') } before do namespace.add_owner(user) -- cgit v1.2.1 From ce12749a8a64a880ff415941d7efc9e45d87aa94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 20 Sep 2016 09:52:06 +0200 Subject: Improve the Unsubscribe confirmation page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/unsubscribe_links_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index 3802f5f1335..cc40671787c 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -24,8 +24,8 @@ describe 'Unsubscribe links', feature: true do visit body_link expect(current_path).to eq unsubscribe_sent_notification_path(SentNotification.last) - expect(page).to have_text(%(Unsubscribe from issue "#{issue.title}" (#{issue.to_reference}))) - expect(page).to have_text(%(Are you sure you want to unsubscribe from issue "#{issue.title}" (#{issue.to_reference})?)) + expect(page).to have_text(%(Unsubscribe from issue #{issue.title} (#{issue.to_reference}))) + expect(page).to have_text(%(Are you sure you want to unsubscribe from issue #{issue.title} (#{issue.to_reference})?)) expect(issue.subscribed?(recipient)).to be_truthy click_link 'Unsubscribe' -- cgit v1.2.1 From e109166db2f3c16ae55642be3d31a581f76b70fc Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 20 Sep 2016 16:53:12 +0530 Subject: Fix spec failures. --- spec/models/ci/pipeline_spec.rb | 4 ++-- spec/models/issue/metrics_spec.rb | 8 ++++---- spec/models/merge_request/metrics_spec.rb | 2 +- spec/services/create_deployment_service_spec.rb | 6 +++--- spec/services/git_push_service_spec.rb | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 0b989b98b61..70051e4516d 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -197,7 +197,7 @@ describe Ci::Pipeline, models: true do time = Time.now Timecop.freeze(time) { build.run } - expect(merge_request.metrics.latest_build_started_at).to eq(time) + expect(merge_request.metrics.latest_build_started_at).to be_within(1.second).of(time) end it 'clears the build end time' do @@ -213,7 +213,7 @@ describe Ci::Pipeline, models: true do time = Time.now Timecop.freeze(time) { build.success } - expect(merge_request.metrics.latest_build_finished_at).to eq(time) + expect(merge_request.metrics.latest_build_finished_at).to be_within(1.second).of(time) end end end diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb index df977486943..e170b087ebc 100644 --- a/spec/models/issue/metrics_spec.rb +++ b/spec/models/issue/metrics_spec.rb @@ -13,7 +13,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_associated_with_milestone_at).to eq(time) + expect(metrics.first_associated_with_milestone_at).to be_within(1.second).of(time) end it "does not record the second time an issue is associated with a milestone" do @@ -24,7 +24,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_associated_with_milestone_at).to eq(time) + expect(metrics.first_associated_with_milestone_at).to be_within(1.second).of(time) end end @@ -36,7 +36,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_added_to_board_at).to eq(time) + expect(metrics.first_added_to_board_at).to be_within(1.second).of(time) end it "does not record the second time an issue is associated with a list label" do @@ -48,7 +48,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_added_to_board_at).to eq(time) + expect(metrics.first_added_to_board_at).to be_within(1.second).of(time) end end end diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb index 718b50642ad..a79dd215d41 100644 --- a/spec/models/merge_request/metrics_spec.rb +++ b/spec/models/merge_request/metrics_spec.rb @@ -12,7 +12,7 @@ describe MergeRequest::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.merged_at).to eq(time) + expect(metrics.merged_at).to be_within(1.second).of(time) end end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index f80f8953486..3a565fa44b5 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -190,7 +190,7 @@ describe CreateDeploymentService, services: true do time = Time.now Timecop.freeze(time) { service.execute } - expect(merge_request.metrics.first_deployed_to_production_at).to eq(time) + expect(merge_request.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) end it "doesn't set the time if the deploy's environment is not 'production'" do @@ -216,13 +216,13 @@ describe CreateDeploymentService, services: true do time = Time.now Timecop.freeze(time) { service.execute } - expect(merge_request.reload.metrics.first_deployed_to_production_at).to eq(time) + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) # Current deploy service = described_class.new(project, user, params) Timecop.freeze(time + 12.hours) { service.execute } - expect(merge_request.reload.metrics.first_deployed_to_production_at).to eq(time) + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index f2ef9f3dd81..cdf0d44a32b 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -364,7 +364,7 @@ describe GitPushService, services: true do it 'sets the metric for referenced issues' do execute_service(project, user, @oldrev, @newrev, @ref) - expect(issue.metrics.first_mentioned_in_commit_at).to eq(commit_time) + expect(issue.metrics.first_mentioned_in_commit_at).to be_within(1.second).of(commit_time) end it 'does not set the metric for non-referenced issues' do -- cgit v1.2.1 From 3970640b48fe9647ad97cf795aa2bb44a81d21a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 15 Sep 2016 16:57:06 +0200 Subject: Fix note form hint showing slash commands supported for commits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/projects/commits/note_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 spec/features/projects/commits/note_spec.rb (limited to 'spec') diff --git a/spec/features/projects/commits/note_spec.rb b/spec/features/projects/commits/note_spec.rb new file mode 100644 index 00000000000..bc42b63c371 --- /dev/null +++ b/spec/features/projects/commits/note_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe 'Projects > Commits > Note' do + let(:project) { create(:project) } + let(:commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') } + + before do + login_as :user + project.team << [@user, :master] + visit namespace_project_commit_path(project.namespace, project, commit.id) + end + + it 'says that only markdown is supported, not slash commands' do + expect(page).to have_content('Styling with Markdown is supported') + end +end -- cgit v1.2.1 From 929ff01ac08db320402c31bb70b463007d1b379d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 20 Sep 2016 10:23:13 +0200 Subject: Ensure we have a user before checking for their permission in Notes::SlashCommandsService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/services/notes/slash_commands_service_spec.rb | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'spec') diff --git a/spec/services/notes/slash_commands_service_spec.rb b/spec/services/notes/slash_commands_service_spec.rb index 4f231aab161..d1099884a02 100644 --- a/spec/services/notes/slash_commands_service_spec.rb +++ b/spec/services/notes/slash_commands_service_spec.rb @@ -122,6 +122,75 @@ describe Notes::SlashCommandsService, services: true do end end + describe '.noteable_update_service' do + include_context 'note on noteable' + + it 'returns Issues::UpdateService for a note on an issue' do + note = create(:note_on_issue, project: project) + + expect(described_class.noteable_update_service(note)).to eq(Issues::UpdateService) + end + + it 'returns Issues::UpdateService for a note on a merge request' do + note = create(:note_on_merge_request, project: project) + + expect(described_class.noteable_update_service(note)).to eq(MergeRequests::UpdateService) + end + + it 'returns nil for a note on a commit' do + note = create(:note_on_commit, project: project) + + expect(described_class.noteable_update_service(note)).to be_nil + end + end + + describe '.supported?' do + include_context 'note on noteable' + + let(:note) { create(:note_on_issue, project: project) } + + context 'with no current_user' do + it 'returns false' do + expect(described_class.supported?(note, nil)).to be_falsy + end + end + + context 'when current_user cannot update the noteable' do + it 'returns false' do + user = create(:user) + + expect(described_class.supported?(note, user)).to be_falsy + end + end + + context 'when current_user can update the noteable' do + it 'returns true' do + expect(described_class.supported?(note, master)).to be_truthy + end + + context 'with a note on a commit' do + let(:note) { create(:note_on_commit, project: project) } + + it 'returns false' do + expect(described_class.supported?(note, nil)).to be_falsy + end + end + end + end + + describe '#supported?' do + include_context 'note on noteable' + + it 'delegates to the class method' do + service = described_class.new(project, master) + note = create(:note_on_issue, project: project) + + expect(described_class).to receive(:supported?).with(note, master) + + service.supported?(note) + end + end + describe '#execute' do let(:service) { described_class.new(project, master) } -- cgit v1.2.1 From f6e5cc3c37f83044ca06d82aacf8ccb2796df724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 20 Sep 2016 10:45:00 +0200 Subject: Add a view spec for projects/notes/_form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/projects/commits/note_spec.rb | 16 ---------- spec/views/projects/notes/_form.html.haml_spec.rb | 36 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) delete mode 100644 spec/features/projects/commits/note_spec.rb create mode 100644 spec/views/projects/notes/_form.html.haml_spec.rb (limited to 'spec') diff --git a/spec/features/projects/commits/note_spec.rb b/spec/features/projects/commits/note_spec.rb deleted file mode 100644 index bc42b63c371..00000000000 --- a/spec/features/projects/commits/note_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -describe 'Projects > Commits > Note' do - let(:project) { create(:project) } - let(:commit) { project.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') } - - before do - login_as :user - project.team << [@user, :master] - visit namespace_project_commit_path(project.namespace, project, commit.id) - end - - it 'says that only markdown is supported, not slash commands' do - expect(page).to have_content('Styling with Markdown is supported') - end -end diff --git a/spec/views/projects/notes/_form.html.haml_spec.rb b/spec/views/projects/notes/_form.html.haml_spec.rb new file mode 100644 index 00000000000..932d6756ad2 --- /dev/null +++ b/spec/views/projects/notes/_form.html.haml_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe 'projects/notes/_form' do + include Devise::TestHelpers + + let(:user) { create(:user) } + let(:project) { create(:empty_project) } + + before do + project.team << [user, :master] + assign(:project, project) + assign(:note, note) + + allow(view).to receive(:current_user).and_return(user) + + render + end + + %w[issue merge_request].each do |noteable| + context "with a note on #{noteable}" do + let(:note) { build(:"note_on_#{noteable}", project: project) } + + it 'says that only markdown is supported, not slash commands' do + expect(rendered).to have_content('Styling with Markdown and slash commands are supported') + end + end + end + + context 'with a note on a commit' do + let(:note) { build(:note_on_commit, project: project) } + + it 'says that only markdown is supported, not slash commands' do + expect(rendered).to have_content('Styling with Markdown is supported') + end + end +end -- cgit v1.2.1 From 55de6e15d3b29c89a137e3e8824f02ddc4b7c1e7 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 20 Sep 2016 20:07:56 +0800 Subject: Test against MergeRequest#all_commits_sha, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6414#note_15750344 So that we could just use it in testing for MergeRequest#all_pipelines --- spec/models/merge_request_spec.rb | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index fb599e1207d..5baed2946e5 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -496,20 +496,18 @@ describe MergeRequest, models: true do describe '#all_pipelines' do shared_examples 'returning pipelines with proper ordering' do - let!(:pipelines) do - subject.merge_request_diffs.flat_map do |diff| - diff.commits.map do |commit| - create(:ci_empty_pipeline, - project: subject.source_project, - sha: commit.id, - ref: subject.source_branch) - end + let!(:all_pipelines) do + subject.all_commits_sha.map do |sha| + create(:ci_empty_pipeline, + project: subject.source_project, + sha: sha, + ref: subject.source_branch) end end it 'returns all pipelines' do expect(subject.all_pipelines).not_to be_empty - expect(subject.all_pipelines).to eq(pipelines.reverse) + expect(subject.all_pipelines).to eq(all_pipelines.reverse) end end @@ -526,6 +524,21 @@ describe MergeRequest, models: true do end end + describe '#all_commits_sha' do + let(:all_commits_sha) do + subject.merge_request_diffs.flat_map(&:commits).map(&:sha).uniq + end + + before do + subject.update(target_branch: 'markdown') + end + + it 'returns all SHA from all merge_request_diffs' do + expect(subject.merge_request_diffs.size).to eq(2) + expect(subject.all_commits_sha).to eq(all_commits_sha) + end + end + describe '#participants' do let(:project) { create(:project, :public) } -- cgit v1.2.1 From b674ab529ac26169249a91261a070da733cec84e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 20 Sep 2016 15:18:11 +0300 Subject: Add specs for ProjectTeam#fetch_members --- spec/factories/group_members.rb | 6 ++++ spec/models/project_team_spec.rb | 61 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) (limited to 'spec') diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb index 2044ebec09a..795df5dfda9 100644 --- a/spec/factories/group_members.rb +++ b/spec/factories/group_members.rb @@ -3,5 +3,11 @@ FactoryGirl.define do access_level { GroupMember::OWNER } group user + + trait(:guest) { access_level GroupMember::GUEST } + trait(:reporter) { access_level GroupMember::REPORTER } + trait(:developer) { access_level GroupMember::DEVELOPER } + trait(:master) { access_level GroupMember::MASTER } + trait(:owner) { access_level GroupMember::OWNER } end end diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 5eaf0d3b7a6..469e306044b 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -73,6 +73,67 @@ describe ProjectTeam, models: true do end end + describe '#fetch_members' do + context 'personal project' do + let(:project) { create(:empty_project) } + + it 'returns project members' do + user = create(:user) + project.team << [user, :guest] + + expect(project.team.members).to contain_exactly(user) + end + + it 'returns project members of a specified level' do + user = create(:user) + project.team << [user, :reporter] + + expect(project.team.guests).to be_empty + expect(project.team.reporters).to contain_exactly(user) + end + + it 'returns invited members of a group' do + group_member = create(:group_member) + + project.project_group_links.create!( + group: group_member.group, + group_access: Gitlab::Access::GUEST + ) + + expect(project.team.members).to contain_exactly(group_member.user) + end + + it 'returns invited members of a group of a specified level' do + group_member = create(:group_member) + + project.project_group_links.create!( + group: group_member.group, + group_access: Gitlab::Access::REPORTER + ) + + expect(project.team.reporters).to contain_exactly(group_member.user) + end + end + + context 'group project' do + let(:group) { create(:group) } + let(:project) { create(:empty_project, group: group) } + + it 'returns project members' do + group_member = create(:group_member, group: group) + + expect(project.team.members).to contain_exactly(group_member.user) + end + + it 'returns project members of a specified level' do + group_member = create(:group_member, :reporter, group: group) + + expect(project.team.guests).to be_empty + expect(project.team.reporters).to contain_exactly(group_member.user) + end + end + end + describe '#find_member' do context 'personal project' do let(:project) { create(:empty_project) } -- cgit v1.2.1 From a14d6a9e4ba755cd35f911d58e5c64ad56a81093 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 20 Sep 2016 20:51:14 +0800 Subject: Add a test for non-persisted merge request --- spec/models/merge_request_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 5baed2946e5..fce236bcb5d 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -522,6 +522,28 @@ describe MergeRequest, models: true do it_behaves_like 'returning pipelines with proper ordering' end + + context 'with unsaved merge request' do + let(:project) { create(:project) } + + subject do + MergeRequest.new(source_project: project, + target_project: project, + source_branch: 'master', + target_branch: 'feature') + end + + let!(:pipeline) do + create(:ci_empty_pipeline, + project: project, + sha: subject.diff_head_sha, + ref: subject.source_branch) + end + + it 'returns pipelines from diff_head_sha' do + expect(subject.all_pipelines).to contain_exactly(pipeline) + end + end end describe '#all_commits_sha' do -- cgit v1.2.1 From 231a9f5b8788aa0bbb2fa304f8b937f7c09fcee1 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Tue, 20 Sep 2016 18:21:59 +0530 Subject: Fix rubocop spec. And `scss_lint` --- spec/models/cycle_analytics/plan_spec.rb | 8 ++++++-- spec/services/merge_requests/update_service_spec.rb | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index aa779e5050f..4a66615e53b 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -7,8 +7,12 @@ describe 'CycleAnalytics#plan', feature: true do subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec(phase: :plan, - data_fn: -> (context) { { issue: context.create(:issue, project: context.project), - branch_name: context.random_git_name } }, + data_fn: -> (context) do + { + issue: context.create(:issue, project: context.project), + branch_name: context.random_git_name + } + end, start_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) }], ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) }]], end_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue], branch_name: data[:branch_name]) }]], diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index cfd506707de..84b0acffaac 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -276,7 +276,6 @@ describe MergeRequests::UpdateService, services: true do expect(merge_request.reload.issues_closed).to match_array([first_issue, second_issue]) end - end it 'removes `MergeRequestsClosingIssues` records when issues are not closed anymore' do opts = { @@ -297,5 +296,6 @@ describe MergeRequests::UpdateService, services: true do expect(merge_request.reload.issues_closed).to be_empty end + end end end -- cgit v1.2.1 From 418e95bd5f623c4cbeac8f5c2fdf2a50e8893339 Mon Sep 17 00:00:00 2001 From: barthc Date: Mon, 27 Jun 2016 21:22:19 +0100 Subject: fix issues mr counter --- spec/features/dashboard_issues_spec.rb | 9 ++++++ spec/features/issues/filter_issues_spec.rb | 44 ++++++++++++++++++++++++++---- spec/features/issues/reset_filters_spec.rb | 4 +-- spec/finders/issues_finder_spec.rb | 20 ++++++++++++-- 4 files changed, 67 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index 3fb1cb37544..fc914022a59 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -21,6 +21,9 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'No Milestone' + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '1') + end expect(page).to have_selector('.issue', count: 1) end @@ -29,6 +32,9 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'Any Milestone' + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '2') + end expect(page).to have_selector('.issue', count: 2) end @@ -39,6 +45,9 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link milestone.title end + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '1') + end expect(page).to have_selector('.issue', count: 1) end end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 69fda27cc61..72f39e2fbca 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -206,7 +206,7 @@ describe 'Filter issues', feature: true do context 'only text', js: true do it 'filters issues by searched text' do - fill_in 'issue_search', with: 'Bug' + fill_in 'issuable_search', with: 'Bug' page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) @@ -214,7 +214,7 @@ describe 'Filter issues', feature: true do end it 'does not show any issues' do - fill_in 'issue_search', with: 'testing' + fill_in 'issuable_search', with: 'testing' page.within '.issues-list' do expect(page).not_to have_selector('.issue') @@ -224,12 +224,16 @@ describe 'Filter issues', feature: true do context 'text and dropdown options', js: true do it 'filters by text and label' do - fill_in 'issue_search', with: 'Bug' + fill_in 'issuable_search', with: 'Bug' page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '2') + end + click_button 'Label' page.within '.labels-filter' do click_link 'bug' @@ -239,15 +243,23 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end + + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '1') + end end it 'filters by text and milestone' do - fill_in 'issue_search', with: 'Bug' + fill_in 'issuable_search', with: 'Bug' page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '2') + end + click_button 'Milestone' page.within '.milestone-filter' do click_link '8' @@ -256,15 +268,23 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end + + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '1') + end end it 'filters by text and assignee' do - fill_in 'issue_search', with: 'Bug' + fill_in 'issuable_search', with: 'Bug' page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '2') + end + click_button 'Assignee' page.within '.dropdown-menu-assignee' do click_link user.name @@ -273,15 +293,23 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end + + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '1') + end end it 'filters by text and author' do - fill_in 'issue_search', with: 'Bug' + fill_in 'issuable_search', with: 'Bug' page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '2') + end + click_button 'Author' page.within '.dropdown-menu-author' do click_link user.name @@ -290,6 +318,10 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end + + page.within '.issues-state-filters' do + expect(page).to have_selector('.active .badge', text: '1') + end end end end diff --git a/spec/features/issues/reset_filters_spec.rb b/spec/features/issues/reset_filters_spec.rb index 41f218eaa8b..f4d0f13c3d5 100644 --- a/spec/features/issues/reset_filters_spec.rb +++ b/spec/features/issues/reset_filters_spec.rb @@ -37,7 +37,7 @@ feature 'Issues filter reset button', feature: true, js: true do context 'when a text search has been conducted' do it 'resets the text search filter' do - visit_issues(project, issue_search: 'Bug') + visit_issues(project, search: 'Bug') expect(page).to have_css('.issue', count: 1) reset_filters @@ -67,7 +67,7 @@ feature 'Issues filter reset button', feature: true, js: true do context 'when all filters have been applied' do it 'resets all filters' do - visit_issues(project, assignee_id: user.id, author_id: user.id, milestone_title: milestone.title, label_name: bug.name, issue_search: 'Bug') + visit_issues(project, assignee_id: user.id, author_id: user.id, milestone_title: milestone.title, label_name: bug.name, search: 'Bug') expect(page).to have_css('.issue', count: 0) reset_filters diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index ec8809e6926..40bccb8e50b 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -7,8 +7,8 @@ describe IssuesFinder do let(:project2) { create(:empty_project) } let(:milestone) { create(:milestone, project: project1) } let(:label) { create(:label, project: project2) } - let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) } - let(:issue2) { create(:issue, author: user, assignee: user, project: project2) } + let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone, title: 'gitlab') } + let(:issue2) { create(:issue, author: user, assignee: user, project: project2, description: 'gitlab') } let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2) } let!(:label_link) { create(:label_link, label: label, target: issue2) } @@ -127,6 +127,22 @@ describe IssuesFinder do end end + context 'filtering by issue term' do + let(:params) { { search: 'git' } } + + it 'returns issues with title and description match for search term' do + expect(issues).to contain_exactly(issue1, issue2) + end + end + + context 'filtering by issue iid' do + let(:params) { { search: issue3.to_reference } } + + it 'returns issue with iid match' do + expect(issues).to contain_exactly(issue3) + end + end + context 'when the user is unauthorized' do let(:search_user) { nil } -- cgit v1.2.1 From 0672c5a92e8be90da0cb79f277bb7aee82fdba8a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Sep 2016 15:41:41 +0200 Subject: Post-merge improve of CI permissions --- spec/lib/ci/mask_secret_spec.rb | 12 +++++++++--- spec/lib/gitlab/git_access_spec.rb | 2 +- spec/requests/git_http_spec.rb | 6 +++--- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/mask_secret_spec.rb b/spec/lib/ci/mask_secret_spec.rb index 518de76911c..a6938533138 100644 --- a/spec/lib/ci/mask_secret_spec.rb +++ b/spec/lib/ci/mask_secret_spec.rb @@ -5,15 +5,21 @@ describe Ci::MaskSecret, lib: true do describe '#mask' do it 'masks exact number of characters' do - expect(subject.mask('token', 'oke')).to eq('txxxn') + expect(mask('token', 'oke')).to eq('txxxn') end it 'masks multiple occurrences' do - expect(subject.mask('token token token', 'oke')).to eq('txxxn txxxn txxxn') + expect(mask('token token token', 'oke')).to eq('txxxn txxxn txxxn') end it 'does not mask if not found' do - expect(subject.mask('token', 'not')).to eq('token') + expect(mask('token', 'not')).to eq('token') + end + + def mask(value, token) + value = value.dup + subject.mask!(value, token) + value end end end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index ed43646330f..de68e32e5b4 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -343,7 +343,7 @@ describe Gitlab::GitAccess, lib: true do end context 'to private project' do - let(:project) { create(:project, :internal) } + let(:project) { create(:project) } it { expect(subject).not_to be_allowed } end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index e3922bec689..74516686921 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -335,7 +335,7 @@ describe 'Git HTTP requests', lib: true do project.team << [user, :reporter] end - shared_examples 'can download code only from own projects' do + shared_examples 'can download code only' do it 'downloads get status 200' do clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token @@ -353,7 +353,7 @@ describe 'Git HTTP requests', lib: true do context 'administrator' do let(:user) { create(:admin) } - it_behaves_like 'can download code only from own projects' + it_behaves_like 'can download code only' it 'downloads from other project get status 403' do clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token @@ -365,7 +365,7 @@ describe 'Git HTTP requests', lib: true do context 'regular user' do let(:user) { create(:user) } - it_behaves_like 'can download code only from own projects' + it_behaves_like 'can download code only' it 'downloads from other project get status 404' do clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token -- cgit v1.2.1 From 93ab5856e4de9a13e730cf9d200e4f0934f4bece Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 21 Sep 2016 01:03:47 +0800 Subject: Use factory instead of using new directly. Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6414#note_15765156 --- spec/models/merge_request_spec.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index fce236bcb5d..38c2a28d3e1 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -524,18 +524,11 @@ describe MergeRequest, models: true do end context 'with unsaved merge request' do - let(:project) { create(:project) } - - subject do - MergeRequest.new(source_project: project, - target_project: project, - source_branch: 'master', - target_branch: 'feature') - end + subject { build(:merge_request) } let!(:pipeline) do create(:ci_empty_pipeline, - project: project, + project: subject.project, sha: subject.diff_head_sha, ref: subject.source_branch) end -- cgit v1.2.1 From cf6a35f09a3f38b124bd0e6013950f21b5bb1851 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 20 Sep 2016 17:07:34 +0200 Subject: Improve JwtController implementation --- spec/lib/ci/mask_secret_spec.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/mask_secret_spec.rb b/spec/lib/ci/mask_secret_spec.rb index a6938533138..3101bed20fb 100644 --- a/spec/lib/ci/mask_secret_spec.rb +++ b/spec/lib/ci/mask_secret_spec.rb @@ -16,10 +16,12 @@ describe Ci::MaskSecret, lib: true do expect(mask('token', 'not')).to eq('token') end + it 'does support null token' do + expect(mask('token', nil)).to eq('token') + end + def mask(value, token) - value = value.dup - subject.mask!(value, token) - value + subject.mask!(value.dup, token) end end end -- cgit v1.2.1 From 02d69091bc1d2ea4d14731b103efd5a5e2c9f040 Mon Sep 17 00:00:00 2001 From: Dan Dunckel Date: Tue, 20 Sep 2016 09:07:52 -0700 Subject: Add spec covering 'committer_hash' --- spec/lib/gitlab/git_spec.rb | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 spec/lib/gitlab/git_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb new file mode 100644 index 00000000000..219198eff60 --- /dev/null +++ b/spec/lib/gitlab/git_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe Gitlab::Git, lib: true do + let(:committer_email) { FFaker::Internet.email } + + # I have to remove periods from the end of the name + # This happened when the user's name had a suffix (i.e. "Sr.") + # This seems to be what git does under the hood. For example, this commit: + # + # $ git commit --author='Foo Sr. ' -m 'Where's my trailing period?' + # + # results in this: + # + # $ git show --pretty + # ... + # Author: Foo Sr + # ... + let(:committer_name) { FFaker::Name.name.chomp("\.") } + + describe 'committer_hash' do + it "returns a hash containing the given email and name" do + committer_hash = Gitlab::Git::committer_hash(email: committer_email, name: committer_name) + + expect(committer_hash[:email]).to eq(committer_email) + expect(committer_hash[:name]).to eq(committer_name) + expect(committer_hash[:time]).to be_a(Time) + end + + context 'when email is nil' do + it "returns nil" do + committer_hash = Gitlab::Git::committer_hash(email: nil, name: committer_name) + + expect(committer_hash).to be_nil + end + end + + context 'when name is nil' do + it "returns nil" do + committer_hash = Gitlab::Git::committer_hash(email: committer_email, name: nil) + + expect(committer_hash).to be_nil + end + end + end +end -- cgit v1.2.1 From 98559adf710eb2142ba072f2ac91a1db9d0578cf Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 19 Sep 2016 17:21:58 -0300 Subject: Test if issue authors can access private projects --- spec/policies/project_policy_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'spec') diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index eda1cafd65e..a7a06744428 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -33,4 +33,17 @@ describe ProjectPolicy, models: true do it 'returns increasing permissions for each level' do expect(users_permissions).to eq(users_permissions.sort.uniq) end + + it 'does not include the read_issue permission when the issue author is not a member of the private project' do + project = create(:project, :private) + issue = create(:issue, project: project) + user = issue.author + + expect(project.team.member?(issue.author)).to eq(false) + + expect(BasePolicy.class_for(project).abilities(user, project).can_set). + not_to include(:read_issue) + + expect(Ability.allowed?(user, :read_issue, project)).to be_falsy + end end -- cgit v1.2.1 From 6f558121b45f705624b76c2ba39491dc72810c13 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 20 Sep 2016 21:48:58 +0300 Subject: Fix a logic error in ProjectTeam#fetch_invited_members We were calling `.where` and `.send` on the relation, but never doing anything with the return value, resulting in proper access-level filtering never being of any consequence. --- spec/models/project_team_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 469e306044b..f979d66c88c 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -111,6 +111,7 @@ describe ProjectTeam, models: true do group_access: Gitlab::Access::REPORTER ) + expect(project.team.guests).to be_empty expect(project.team.reporters).to contain_exactly(group_member.user) end end -- cgit v1.2.1 From 918e589c2b29c18d9fe3a8e6c93a3f490c86beb1 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 21 Sep 2016 00:47:37 +0530 Subject: Implement a second round of review comments from @DouweM. - Don't use `TableReferences` - using `.arel_table` is shorter! - Move some database-related code to `Gitlab::Database` - Remove the `MergeRequest#issues_closed` and `Issue#closed_by_merge_requests` associations. They were either shadowing or were too similar to existing methods. They are not being used anywhere, so it's better to remove them to reduce confusion. - Use Rails 3-style validations - Index for `MergeRequest::Metrics#first_deployed_to_production_at` - Only include `CycleAnalyticsHelpers::TestGeneration` for specs that need it. - Other minor refactorings. --- spec/models/cycle_analytics/code_spec.rb | 25 ++++++++---- spec/models/cycle_analytics/issue_spec.rb | 37 ++++++++++++------ spec/models/cycle_analytics/plan_spec.rb | 42 ++++++++++++-------- spec/models/cycle_analytics/production_spec.rb | 37 ++++++++++-------- spec/models/cycle_analytics/review_spec.rb | 19 ++++++--- spec/models/cycle_analytics/staging_spec.rb | 45 ++++++++++++++-------- spec/models/cycle_analytics/test_spec.rb | 31 +++++++-------- .../services/merge_requests/create_service_spec.rb | 2 +- .../merge_requests/refresh_service_spec.rb | 2 +- .../services/merge_requests/update_service_spec.rb | 6 +-- .../cycle_analytics_helpers/test_generation.rb | 4 -- 11 files changed, 154 insertions(+), 96 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index e81c78df8f0..b9381e33914 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -1,19 +1,28 @@ require 'spec_helper' describe 'CycleAnalytics#code', feature: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :code, - data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, - start_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue]) }]], - end_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]], - post_fn: -> (context, data) do - context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master - end) + generate_cycle_analytics_spec( + phase: :code, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["issue mentioned in a commit", + -> (context, data) do + context.create_commit_referencing_issue(data[:issue]) + end]], + end_time_conditions: [["merge request that closes issue is created", + -> (context, data) do + context.create_merge_request_closing_issue(data[:issue]) + end]], + post_fn: -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) context "when a regular merge request (that doesn't close the issue) is created" do it "returns nil" do diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 8d7d03193f0..e9cc71254ab 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -1,23 +1,36 @@ require 'spec_helper' describe 'CycleAnalytics#issue', models: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :issue, - data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, - start_time_conditions: [["issue created", -> (context, data) { data[:issue].save }]], - end_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) if data[:issue].persisted? }], - ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) if data[:issue].persisted? }]], - post_fn: -> (context, data) do - if data[:issue].persisted? - context.create_merge_request_closing_issue(data[:issue].reload) - context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master - end - end) + generate_cycle_analytics_spec( + phase: :issue, + data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, + start_time_conditions: [["issue created", -> (context, data) { data[:issue].save }]], + end_time_conditions: [["issue associated with a milestone", + -> (context, data) do + if data[:issue].persisted? + data[:issue].update(milestone: context.create(:milestone, project: context.project)) + end + end], + ["list label added to issue", + -> (context, data) do + if data[:issue].persisted? + data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) + end + end]], + post_fn: -> (context, data) do + if data[:issue].persisted? + context.create_merge_request_closing_issue(data[:issue].reload) + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end + end) context "when a regular label (instead of a list label) is added to the issue" do it "returns nil" do diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 4a66615e53b..5b8c96dc992 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -1,26 +1,38 @@ require 'spec_helper' describe 'CycleAnalytics#plan', feature: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :plan, - data_fn: -> (context) do - { - issue: context.create(:issue, project: context.project), - branch_name: context.random_git_name - } - end, - start_time_conditions: [["issue associated with a milestone", -> (context, data) { data[:issue].update(milestone: context.create(:milestone, project: context.project)) }], - ["list label added to issue", -> (context, data) { data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) }]], - end_time_conditions: [["issue mentioned in a commit", -> (context, data) { context.create_commit_referencing_issue(data[:issue], branch_name: data[:branch_name]) }]], - post_fn: -> (context, data) do - context.create_merge_request_closing_issue(data[:issue], source_branch: data[:branch_name]) - context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master - end) + generate_cycle_analytics_spec( + phase: :plan, + data_fn: -> (context) do + { + issue: context.create(:issue, project: context.project), + branch_name: context.random_git_name + } + end, + start_time_conditions: [["issue associated with a milestone", + -> (context, data) do + data[:issue].update(milestone: context.create(:milestone, project: context.project)) + end], + ["list label added to issue", + -> (context, data) do + data[:issue].update(label_ids: [context.create(:label, lists: [context.create(:list)]).id]) + end]], + end_time_conditions: [["issue mentioned in a commit", + -> (context, data) do + context.create_commit_referencing_issue(data[:issue], branch_name: data[:branch_name]) + end]], + post_fn: -> (context, data) do + context.create_merge_request_closing_issue(data[:issue], source_branch: data[:branch_name]) + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) context "when a regular label (instead of a list label) is added to the issue" do it "returns nil" do diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 703f8d5f782..1f5e5cab92d 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -1,28 +1,31 @@ require 'spec_helper' describe 'CycleAnalytics#production', feature: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :production, - data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, - start_time_conditions: [["issue is created", -> (context, data) { data[:issue].save }]], - before_end_fn: lambda do |context, data| - context.create_merge_request_closing_issue(data[:issue]) - context.merge_merge_requests_closing_issue(data[:issue]) - end, - end_time_conditions: - [["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master }], - ["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) - context.project.repository.commit(sha) - - context.deploy_master - end]]) + generate_cycle_analytics_spec( + phase: :production, + data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } }, + start_time_conditions: [["issue is created", -> (context, data) { data[:issue].save }]], + before_end_fn: lambda do |context, data| + context.create_merge_request_closing_issue(data[:issue]) + context.merge_merge_requests_closing_issue(data[:issue]) + end, + end_time_conditions: + [["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master }], + ["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) + context.project.repository.commit(sha) + + context.deploy_master + end]]) context "when a regular merge request (that doesn't close the issue) is merged and deployed" do it "returns nil" do diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 100ce11299a..b6e26d8f261 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -1,16 +1,25 @@ require 'spec_helper' describe 'CycleAnalytics#review', feature: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :review, - data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, - start_time_conditions: [["merge request that closes issue is created", -> (context, data) { context.create_merge_request_closing_issue(data[:issue]) }]], - end_time_conditions: [["merge request that closes issue is merged", -> (context, data) { context.merge_merge_requests_closing_issue(data[:issue]) }]], - post_fn: -> (context, data) { context.deploy_master }) + generate_cycle_analytics_spec( + phase: :review, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["merge request that closes issue is created", + -> (context, data) do + context.create_merge_request_closing_issue(data[:issue]) + end]], + end_time_conditions: [["merge request that closes issue is merged", + -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + end]], + post_fn: -> (context, data) { context.deploy_master }) context "when a regular merge request (that doesn't close the issue) is created and merged" do it "returns nil" do diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index 105f566f41c..af1c4477ddb 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -1,26 +1,41 @@ require 'spec_helper' describe 'CycleAnalytics#staging', feature: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :staging, - data_fn: lambda do |context| - issue = context.create(:issue, project: context.project) - { issue: issue, merge_request: context.create_merge_request_closing_issue(issue) } - end, - start_time_conditions: [["merge request that closes issue is merged", -> (context, data) { context.merge_merge_requests_closing_issue(data[:issue])} ]], - end_time_conditions: [["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master }], - ["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) - context.project.repository.commit(sha) - - context.deploy_master - end]]) + generate_cycle_analytics_spec( + phase: :staging, + data_fn: lambda do |context| + issue = context.create(:issue, project: context.project) + { issue: issue, merge_request: context.create_merge_request_closing_issue(issue) } + end, + start_time_conditions: [["merge request that closes issue is merged", + -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + end ]], + end_time_conditions: [["merge request that closes issue is deployed to production", + -> (context, data) do + context.deploy_master + end], + ["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) + context.project.repository.commit(sha) + + context.deploy_master + end]]) context "when a regular merge request (that doesn't close the issue) is merged and deployed" do it "returns nil" do diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index 79edc29c173..89ace0b2742 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -1,26 +1,27 @@ require 'spec_helper' describe 'CycleAnalytics#test', feature: true do + extend CycleAnalyticsHelpers::TestGeneration + let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec(phase: :test, - data_fn: lambda do |context| - issue = context.create(:issue, project: context.project) - merge_request = context.create_merge_request_closing_issue(issue) - { - pipeline: context.create(:ci_pipeline, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, project: context.project), - issue: issue - } - end, - start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]], - end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]], - post_fn: -> (context, data) do - context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master - end) + generate_cycle_analytics_spec( + phase: :test, + data_fn: lambda do |context| + issue = context.create(:issue, project: context.project) + merge_request = context.create_merge_request_closing_issue(issue) + pipeline = context.create(:ci_pipeline, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, project: context.project) + { pipeline: pipeline, issue: issue } + end, + start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]], + end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]], + post_fn: -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) context "when the pipeline is for a regular merge request (that doesn't close an issue)" do it "returns nil" do diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index a0614abcf62..ff6bad6aaba 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -108,7 +108,7 @@ describe MergeRequests::CreateService, services: true do allow(service).to receive(:execute_hooks) merge_request = service.execute - expect(merge_request.issues_closed).to match_array([first_issue, second_issue]) + expect(merge_request.reload.closes_issues).to match_array([first_issue, second_issue]) end end end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 7ecad8d6bad..22cb122526c 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -200,7 +200,7 @@ describe MergeRequests::RefreshService, services: true do allow(refresh_service).to receive(:execute_hooks) refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature') - expect(merge_request.reload.issues_closed).to eq([issue]) + expect(merge_request.reload.closes_issues).to eq([issue]) end end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 84b0acffaac..68dd0382a3d 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -274,7 +274,7 @@ describe MergeRequests::UpdateService, services: true do allow(service).to receive(:execute_hooks) service.execute(merge_request) - expect(merge_request.reload.issues_closed).to match_array([first_issue, second_issue]) + expect(merge_request.reload.closes_issues).to match_array([first_issue, second_issue]) end it 'removes `MergeRequestsClosingIssues` records when issues are not closed anymore' do @@ -288,13 +288,13 @@ describe MergeRequests::UpdateService, services: true do merge_request = MergeRequests::CreateService.new(project, user, opts).execute - expect(merge_request.issues_closed).to match_array([first_issue, second_issue]) + expect(merge_request.reload.closes_issues).to match_array([first_issue, second_issue]) service = described_class.new(project, user, description: "not closing any issues") allow(service).to receive(:execute_hooks) service.execute(merge_request.reload) - expect(merge_request.reload.issues_closed).to be_empty + expect(merge_request.reload.closes_issues).to be_empty end end end diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb index 4d5ce86691f..8e19a6c92e2 100644 --- a/spec/support/cycle_analytics_helpers/test_generation.rb +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -159,7 +159,3 @@ module CycleAnalyticsHelpers end end end - -RSpec.configure do |config| - config.extend CycleAnalyticsHelpers::TestGeneration -end -- cgit v1.2.1 From 68e1b5bbc076398b2886fe1fe2cc440a52d7cab1 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 21 Sep 2016 01:22:20 +0530 Subject: Use the `IssuableBaseService` lifecycle hooks to cache `MergeRequestsClosingIssues` - Instead of overriding `create` and `update` in `MergeRequests::BaseService` - Get all merge request service specs passing --- spec/services/merge_requests/create_service_spec.rb | 2 +- spec/services/merge_requests/refresh_service_spec.rb | 2 +- spec/services/merge_requests/update_service_spec.rb | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index ff6bad6aaba..d400655617a 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -108,7 +108,7 @@ describe MergeRequests::CreateService, services: true do allow(service).to receive(:execute_hooks) merge_request = service.execute - expect(merge_request.reload.closes_issues).to match_array([first_issue, second_issue]) + expect(merge_request.reload.closes_issues(user)).to match_array([first_issue, second_issue]) end end end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 22cb122526c..dac4ba060c9 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -200,7 +200,7 @@ describe MergeRequests::RefreshService, services: true do allow(refresh_service).to receive(:execute_hooks) refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature') - expect(merge_request.reload.closes_issues).to eq([issue]) + expect(merge_request.reload.closes_issues(@user)).to eq([issue]) end end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 68dd0382a3d..e9c908ede78 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -274,7 +274,7 @@ describe MergeRequests::UpdateService, services: true do allow(service).to receive(:execute_hooks) service.execute(merge_request) - expect(merge_request.reload.closes_issues).to match_array([first_issue, second_issue]) + expect(merge_request.reload.closes_issues(user)).to match_array([first_issue, second_issue]) end it 'removes `MergeRequestsClosingIssues` records when issues are not closed anymore' do @@ -288,13 +288,13 @@ describe MergeRequests::UpdateService, services: true do merge_request = MergeRequests::CreateService.new(project, user, opts).execute - expect(merge_request.reload.closes_issues).to match_array([first_issue, second_issue]) + expect(merge_request.reload.closes_issues(user)).to match_array([first_issue, second_issue]) service = described_class.new(project, user, description: "not closing any issues") allow(service).to receive(:execute_hooks) service.execute(merge_request.reload) - expect(merge_request.reload.closes_issues).to be_empty + expect(merge_request.reload.closes_issues(user)).to be_empty end end end -- cgit v1.2.1 From a57c77f6c2aa79b23f9aa59e6552ffeb514607de Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 21 Sep 2016 02:15:02 +0530 Subject: Add a spec for merge request metric caching while refreshing a merge request from a forked project. --- .../services/merge_requests/create_service_spec.rb | 3 +- .../merge_requests/refresh_service_spec.rb | 36 +++++++++++++++++----- .../services/merge_requests/update_service_spec.rb | 9 ++++-- 3 files changed, 37 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index d400655617a..b8142889075 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -108,7 +108,8 @@ describe MergeRequests::CreateService, services: true do allow(service).to receive(:execute_hooks) merge_request = service.execute - expect(merge_request.reload.closes_issues(user)).to match_array([first_issue, second_issue]) + issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id) + expect(issue_ids).to match_array([first_issue.id, second_issue.id]) end end end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index dac4ba060c9..a162df5fc34 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -174,11 +174,10 @@ describe MergeRequests::RefreshService, services: true do end end - context 'push commits closing issues' do + context 'merge request metrics' do let(:issue) { create :issue, project: @project } let(:commit_author) { create :user } let(:commit) { project.commit } - let!(:merge_request) { create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: @project) } before do project.team << [commit_author, :developer] @@ -195,12 +194,35 @@ describe MergeRequests::RefreshService, services: true do allow_any_instance_of(MergeRequest).to receive(:commits).and_return([commit]) end - it 'creates a `MergeRequestsClosingIssues` record for each closed issue' do - refresh_service = service.new(@project, @user) - allow(refresh_service).to receive(:execute_hooks) - refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature') + context 'when the merge request is sourced from the same project' do + it 'creates a `MergeRequestsClosingIssues` record for each issue closed by a commit' do + merge_request = create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: @project) + refresh_service = service.new(@project, @user) + allow(refresh_service).to receive(:execute_hooks) + refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature') + + issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id) + expect(issue_ids).to eq([issue.id]) + end + end - expect(merge_request.reload.closes_issues(@user)).to eq([issue]) + context 'when the merge request is sourced from a different project' do + it 'creates a `MergeRequestsClosingIssues` record for each issue closed by a commit' do + forked_project = create(:project) + create(:forked_project_link, forked_to_project: forked_project, forked_from_project: @project) + + merge_request = create(:merge_request, + target_branch: 'master', + source_branch: 'feature', + target_project: @project, + source_project: forked_project) + refresh_service = service.new(@project, @user) + allow(refresh_service).to receive(:execute_hooks) + refresh_service.execute(@oldrev, @newrev, 'refs/heads/feature') + + issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id) + expect(issue_ids).to eq([issue.id]) + end end end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index e9c908ede78..33db34c0f62 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -274,7 +274,8 @@ describe MergeRequests::UpdateService, services: true do allow(service).to receive(:execute_hooks) service.execute(merge_request) - expect(merge_request.reload.closes_issues(user)).to match_array([first_issue, second_issue]) + issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id) + expect(issue_ids).to match_array([first_issue.id, second_issue.id]) end it 'removes `MergeRequestsClosingIssues` records when issues are not closed anymore' do @@ -288,13 +289,15 @@ describe MergeRequests::UpdateService, services: true do merge_request = MergeRequests::CreateService.new(project, user, opts).execute - expect(merge_request.reload.closes_issues(user)).to match_array([first_issue, second_issue]) + issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id) + expect(issue_ids).to match_array([first_issue.id, second_issue.id]) service = described_class.new(project, user, description: "not closing any issues") allow(service).to receive(:execute_hooks) service.execute(merge_request.reload) - expect(merge_request.reload.closes_issues(user)).to be_empty + issue_ids = MergeRequestsClosingIssues.where(merge_request: merge_request).pluck(:issue_id) + expect(issue_ids).to be_empty end end end -- cgit v1.2.1 From 0a2649ce694a0ba70fa6c4caa84ea21dd53446c8 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 21 Sep 2016 02:51:43 +0530 Subject: Fix build. --- spec/models/ci/pipeline_spec.rb | 6 +++--- spec/services/create_deployment_service_spec.rb | 6 +++--- spec/services/git_push_service_spec.rb | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 70051e4516d..550a890797e 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -197,13 +197,13 @@ describe Ci::Pipeline, models: true do time = Time.now Timecop.freeze(time) { build.run } - expect(merge_request.metrics.latest_build_started_at).to be_within(1.second).of(time) + expect(merge_request.reload.metrics.latest_build_started_at).to be_within(1.second).of(time) end it 'clears the build end time' do build.run - expect(merge_request.metrics.latest_build_finished_at).to be_nil + expect(merge_request.reload.metrics.latest_build_finished_at).to be_nil end end @@ -213,7 +213,7 @@ describe Ci::Pipeline, models: true do time = Time.now Timecop.freeze(time) { build.success } - expect(merge_request.metrics.latest_build_finished_at).to be_within(1.second).of(time) + expect(merge_request.reload.metrics.latest_build_finished_at).to be_within(1.second).of(time) end end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 3a565fa44b5..cfcf1dc4ab8 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -190,7 +190,7 @@ describe CreateDeploymentService, services: true do time = Time.now Timecop.freeze(time) { service.execute } - expect(merge_request.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) end it "doesn't set the time if the deploy's environment is not 'production'" do @@ -198,7 +198,7 @@ describe CreateDeploymentService, services: true do service = described_class.new(project, user, staging_params) service.execute - expect(merge_request.metrics.first_deployed_to_production_at).to be_nil + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil end it 'does not raise errors if the merge request does not have a metrics record' do @@ -231,7 +231,7 @@ describe CreateDeploymentService, services: true do # Previous deploy time = Time.now Timecop.freeze(time) { service.execute } - merge_request.metrics.update(first_deployed_to_production_at: nil) + merge_request.reload.metrics.update(first_deployed_to_production_at: nil) expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index cdf0d44a32b..22991c5bc86 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -364,14 +364,14 @@ describe GitPushService, services: true do it 'sets the metric for referenced issues' do execute_service(project, user, @oldrev, @newrev, @ref) - expect(issue.metrics.first_mentioned_in_commit_at).to be_within(1.second).of(commit_time) + expect(issue.reload.metrics.first_mentioned_in_commit_at).to be_within(1.second).of(commit_time) end it 'does not set the metric for non-referenced issues' do non_referenced_issue = create(:issue, project: project) execute_service(project, user, @oldrev, @newrev, @ref) - expect(non_referenced_issue.metrics.first_mentioned_in_commit_at).to be_nil + expect(non_referenced_issue.reload.metrics.first_mentioned_in_commit_at).to be_nil end end end -- cgit v1.2.1 From ef8badb6a7db5719f78eaccae5826b3543dc0c7b Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 20 Sep 2016 19:40:37 -0700 Subject: Reload issues in spec to ensure label<->issue mapping properly loaded --- spec/services/notification_service_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index f81a58899fd..0d152534c38 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -379,6 +379,7 @@ describe NotificationService, services: true do it "emails subscribers of the issue's labels" do subscriber = create(:user) label = create(:label, issues: [issue]) + issue.reload label.toggle_subscription(subscriber) notification.new_issue(issue, @u_disabled) @@ -399,6 +400,7 @@ describe NotificationService, services: true do project.team << [guest, :guest] label = create(:label, issues: [confidential_issue]) + confidential_issue.reload label.toggle_subscription(non_member) label.toggle_subscription(author) label.toggle_subscription(assignee) -- cgit v1.2.1 From cc3adcd4bffe262f8581354b8190869f94ef17f2 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 21 Sep 2016 09:17:00 +0530 Subject: Fix `CreateDeploymentService` spec. 1. The spec tests that if: - The merge request is merged - The target branch is deployed to production - The `first_deployed_to_production_at` metric is `nil` (for some reason) - The target branch is deployed to production again - The `first_deployed_to_production_at` metric stays as `nil` (and is not overwritten). 2. Failure only on MySQL due to some datetime weirdness. --- spec/services/create_deployment_service_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index cfcf1dc4ab8..343b4385bf2 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -229,8 +229,11 @@ describe CreateDeploymentService, services: true do context "if the 'first_deployed_to_production_at' time is not already set" do it "does not overwrite the older 'first_deployed_to_production_at' time" do # Previous deploy - time = Time.now + time = 5.minutes.from_now Timecop.freeze(time) { service.execute } + + expect(merge_request.reload.metrics.merged_at).to be < merge_request.reload.metrics.first_deployed_to_production_at + merge_request.reload.metrics.update(first_deployed_to_production_at: nil) expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil -- cgit v1.2.1 From 63e03dada7e754a92ca088c683f4189424ab34b1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 21 Sep 2016 16:12:32 +0800 Subject: Make various trace methods take last_lines argument: So that we could read last few lines rather than read the entire file which could be huge. --- spec/lib/gitlab/ci/trace_reader_spec.rb | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 spec/lib/gitlab/ci/trace_reader_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/ci/trace_reader_spec.rb b/spec/lib/gitlab/ci/trace_reader_spec.rb new file mode 100644 index 00000000000..f06d78694d6 --- /dev/null +++ b/spec/lib/gitlab/ci/trace_reader_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Gitlab::Ci::TraceReader do + let(:path) { __FILE__ } + let(:lines) { File.readlines(path) } + let(:bytesize) { lines.sum(&:bytesize) } + + it 'returns last few lines' do + 10.times do + subject = build_subject + last_lines = random_lines + + expected = lines.last(last_lines).join + + expect(subject.read(last_lines: last_lines)).to eq(expected) + end + end + + it 'returns everything if trying to get too many lines' do + expect(build_subject.read(last_lines: lines.size * 2)).to eq(lines.join) + end + + it 'raises an error if not passing an integer for last_lines' do + expect do + build_subject.read(last_lines: lines) + end.to raise_error(ArgumentError) + end + + def random_lines + Random.rand(lines.size) + 1 + end + + def random_buffer + Random.rand(bytesize) + 1 + end + + def build_subject + described_class.new(__FILE__, buffer_size: random_buffer) + end +end -- cgit v1.2.1 From 955b9347a470a9c546bd1777640bfeb6104e3dd6 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 21 Sep 2016 12:08:11 +0200 Subject: Add tests to verify the correctness of returned environments --- spec/models/merge_request_spec.rb | 52 ++++++++++++++++++++++++++++++++++----- spec/models/project_spec.rb | 41 ++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 06feeb1bbba..4636f2023f6 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -701,16 +701,56 @@ describe MergeRequest, models: true do end end - describe "#environments" do + describe '#environments' do let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project) } - it 'selects deployed environments' do - environments = create_list(:environment, 3, project: project) - create(:deployment, environment: environments.first, sha: project.commit('master').id) - create(:deployment, environment: environments.second, sha: project.commit('feature').id) + context 'with multiple environments' do + let(:environments) { create_list(:environment, 3, project: project) } - expect(merge_request.environments).to eq [environments.first] + before do + create(:deployment, environment: environments.first, ref: 'master', sha: project.commit('master').id) + create(:deployment, environment: environments.second, ref: 'feature', sha: project.commit('feature').id) + end + + it 'selects deployed environments' do + expect(merge_request.environments).to contain_exactly(environments.first) + end + end + + context 'with environments on source project' do + let(:source_project) do + create(:project) do |fork_project| + fork_project.create_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id) + end + end + let(:merge_request) do + create(:merge_request, + source_project: source_project, source_branch: 'feature', + target_project: project) + end + + let(:source_environment) { create(:environment, project: source_project) } + + before do + create(:deployment, environment: source_environment, ref: 'feature', sha: merge_request.diff_head_sha) + end + + it 'selects deployed environments' do + expect(merge_request.environments).to contain_exactly(source_environment) + end + + context 'with environments on target project' do + let(:target_environment) { create(:environment, project: project) } + + before do + create(:deployment, environment: target_environment, tag: true, sha: merge_request.diff_head_sha) + end + + it 'selects deployed environments' do + expect(merge_request.environments).to contain_exactly(source_environment, target_environment) + end + end end context 'without a diff_head_commit' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index a388ff703a6..68f3128bf63 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1647,6 +1647,47 @@ describe Project, models: true do end end + describe '#environments_for' do + let(:project) { create(:project) } + let(:environment) { create(:environment, project: project) } + + context 'tagged deployment' do + before do + create(:deployment, environment: environment, ref: '1.0', tag: true, sha: project.commit.id) + end + + it 'returns environment when with_tags is set' do + expect(project.environments_for('master', project.commit, with_tags: true)).to contain_exactly(environment) + end + + it 'does not return environment when no with_tags is set' do + expect(project.environments_for('master', project.commit)).not_to contain_exactly(environment) + end + + it 'does not return environment when commit is not part of deployment' do + expect(project.environments_for('master', project.commit('feature'))).not_to contain_exactly(environment) + end + end + + context 'branch deployment' do + before do + create(:deployment, environment: environment, ref: 'master', sha: project.commit.id) + end + + it 'returns environment when ref is set' do + expect(project.environments_for('master', project.commit)).to contain_exactly(environment) + end + + it 'does not environment when ref is different' do + expect(project.environments_for('feature', project.commit)).not_to contain_exactly(environment) + end + + it 'does not return environment when commit is not part of deployment' do + expect(project.environments_for('master', project.commit('feature'))).not_to contain_exactly(environment) + end + end + end + def enable_lfs allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) end -- cgit v1.2.1 From 29a64950dd9417452707cb8677a480a35f8da876 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 21 Sep 2016 12:32:15 +0200 Subject: Improve specs --- spec/models/merge_request_spec.rb | 1 + spec/models/project_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 4636f2023f6..7cb97113c04 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -724,6 +724,7 @@ describe MergeRequest, models: true do fork_project.create_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id) end end + let(:merge_request) do create(:merge_request, source_project: source_project, source_branch: 'feature', diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 68f3128bf63..83f61f0af0a 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1661,11 +1661,11 @@ describe Project, models: true do end it 'does not return environment when no with_tags is set' do - expect(project.environments_for('master', project.commit)).not_to contain_exactly(environment) + expect(project.environments_for('master', project.commit)).to be_empty end it 'does not return environment when commit is not part of deployment' do - expect(project.environments_for('master', project.commit('feature'))).not_to contain_exactly(environment) + expect(project.environments_for('master', project.commit('feature'))).to be_empty end end @@ -1679,11 +1679,11 @@ describe Project, models: true do end it 'does not environment when ref is different' do - expect(project.environments_for('feature', project.commit)).not_to contain_exactly(environment) + expect(project.environments_for('feature', project.commit)).to be_empty end it 'does not return environment when commit is not part of deployment' do - expect(project.environments_for('master', project.commit('feature'))).not_to contain_exactly(environment) + expect(project.environments_for('master', project.commit('feature'))).to be_empty end end end -- cgit v1.2.1 From 9410599391edfb1b16472fbfaad362bb4e14eb55 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 21 Sep 2016 13:13:50 +0200 Subject: Scope environments to project --- spec/views/projects/merge_requests/_heading.html.haml_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/views/projects/merge_requests/_heading.html.haml_spec.rb b/spec/views/projects/merge_requests/_heading.html.haml_spec.rb index 733b2dfa7ff..21f49d396e7 100644 --- a/spec/views/projects/merge_requests/_heading.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/_heading.html.haml_spec.rb @@ -15,6 +15,8 @@ describe 'projects/merge_requests/widget/_heading' do assign(:merge_request, merge_request) assign(:project, project) + allow(view).to receive(:can?).and_return(true) + render end -- cgit v1.2.1 From ce48a595b04ba682409dd55a6272c8dd9a8553f3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 21 Sep 2016 13:01:46 +0200 Subject: fixing security specs after merge --- spec/features/projects/import_export/export_file_spec.rb | 2 +- spec/lib/gitlab/import_export/all_models.yml | 8 ++++++++ spec/lib/gitlab/import_export/safe_model_attributes.yml | 15 ++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 7e2c701e401..27c986c5187 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -15,7 +15,7 @@ feature 'Import/Export - project export integration test', feature: true, js: tr let(:sensitive_words) { %w[pass secret token key] } let(:safe_list) do { - token: [ProjectHook, Ci::Trigger], + token: [ProjectHook, Ci::Trigger, CommitStatus], key: [Project, Ci::Variable, :yaml_variables] } end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 30968ba2d5f..2d8d1bb441c 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -13,6 +13,8 @@ issues: - user_agent_detail - moved_to - events +- merge_requests_closing_issues +- metrics events: - author - project @@ -71,6 +73,8 @@ merge_requests: - merge_request_diffs - merge_request_diff - events +- merge_requests_closing_issues +- metrics merge_request_diff: - merge_request pipelines: @@ -101,6 +105,10 @@ protected_branches: - project - merge_access_levels - push_access_levels +merge_access_levels: +- protected_branch +push_access_levels: +- protected_branch project: - taggings - base_tags diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index f2d272ca7e2..7efe14545b5 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -214,6 +214,7 @@ CommitStatus: - when - yaml_variables - queued_at +- token Ci::Variable: - id - project_id @@ -307,4 +308,16 @@ ProjectFeature: - snippets_access_level - builds_access_level - created_at -- updated_at \ No newline at end of file +- updated_at +ProtectedBranch::MergeAccessLevel: +- id +- protected_branch_id +- access_level +- created_at +- updated_at +ProtectedBranch::PushAccessLevel: +- id +- protected_branch_id +- access_level +- created_at +- updated_at -- cgit v1.2.1 From ad62a25e0f5b2e35b7101024982139997633768d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 21 Sep 2016 20:43:29 +0200 Subject: fix import/export security specs after merge --- spec/lib/gitlab/import_export/all_models.yml | 6 +++++- spec/lib/gitlab/import_export/safe_model_attributes.yml | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 2d8d1bb441c..006569254a6 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -49,6 +49,7 @@ snippets: - author - project - notes +- award_emoji releases: - project project_members: @@ -180,4 +181,7 @@ project: - triggers - environments - deployments -- project_feature \ No newline at end of file +- project_feature +award_emoji: +- awardable +- user \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 7efe14545b5..8bccd313d6c 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -321,3 +321,10 @@ ProtectedBranch::PushAccessLevel: - access_level - created_at - updated_at +AwardEmoji: +- id +- user_id +- name +- awardable_type +- created_at +- updated_at -- cgit v1.2.1 From 6987ec29b084ca842e46601965a60519fe96dc33 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 22 Sep 2016 17:01:01 +0800 Subject: For empty merge_request_diff st_commits would be nil Closes #22438 --- spec/models/merge_request_spec.rb | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 433aba7747b..12df6adde44 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -517,7 +517,7 @@ describe MergeRequest, models: true do context 'with multiple irrelevant merge_request_diffs' do before do - subject.update(target_branch: 'markdown') + subject.update(target_branch: 'v1.0.0') end it_behaves_like 'returning pipelines with proper ordering' @@ -544,13 +544,28 @@ describe MergeRequest, models: true do subject.merge_request_diffs.flat_map(&:commits).map(&:sha).uniq end - before do - subject.update(target_branch: 'markdown') + shared_examples 'returning all SHA' do + it 'returns all SHA from all merge_request_diffs' do + expect(subject.merge_request_diffs.size).to eq(2) + expect(subject.all_commits_sha).to eq(all_commits_sha) + end + end + + context 'with a completely different branch' do + before do + subject.update(target_branch: 'v1.0.0') + end + + it_behaves_like 'returning all SHA' end - it 'returns all SHA from all merge_request_diffs' do - expect(subject.merge_request_diffs.size).to eq(2) - expect(subject.all_commits_sha).to eq(all_commits_sha) + context 'with a branch having no difference' do + before do + subject.update(target_branch: 'v1.1.0') + subject.reload # make sure commits were not cached + end + + it_behaves_like 'returning all SHA' end end -- cgit v1.2.1 From 6b02127f03b1f8e1dbbecccfc2ba16e62aadcbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 28 Jul 2016 19:28:56 +0200 Subject: New Members::RequestAccessService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/models/concerns/access_requestable_spec.rb | 40 --------------- spec/models/group_spec.rb | 7 +++ spec/models/project_spec.rb | 8 +++ spec/requests/api/access_requests_spec.rb | 18 ++++++- .../members/request_access_service_spec.rb | 57 ++++++++++++++++++++++ 5 files changed, 88 insertions(+), 42 deletions(-) delete mode 100644 spec/models/concerns/access_requestable_spec.rb create mode 100644 spec/services/members/request_access_service_spec.rb (limited to 'spec') diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb deleted file mode 100644 index 96eee0e8bdd..00000000000 --- a/spec/models/concerns/access_requestable_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'spec_helper' - -describe AccessRequestable do - describe 'Group' do - describe '#request_access' do - let(:group) { create(:group, :public) } - let(:user) { create(:user) } - - it { expect(group.request_access(user)).to be_a(GroupMember) } - it { expect(group.request_access(user).user).to eq(user) } - end - - describe '#access_requested?' do - let(:group) { create(:group, :public) } - let(:user) { create(:user) } - - before { group.request_access(user) } - - it { expect(group.requesters.exists?(user_id: user)).to be_truthy } - end - end - - describe 'Project' do - describe '#request_access' do - let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - - it { expect(project.request_access(user)).to be_a(ProjectMember) } - end - - describe '#access_requested?' do - let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - - before { project.request_access(user) } - - it { expect(project.requesters.exists?(user_id: user)).to be_truthy } - end - end -end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 0b3ef9b98fd..c015147f0db 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -105,6 +105,13 @@ describe Group, models: true do it { expect(group.human_name).to eq(group.name) } end + describe '#request_access' do + let(:user) { create(:user) } + + it { expect(group.request_access(user)).to be_a(GroupMember) } + it { expect(group.request_access(user).user).to eq(user) } + end + describe '#add_user' do let(:user) { create(:user) } before { group.add_user(user, GroupMember::MASTER) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 83f61f0af0a..f88636e1c19 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -942,6 +942,14 @@ describe Project, models: true do end end + describe '#request_access' do + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + + it { expect(project.request_access(user)).to be_a(ProjectMember) } + it { expect(project.request_access(user).user).to eq(user) } + end + describe '.search' do let(:project) { create(:project, description: 'kitten mittens') } diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb index d78494b76fa..905a7311372 100644 --- a/spec/requests/api/access_requests_spec.rb +++ b/spec/requests/api/access_requests_spec.rb @@ -64,12 +64,12 @@ describe API::AccessRequests, api: true do context 'when authenticated as a member' do %i[developer master].each do |type| context "as a #{type}" do - it 'returns 400' do + it 'returns 403' do expect do user = public_send(type) post api("/#{source_type.pluralize}/#{source.id}/access_requests", user) - expect(response).to have_http_status(400) + expect(response).to have_http_status(403) end.not_to change { source.requesters.count } end end @@ -87,6 +87,20 @@ describe API::AccessRequests, api: true do end context 'when authenticated as a stranger' do + context "when access request is disabled for the #{source_type}" do + before do + source.update(request_access_enabled: false) + end + + it 'returns 403' do + expect do + post api("/#{source_type.pluralize}/#{source.id}/access_requests", stranger) + + expect(response).to have_http_status(403) + end.not_to change { source.requesters.count } + end + end + it 'returns 201' do expect do post api("/#{source_type.pluralize}/#{source.id}/access_requests", stranger) diff --git a/spec/services/members/request_access_service_spec.rb b/spec/services/members/request_access_service_spec.rb new file mode 100644 index 00000000000..dff5b4917ae --- /dev/null +++ b/spec/services/members/request_access_service_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +describe Members::RequestAccessService, services: true do + let(:user) { create(:user) } + let(:project) { create(:project, :private) } + let(:group) { create(:group, :private) } + + shared_examples 'a service raising Gitlab::Access::AccessDeniedError' do + it 'raises Gitlab::Access::AccessDeniedError' do + expect { described_class.new(source, user).execute }.to raise_error(Gitlab::Access::AccessDeniedError) + end + end + + shared_examples 'a service creating a access request' do + it 'succeeds' do + expect { described_class.new(source, user).execute }.to change { source.requesters.count }.by(1) + end + + it 'returns a Member' do + member = described_class.new(source, user).execute + + expect(member).to be_a "#{source.class.to_s}Member".constantize + expect(member.requested_at).to be_present + end + end + + context 'when source is nil' do + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { nil } + end + end + + context 'when current user cannot request access to the project' do + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { project } + end + + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { group } + end + end + + context 'when current user can request access to the project' do + before do + project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + group.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + end + + it_behaves_like 'a service creating a access request' do + let(:source) { project } + end + + it_behaves_like 'a service creating a access request' do + let(:source) { group } + end + end +end -- cgit v1.2.1 From 178e2758f685ee124c06d2ce8961950a4d39f013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 9 Sep 2016 17:09:43 +0200 Subject: Fix specs that requires an access request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/helpers/members_helper_spec.rb | 4 ++-- spec/mailers/notify_spec.rb | 4 ++-- spec/models/member_spec.rb | 2 +- spec/models/project_spec.rb | 2 +- spec/models/project_team_spec.rb | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb index 7998209b7b0..6703d88e357 100644 --- a/spec/helpers/members_helper_spec.rb +++ b/spec/helpers/members_helper_spec.rb @@ -11,7 +11,7 @@ describe MembersHelper do describe '#remove_member_message' do let(:requester) { build(:user) } - let(:project) { create(:project) } + let(:project) { create(:empty_project, :public) } let(:project_member) { build(:project_member, project: project) } let(:project_member_invite) { build(:project_member, project: project).tap { |m| m.generate_invite_token! } } let(:project_member_request) { project.request_access(requester) } @@ -32,7 +32,7 @@ describe MembersHelper do describe '#remove_member_title' do let(:requester) { build(:user) } - let(:project) { create(:project) } + let(:project) { create(:empty_project, :public) } let(:project_member) { build(:project_member, project: project) } let(:project_member_request) { project.request_access(requester) } let(:group) { create(:group) } diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 0363bc74939..2e558018d74 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -402,7 +402,7 @@ describe Notify do describe 'project access requested' do context 'for a project in a user namespace' do - let(:project) { create(:project).tap { |p| p.team << [p.owner, :master, p.owner] } } + let(:project) { create(:project, :public).tap { |p| p.team << [p.owner, :master, p.owner] } } let(:user) { create(:user) } let(:project_member) do project.request_access(user) @@ -429,7 +429,7 @@ describe Notify do context 'for a project in a group' do let(:group_owner) { create(:user) } let(:group) { create(:group).tap { |g| g.add_owner(group_owner) } } - let(:project) { create(:project, namespace: group) } + let(:project) { create(:project, :public, namespace: group) } let(:user) { create(:user) } let(:project_member) do project.request_access(user) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 0b1634f654a..c2f4601790d 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -57,7 +57,7 @@ describe Member, models: true do describe 'Scopes & finders' do before do - project = create(:empty_project) + project = create(:empty_project, :public) group = create(:group) @owner_user = create(:user).tap { |u| group.add_owner(u) } @owner = group.members.find_by(user_id: @owner_user.id) diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index f88636e1c19..b8f268e95c3 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -68,7 +68,7 @@ describe Project, models: true do it { is_expected.to have_many(:forks).through(:forked_project_links) } describe '#members & #requesters' do - let(:project) { create(:project) } + let(:project) { create(:project, :public) } let(:requester) { create(:user) } let(:developer) { create(:user) } before do diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index f979d66c88c..e0f2dadf189 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -137,7 +137,7 @@ describe ProjectTeam, models: true do describe '#find_member' do context 'personal project' do - let(:project) { create(:empty_project) } + let(:project) { create(:empty_project, :public) } let(:requester) { create(:user) } before do @@ -200,7 +200,7 @@ describe ProjectTeam, models: true do let(:requester) { create(:user) } context 'personal project' do - let(:project) { create(:empty_project) } + let(:project) { create(:empty_project, :public) } context 'when project is not shared with group' do before do -- cgit v1.2.1 From 29cb161e925f787624e7c6b7bdfdeb4d2462c43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 19 Sep 2016 15:15:01 +0200 Subject: Re-add the AccessRequestable concern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/models/concerns/access_requestable_spec.rb | 40 +++++++++++++++++++++++++ spec/models/group_spec.rb | 7 ----- spec/models/project_spec.rb | 8 ----- 3 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 spec/models/concerns/access_requestable_spec.rb (limited to 'spec') diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb new file mode 100644 index 00000000000..96eee0e8bdd --- /dev/null +++ b/spec/models/concerns/access_requestable_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe AccessRequestable do + describe 'Group' do + describe '#request_access' do + let(:group) { create(:group, :public) } + let(:user) { create(:user) } + + it { expect(group.request_access(user)).to be_a(GroupMember) } + it { expect(group.request_access(user).user).to eq(user) } + end + + describe '#access_requested?' do + let(:group) { create(:group, :public) } + let(:user) { create(:user) } + + before { group.request_access(user) } + + it { expect(group.requesters.exists?(user_id: user)).to be_truthy } + end + end + + describe 'Project' do + describe '#request_access' do + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + + it { expect(project.request_access(user)).to be_a(ProjectMember) } + end + + describe '#access_requested?' do + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + + before { project.request_access(user) } + + it { expect(project.requesters.exists?(user_id: user)).to be_truthy } + end + end +end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index c015147f0db..0b3ef9b98fd 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -105,13 +105,6 @@ describe Group, models: true do it { expect(group.human_name).to eq(group.name) } end - describe '#request_access' do - let(:user) { create(:user) } - - it { expect(group.request_access(user)).to be_a(GroupMember) } - it { expect(group.request_access(user).user).to eq(user) } - end - describe '#add_user' do let(:user) { create(:user) } before { group.add_user(user, GroupMember::MASTER) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index b8f268e95c3..98f5305a855 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -942,14 +942,6 @@ describe Project, models: true do end end - describe '#request_access' do - let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - - it { expect(project.request_access(user)).to be_a(ProjectMember) } - it { expect(project.request_access(user).user).to eq(user) } - end - describe '.search' do let(:project) { create(:project, description: 'kitten mittens') } -- cgit v1.2.1 From d626b429a7d42609a5e385e0de6d4c09f539e4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 21 Sep 2016 19:02:09 +0200 Subject: Hotfix the issuable counters when filtering by multiple labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/issues/filter_by_labels_spec.rb | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index 908b18e5339..7e2abd759e1 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -6,20 +6,19 @@ feature 'Issue filtering by Labels', feature: true do let(:project) { create(:project, :public) } let!(:user) { create(:user)} let!(:label) { create(:label, project: project) } + let(:bug) { create(:label, project: project, title: 'bug') } + let(:feature) { create(:label, project: project, title: 'feature') } + let(:enhancement) { create(:label, project: project, title: 'enhancement') } + let(:issue1) { create(:issue, title: "Bugfix1", project: project) } + let(:issue2) { create(:issue, title: "Bugfix2", project: project) } + let(:issue3) { create(:issue, title: "Feature1", project: project) } before do - bug = create(:label, project: project, title: 'bug') - feature = create(:label, project: project, title: 'feature') - enhancement = create(:label, project: project, title: 'enhancement') - - issue1 = create(:issue, title: "Bugfix1", project: project) issue1.labels << bug - issue2 = create(:issue, title: "Bugfix2", project: project) issue2.labels << bug issue2.labels << enhancement - issue3 = create(:issue, title: "Feature1", project: project) issue3.labels << feature project.team << [user, :master] @@ -159,6 +158,13 @@ feature 'Issue filtering by Labels', feature: true do wait_for_ajax end + it 'shows a correct "Open" counter' do + page.within '.issues-state-filters' do + expect(page).not_to have_content "{#{issue2.id} => 1}" + expect(page).to have_content "Open 1" + end + end + it 'shows issue "Bugfix2" in issues list' do expect(page).to have_content "Bugfix2" end -- cgit v1.2.1 From b0ce4ca11012388b1e4fbc1d928cbf4c0da66104 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 22 Sep 2016 17:34:46 +0800 Subject: Add test for MergeRequestDiff#commits_sha, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6470#note_15856755 --- spec/models/merge_request_diff_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'spec') diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index e5b185dc3f6..530a7def553 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -64,5 +64,27 @@ describe MergeRequestDiff, models: true do end end end + + describe '#commits_sha' do + shared_examples 'returning all commits SHA' do + it 'returns all commits SHA' do + commits_sha = subject.commits_sha + + expect(commits_sha).to eq(subject.commits.map(&:sha)) + end + end + + context 'when commits were loaded' do + before do + subject.commits + end + + it_behaves_like 'returning all commits SHA' + end + + context 'when commits were not loaded' do + it_behaves_like 'returning all commits SHA' + end + end end end -- cgit v1.2.1 From 7458126111fab210974edb6e59cd722bee248088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 21 Sep 2016 16:40:46 +0200 Subject: API: Return 404 when trying to fork to unaccessible namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/fork_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/fork_spec.rb b/spec/requests/api/fork_spec.rb index 06e3a2183c0..34f84f78952 100644 --- a/spec/requests/api/fork_spec.rb +++ b/spec/requests/api/fork_spec.rb @@ -94,7 +94,7 @@ describe API::API, api: true do it 'fails if trying to fork to another user when not admin' do post api("/projects/fork/#{project.id}", user2), namespace: admin.namespace.id - expect(response).to have_http_status(409) + expect(response).to have_http_status(404) end it 'fails if trying to fork to non-existent namespace' do @@ -114,7 +114,7 @@ describe API::API, api: true do it 'fails to fork to not owned group' do post api("/projects/fork/#{project.id}", user2), namespace: group.name - expect(response).to have_http_status(409) + expect(response).to have_http_status(404) end it 'forks to not owned group when admin' do -- cgit v1.2.1 From dfc2fe774de3a1768afe4e2fb24f32858b430da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 22 Sep 2016 14:39:13 +0200 Subject: Revert "Merge branch '22421-fix-issuable-counter-when-more-than-one-label-is-selected' into 'master' " This reverts commit 8ed5be5935a77fffe730baa188d1e1fc1c739d72, reversing changes made to fb0d1378f4f3365a9cae0938829da0560a92b6e6. --- spec/features/issues/filter_by_labels_spec.rb | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index 7e2abd759e1..908b18e5339 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -6,19 +6,20 @@ feature 'Issue filtering by Labels', feature: true do let(:project) { create(:project, :public) } let!(:user) { create(:user)} let!(:label) { create(:label, project: project) } - let(:bug) { create(:label, project: project, title: 'bug') } - let(:feature) { create(:label, project: project, title: 'feature') } - let(:enhancement) { create(:label, project: project, title: 'enhancement') } - let(:issue1) { create(:issue, title: "Bugfix1", project: project) } - let(:issue2) { create(:issue, title: "Bugfix2", project: project) } - let(:issue3) { create(:issue, title: "Feature1", project: project) } before do + bug = create(:label, project: project, title: 'bug') + feature = create(:label, project: project, title: 'feature') + enhancement = create(:label, project: project, title: 'enhancement') + + issue1 = create(:issue, title: "Bugfix1", project: project) issue1.labels << bug + issue2 = create(:issue, title: "Bugfix2", project: project) issue2.labels << bug issue2.labels << enhancement + issue3 = create(:issue, title: "Feature1", project: project) issue3.labels << feature project.team << [user, :master] @@ -158,13 +159,6 @@ feature 'Issue filtering by Labels', feature: true do wait_for_ajax end - it 'shows a correct "Open" counter' do - page.within '.issues-state-filters' do - expect(page).not_to have_content "{#{issue2.id} => 1}" - expect(page).to have_content "Open 1" - end - end - it 'shows issue "Bugfix2" in issues list' do expect(page).to have_content "Bugfix2" end -- cgit v1.2.1 From d4e91b22fcef64cef412eb81086ef1c90ca55f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 22 Sep 2016 15:23:01 +0200 Subject: Revert part of "Merge branch 'update_issues_mr_counter' into 'master' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/dashboard_issues_spec.rb | 9 --------- spec/features/issues/filter_issues_spec.rb | 32 ------------------------------ 2 files changed, 41 deletions(-) (limited to 'spec') diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index fc914022a59..3fb1cb37544 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -21,9 +21,6 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'No Milestone' - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '1') - end expect(page).to have_selector('.issue', count: 1) end @@ -32,9 +29,6 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'Any Milestone' - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '2') - end expect(page).to have_selector('.issue', count: 2) end @@ -45,9 +39,6 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link milestone.title end - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '1') - end expect(page).to have_selector('.issue', count: 1) end end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 72f39e2fbca..d1501c9791a 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -230,10 +230,6 @@ describe 'Filter issues', feature: true do expect(page).to have_selector('.issue', count: 2) end - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '2') - end - click_button 'Label' page.within '.labels-filter' do click_link 'bug' @@ -243,10 +239,6 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end - - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '1') - end end it 'filters by text and milestone' do @@ -256,10 +248,6 @@ describe 'Filter issues', feature: true do expect(page).to have_selector('.issue', count: 2) end - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '2') - end - click_button 'Milestone' page.within '.milestone-filter' do click_link '8' @@ -268,10 +256,6 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end - - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '1') - end end it 'filters by text and assignee' do @@ -281,10 +265,6 @@ describe 'Filter issues', feature: true do expect(page).to have_selector('.issue', count: 2) end - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '2') - end - click_button 'Assignee' page.within '.dropdown-menu-assignee' do click_link user.name @@ -293,10 +273,6 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end - - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '1') - end end it 'filters by text and author' do @@ -306,10 +282,6 @@ describe 'Filter issues', feature: true do expect(page).to have_selector('.issue', count: 2) end - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '2') - end - click_button 'Author' page.within '.dropdown-menu-author' do click_link user.name @@ -318,10 +290,6 @@ describe 'Filter issues', feature: true do page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end - - page.within '.issues-state-filters' do - expect(page).to have_selector('.active .badge', text: '1') - end end end end -- cgit v1.2.1 From b3f0a82f501ce26717a6f9e57d91cb2b1f1a967b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 28 Jul 2016 19:30:34 +0200 Subject: New Members::ApproveAccessRequestService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../members/approve_access_request_service_spec.rb | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 spec/services/members/approve_access_request_service_spec.rb (limited to 'spec') diff --git a/spec/services/members/approve_access_request_service_spec.rb b/spec/services/members/approve_access_request_service_spec.rb new file mode 100644 index 00000000000..6951adc5828 --- /dev/null +++ b/spec/services/members/approve_access_request_service_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +describe Members::ApproveAccessRequestService, services: true do + let(:user) { create(:user) } + let(:access_requester) { create(:user) } + let(:project) { create(:project, :public) } + let(:group) { create(:group, :public) } + + shared_examples 'a service raising ActiveRecord::RecordNotFound' do + it 'raises ActiveRecord::RecordNotFound' do + expect { described_class.new(source, user, params).execute }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + shared_examples 'a service raising Gitlab::Access::AccessDeniedError' do + it 'raises Gitlab::Access::AccessDeniedError' do + expect { described_class.new(source, user, params).execute }.to raise_error(Gitlab::Access::AccessDeniedError) + end + end + + shared_examples 'a service approving an access request' do + it 'succeeds' do + expect { described_class.new(source, user, params).execute }.to change { source.requesters.count }.by(-1) + end + + it 'returns a Member' do + member = described_class.new(source, user, params).execute + + expect(member).to be_a "#{source.class.to_s}Member".constantize + expect(member.requested_at).to be_nil + end + + context 'with a custom access level' do + let(:params) { { user_id: access_requester.id, access_level: Gitlab::Access::MASTER } } + + it 'returns a ProjectMember with the custom access level' do + member = described_class.new(source, user, params).execute + + expect(member.access_level).to eq Gitlab::Access::MASTER + end + end + end + + context 'when no access requester are found' do + let(:params) { { user_id: 42 } } + + it_behaves_like 'a service raising ActiveRecord::RecordNotFound' do + let(:source) { project } + end + + it_behaves_like 'a service raising ActiveRecord::RecordNotFound' do + let(:source) { group } + end + end + + context 'when an access requester is found' do + before do + project.request_access(access_requester) + group.request_access(access_requester) + end + let(:params) { { user_id: access_requester.id } } + + context 'when current user cannot approve access request to the project' do + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { project } + end + + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { group } + end + end + + context 'when current user can approve access request to the project' do + before do + project.team << [user, :master] + group.add_owner(user) + end + + it_behaves_like 'a service approving an access request' do + let(:source) { project } + end + + it_behaves_like 'a service approving an access request' do + let(:source) { group } + end + end + end +end -- cgit v1.2.1 From 5dcdf1d51bbd5bde4ea9417dd4402571608c90f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 9 Sep 2016 18:06:36 +0200 Subject: Ensure Members::ApproveAccessRequestService can fin a requester by ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/groups/group_members_controller_spec.rb | 3 ++- spec/services/members/approve_access_request_service_spec.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index c34475976c6..92b97bf3d0c 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -2,9 +2,10 @@ require 'spec_helper' describe Groups::GroupMembersController do let(:user) { create(:user) } - let(:group) { create(:group) } describe '#index' do + let(:group) { create(:group) } + before do group.add_owner(user) stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) diff --git a/spec/services/members/approve_access_request_service_spec.rb b/spec/services/members/approve_access_request_service_spec.rb index 6951adc5828..6fca80b5613 100644 --- a/spec/services/members/approve_access_request_service_spec.rb +++ b/spec/services/members/approve_access_request_service_spec.rb @@ -83,6 +83,14 @@ describe Members::ApproveAccessRequestService, services: true do it_behaves_like 'a service approving an access request' do let(:source) { group } end + + context 'when given a :id' do + let(:params) { { id: project.requesters.find_by!(user_id: access_requester.id).id } } + + it_behaves_like 'a service approving an access request' do + let(:source) { project } + end + end end end end -- cgit v1.2.1 From b228b86b3e644c7c277b8004e3fd9291ba493cc2 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 22 Sep 2016 11:32:49 +0200 Subject: Make Gitlab::Redis.params safe for mutation --- spec/lib/gitlab/redis_spec.rb | 52 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/redis_spec.rb b/spec/lib/gitlab/redis_spec.rb index e54f5ffb312..cb54c020b31 100644 --- a/spec/lib/gitlab/redis_spec.rb +++ b/spec/lib/gitlab/redis_spec.rb @@ -3,19 +3,27 @@ require 'spec_helper' describe Gitlab::Redis do let(:redis_config) { Rails.root.join('config', 'resque.yml').to_s } - before(:each) { described_class.reset_params! } - after(:each) { described_class.reset_params! } + before(:each) { clear_raw_config } + after(:each) { clear_raw_config } describe '.params' do subject { described_class.params } + it 'withstands mutation' do + params1 = described_class.params + params2 = described_class.params + params1[:foo] = :bar + + expect(params2).not_to have_key(:foo) + end + context 'when url contains unix socket reference' do let(:config_old) { Rails.root.join('spec/fixtures/config/redis_old_format_socket.yml').to_s } let(:config_new) { Rails.root.join('spec/fixtures/config/redis_new_format_socket.yml').to_s } context 'with old format' do it 'returns path key instead' do - expect_any_instance_of(described_class).to receive(:config_file) { config_old } + stub_const("#{described_class}::CONFIG_FILE", config_old) is_expected.to include(path: '/path/to/old/redis.sock') is_expected.not_to have_key(:url) @@ -24,7 +32,7 @@ describe Gitlab::Redis do context 'with new format' do it 'returns path key instead' do - expect_any_instance_of(described_class).to receive(:config_file) { config_new } + stub_const("#{described_class}::CONFIG_FILE", config_new) is_expected.to include(path: '/path/to/redis.sock') is_expected.not_to have_key(:url) @@ -38,7 +46,7 @@ describe Gitlab::Redis do context 'with old format' do it 'returns hash with host, port, db, and password' do - expect_any_instance_of(described_class).to receive(:config_file) { config_old } + stub_const("#{described_class}::CONFIG_FILE", config_old) is_expected.to include(host: 'localhost', password: 'mypassword', port: 6379, db: 99) is_expected.not_to have_key(:url) @@ -47,7 +55,7 @@ describe Gitlab::Redis do context 'with new format' do it 'returns hash with host, port, db, and password' do - expect_any_instance_of(described_class).to receive(:config_file) { config_new } + stub_const("#{described_class}::CONFIG_FILE", config_new) is_expected.to include(host: 'localhost', password: 'mynewpassword', port: 6379, db: 99) is_expected.not_to have_key(:url) @@ -56,6 +64,30 @@ describe Gitlab::Redis do end end + describe '.url' do + it 'withstands mutation' do + url1 = described_class.url + url2 = described_class.url + url1 << 'foobar' + + expect(url2).not_to end_with('foobar') + end + end + + describe '._raw_config' do + subject { described_class._raw_config } + + it 'should be frozen' do + expect(subject).to be_frozen + end + + it 'returns false when the file does not exist' do + stub_const("#{described_class}::CONFIG_FILE", '/var/empty/doesnotexist') + + expect(subject).to eq(false) + end + end + describe '#raw_config_hash' do it 'returns default redis url when no config file is present' do expect(subject).to receive(:fetch_config) { false } @@ -71,9 +103,15 @@ describe Gitlab::Redis do describe '#fetch_config' do it 'returns false when no config file is present' do - allow(File).to receive(:exist?).with(redis_config) { false } + allow(described_class).to receive(:_raw_config) { false } expect(subject.send(:fetch_config)).to be_falsey end end + + def clear_raw_config + described_class.remove_instance_variable(:@_raw_config) + rescue NameError + # raised if @_raw_config was not set; ignore + end end -- cgit v1.2.1 From a8829f25d3c2de4b7ca17c83f80bdd2907cf5f9a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 20 Sep 2016 17:21:52 +0100 Subject: Use base SHA for patches and diffs This commit changes the revisions used for diffs. The current behaviour is to show all changes between current tip of master and tip of the MR, rather than matching the output of the web frontend (which just shows the changes in the MR). Switching from start_sha to base_sha fixes this. --- spec/lib/gitlab/workhorse_spec.rb | 40 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb index 6c7fa7e7c15..b5b685da904 100644 --- a/spec/lib/gitlab/workhorse_spec.rb +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -1,8 +1,16 @@ require 'spec_helper' describe Gitlab::Workhorse, lib: true do - let(:project) { create(:project) } - let(:subject) { Gitlab::Workhorse } + let(:project) { create(:project) } + let(:repository) { project.repository } + + def decode_workhorse_header(array) + key, value = array + command, encoded_params = value.split(":") + params = JSON.parse(Base64.urlsafe_decode64(encoded_params)) + + [key, command, params] + end describe ".send_git_archive" do context "when the repository doesn't have an archive file path" do @@ -11,11 +19,37 @@ describe Gitlab::Workhorse, lib: true do end it "raises an error" do - expect { subject.send_git_archive(project.repository, ref: "master", format: "zip") }.to raise_error(RuntimeError) + expect { described_class.send_git_archive(project.repository, ref: "master", format: "zip") }.to raise_error(RuntimeError) end end end + describe '.send_git_patch' do + let(:diff_refs) { double(base_sha: "base", head_sha: "head") } + subject { described_class.send_git_patch(repository, diff_refs) } + + it 'sets the header correctly' do + key, command, params = decode_workhorse_header(subject) + + expect(key).to eq("Gitlab-Workhorse-Send-Data") + expect(command).to eq("git-format-patch") + expect(params).to eq("RepoPath" => repository.path_to_repo, "ShaFrom" => "base", "ShaTo" => "head") + end + end + + describe '.send_git_diff' do + let(:diff_refs) { double(base_sha: "base", head_sha: "head") } + subject { described_class.send_git_patch(repository, diff_refs) } + + it 'sets the header correctly' do + key, command, params = decode_workhorse_header(subject) + + expect(key).to eq("Gitlab-Workhorse-Send-Data") + expect(command).to eq("git-format-patch") + expect(params).to eq("RepoPath" => repository.path_to_repo, "ShaFrom" => "base", "ShaTo" => "head") + end + end + describe ".secret" do subject { described_class.secret } -- cgit v1.2.1 From 2bb52d952718d5f8d78f18c0cec76425a72c919d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 23 Sep 2016 19:11:16 +0800 Subject: Fix test by having a real commit --- spec/models/project_services/pipeline_email_service_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index c352ddc00c3..1368a2925e8 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -1,7 +1,11 @@ require 'spec_helper' describe PipelinesEmailService do - let(:pipeline) { create(:ci_pipeline) } + let(:pipeline) do + create(:ci_pipeline, project: project, sha: project.commit('master').sha) + end + + let(:project) { create(:project) } let(:recipient) { 'test@gitlab.com' } let(:data) do -- cgit v1.2.1 From fd51f19c978023160ad759676a0363c12aea3fc8 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 22 Sep 2016 13:56:43 +0100 Subject: API: disable rails session auth for non-GET/HEAD requests --- spec/requests/api/api_helpers_spec.rb | 39 +++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index e66faeed705..0f41f8dc7f1 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -10,7 +10,8 @@ describe API::Helpers, api: true do let(:key) { create(:key, user: user) } let(:params) { {} } - let(:env) { {} } + let(:env) { { 'REQUEST_METHOD' => 'GET' } } + let(:request) { Rack::Request.new(env) } def set_env(token_usr, identifier) clear_env @@ -52,17 +53,43 @@ describe API::Helpers, api: true do describe ".current_user" do subject { current_user } - describe "when authenticating via Warden" do + describe "Warden authentication" do before { doorkeeper_guard_returns false } - context "fails" do - it { is_expected.to be_nil } + context "with invalid credentials" do + context "GET request" do + before { env['REQUEST_METHOD'] = 'GET' } + it { is_expected.to be_nil } + end end - context "succeeds" do + context "with valid credentials" do before { warden_authenticate_returns user } - it { is_expected.to eq(user) } + context "GET request" do + before { env['REQUEST_METHOD'] = 'GET' } + it { is_expected.to eq(user) } + end + + context "HEAD request" do + before { env['REQUEST_METHOD'] = 'HEAD' } + it { is_expected.to eq(user) } + end + + context "PUT request" do + before { env['REQUEST_METHOD'] = 'PUT' } + it { is_expected.to be_nil } + end + + context "POST request" do + before { env['REQUEST_METHOD'] = 'POST' } + it { is_expected.to be_nil } + end + + context "DELETE request" do + before { env['REQUEST_METHOD'] = 'DELETE' } + it { is_expected.to be_nil } + end end end -- cgit v1.2.1 From b5132118cd43a3e005f0ed159d4a1be34b9a6ce6 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Fri, 23 Sep 2016 13:34:39 +0200 Subject: Ensure milestones passed to GlobalMilestone is an ActiveRecord::Relation --- spec/models/global_milestone_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb index 92e0f7f27ce..dd033480527 100644 --- a/spec/models/global_milestone_spec.rb +++ b/spec/models/global_milestone_spec.rb @@ -50,8 +50,9 @@ describe GlobalMilestone, models: true do milestone1_project2, milestone1_project3, ] + milestones_relation = Milestone.where(id: milestones.map(&:id)) - @global_milestone = GlobalMilestone.new(milestone1_project1.title, milestones) + @global_milestone = GlobalMilestone.new(milestone1_project1.title, milestones_relation) end it 'has exactly one group milestone' do @@ -67,7 +68,7 @@ describe GlobalMilestone, models: true do let(:milestone) { create(:milestone, title: "git / test", project: project1) } it 'strips out slashes and spaces' do - global_milestone = GlobalMilestone.new(milestone.title, [milestone]) + global_milestone = GlobalMilestone.new(milestone.title, Milestone.where(id: milestone.id)) expect(global_milestone.safe_title).to eq('git-test') end -- cgit v1.2.1 From 61d650fed72ad15916168cefaf01cdcde888cc59 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 23 Sep 2016 19:45:48 +0800 Subject: Fix the other missing commit --- spec/services/ci/send_pipeline_notification_service_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index cb53ba8b051..aa5c14e10f9 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -1,8 +1,12 @@ require 'spec_helper' describe Ci::SendPipelineNotificationService, services: true do + let(:pipeline) do + create(:ci_pipeline, project: project, sha: project.commit('master').sha) + end + + let(:project) { create(:project) } let(:user) { create(:user) } - let(:pipeline) { create(:ci_pipeline, user: user, status: status) } subject{ described_class.new(pipeline) } describe '#execute' do -- cgit v1.2.1 From 225ab2a7db76862a5517992e029547a0bedfed38 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 23 Sep 2016 20:27:20 +0800 Subject: Cleanup emails between tests --- spec/services/ci/send_pipeline_notification_service_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index aa5c14e10f9..e7e1c4f297a 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -10,6 +10,10 @@ describe Ci::SendPipelineNotificationService, services: true do subject{ described_class.new(pipeline) } describe '#execute' do + before do + reset_delivered_emails! + end + shared_examples 'sending emails' do it 'sends an email to pipeline user' do perform_enqueued_jobs do -- cgit v1.2.1 From db3fe3109ad716ff83387898024474935228195f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 23 Sep 2016 21:43:40 +0800 Subject: Not sure why I missed this --- spec/services/ci/send_pipeline_notification_service_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index e7e1c4f297a..f6cf1039287 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -2,7 +2,11 @@ require 'spec_helper' describe Ci::SendPipelineNotificationService, services: true do let(:pipeline) do - create(:ci_pipeline, project: project, sha: project.commit('master').sha) + create(:ci_pipeline, + project: project, + sha: project.commit('master').sha, + user: user, + status: status) end let(:project) { create(:project) } -- cgit v1.2.1 From a9f1e972ec12bd628e8fc85388c6ba598902ae25 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 23 Sep 2016 16:52:39 +0200 Subject: Fixes issue with rails reserved keyword type exporting/importing services. Also fixed CustomIssueTrackerService title setter and added relevant specs. --- spec/lib/gitlab/import_export/project.json | 1 + spec/lib/gitlab/import_export/project_tree_restorer_spec.rb | 6 ++++++ spec/lib/gitlab/import_export/project_tree_saver_spec.rb | 5 +++++ 3 files changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 281f6cf1177..056eaa2d719 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -6918,6 +6918,7 @@ "note_events": true, "build_events": true, "category": "issue_tracker", + "type": "CustomIssueTrackerService", "default": true, "wiki_page_events": true }, diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index feacb295231..65d0aaf53d6 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -107,6 +107,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(Label.first.label_links.first.target).not_to be_nil end + it 'restores the correct service' do + restored_project_json + + expect(CustomIssueTrackerService.first).not_to be_nil + end + context 'Merge requests' do before do restored_project_json diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index d891c2d0cc6..31a312d6ed5 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -111,6 +111,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['issues'].first['label_links'].first['label']).not_to be_empty end + it 'saves the correct service type' do + expect(saved_project_json['services'].first['type']).not_to be_nil + end + it 'has project feature' do project_feature = saved_project_json['project_feature'] expect(project_feature).not_to be_empty @@ -161,6 +165,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do commit_id: ci_pipeline.sha) create(:event, target: milestone, project: project, action: Event::CREATED, author: user) + create(:service, project: project, type: 'CustomIssueTrackerService', category: 'issue_tracker') project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::ENABLED) -- cgit v1.2.1 From a5b9e1c2604348c7e624b4ee85610c92230551c5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 26 Sep 2016 09:44:37 +0200 Subject: added more specs --- spec/lib/gitlab/import_export/project_tree_saver_spec.rb | 2 +- .../custom_issue_tracker_service_spec.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index 31a312d6ed5..cf8f2200c57 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -112,7 +112,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do end it 'saves the correct service type' do - expect(saved_project_json['services'].first['type']).not_to be_nil + expect(saved_project_json['services'].first['type']).to eq('CustomIssueTrackerService') end it 'has project feature' do diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb index 7020667ea58..63320931e76 100644 --- a/spec/models/project_services/custom_issue_tracker_service_spec.rb +++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb @@ -25,5 +25,21 @@ describe CustomIssueTrackerService, models: true do it { is_expected.not_to validate_presence_of(:issues_url) } it { is_expected.not_to validate_presence_of(:new_issue_url) } end + + context 'title' do + let(:issue_tracker) { described_class.new(properties: {}) } + + it 'sets a default title' do + issue_tracker.title = nil + + expect(issue_tracker.title).to eq('Custom Issue Tracker') + end + + it 'sets the custom title' do + issue_tracker.title = 'test title' + + expect(issue_tracker.title).to eq('test title') + end + end end end -- cgit v1.2.1 From 528b988aea44cc1016ee5a3c09ce0d383114e395 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 26 Sep 2016 11:43:55 +0200 Subject: Escape HTML nodes in builds commands in ci linter --- spec/views/ci/lints/show.html.haml_spec.rb | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 spec/views/ci/lints/show.html.haml_spec.rb (limited to 'spec') diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/ci/lints/show.html.haml_spec.rb new file mode 100644 index 00000000000..3a65a86cd88 --- /dev/null +++ b/spec/views/ci/lints/show.html.haml_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe 'ci/lints/show' do + include Devise::TestHelpers + + before do + assign(:status, true) + assign(:stages, %w[test]) + assign(:builds, builds) + end + + context 'when builds attrbiutes contain HTML nodes' do + let(:builds) do + [ { name: 'rspec', stage: 'test', commands: '

rspec

' } ] + end + + it 'does not render HTML elements' do + render + + expect(rendered).not_to have_css('h1', text: 'rspec') + end + end + + context 'when builds attributes do not contain HTML nodes' do + let(:builds) do + [ { name: 'rspec', stage: 'test', commands: 'rspec' } ] + end + + it 'shows configuration in the table' do + render + + expect(rendered).to have_css('td pre', text: 'rspec') + end + end +end -- cgit v1.2.1 From f99d8786b74cbd8d37308217b914bceaccbdc71d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 23 Sep 2016 19:28:14 +0200 Subject: Fix snippets pagination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/dashboard/snippets_spec.rb | 15 +++++++++++++++ spec/features/projects/snippets_spec.rb | 14 ++++++++++++++ spec/features/snippets_spec.rb | 14 ++++++++++++++ spec/features/users/snippets_spec.rb | 22 ++++------------------ spec/support/snippets_shared_examples.rb | 18 ++++++++++++++++++ 5 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 spec/features/dashboard/snippets_spec.rb create mode 100644 spec/features/projects/snippets_spec.rb create mode 100644 spec/features/snippets_spec.rb create mode 100644 spec/support/snippets_shared_examples.rb (limited to 'spec') diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb new file mode 100644 index 00000000000..62937688c22 --- /dev/null +++ b/spec/features/dashboard/snippets_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe 'Dashboard snippets', feature: true do + context 'when the project has snippets' do + let(:project) { create(:empty_project, :public) } + let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) } + before do + allow(Snippet).to receive(:default_per_page).and_return(1) + login_as(project.owner) + visit dashboard_snippets_path + end + + it_behaves_like 'paginated snippets' + end +end diff --git a/spec/features/projects/snippets_spec.rb b/spec/features/projects/snippets_spec.rb new file mode 100644 index 00000000000..d37e8ed4699 --- /dev/null +++ b/spec/features/projects/snippets_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe 'Project snippets', feature: true do + context 'when the project has snippets' do + let(:project) { create(:empty_project, :public) } + let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) } + before do + allow(Snippet).to receive(:default_per_page).and_return(1) + visit namespace_project_snippets_path(project.namespace, project) + end + + it_behaves_like 'paginated snippets' + end +end diff --git a/spec/features/snippets_spec.rb b/spec/features/snippets_spec.rb new file mode 100644 index 00000000000..70b16bfc810 --- /dev/null +++ b/spec/features/snippets_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe 'Snippets', feature: true do + context 'when the project has snippets' do + let(:project) { create(:empty_project, :public) } + let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) } + before do + allow(Snippet).to receive(:default_per_page).and_return(1) + visit snippets_path(username: project.owner.username) + end + + it_behaves_like 'paginated snippets' + end +end diff --git a/spec/features/users/snippets_spec.rb b/spec/features/users/snippets_spec.rb index f00abd82fea..ce7e809ec76 100644 --- a/spec/features/users/snippets_spec.rb +++ b/spec/features/users/snippets_spec.rb @@ -3,30 +3,16 @@ require 'spec_helper' describe 'Snippets tab on a user profile', feature: true, js: true do include WaitForAjax - let(:user) { create(:user) } - context 'when the user has snippets' do + let(:user) { create(:user) } + let!(:snippets) { create_list(:snippet, 2, :public, author: user) } before do - create_list(:snippet, 25, :public, author: user) - + allow(Snippet).to receive(:default_per_page).and_return(1) visit user_path(user) page.within('.user-profile-nav') { click_link 'Snippets' } wait_for_ajax end - it 'is limited to 20 items per page' do - expect(page.all('.snippets-list-holder .snippet-row').count).to eq(20) - end - - context 'clicking on the link to the second page' do - before do - click_link('2') - wait_for_ajax - end - - it 'shows the remaining snippets' do - expect(page.all('.snippets-list-holder .snippet-row').count).to eq(5) - end - end + it_behaves_like 'paginated snippets', remote: true end end diff --git a/spec/support/snippets_shared_examples.rb b/spec/support/snippets_shared_examples.rb new file mode 100644 index 00000000000..57dfff3471f --- /dev/null +++ b/spec/support/snippets_shared_examples.rb @@ -0,0 +1,18 @@ +# These shared examples expect a `snippets` array of snippets +RSpec.shared_examples 'paginated snippets' do |remote: false| + it "is limited to #{Snippet.default_per_page} items per page" do + expect(page.all('.snippets-list-holder .snippet-row').count).to eq(Snippet.default_per_page) + end + + context 'clicking on the link to the second page' do + before do + click_link('2') + wait_for_ajax if remote + end + + it 'shows the remaining snippets' do + remaining_snippets_count = [snippets.size - Snippet.default_per_page, Snippet.default_per_page].min + expect(page).to have_selector('.snippets-list-holder .snippet-row', count: remaining_snippets_count) + end + end +end -- cgit v1.2.1 From c0ecef79fe936b9e71384f8d951fc5503f26f4a7 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Mon, 26 Sep 2016 10:03:57 +0530 Subject: Fix the "Commits" section of the cycle analytics summary. - The commit count was capped at 10, due to `Gitlab::Git::Repository#log` enforcing a limit, with the default set to 10. - Reimplement a small portion of this `log` function to get just the data we need. --- spec/models/cycle_analytics/summary_spec.rb | 6 ++++++ spec/support/cycle_analytics_helpers.rb | 26 +++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/summary_spec.rb b/spec/models/cycle_analytics/summary_spec.rb index 743bc2da33f..9d67bc82cba 100644 --- a/spec/models/cycle_analytics/summary_spec.rb +++ b/spec/models/cycle_analytics/summary_spec.rb @@ -34,6 +34,12 @@ describe CycleAnalytics::Summary, models: true do expect(subject.commits).to eq(0) end + + it "finds a large (> 100) snumber of commits if present" do + Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master', count: 100) } + + expect(subject.commits).to eq(100) + end end describe "#deploys" do diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index e8e760a6187..62a5b46d47b 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -4,24 +4,28 @@ module CycleAnalyticsHelpers create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name) end - def create_commit(message, project, user, branch_name) - filename = random_git_name + def create_commit(message, project, user, branch_name, count: 1) oldrev = project.repository.commit(branch_name).sha + commit_shas = Array.new(count) do |index| + filename = random_git_name - options = { - committer: project.repository.user_to_committer(user), - author: project.repository.user_to_committer(user), - commit: { message: message, branch: branch_name, update_ref: true }, - file: { content: "content", path: filename, update: false } - } + options = { + committer: project.repository.user_to_committer(user), + author: project.repository.user_to_committer(user), + commit: { message: message, branch: branch_name, update_ref: true }, + file: { content: "content", path: filename, update: false } + } + + commit_sha = Gitlab::Git::Blob.commit(project.repository, options) + project.repository.commit(commit_sha) - commit_sha = Gitlab::Git::Blob.commit(project.repository, options) - project.repository.commit(commit_sha) + commit_sha + end GitPushService.new(project, user, oldrev: oldrev, - newrev: commit_sha, + newrev: commit_shas.last, ref: 'refs/heads/master').execute end -- cgit v1.2.1 From 20de47235e39e585ac1c8746fc9c4f673da910a0 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Sun, 25 Sep 2016 17:06:09 +0100 Subject: Wrap List-Unsubscribe link in angle brackets --- spec/features/unsubscribe_links_spec.rb | 2 +- spec/mailers/shared/notify.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index cc40671787c..33b52d1547e 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -11,7 +11,7 @@ describe 'Unsubscribe links', feature: true do let(:mail) { ActionMailer::Base.deliveries.last } let(:body) { Capybara::Node::Simple.new(mail.default_part_body.to_s) } - let(:header_link) { mail.header['List-Unsubscribe'] } + let(:header_link) { mail.header['List-Unsubscribe'].to_s[1..-2] } # Strip angle brackets let(:body_link) { body.find_link('unsubscribe')['href'] } before do diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 56872da9a8f..5c9851f14c7 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -169,8 +169,9 @@ shared_examples 'it should show Gmail Actions View Commit link' do end shared_examples 'an unsubscribeable thread' do - it 'has a List-Unsubscribe header' do + it 'has a List-Unsubscribe header in the correct format' do is_expected.to have_header 'List-Unsubscribe', /unsubscribe/ + is_expected.to have_header 'List-Unsubscribe', /^<.+>$/ end it { is_expected.to have_body_text /unsubscribe/ } -- cgit v1.2.1 From 9806d879561d2dd6795bcca65da862e5fcc7fba5 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Mon, 19 Sep 2016 16:04:19 -0500 Subject: Add more tests for calendar contribution --- spec/features/calendar_spec.rb | 109 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index fd5fbaf2af4..f52682f229c 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -5,13 +5,41 @@ feature 'Contributions Calendar', js: true, feature: true do let(:contributed_project) { create(:project, :public) } - before do - login_as :user + date_format = '%A %b %d, %Y' + issue_title = 'Bug in old browser' + issue_params = { title: issue_title } + + def get_cell_color_selector(contributions) + contribution_cell = '.user-contrib-cell' + activity_colors = Array['#ededed', '#acd5f2', '#7fa8c9', '#527ba0', '#254e77'] + activity_colors_index = 0 + + if contributions > 0 && contributions < 10 + activity_colors_index = 1 + elsif contributions >= 10 && contributions < 20 + activity_colors_index = 2 + elsif contributions >= 20 && contributions < 30 + activity_colors_index = 3 + elsif contributions >= 30 + activity_colors_index = 4 + end + + "#{contribution_cell}[fill='#{activity_colors[activity_colors_index]}']" + end + + def get_cell_date_selector(contributions, date) + contribution_text = 'No contributions' - issue_params = { title: 'Bug in old browser' } - Issues::CreateService.new(contributed_project, @user, issue_params).execute + if contributions === 1 + contribution_text = '1 contribution' + elsif contributions > 1 + contribution_text = "#{contributions} contributions" + end - # Push code contribution + "#{get_cell_color_selector(contributions)}[data-original-title='#{contribution_text}
#{date}']" + end + + def push_code_contribution push_params = { project: contributed_project, action: Event::PUSHED, @@ -20,7 +48,10 @@ feature 'Contributions Calendar', js: true, feature: true do } Event.create(push_params) + end + before do + login_as :user visit @user.username wait_for_ajax end @@ -29,11 +60,71 @@ feature 'Contributions Calendar', js: true, feature: true do expect(page).to have_css('.js-contrib-calendar') end - it 'displays calendar activity log', js: true do - expect(find('.content_list .event-note')).to have_content "Bug in old browser" + describe '1 calendar activity' do + before do + Issues::CreateService.new(contributed_project, @user, issue_params).execute + visit @user.username + wait_for_ajax + end + + it 'displays calendar activity log', js: true do + expect(find('.content_list .event-note')).to have_content issue_title + end + + it 'displays calendar activity square color for 1 contribution', js: true do + expect(page).to have_selector(get_cell_color_selector(1), count: 1) + end + + it 'displays calendar activity square on the correct date', js: true do + today = Date.today.strftime(date_format) + expect(page).to have_selector(get_cell_date_selector(1, today), count: 1) + end + end + + describe '10 calendar activities' do + before do + (0..9).each do |i| + push_code_contribution() + end + + visit @user.username + wait_for_ajax + end + + it 'displays calendar activity square color for 10 contributions', js: true do + expect(page).to have_selector(get_cell_color_selector(10), count: 1) + end + + it 'displays calendar activity square on the correct date', js: true do + today = Date.today.strftime(date_format) + expect(page).to have_selector(get_cell_date_selector(10, today), count: 1) + end end - it 'displays calendar activity square color', js: true do - expect(page).to have_selector('.user-contrib-cell[fill=\'#acd5f2\']', count: 1) + describe 'calendar activity on two days' do + before do + push_code_contribution() + + Timecop.freeze(Date.yesterday) + Issues::CreateService.new(contributed_project, @user, issue_params).execute + Timecop.return + + visit @user.username + wait_for_ajax + end + + it 'displays calendar activity squares for both days', js: true do + expect(page).to have_selector(get_cell_color_selector(1), count: 2) + end + + it 'displays calendar activity square for yesterday', js: true do + yesterday = Date.yesterday.strftime(date_format) + expect(page).to have_selector(get_cell_date_selector(1, yesterday), count: 1) + end + + it 'displays calendar activity square for today', js: true do + today = Date.today.strftime(date_format) + expect(page).to have_selector(get_cell_date_selector(1, today), count: 1) + end end end -- cgit v1.2.1 From 97551e8dd9dc5711951e865e7f9875f8cd5712ac Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 26 Sep 2016 14:39:41 -0300 Subject: Improve project_with_board factory to create the default lists --- spec/controllers/projects/boards/lists_controller_spec.rb | 3 --- spec/factories/projects.rb | 2 ++ spec/features/boards/boards_spec.rb | 6 +----- spec/services/boards/issues/list_service_spec.rb | 4 ++-- spec/services/boards/issues/move_service_spec.rb | 4 ++-- spec/services/boards/lists/create_service_spec.rb | 8 ++------ spec/services/boards/lists/destroy_service_spec.rb | 8 ++++---- spec/services/boards/lists/move_service_spec.rb | 4 ++-- 8 files changed, 15 insertions(+), 24 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/lists_controller_spec.rb b/spec/controllers/projects/boards/lists_controller_spec.rb index d687dea3c3b..709006a3601 100644 --- a/spec/controllers/projects/boards/lists_controller_spec.rb +++ b/spec/controllers/projects/boards/lists_controller_spec.rb @@ -20,10 +20,7 @@ describe Projects::Boards::ListsController do end it 'returns a list of board lists' do - board = project.create_board - create(:backlog_list, board: board) create(:list, board: board) - create(:done_list, board: board) read_board_list user: user diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index fb84ba07d25..e61b1fd9647 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -106,6 +106,8 @@ FactoryGirl.define do factory :project_with_board, parent: :empty_project do after(:create) do |project| project.create_board + project.board.lists.create(list_type: :backlog) + project.board.lists.create(list_type: :done) end end end diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 19941978c5f..4bb7bacb46f 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -4,15 +4,11 @@ describe 'Issue Boards', feature: true, js: true do include WaitForAjax include WaitForVueResource - let(:project) { create(:empty_project, :public) } + let(:project) { create(:project_with_board, :public) } let(:user) { create(:user) } let!(:user2) { create(:user) } before do - project.create_board - project.board.lists.create(list_type: :backlog) - project.board.lists.create(list_type: :done) - project.team << [user, :master] project.team << [user2, :master] diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index cf4c5f13635..e65da15aca8 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -13,10 +13,10 @@ describe Boards::Issues::ListService, services: true do let(:p2) { create(:label, title: 'P2', project: project, priority: 2) } let(:p3) { create(:label, title: 'P3', project: project, priority: 3) } - let!(:backlog) { create(:backlog_list, board: board) } + let!(:backlog) { project.board.backlog_list } let!(:list1) { create(:list, board: board, label: development, position: 0) } let!(:list2) { create(:list, board: board, label: testing, position: 1) } - let!(:done) { create(:done_list, board: board) } + let!(:done) { project.board.done_list } let!(:opened_issue1) { create(:labeled_issue, project: project, labels: [bug]) } let!(:opened_issue2) { create(:labeled_issue, project: project, labels: [p2]) } diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb index 0122159cab8..180f1b08631 100644 --- a/spec/services/boards/issues/move_service_spec.rb +++ b/spec/services/boards/issues/move_service_spec.rb @@ -10,10 +10,10 @@ describe Boards::Issues::MoveService, services: true do let(:development) { create(:label, project: project, name: 'Development') } let(:testing) { create(:label, project: project, name: 'Testing') } - let!(:backlog) { create(:backlog_list, board: board) } + let!(:backlog) { project.board.backlog_list } let!(:list1) { create(:list, board: board, label: development, position: 0) } let!(:list2) { create(:list, board: board, label: testing, position: 1) } - let!(:done) { create(:done_list, board: board) } + let!(:done) { project.board.done_list } before do project.team << [user, :developer] diff --git a/spec/services/boards/lists/create_service_spec.rb b/spec/services/boards/lists/create_service_spec.rb index 90764b86b16..bff9c1fd1fe 100644 --- a/spec/services/boards/lists/create_service_spec.rb +++ b/spec/services/boards/lists/create_service_spec.rb @@ -17,17 +17,15 @@ describe Boards::Lists::CreateService, services: true do end end - context 'when board lists has only a backlog list' do + context 'when board lists has backlog, and done lists' do it 'creates a new list at beginning of the list' do - create(:backlog_list, board: board) - list = service.execute expect(list.position).to eq 0 end end - context 'when board lists has only labels lists' do + context 'when board lists has labels lists' do it 'creates a new list at end of the lists' do create(:list, board: board, position: 0) create(:list, board: board, position: 1) @@ -40,8 +38,6 @@ describe Boards::Lists::CreateService, services: true do context 'when board lists has backlog, label and done lists' do it 'creates a new list at end of the label lists' do - create(:backlog_list, board: board) - create(:done_list, board: board) list1 = create(:list, board: board, position: 0) list2 = service.execute diff --git a/spec/services/boards/lists/destroy_service_spec.rb b/spec/services/boards/lists/destroy_service_spec.rb index 6eff445feee..474c4512471 100644 --- a/spec/services/boards/lists/destroy_service_spec.rb +++ b/spec/services/boards/lists/destroy_service_spec.rb @@ -15,11 +15,11 @@ describe Boards::Lists::DestroyService, services: true do end it 'decrements position of higher lists' do - backlog = create(:backlog_list, board: board) + backlog = project.board.backlog_list development = create(:list, board: board, position: 0) review = create(:list, board: board, position: 1) staging = create(:list, board: board, position: 2) - done = create(:done_list, board: board) + done = project.board.done_list described_class.new(project, user).execute(development) @@ -31,14 +31,14 @@ describe Boards::Lists::DestroyService, services: true do end it 'does not remove list from board when list type is backlog' do - list = create(:backlog_list, board: board) + list = project.board.backlog_list service = described_class.new(project, user) expect { service.execute(list) }.not_to change(board.lists, :count) end it 'does not remove list from board when list type is done' do - list = create(:done_list, board: board) + list = project.board.done_list service = described_class.new(project, user) expect { service.execute(list) }.not_to change(board.lists, :count) diff --git a/spec/services/boards/lists/move_service_spec.rb b/spec/services/boards/lists/move_service_spec.rb index 3e9b7d07fc6..102ed67449d 100644 --- a/spec/services/boards/lists/move_service_spec.rb +++ b/spec/services/boards/lists/move_service_spec.rb @@ -6,12 +6,12 @@ describe Boards::Lists::MoveService, services: true do let(:board) { project.board } let(:user) { create(:user) } - let!(:backlog) { create(:backlog_list, board: board) } + let!(:backlog) { project.board.backlog_list } let!(:planning) { create(:list, board: board, position: 0) } let!(:development) { create(:list, board: board, position: 1) } let!(:review) { create(:list, board: board, position: 2) } let!(:staging) { create(:list, board: board, position: 3) } - let!(:done) { create(:done_list, board: board) } + let!(:done) { project.board.done_list } context 'when list type is set to label' do it 'keeps position of lists when new position is nil' do -- cgit v1.2.1 From d0b556eb1b9d4bcdfa2eeb21a99d9675eca64f25 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Sep 2016 20:33:00 +0300 Subject: Add User#organization to users api Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/users_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index ef73778efa9..e11dbfef591 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -265,6 +265,13 @@ describe API::API, api: true do expect(user.reload.bio).to eq('new test bio') end + it "updates user with organization" do + put api("/users/#{user.id}", admin), { organization: 'GitLab' } + expect(response).to have_http_status(200) + expect(json_response['organization']).to eq('GitLab') + expect(user.reload.organization).to eq('GitLab') + end + it 'updates user with his own email' do put api("/users/#{user.id}", admin), email: user.email expect(response).to have_http_status(200) -- cgit v1.2.1 From c17383a73075f79ffd4b220ba415efa6bf4716b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Sep 2016 13:19:12 +0300 Subject: Improvements to user organization field feature after code review * Add newline to user organization spec according to test guide * Remove unnecessary comments from user organization database migration Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/users_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index e11dbfef591..c5a1cdf8c32 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -267,6 +267,7 @@ describe API::API, api: true do it "updates user with organization" do put api("/users/#{user.id}", admin), { organization: 'GitLab' } + expect(response).to have_http_status(200) expect(json_response['organization']).to eq('GitLab') expect(user.reload.organization).to eq('GitLab') -- cgit v1.2.1 From 0614cf19542a27ec232a69ab672242310d1b7733 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Sep 2016 14:46:39 +0300 Subject: Add extra check for api users spec Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/users_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index c5a1cdf8c32..f4ea3bebb4c 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -62,6 +62,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.first.keys).to include 'email' + expect(json_response.first.keys).to include 'organization' expect(json_response.first.keys).to include 'identities' expect(json_response.first.keys).to include 'can_create_project' expect(json_response.first.keys).to include 'two_factor_enabled' -- cgit v1.2.1 From b007bd810175dac80a509fb0c066d854f044fb96 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 21 Sep 2016 17:22:54 +0300 Subject: Improve how MergeCommit#merge_commit_message builds the message Now a merge request with a blank description will no longer produce a merge commit message like this: ``` Merge branch 'foo' into 'master' Bring the wonders of foo into the world See merge request !7283 ``` What an improvement! :tada: --- spec/models/merge_request_spec.rb | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 12df6adde44..580a3235127 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -328,6 +328,42 @@ describe MergeRequest, models: true do end end + describe '#merge_commit_message' do + it 'includes merge information as the title' do + request = build(:merge_request, source_branch: 'source', target_branch: 'target') + + expect(request.merge_commit_message) + .to match("Merge branch 'source' into 'target'\n\n") + end + + it 'includes its title in the body' do + request = build(:merge_request, title: 'Remove all technical debt') + + expect(request.merge_commit_message) + .to match("Remove all technical debt\n\n") + end + + it 'includes its description in the body' do + request = build(:merge_request, description: 'By removing all code') + + expect(request.merge_commit_message) + .to match("By removing all code\n\n") + end + + it 'includes its reference in the body' do + request = build_stubbed(:merge_request) + + expect(request.merge_commit_message) + .to match("See merge request #{request.to_reference}") + end + + it 'excludes multiple linebreak runs when description is blank' do + request = build(:merge_request, title: 'Title', description: nil) + + expect(request.merge_commit_message).not_to match("Title\n\n\n\n") + end + end + describe "#reset_merge_when_build_succeeds" do let(:merge_if_green) do create :merge_request, merge_when_build_succeeds: true, merge_user: create(:user), -- cgit v1.2.1 From 3ed80a0176a0c8155ff6f84a8f3e70718babd8ce Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 19 Sep 2016 19:28:41 +0100 Subject: Enforce the fork_project permission in Projects::CreateService Projects::ForkService delegates to this service almost entirely, but needed one small change so it would propagate create errors correctly. CreateService#execute needs significant refactoring; it is now right at the complexity limit set by Rubocop. I avoided doing so in this commit to keep the diff as small as possible. Several tests depend on the insecure behaviour of ForkService, so fi them up at the same time. --- spec/controllers/users_controller_spec.rb | 4 ++-- spec/helpers/projects_helper_spec.rb | 2 +- spec/models/forked_project_link_spec.rb | 1 + spec/requests/api/fork_spec.rb | 2 +- spec/services/projects/fork_service_spec.rb | 25 +++++++++++++++++++++++-- spec/services/system_note_service_spec.rb | 2 +- 6 files changed, 29 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 54a2d3d9460..19a8b1fe524 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -73,8 +73,8 @@ describe UsersController do end context 'forked project' do - let!(:project) { create(:project) } - let!(:forked_project) { Projects::ForkService.new(project, user).execute } + let(:project) { create(:project) } + let(:forked_project) { Projects::ForkService.new(project, user).execute } before do sign_in(user) diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 70032e7df94..bcd53440cb4 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -11,7 +11,7 @@ describe ProjectsHelper do describe "can_change_visibility_level?" do let(:project) { create(:project) } - let(:user) { create(:user) } + let(:user) { create(:project_member, :reporter, user: create(:user), project: project).user } let(:fork_project) { Projects::ForkService.new(project, user).execute } it "returns false if there are no appropriate permissions" do diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb index 9c81d159cdf..1863581f57b 100644 --- a/spec/models/forked_project_link_spec.rb +++ b/spec/models/forked_project_link_spec.rb @@ -6,6 +6,7 @@ describe ForkedProjectLink, "add link on fork" do let(:user) { create(:user, namespace: namespace) } before do + create(:project_member, :reporter, user: user, project: project_from) @project_to = fork_project(project_from, user) end diff --git a/spec/requests/api/fork_spec.rb b/spec/requests/api/fork_spec.rb index 34f84f78952..e38d5745d44 100644 --- a/spec/requests/api/fork_spec.rb +++ b/spec/requests/api/fork_spec.rb @@ -18,7 +18,7 @@ describe API::API, api: true do end let(:project_user2) do - create(:project_member, :guest, user: user2, project: project) + create(:project_member, :reporter, user: user2, project: project) end describe 'POST /projects/fork/:id' do diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index ef2036c78b1..64d15c0523c 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -12,12 +12,26 @@ describe Projects::ForkService, services: true do description: 'wow such project') @to_namespace = create(:namespace) @to_user = create(:user, namespace: @to_namespace) + @from_project.add_user(@to_user, :developer) end context 'fork project' do + context 'when forker is a guest' do + before do + @guest = create(:user) + @from_project.add_user(@guest, :guest) + end + subject { fork_project(@from_project, @guest) } + + it { is_expected.not_to be_persisted } + it { expect(subject.errors[:forked_from_project_id]).to eq(['is forbidden']) } + end + describe "successfully creates project in the user namespace" do let(:to_project) { fork_project(@from_project, @to_user) } + it { expect(to_project).to be_persisted } + it { expect(to_project.errors).to be_empty } it { expect(to_project.owner).to eq(@to_user) } it { expect(to_project.namespace).to eq(@to_user.namespace) } it { expect(to_project.star_count).to be_zero } @@ -29,7 +43,9 @@ describe Projects::ForkService, services: true do it "fails due to validation, not transaction failure" do @existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace) @to_project = fork_project(@from_project, @to_user) - expect(@existing_project.persisted?).to be_truthy + expect(@existing_project).to be_persisted + + expect(@to_project).not_to be_persisted expect(@to_project.errors[:name]).to eq(['has already been taken']) expect(@to_project.errors[:path]).to eq(['has already been taken']) end @@ -81,18 +97,23 @@ describe Projects::ForkService, services: true do @group = create(:group) @group.add_user(@group_owner, GroupMember::OWNER) @group.add_user(@developer, GroupMember::DEVELOPER) + @project.add_user(@developer, :developer) + @project.add_user(@group_owner, :developer) @opts = { namespace: @group } end context 'fork project for group' do it 'group owner successfully forks project into the group' do to_project = fork_project(@project, @group_owner, @opts) + + expect(to_project).to be_persisted + expect(to_project.errors).to be_empty expect(to_project.owner).to eq(@group) expect(to_project.namespace).to eq(@group) expect(to_project.name).to eq(@project.name) expect(to_project.path).to eq(@project.path) expect(to_project.description).to eq(@project.description) - expect(to_project.star_count).to be_zero + expect(to_project.star_count).to be_zero end end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 3d854a959f3..a3f16e2d945 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -445,7 +445,7 @@ describe SystemNoteService, services: true do end context 'commit with cross-reference from fork' do - let(:author2) { create(:user) } + let(:author2) { create(:project_member, :reporter, user: create(:user), project: project).user } let(:forked_project) { Projects::ForkService.new(project, author2).execute } let(:commit2) { forked_project.commit } -- cgit v1.2.1 From fc548207d5717f0d54840a8d2d79a2fe15e86c82 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 26 Sep 2016 11:32:26 +0200 Subject: fix model order in import/export config and 1to1 relation issue. Added relevant specs. --- spec/lib/gitlab/import_export/project.json | 38 +++++++++++++++++++++- .../import_export/project_tree_restorer_spec.rb | 6 ++++ 2 files changed, 43 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 056eaa2d719..98323fe6be4 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -2231,6 +2231,31 @@ ], "milestones": [ + { + "id": 1, + "title": "test milestone", + "project_id": 8, + "description": "test milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "events": [ + { + "id": 487, + "target_type": "Milestone", + "target_id": 1, + "title": null, + "data": null, + "project_id": 46, + "created_at": "2016-06-14T15:02:04.418Z", + "updated_at": "2016-06-14T15:02:04.418Z", + "action": 1, + "author_id": 18 + } + ] + }, { "id": 20, "title": "v4.0", @@ -7373,5 +7398,16 @@ } ] } - ] + ], + "project_feature": { + "builds_access_level": 0, + "created_at": "2014-12-26T09:26:45.000Z", + "id": 2, + "issues_access_level": 0, + "merge_requests_access_level": 20, + "project_id": 4, + "snippets_access_level": 20, + "updated_at": "2016-09-23T11:58:28.000Z", + "wiki_access_level": 20 + } } \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 65d0aaf53d6..7582a732cdf 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -107,6 +107,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(Label.first.label_links.first.target).not_to be_nil end + it 'has a project feature' do + restored_project_json + + expect(project.project_feature).not_to be_nil + end + it 'restores the correct service' do restored_project_json -- cgit v1.2.1 From 4c480be39b0862f41043e94a6dc5b943b6f8e8f0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 12 Aug 2016 12:04:33 +0200 Subject: Prevent claiming associated model IDs via import and added relevant specs --- .../gitlab/import_export/attribute_cleaner_spec.rb | 34 ++++++ .../gitlab/import_export/relation_factory_spec.rb | 125 +++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 spec/lib/gitlab/import_export/attribute_cleaner_spec.rb create mode 100644 spec/lib/gitlab/import_export/relation_factory_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb new file mode 100644 index 00000000000..b8e7932eb4a --- /dev/null +++ b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::AttributeCleaner, lib: true do + let(:unsafe_hash) do + { + 'service_id' => 99, + 'moved_to_id' => 99, + 'namespace_id' => 99, + 'ci_id' => 99, + 'random_project_id' => 99, + 'random_id' => 99, + 'milestone_id' => 99, + 'project_id' => 99, + 'user_id' => 99, + 'random_id_in_the_middle' => 99, + 'notid' => 99 + } + end + + let(:post_safe_hash) do + { + 'project_id' => 99, + 'user_id' => 99, + 'random_id_in_the_middle' => 99, + 'notid' => 99 + } + end + + it 'removes unwanted attributes from the hash' do + described_class.clean!(relation_hash: unsafe_hash) + + expect(unsafe_hash).to eq(post_safe_hash) + end +end diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb new file mode 100644 index 00000000000..3aa492a8ab1 --- /dev/null +++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb @@ -0,0 +1,125 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::RelationFactory, lib: true do + let(:project) { create(:empty_project) } + let(:members_mapper) { double('members_mapper').as_null_object } + let(:user) { create(:user) } + let(:created_object) do + described_class.create(relation_sym: relation_sym, + relation_hash: relation_hash, + members_mapper: members_mapper, + user: user, + project_id: project.id) + end + + context 'hook object' do + let(:relation_sym) { :hooks } + let(:id) { 999 } + let(:service_id) { 99 } + let(:original_project_id) { 8 } + let(:token) { 'secret' } + + let(:relation_hash) do + { + 'id' => id, + 'url' => 'https://example.json', + 'project_id' => original_project_id, + 'created_at' => '2016-08-12T09:41:03.462Z', + 'updated_at' => '2016-08-12T09:41:03.462Z', + 'service_id' => service_id, + 'push_events' => true, + 'issues_events' => false, + 'merge_requests_events' => true, + 'tag_push_events' => false, + 'note_events' => true, + 'enable_ssl_verification' => true, + 'build_events' => false, + 'wiki_page_events' => true, + 'token' => token + } + end + + it 'does not have the original ID' do + expect(created_object.id).not_to eq(id) + end + + it 'does not have the original service_id' do + expect(created_object.service_id).not_to eq(service_id) + end + + it 'does not have the original project_id' do + expect(created_object.project_id).not_to eq(original_project_id) + end + + it 'has the new project_id' do + expect(created_object.project_id).to eq(project.id) + end + + it 'has a token' do + expect(created_object.token).to eq(token) + end + + context 'original service exists' do + let(:service_id) { Service.create(project: project).id } + + it 'does not have the original service_id' do + expect(created_object.service_id).not_to eq(service_id) + end + end + end + + # Mocks an ActiveRecordish object with the dodgy columns + class FooModel + include ActiveModel::Model + + def initialize(params) + params.each { |key, value| send("#{key}=", value) } + end + + def values + instance_variables.map { |ivar| instance_variable_get(ivar) } + end + end + + # `project_id`, `described_class.USER_REFERENCES`, noteable_id, target_id, and some project IDs are already + # re-assigned by described_class. + context 'Potentially hazardous foreign keys' do + let(:relation_sym) { :hazardous_foo_model } + let(:relation_hash) do + { + 'service_id' => 99, + 'moved_to_id' => 99, + 'namespace_id' => 99, + 'ci_id' => 99, + 'random_project_id' => 99, + 'random_id' => 99, + 'milestone_id' => 99, + 'project_id' => 99, + 'user_id' => 99, + } + end + + class HazardousFooModel < FooModel + attr_accessor :service_id, :moved_to_id, :namespace_id, :ci_id, :random_project_id, :random_id, :milestone_id, :project_id + end + + it 'does not preserve any foreign key IDs' do + expect(created_object.values).not_to include(99) + end + end + + context 'Project references' do + let(:relation_sym) { :project_foo_model } + let(:relation_hash) do + Gitlab::ImportExport::RelationFactory::PROJECT_REFERENCES.map { |ref| { ref => 99 } }.inject(:merge) + end + + class ProjectFooModel < FooModel + attr_accessor(*Gitlab::ImportExport::RelationFactory::PROJECT_REFERENCES) + end + + it 'does not preserve any project foreign key IDs' do + expect(created_object.values).not_to include(99) + end + end +end -- cgit v1.2.1 From 137a8016153b6f84086ef6f027e1ba594b48d936 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 26 Sep 2016 12:18:21 +0200 Subject: Be nice to Docker Clients talking to JWT/auth --- spec/requests/jwt_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 6b956e63004..f0ef155bd7b 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -39,7 +39,7 @@ describe JwtController do subject! { get '/jwt/auth', parameters, headers } - it { expect(response).to have_http_status(403) } + it { expect(response).to have_http_status(401) } end end @@ -77,7 +77,7 @@ describe JwtController do subject! { get '/jwt/auth', parameters, headers } - it { expect(response).to have_http_status(403) } + it { expect(response).to have_http_status(401) } end end -- cgit v1.2.1 From b13213e6be86c7aaf3005a79836d62049a3e5820 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 27 Sep 2016 10:23:15 -0500 Subject: Send ajax request for label update only if they are changed (#19472 !5071) --- spec/features/issues_spec.rb | 18 ++++++++++++++++++ spec/javascripts/labels_issue_sidebar_spec.js.es6 | 13 ++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 22359c8f938..9fe40ea0892 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -369,6 +369,24 @@ describe 'Issues', feature: true do end end + describe 'update labels from issue#show', js: true do + let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } + let!(:label) { create(:label, project: project) } + + before do + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'will not send ajax request when no data is changed' do + page.within '.labels' do + click_link 'Edit' + first('.dropdown-menu-close').click + + expect(page).not_to have_selector('.block-loading') + end + end + end + describe 'update assignee from issue#show' do let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } diff --git a/spec/javascripts/labels_issue_sidebar_spec.js.es6 b/spec/javascripts/labels_issue_sidebar_spec.js.es6 index 840c7b6d015..1ad6f612210 100644 --- a/spec/javascripts/labels_issue_sidebar_spec.js.es6 +++ b/spec/javascripts/labels_issue_sidebar_spec.js.es6 @@ -48,9 +48,9 @@ setTimeout(() => { expect($('.dropdown-content a').length).toBe(10); - $('.dropdow-content a').each((i, $link) => { - if (i < 5) { - $link.get(0).click(); + $('.dropdown-content a').each(function (i) { + if (i < saveLabelCount) { + $(this).get(0).click(); } }); @@ -70,9 +70,9 @@ setTimeout(() => { expect($('.dropdown-content a').length).toBe(10); - $('.dropdow-content a').each((i, $link) => { - if (i < 5) { - $link.get(0).click(); + $('.dropdown-content a').each(function (i) { + if (i < saveLabelCount) { + $(this).get(0).click(); } }); @@ -86,4 +86,3 @@ }); }); })(); - -- cgit v1.2.1 From a4944fb7155fc8aa4d1541d9f1e4e80c00f49292 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 27 Sep 2016 13:23:51 -0500 Subject: Do not regenerate the `lfs_token` every time `git-lfs-authenticate` is called, instead return the saved token if one is present. --- spec/requests/lfs_http_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'spec') diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 09e4e265dd1..a84be1b7c9e 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -257,6 +257,29 @@ describe 'Git LFS API and storage' do it_behaves_like 'responds with a file' end + describe 'when using a user key' do + let(:authorization) { authorize_user_key } + + context 'when user allowed' do + let(:update_permissions) do + project.team << [user, :master] + project.lfs_objects << lfs_object + end + + it_behaves_like 'responds with a file' + end + + context 'when user not allowed' do + let(:update_permissions) do + project.lfs_objects << lfs_object + end + + it 'responds with status 404' do + expect(response).to have_http_status(404) + end + end + end + context 'when build is authorized as' do let(:authorization) { authorize_ci_project } @@ -1113,6 +1136,10 @@ describe 'Git LFS API and storage' do ActionController::HttpAuthentication::Basic.encode_credentials("lfs+deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) end + def authorize_user_key + ActionController::HttpAuthentication::Basic.encode_credentials(user.username, Gitlab::LfsToken.new(user).generate) + end + def fork_project(project, user, object = nil) allow(RepositoryForkWorker).to receive(:perform_async).and_return(true) Projects::ForkService.new(project, user, {}).execute -- cgit v1.2.1 From 395a9301b233da30a9abef56bb7b6fa6229f3acd Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Tue, 27 Sep 2016 19:32:47 +0200 Subject: Process each page of GitHub resources instead of concating them then processing This should avoid having large memory growth when importing GitHub repos with lots of resources. --- spec/lib/gitlab/github_import/client_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb index 613c47d55f1..e829b936343 100644 --- a/spec/lib/gitlab/github_import/client_spec.rb +++ b/spec/lib/gitlab/github_import/client_spec.rb @@ -66,6 +66,6 @@ describe Gitlab::GithubImport::Client, lib: true do stub_request(:get, /api.github.com/) allow(client.api).to receive(:rate_limit!).and_raise(Octokit::NotFound) - expect { client.issues }.not_to raise_error + expect { client.issues {} }.not_to raise_error end end -- cgit v1.2.1 From dbcbbf262b731e30446167fbd10ef081d195c862 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Tue, 27 Sep 2016 19:35:39 +0200 Subject: Speed up label-applying process for GitHub importing * No need to re-fetch issues from GH to read their labels, the labels are already there from the index request. * No need to look up labels on the database for every application, so we cache them. --- spec/lib/gitlab/github_import/importer_spec.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/importer_spec.rb b/spec/lib/gitlab/github_import/importer_spec.rb index 553c849c9b4..844c081fc7f 100644 --- a/spec/lib/gitlab/github_import/importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer_spec.rb @@ -57,7 +57,8 @@ describe Gitlab::GithubImport::Importer, lib: true do created_at: created_at, updated_at: updated_at, closed_at: nil, - url: 'https://api.github.com/repos/octocat/Hello-World/issues/1347' + url: 'https://api.github.com/repos/octocat/Hello-World/issues/1347', + labels: [double(name: 'Label #1')], ) end @@ -75,7 +76,8 @@ describe Gitlab::GithubImport::Importer, lib: true do created_at: created_at, updated_at: updated_at, closed_at: nil, - url: 'https://api.github.com/repos/octocat/Hello-World/issues/1348' + url: 'https://api.github.com/repos/octocat/Hello-World/issues/1348', + labels: [double(name: 'Label #2')], ) end @@ -94,7 +96,8 @@ describe Gitlab::GithubImport::Importer, lib: true do updated_at: updated_at, closed_at: nil, merged_at: nil, - url: 'https://api.github.com/repos/octocat/Hello-World/pulls/1347' + url: 'https://api.github.com/repos/octocat/Hello-World/pulls/1347', + labels: [double(name: 'Label #3')], ) end @@ -148,9 +151,7 @@ describe Gitlab::GithubImport::Importer, lib: true do errors: [ { type: :label, url: "https://api.github.com/repos/octocat/Hello-World/labels/bug", errors: "Validation failed: Title can't be blank, Title is invalid" }, { type: :milestone, url: "https://api.github.com/repos/octocat/Hello-World/milestones/1", errors: "Validation failed: Title has already been taken" }, - { type: :issue, url: "https://api.github.com/repos/octocat/Hello-World/issues/1347", errors: "Invalid Repository. Use user/repo format." }, { type: :issue, url: "https://api.github.com/repos/octocat/Hello-World/issues/1348", errors: "Validation failed: Title can't be blank, Title is too short (minimum is 0 characters)" }, - { type: :pull_request, url: "https://api.github.com/repos/octocat/Hello-World/pulls/1347", errors: "Invalid Repository. Use user/repo format." }, { type: :pull_request, url: "https://api.github.com/repos/octocat/Hello-World/pulls/1347", errors: "Validation failed: Validate branches Cannot Create: This merge request already exists: [\"New feature\"]" }, { type: :wiki, errors: "Gitlab::Shell::Error" }, { type: :release, url: 'https://api.github.com/repos/octocat/Hello-World/releases/2', errors: "Validation failed: Description can't be blank" } -- cgit v1.2.1 From e30bfb809afdbf5596176cf0fe0ea63e976cbb9f Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Tue, 27 Sep 2016 19:41:22 +0200 Subject: Import all GitHub comments after importing issues and PRs --- spec/lib/gitlab/github_import/importer_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/importer_spec.rb b/spec/lib/gitlab/github_import/importer_spec.rb index 844c081fc7f..8854c8431b5 100644 --- a/spec/lib/gitlab/github_import/importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer_spec.rb @@ -132,6 +132,8 @@ describe Gitlab::GithubImport::Importer, lib: true do allow_any_instance_of(Octokit::Client).to receive(:milestones).and_return([milestone, milestone]) allow_any_instance_of(Octokit::Client).to receive(:issues).and_return([issue1, issue2]) allow_any_instance_of(Octokit::Client).to receive(:pull_requests).and_return([pull_request, pull_request]) + allow_any_instance_of(Octokit::Client).to receive(:issues_comments).and_return([]) + allow_any_instance_of(Octokit::Client).to receive(:pull_requests_comments).and_return([]) allow_any_instance_of(Octokit::Client).to receive(:last_response).and_return(double(rels: { next: nil })) allow_any_instance_of(Octokit::Client).to receive(:releases).and_return([release1, release2]) allow_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_raise(Gitlab::Shell::Error) -- cgit v1.2.1 From 0d1fa878a90026a1724025c97a9484d96f903840 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 27 Sep 2016 18:29:12 +0100 Subject: Changed compare dropdowns to dropdowns with isolated search input Updated compare specs --- spec/features/compare_spec.rb | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/features/compare_spec.rb b/spec/features/compare_spec.rb index ca7f73e24cc..33dfd0d5b62 100644 --- a/spec/features/compare_spec.rb +++ b/spec/features/compare_spec.rb @@ -12,15 +12,16 @@ describe "Compare", js: true do describe "branches" do it "pre-populates fields" do - expect(page.find_field("from").value).to eq("master") + expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("master") + expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("master") end it "compares branches" do - fill_in "from", with: "fea" - find("#from").click + select_using_dropdown "from", "feature" + expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("feature") - click_link "feature" - expect(page.find_field("from").value).to eq("feature") + select_using_dropdown "to", "binary-encoding" + expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("binary-encoding") click_button "Compare" expect(page).to have_content "Commits" @@ -29,14 +30,21 @@ describe "Compare", js: true do describe "tags" do it "compares tags" do - fill_in "from", with: "v1.0" - find("#from").click + select_using_dropdown "from", "v1.0.0" + expect(find(".js-compare-from-dropdown .dropdown-toggle-text")).to have_content("v1.0.0") - click_link "v1.0.0" - expect(page.find_field("from").value).to eq("v1.0.0") + select_using_dropdown "to", "v1.1.0" + expect(find(".js-compare-to-dropdown .dropdown-toggle-text")).to have_content("v1.1.0") click_button "Compare" expect(page).to have_content "Commits" end end + + def select_using_dropdown(dropdown_type, selection) + dropdown = find(".js-compare-#{dropdown_type}-dropdown") + dropdown.find(".compare-dropdown-toggle").click + dropdown.fill_in("Filter by branch/tag", with: selection) + click_link selection + end end -- cgit v1.2.1 From 8062380f60df576478677e9819ff602303166e4d Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Wed, 21 Sep 2016 17:06:33 -0600 Subject: Upgrade Devise from 4.1.1 to 4.2.0. This fixes an issue with Rails 5 and brings us up-to-date with the latest Devise release. This also replaces the deprecated Devise::TestHelpers with Devise::Test::ControllerHelpers. Changelog: https://github.com/plataformatec/devise/blob/v4.2.0/CHANGELOG.md#420---2016-07-01 --- spec/spec_helper.rb | 2 +- spec/views/admin/dashboard/index.html.haml_spec.rb | 2 +- spec/views/projects/builds/show.html.haml_spec.rb | 2 +- spec/views/projects/issues/_related_branches.html.haml_spec.rb | 2 +- spec/views/projects/merge_requests/_heading.html.haml_spec.rb | 2 +- spec/views/projects/merge_requests/edit.html.haml_spec.rb | 2 +- spec/views/projects/merge_requests/show.html.haml_spec.rb | 2 +- spec/views/projects/notes/_form.html.haml_spec.rb | 2 +- spec/views/projects/pipelines/show.html.haml_spec.rb | 2 +- spec/views/projects/tree/show.html.haml_spec.rb | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 02b2b3ca101..b19f5824236 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,7 +26,7 @@ RSpec.configure do |config| config.verbose_retry = true config.display_try_failure_messages = true - config.include Devise::TestHelpers, type: :controller + config.include Devise::Test::ControllerHelpers, type: :controller config.include Warden::Test::Helpers, type: :request config.include LoginHelpers, type: :feature config.include StubConfiguration diff --git a/spec/views/admin/dashboard/index.html.haml_spec.rb b/spec/views/admin/dashboard/index.html.haml_spec.rb index dae858a52f6..68d2d72876e 100644 --- a/spec/views/admin/dashboard/index.html.haml_spec.rb +++ b/spec/views/admin/dashboard/index.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'admin/dashboard/index.html.haml' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers before do assign(:projects, create_list(:empty_project, 1)) diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index 446ba3bfa14..da43622d3f9 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/builds/show' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:project) { create(:project) } let(:pipeline) do diff --git a/spec/views/projects/issues/_related_branches.html.haml_spec.rb b/spec/views/projects/issues/_related_branches.html.haml_spec.rb index 78af61f15a7..c8a3d02d8fd 100644 --- a/spec/views/projects/issues/_related_branches.html.haml_spec.rb +++ b/spec/views/projects/issues/_related_branches.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/issues/_related_branches' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:project) { create(:project) } let(:branch) { project.repository.find_branch('feature') } diff --git a/spec/views/projects/merge_requests/_heading.html.haml_spec.rb b/spec/views/projects/merge_requests/_heading.html.haml_spec.rb index 21f49d396e7..86980f59cd8 100644 --- a/spec/views/projects/merge_requests/_heading.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/_heading.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/merge_requests/widget/_heading' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers context 'when released to an environment' do let(:project) { merge_request.target_project } diff --git a/spec/views/projects/merge_requests/edit.html.haml_spec.rb b/spec/views/projects/merge_requests/edit.html.haml_spec.rb index 31bbb150698..26ea252fecb 100644 --- a/spec/views/projects/merge_requests/edit.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/edit.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/merge_requests/edit.html.haml' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb index fe0780e72df..68fbb4585c1 100644 --- a/spec/views/projects/merge_requests/show.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/merge_requests/show.html.haml' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/views/projects/notes/_form.html.haml_spec.rb b/spec/views/projects/notes/_form.html.haml_spec.rb index 932d6756ad2..b14b1ece2d0 100644 --- a/spec/views/projects/notes/_form.html.haml_spec.rb +++ b/spec/views/projects/notes/_form.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/notes/_form' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:user) { create(:user) } let(:project) { create(:empty_project) } diff --git a/spec/views/projects/pipelines/show.html.haml_spec.rb b/spec/views/projects/pipelines/show.html.haml_spec.rb index ac7f3ffb157..bf027499c94 100644 --- a/spec/views/projects/pipelines/show.html.haml_spec.rb +++ b/spec/views/projects/pipelines/show.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/pipelines/show' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:project) { create(:project) } let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id) } diff --git a/spec/views/projects/tree/show.html.haml_spec.rb b/spec/views/projects/tree/show.html.haml_spec.rb index 0f3fc1ee1ac..c381b1a86df 100644 --- a/spec/views/projects/tree/show.html.haml_spec.rb +++ b/spec/views/projects/tree/show.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'projects/tree/show' do - include Devise::TestHelpers + include Devise::Test::ControllerHelpers let(:project) { create(:project) } let(:repository) { project.repository } -- cgit v1.2.1 From e13dc69be271e57fe9cc1a3cbf0f7a86d735b2c6 Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Tue, 27 Sep 2016 20:52:41 -0600 Subject: Fix test failure by accessing Content-Type header directly. --- spec/controllers/projects/repositories_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index 2fe3c263524..38e02a46626 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -8,7 +8,7 @@ describe Projects::RepositoriesController do it 'responds with redirect in correct format' do get :archive, namespace_id: project.namespace.path, project_id: project.path, format: "zip" - expect(response.content_type).to start_with 'text/html' + expect(response.header["Content-Type"]).to start_with('text/html') expect(response).to be_redirect end end -- cgit v1.2.1 From 68364fe2f03a543c4ad89553f50b6fa30d143331 Mon Sep 17 00:00:00 2001 From: Markus Koller Date: Tue, 30 Aug 2016 13:21:33 +0200 Subject: Log LDAP lookup errors and don't swallow unrelated exceptions Signed-off-by: Roger Meier --- spec/lib/gitlab/ldap/adapter_spec.rb | 37 +++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/ldap/adapter_spec.rb b/spec/lib/gitlab/ldap/adapter_spec.rb index 0600893f4cf..563c074017a 100644 --- a/spec/lib/gitlab/ldap/adapter_spec.rb +++ b/spec/lib/gitlab/ldap/adapter_spec.rb @@ -73,17 +73,33 @@ describe Gitlab::LDAP::Adapter, lib: true do describe '#dn_matches_filter?' do subject { adapter.dn_matches_filter?(:dn, :filter) } + context "when the search result is non-empty" do + before { allow(adapter).to receive(:ldap_search).and_return([:foo]) } + + it { is_expected.to be_truthy } + end + + context "when the search result is empty" do + before { allow(adapter).to receive(:ldap_search).and_return([]) } + + it { is_expected.to be_falsey } + end + end + + describe '#ldap_search' do + subject { adapter.ldap_search(base: :dn, filter: :filter) } + context "when the search is successful" do context "and the result is non-empty" do before { allow(ldap).to receive(:search).and_return([:foo]) } - it { is_expected.to be_truthy } + it { is_expected.to eq [:foo] } end context "and the result is empty" do before { allow(ldap).to receive(:search).and_return([]) } - it { is_expected.to be_falsey } + it { is_expected.to eq [] } end end @@ -95,7 +111,22 @@ describe Gitlab::LDAP::Adapter, lib: true do ) end - it { is_expected.to be_falsey } + it { is_expected.to eq [] } + end + + context "when the search raises an LDAP exception" do + before do + allow(ldap).to receive(:search) { raise Net::LDAP::Error, "some error" } + allow(Rails.logger).to receive(:warn) + end + + it { is_expected.to eq [] } + + it 'logs the error' do + subject + expect(Rails.logger).to have_received(:warn).with( + "LDAP search raised exception Net::LDAP::Error: some error") + end end end end -- cgit v1.2.1 From dc15201c0b10b5e7a50830a9512999461c18ca0f Mon Sep 17 00:00:00 2001 From: Horatiu Eugen Vlad Date: Mon, 15 Aug 2016 12:33:46 +0200 Subject: Added git http requests tests for user with LDAP identity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/git_http_spec.rb | 657 ++++++++++++++++++++------------------- spec/support/git_http_helpers.rb | 48 +++ 2 files changed, 381 insertions(+), 324 deletions(-) create mode 100644 spec/support/git_http_helpers.rb (limited to 'spec') diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 74516686921..c0c1e62e910 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -1,508 +1,517 @@ require "spec_helper" describe 'Git HTTP requests', lib: true do + include GitHttpHelpers include WorkhorseHelpers - let(:user) { create(:user) } - let(:project) { create(:project, path: 'project.git-project') } - it "gives WWW-Authenticate hints" do clone_get('doesnt/exist.git') expect(response.header['WWW-Authenticate']).to start_with('Basic ') end - context "when the project doesn't exist" do - context "when no authentication is provided" do - it "responds with status 401 (no project existence information leak)" do - download('doesnt/exist.git') do |response| - expect(response).to have_http_status(401) - end - end - end + describe "User with no identities" do + let(:user) { create(:user) } + let(:project) { create(:project, path: 'project.git-project') } - context "when username and password are provided" do - context "when authentication fails" do - it "responds with status 401" do - download('doesnt/exist.git', user: user.username, password: "nope") do |response| + context "when the project doesn't exist" do + context "when no authentication is provided" do + it "responds with status 401 (no project existence information leak)" do + download('doesnt/exist.git') do |response| expect(response).to have_http_status(401) end end end - context "when authentication succeeds" do - it "responds with status 404" do - download('/doesnt/exist.git', user: user.username, password: user.password) do |response| - expect(response).to have_http_status(404) + context "when username and password are provided" do + context "when authentication fails" do + it "responds with status 401" do + download('doesnt/exist.git', user: user.username, password: "nope") do |response| + expect(response).to have_http_status(401) + end end end - end - end - end - - context "when the Wiki for a project exists" do - it "responds with the right project" do - wiki = ProjectWiki.new(project) - project.update_attribute(:visibility_level, Project::PUBLIC) - download("/#{wiki.repository.path_with_namespace}.git") do |response| - json_body = ActiveSupport::JSON.decode(response.body) - - expect(response).to have_http_status(200) - expect(json_body['RepoPath']).to include(wiki.repository.path_with_namespace) - expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + context "when authentication succeeds" do + it "responds with status 404" do + download('/doesnt/exist.git', user: user.username, password: user.password) do |response| + expect(response).to have_http_status(404) + end + end + end end end - end - context "when the project exists" do - let(:path) { "#{project.path_with_namespace}.git" } - - context "when the project is public" do - before do + context "when the Wiki for a project exists" do + it "responds with the right project" do + wiki = ProjectWiki.new(project) project.update_attribute(:visibility_level, Project::PUBLIC) - end - it "downloads get status 200" do - download(path, {}) do |response| + download("/#{wiki.repository.path_with_namespace}.git") do |response| + json_body = ActiveSupport::JSON.decode(response.body) + expect(response).to have_http_status(200) + expect(json_body['RepoPath']).to include(wiki.repository.path_with_namespace) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) end end + end + + context "when the project exists" do + let(:path) { "#{project.path_with_namespace}.git" } - it "uploads get status 401" do - upload(path, {}) do |response| - expect(response).to have_http_status(401) + context "when the project is public" do + before do + project.update_attribute(:visibility_level, Project::PUBLIC) end - end - context "with correct credentials" do - let(:env) { { user: user.username, password: user.password } } + it "downloads get status 200" do + download(path, {}) do |response| + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end + end - it "uploads get status 403" do - upload(path, env) do |response| - expect(response).to have_http_status(403) + it "uploads get status 401" do + upload(path, {}) do |response| + expect(response).to have_http_status(401) end end - context 'but git-receive-pack is disabled' do - it "responds with status 404" do - allow(Gitlab.config.gitlab_shell).to receive(:receive_pack).and_return(false) + context "with correct credentials" do + let(:env) { { user: user.username, password: user.password } } + it "uploads get status 403" do upload(path, env) do |response| expect(response).to have_http_status(403) end end - end - end - context 'but git-upload-pack is disabled' do - it "responds with status 404" do - allow(Gitlab.config.gitlab_shell).to receive(:upload_pack).and_return(false) + context 'but git-receive-pack is disabled' do + it "responds with status 404" do + allow(Gitlab.config.gitlab_shell).to receive(:receive_pack).and_return(false) - download(path, {}) do |response| - expect(response).to have_http_status(404) + upload(path, env) do |response| + expect(response).to have_http_status(403) + end + end end end - end - - context 'when the request is not from gitlab-workhorse' do - it 'raises an exception' do - expect do - get("/#{project.path_with_namespace}.git/info/refs?service=git-upload-pack") - end.to raise_error(JWT::DecodeError) - end - end - end - context "when the project is private" do - before do - project.update_attribute(:visibility_level, Project::PRIVATE) - end + context 'but git-upload-pack is disabled' do + it "responds with status 404" do + allow(Gitlab.config.gitlab_shell).to receive(:upload_pack).and_return(false) - context "when no authentication is provided" do - it "responds with status 401 to downloads" do - download(path, {}) do |response| - expect(response).to have_http_status(401) + download(path, {}) do |response| + expect(response).to have_http_status(404) + end end end - it "responds with status 401 to uploads" do - upload(path, {}) do |response| - expect(response).to have_http_status(401) + context 'when the request is not from gitlab-workhorse' do + it 'raises an exception' do + expect do + get("/#{project.path_with_namespace}.git/info/refs?service=git-upload-pack") + end.to raise_error(JWT::DecodeError) end end end - context "when username and password are provided" do - let(:env) { { user: user.username, password: 'nope' } } + context "when the project is private" do + before do + project.update_attribute(:visibility_level, Project::PRIVATE) + end - context "when authentication fails" do - it "responds with status 401" do - download(path, env) do |response| + context "when no authentication is provided" do + it "responds with status 401 to downloads" do + download(path, {}) do |response| expect(response).to have_http_status(401) end end - context "when the user is IP banned" do - it "responds with status 401" do - expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true) - allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4') - - clone_get(path, env) - + it "responds with status 401 to uploads" do + upload(path, {}) do |response| expect(response).to have_http_status(401) end end end - context "when authentication succeeds" do - let(:env) { { user: user.username, password: user.password } } + context "when username and password are provided" do + let(:env) { { user: user.username, password: 'nope' } } - context "when the user has access to the project" do - before do - project.team << [user, :master] + context "when authentication fails" do + it "responds with status 401" do + download(path, env) do |response| + expect(response).to have_http_status(401) + end end - context "when the user is blocked" do - it "responds with status 404" do - user.block - project.team << [user, :master] + context "when the user is IP banned" do + it "responds with status 401" do + expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true) + allow_any_instance_of(Rack::Request).to receive(:ip).and_return('1.2.3.4') - download(path, env) do |response| - expect(response).to have_http_status(404) - end + clone_get(path, env) + + expect(response).to have_http_status(401) end end + end - context "when the user isn't blocked" do - it "downloads get status 200" do - expect(Rack::Attack::Allow2Ban).to receive(:reset) + context "when authentication succeeds" do + let(:env) { { user: user.username, password: user.password } } - clone_get(path, env) + context "when the user has access to the project" do + before do + project.team << [user, :master] + end - expect(response).to have_http_status(200) - expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + context "when the user is blocked" do + it "responds with status 404" do + user.block + project.team << [user, :master] + + download(path, env) do |response| + expect(response).to have_http_status(404) + end + end end - it "uploads get status 200" do - upload(path, env) do |response| + context "when the user isn't blocked" do + it "downloads get status 200" do + expect(Rack::Attack::Allow2Ban).to receive(:reset) + + clone_get(path, env) + expect(response).to have_http_status(200) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) end - end - end - context "when an oauth token is provided" do - before do - 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) + it "uploads get status 200" do + upload(path, env) do |response| + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end + end end - it "downloads get status 200" do - clone_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token + context "when an oauth token is provided" do + before do + 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) + end - expect(response).to have_http_status(200) - expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) - end + it "downloads get status 200" do + clone_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token - it "uploads get status 401 (no project existence information leak)" do - push_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end - expect(response).to have_http_status(401) + it "uploads get status 401 (no project existence information leak)" do + push_get "#{project.path_with_namespace}.git", user: 'oauth2', password: @token.token + + expect(response).to have_http_status(401) + end end - end - context 'when user has 2FA enabled' do - let(:user) { create(:user, :two_factor) } - let(:access_token) { create(:personal_access_token, user: user) } + context 'when user has 2FA enabled' do + let(:user) { create(:user, :two_factor) } + let(:access_token) { create(:personal_access_token, user: user) } - before do - project.team << [user, :master] - end + before do + project.team << [user, :master] + end - context 'when username and password are provided' do - it 'rejects the clone attempt' do - download("#{project.path_with_namespace}.git", user: user.username, password: user.password) do |response| - expect(response).to have_http_status(401) - expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + context 'when username and password are provided' do + it 'rejects the clone attempt' do + download("#{project.path_with_namespace}.git", user: user.username, password: user.password) do |response| + expect(response).to have_http_status(401) + expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + end end - end - it 'rejects the push attempt' do - upload("#{project.path_with_namespace}.git", user: user.username, password: user.password) do |response| - expect(response).to have_http_status(401) - expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + it 'rejects the push attempt' do + upload("#{project.path_with_namespace}.git", user: user.username, password: user.password) do |response| + expect(response).to have_http_status(401) + expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP') + end end end - end - context 'when username and personal access token are provided' do - it 'allows clones' do - download("#{project.path_with_namespace}.git", user: user.username, password: access_token.token) do |response| - expect(response).to have_http_status(200) + context 'when username and personal access token are provided' do + it 'allows clones' do + download("#{project.path_with_namespace}.git", user: user.username, password: access_token.token) do |response| + expect(response).to have_http_status(200) + end end - end - it 'allows pushes' do - upload("#{project.path_with_namespace}.git", user: user.username, password: access_token.token) do |response| - expect(response).to have_http_status(200) + it 'allows pushes' do + upload("#{project.path_with_namespace}.git", user: user.username, password: access_token.token) do |response| + expect(response).to have_http_status(200) + end end end end - end - context "when blank password attempts follow a valid login" do - def attempt_login(include_password) - password = include_password ? user.password : "" - clone_get path, user: user.username, password: password - response.status - end + context "when blank password attempts follow a valid login" do + def attempt_login(include_password) + password = include_password ? user.password : "" + clone_get path, user: user.username, password: password + response.status + end - it "repeated attempts followed by successful attempt" do - options = Gitlab.config.rack_attack.git_basic_auth - maxretry = options[:maxretry] - 1 - ip = '1.2.3.4' + it "repeated attempts followed by successful attempt" do + options = Gitlab.config.rack_attack.git_basic_auth + maxretry = options[:maxretry] - 1 + ip = '1.2.3.4' - allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip) - Rack::Attack::Allow2Ban.reset(ip, options) + allow_any_instance_of(Rack::Request).to receive(:ip).and_return(ip) + Rack::Attack::Allow2Ban.reset(ip, options) - maxretry.times.each do - expect(attempt_login(false)).to eq(401) - end + maxretry.times.each do + expect(attempt_login(false)).to eq(401) + end - expect(attempt_login(true)).to eq(200) - expect(Rack::Attack::Allow2Ban.banned?(ip)).to be_falsey + expect(attempt_login(true)).to eq(200) + expect(Rack::Attack::Allow2Ban.banned?(ip)).to be_falsey - maxretry.times.each do - expect(attempt_login(false)).to eq(401) - end + maxretry.times.each do + expect(attempt_login(false)).to eq(401) + end - Rack::Attack::Allow2Ban.reset(ip, options) + Rack::Attack::Allow2Ban.reset(ip, options) + end end end - end - context "when the user doesn't have access to the project" do - it "downloads get status 404" do - download(path, user: user.username, password: user.password) do |response| - expect(response).to have_http_status(404) + context "when the user doesn't have access to the project" do + it "downloads get status 404" do + download(path, user: user.username, password: user.password) do |response| + expect(response).to have_http_status(404) + end end - end - it "uploads get status 404" do - upload(path, user: user.username, password: user.password) do |response| - expect(response).to have_http_status(404) + it "uploads get status 404" do + upload(path, user: user.username, password: user.password) do |response| + expect(response).to have_http_status(404) + end end end end end - end - - context "when a gitlab ci token is provided" do - let(:build) { create(:ci_build, :running) } - let(:project) { build.project } - let(:other_project) { create(:empty_project) } - - before do - project.project_feature.update_attributes(builds_access_level: ProjectFeature::ENABLED) - end - - context 'when build created by system is authenticated' do - it "downloads get status 200" do - clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - - expect(response).to have_http_status(200) - expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) - end - - it "uploads get status 401 (no project existence information leak)" do - push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - - expect(response).to have_http_status(401) - end - - it "downloads from other project get status 404" do - clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - expect(response).to have_http_status(404) - end - end + context "when a gitlab ci token is provided" do + let(:build) { create(:ci_build, :running) } + let(:project) { build.project } + let(:other_project) { create(:empty_project) } - context 'and build created by' do before do - build.update(user: user) - project.team << [user, :reporter] + project.project_feature.update_attributes(builds_access_level: ProjectFeature::ENABLED) end - shared_examples 'can download code only' do - it 'downloads get status 200' do + context 'when build created by system is authenticated' do + it "downloads get status 200" do clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token expect(response).to have_http_status(200) expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) end - it 'uploads get status 403' do + it "uploads get status 401 (no project existence information leak)" do push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token expect(response).to have_http_status(401) end + + it "downloads from other project get status 404" do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(404) + end end - context 'administrator' do - let(:user) { create(:admin) } + context 'and build created by' do + before do + build.update(user: user) + project.team << [user, :reporter] + end - it_behaves_like 'can download code only' + shared_examples 'can download code only' do + it 'downloads get status 200' do + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - it 'downloads from other project get status 403' do - clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end - expect(response).to have_http_status(403) + it 'uploads get status 403' do + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(401) + end end - end - context 'regular user' do - let(:user) { create(:user) } + context 'administrator' do + let(:user) { create(:admin) } - it_behaves_like 'can download code only' + it_behaves_like 'can download code only' - it 'downloads from other project get status 404' do - clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + it 'downloads from other project get status 403' do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - expect(response).to have_http_status(404) + expect(response).to have_http_status(403) + end + end + + context 'regular user' do + let(:user) { create(:user) } + + it_behaves_like 'can download code only' + + it 'downloads from other project get status 404' do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(404) + end end end end end end - end - context "when the project path doesn't end in .git" do - context "GET info/refs" do - let(:path) { "/#{project.path_with_namespace}/info/refs" } + context "when the project path doesn't end in .git" do + context "GET info/refs" do + let(:path) { "/#{project.path_with_namespace}/info/refs" } - context "when no params are added" do - before { get path } + context "when no params are added" do + before { get path } - it "redirects to the .git suffix version" do - expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs") + it "redirects to the .git suffix version" do + expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs") + end end - end - context "when the upload-pack service is requested" do - let(:params) { { service: 'git-upload-pack' } } - before { get path, params } + context "when the upload-pack service is requested" do + let(:params) { { service: 'git-upload-pack' } } + before { get path, params } - it "redirects to the .git suffix version" do - expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + it "redirects to the .git suffix version" do + expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + end end - end - context "when the receive-pack service is requested" do - let(:params) { { service: 'git-receive-pack' } } - before { get path, params } + context "when the receive-pack service is requested" do + let(:params) { { service: 'git-receive-pack' } } + before { get path, params } - it "redirects to the .git suffix version" do - expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + it "redirects to the .git suffix version" do + expect(response).to redirect_to("/#{project.path_with_namespace}.git/info/refs?service=#{params[:service]}") + end end - end - context "when the params are anything else" do - let(:params) { { service: 'git-implode-pack' } } - before { get path, params } + context "when the params are anything else" do + let(:params) { { service: 'git-implode-pack' } } + before { get path, params } - it "redirects to the sign-in page" do - expect(response).to redirect_to(new_user_session_path) + it "redirects to the sign-in page" do + expect(response).to redirect_to(new_user_session_path) + end end end - end - context "POST git-upload-pack" do - it "fails to find a route" do - expect { clone_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + context "POST git-upload-pack" do + it "fails to find a route" do + expect { clone_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + end end - end - context "POST git-receive-pack" do - it "failes to find a route" do - expect { push_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + context "POST git-receive-pack" do + it "failes to find a route" do + expect { push_post(project.path_with_namespace) }.to raise_error(ActionController::RoutingError) + end end end - end - context "retrieving an info/refs file" do - before { project.update_attribute(:visibility_level, Project::PUBLIC) } + context "retrieving an info/refs file" do + before { project.update_attribute(:visibility_level, Project::PUBLIC) } - context "when the file exists" do - before do - # Provide a dummy file in its place - allow_any_instance_of(Repository).to receive(:blob_at).and_call_original - allow_any_instance_of(Repository).to receive(:blob_at).with('5937ac0a7beb003549fc5fd26fc247adbce4a52e', 'info/refs') do - Gitlab::Git::Blob.find(project.repository, 'master', '.gitignore') - end + context "when the file exists" do + before do + # Provide a dummy file in its place + allow_any_instance_of(Repository).to receive(:blob_at).and_call_original + allow_any_instance_of(Repository).to receive(:blob_at).with('5937ac0a7beb003549fc5fd26fc247adbce4a52e', 'info/refs') do + Gitlab::Git::Blob.find(project.repository, 'master', '.gitignore') + end - get "/#{project.path_with_namespace}/blob/master/info/refs" - end + get "/#{project.path_with_namespace}/blob/master/info/refs" + end - it "returns the file" do - expect(response).to have_http_status(200) + it "returns the file" do + expect(response).to have_http_status(200) + end end - end - context "when the file does not exist" do - before { get "/#{project.path_with_namespace}/blob/master/info/refs" } + context "when the file does not exist" do + before { get "/#{project.path_with_namespace}/blob/master/info/refs" } - it "returns not found" do - expect(response).to have_http_status(404) + it "returns not found" do + expect(response).to have_http_status(404) + end end end end - def clone_get(project, options = {}) - get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token)) - end - - def clone_post(project, options = {}) - post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token)) - end - - def push_get(project, options = {}) - get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token)) - end - - def push_post(project, options = {}) - post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token)) - end + describe "User with LDAP identity" do + let(:user) { create(:omniauth_user, extern_uid: dn) } + let(:dn) { 'uid=john,ou=people,dc=example,dc=com' } - def download(project, user: nil, password: nil, spnego_request_token: nil) - args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }] + before do + allow(Gitlab::LDAP::Config).to receive(:enabled?).and_return(true) + allow(Gitlab::LDAP::Authentication).to receive(:login).and_return(nil) + allow(Gitlab::LDAP::Authentication).to receive(:login).with(user.username, user.password).and_return(user) + end - clone_get(*args) - yield response + context "when authentication fails" do + context "when no authentication is provided" do + it "responds with status 401" do + download('doesnt/exist.git') do |response| + expect(response).to have_http_status(401) + end + end + end - clone_post(*args) - yield response - end + context "when username and invalid password are provided" do + it "responds with status 401" do + download('doesnt/exist.git', user: user.username, password: "nope") do |response| + expect(response).to have_http_status(401) + end + end + end + end - def upload(project, user: nil, password: nil, spnego_request_token: nil) - args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }] + context "when authentication succeeds" do + context "when the project doesn't exist" do + it "responds with status 404" do + download('/doesnt/exist.git', user: user.username, password: user.password) do |response| + expect(response).to have_http_status(404) + end + end + end - push_get(*args) - yield response + context "when the project exists" do + let(:project) { create(:project, path: 'project.git-project') } - push_post(*args) - yield response - end + before do + project.team << [user, :master] + end - def auth_env(user, password, spnego_request_token) - env = workhorse_internal_api_request_header - if user && password - env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user, password) - elsif spnego_request_token - env['HTTP_AUTHORIZATION'] = "Negotiate #{::Base64.strict_encode64('opaque_request_token')}" + it "responds with status 200" do + clone_get(path, user: user.username, password: user.password) do |response| + expect(response).to have_http_status(200) + end + end + end end - - env end end diff --git a/spec/support/git_http_helpers.rb b/spec/support/git_http_helpers.rb new file mode 100644 index 00000000000..46b686fce94 --- /dev/null +++ b/spec/support/git_http_helpers.rb @@ -0,0 +1,48 @@ +module GitHttpHelpers + def clone_get(project, options = {}) + get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token)) + end + + def clone_post(project, options = {}) + post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token)) + end + + def push_get(project, options = {}) + get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token)) + end + + def push_post(project, options = {}) + post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token)) + end + + def download(project, user: nil, password: nil, spnego_request_token: nil) + args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }] + + clone_get(*args) + yield response + + clone_post(*args) + yield response + end + + def upload(project, user: nil, password: nil, spnego_request_token: nil) + args = [project, { user: user, password: password, spnego_request_token: spnego_request_token }] + + push_get(*args) + yield response + + push_post(*args) + yield response + end + + def auth_env(user, password, spnego_request_token) + env = workhorse_internal_api_request_header + if user && password + env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user, password) + elsif spnego_request_token + env['HTTP_AUTHORIZATION'] = "Negotiate #{::Base64.strict_encode64('opaque_request_token')}" + end + + env + end +end -- cgit v1.2.1 From 924a6b7d33a245845071894de8d46d77bd44b52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 28 Jul 2016 19:38:32 +0200 Subject: New AccessRequestsFinder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/finders/access_requests_finder_spec.rb | 89 +++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 spec/finders/access_requests_finder_spec.rb (limited to 'spec') diff --git a/spec/finders/access_requests_finder_spec.rb b/spec/finders/access_requests_finder_spec.rb new file mode 100644 index 00000000000..6cc90299417 --- /dev/null +++ b/spec/finders/access_requests_finder_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe AccessRequestsFinder, services: true do + let(:user) { create(:user) } + let(:access_requester) { create(:user) } + let(:project) { create(:project) } + let(:group) { create(:group) } + + before do + project.request_access(access_requester) + group.request_access(access_requester) + end + + shared_examples 'a finder returning access requesters' do |method_name| + it 'returns access requesters' do + access_requesters = described_class.new(source).public_send(method_name, user) + + expect(access_requesters.size).to eq(1) + expect(access_requesters.first).to be_a "#{source.class.to_s}Member".constantize + expect(access_requesters.first.user).to eq(access_requester) + end + end + + shared_examples 'a finder returning no results' do |method_name| + it 'raises Gitlab::Access::AccessDeniedError' do + expect(described_class.new(source).public_send(method_name, user)).to be_empty + end + end + + shared_examples 'a finder raising Gitlab::Access::AccessDeniedError' do |method_name| + it 'raises Gitlab::Access::AccessDeniedError' do + expect { described_class.new(source).public_send(method_name, user) }.to raise_error(Gitlab::Access::AccessDeniedError) + end + end + + describe '#execute' do + context 'when current user cannot see project access requests' do + it_behaves_like 'a finder returning no results', :execute do + let(:source) { project } + end + + it_behaves_like 'a finder returning no results', :execute do + let(:source) { group } + end + end + + context 'when current user can see access requests' do + before do + project.team << [user, :master] + group.add_owner(user) + end + + it_behaves_like 'a finder returning access requesters', :execute do + let(:source) { project } + end + + it_behaves_like 'a finder returning access requesters', :execute do + let(:source) { group } + end + end + end + + describe '#execute!' do + context 'when current user cannot see access requests' do + it_behaves_like 'a finder raising Gitlab::Access::AccessDeniedError', :execute! do + let(:source) { project } + end + + it_behaves_like 'a finder raising Gitlab::Access::AccessDeniedError', :execute! do + let(:source) { group } + end + end + + context 'when current user can see access requests' do + before do + project.team << [user, :master] + group.add_owner(user) + end + + it_behaves_like 'a finder returning access requesters', :execute! do + let(:source) { project } + end + + it_behaves_like 'a finder returning access requesters', :execute! do + let(:source) { group } + end + end + end +end -- cgit v1.2.1 From ec0061a95cbba02286b2c143048c93d8f26ff5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 16 Sep 2016 17:54:21 +0200 Subject: Allow Member.add_user to handle access requesters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes include: - Ensure Member.add_user is not called directly when not necessary - New GroupMember.add_users_to_group to have the same abstraction level as for Project - Refactor Member.add_user to take a source instead of an array of members - Fix Rubocop offenses - Always use Project#add_user instead of project.team.add_user - Factorize users addition as members in Member.add_users_to_source - Make access_level a keyword argument in GroupMember.add_users_to_group and ProjectMember.add_users_to_projects - Destroy any requester before adding them as a member - Improve the way we handle access requesters in Member.add_user Instead of removing the requester and creating a new member, we now simply accepts their access request. This way, they will receive a "access request granted" email. - Fix error that was previously silently ignored - Stop raising when access level is invalid in Member, let Rails validation do their work Signed-off-by: Rémy Coutable --- .../projects/templates_controller_spec.rb | 2 +- spec/factories/project_members.rb | 23 +- .../members/owner_cannot_leave_project_spec.rb | 4 +- ...er_cannot_request_access_to_his_project_spec.rb | 4 +- spec/features/projects_spec.rb | 6 +- spec/finders/joined_groups_finder_spec.rb | 2 +- spec/finders/projects_finder_spec.rb | 2 +- spec/lib/gitlab/template/issue_template_spec.rb | 6 +- .../gitlab/template/merge_request_template_spec.rb | 6 +- spec/mailers/notify_spec.rb | 50 +++-- spec/models/issue_spec.rb | 2 +- spec/models/member_spec.rb | 243 +++++++++++++++++---- spec/models/members/group_member_spec.rb | 27 +++ spec/models/members/project_member_spec.rb | 50 +++-- spec/models/project_spec.rb | 2 +- spec/requests/api/merge_requests_spec.rb | 4 +- 16 files changed, 312 insertions(+), 121 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb index 7b3a26d7ca7..19a152bcb05 100644 --- a/spec/controllers/projects/templates_controller_spec.rb +++ b/spec/controllers/projects/templates_controller_spec.rb @@ -13,7 +13,7 @@ describe Projects::TemplatesController do end before do - project.team.add_user(user, Gitlab::Access::MASTER) + project.add_user(user, Gitlab::Access::MASTER) project.repository.commit_file(user, file_path_1, "something valid", "test 3", "master", false) end diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb index cf3659ba275..1ddb305a8af 100644 --- a/spec/factories/project_members.rb +++ b/spec/factories/project_members.rb @@ -4,24 +4,9 @@ FactoryGirl.define do project master - trait :guest do - access_level ProjectMember::GUEST - end - - trait :reporter do - access_level ProjectMember::REPORTER - end - - trait :developer do - access_level ProjectMember::DEVELOPER - end - - trait :master do - access_level ProjectMember::MASTER - end - - trait :owner do - access_level ProjectMember::OWNER - end + trait(:guest) { access_level ProjectMember::GUEST } + trait(:reporter) { access_level ProjectMember::REPORTER } + trait(:developer) { access_level ProjectMember::DEVELOPER } + trait(:master) { access_level ProjectMember::MASTER } end end diff --git a/spec/features/projects/members/owner_cannot_leave_project_spec.rb b/spec/features/projects/members/owner_cannot_leave_project_spec.rb index 67811b1048e..6e948b7a616 100644 --- a/spec/features/projects/members/owner_cannot_leave_project_spec.rb +++ b/spec/features/projects/members/owner_cannot_leave_project_spec.rb @@ -1,12 +1,10 @@ require 'spec_helper' feature 'Projects > Members > Owner cannot leave project', feature: true do - let(:owner) { create(:user) } let(:project) { create(:project) } background do - project.team << [owner, :owner] - login_as(owner) + login_as(project.owner) visit namespace_project_path(project.namespace, project) end diff --git a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb index 0e54c4fdf20..4ca9272b9c1 100644 --- a/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb +++ b/spec/features/projects/members/owner_cannot_request_access_to_his_project_spec.rb @@ -1,12 +1,10 @@ require 'spec_helper' feature 'Projects > Members > Owner cannot request access to his project', feature: true do - let(:owner) { create(:user) } let(:project) { create(:project) } background do - project.team << [owner, :owner] - login_as(owner) + login_as(project.owner) visit namespace_project_path(project.namespace, project) end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 2242cb6236a..c30d38b6508 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -82,7 +82,7 @@ feature 'Project', feature: true do before do login_with(user) - project.team.add_user(user, Gitlab::Access::MASTER) + project.add_user(user, Gitlab::Access::MASTER) visit namespace_project_path(project.namespace, project) end @@ -101,8 +101,8 @@ feature 'Project', feature: true do context 'on issues page', js: true do before do login_with(user) - project.team.add_user(user, Gitlab::Access::MASTER) - project2.team.add_user(user, Gitlab::Access::MASTER) + project.add_user(user, Gitlab::Access::MASTER) + project2.add_user(user, Gitlab::Access::MASTER) visit namespace_project_issue_path(project.namespace, project, issue) end diff --git a/spec/finders/joined_groups_finder_spec.rb b/spec/finders/joined_groups_finder_spec.rb index f90a8e007c8..29a47e005a6 100644 --- a/spec/finders/joined_groups_finder_spec.rb +++ b/spec/finders/joined_groups_finder_spec.rb @@ -43,7 +43,7 @@ describe JoinedGroupsFinder do context 'if profile visitor is in one of the private group projects' do before do project = create(:project, :private, group: private_group, name: 'B', path: 'B') - project.team.add_user(profile_visitor, Gitlab::Access::DEVELOPER) + project.add_user(profile_visitor, Gitlab::Access::DEVELOPER) end it 'shows group' do diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index 7a3a74335e8..13bda5f7c5a 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -38,7 +38,7 @@ describe ProjectsFinder do describe 'with private projects' do before do - private_project.team.add_user(user, Gitlab::Access::MASTER) + private_project.add_user(user, Gitlab::Access::MASTER) end it do diff --git a/spec/lib/gitlab/template/issue_template_spec.rb b/spec/lib/gitlab/template/issue_template_spec.rb index f770857e958..d2d334e6413 100644 --- a/spec/lib/gitlab/template/issue_template_spec.rb +++ b/spec/lib/gitlab/template/issue_template_spec.rb @@ -10,7 +10,7 @@ describe Gitlab::Template::IssueTemplate do let(:file_path_3) { '.gitlab/issue_templates/feature_proposal.md' } before do - project.team.add_user(user, Gitlab::Access::MASTER) + 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) @@ -53,7 +53,7 @@ describe Gitlab::Template::IssueTemplate do context 'when repo is bare or empty' do let(:empty_project) { create(:empty_project) } - before { empty_project.team.add_user(user, Gitlab::Access::MASTER) } + before { empty_project.add_user(user, Gitlab::Access::MASTER) } it "returns empty array" do templates = subject.by_category('', empty_project) @@ -78,7 +78,7 @@ describe Gitlab::Template::IssueTemplate do context "when repo is empty" do let(:empty_project) { create(:empty_project) } - before { empty_project.team.add_user(user, Gitlab::Access::MASTER) } + before { empty_project.add_user(user, Gitlab::Access::MASTER) } it "raises file not found" do issue_template = subject.new('.gitlab/issue_templates/not_existent.md', empty_project) diff --git a/spec/lib/gitlab/template/merge_request_template_spec.rb b/spec/lib/gitlab/template/merge_request_template_spec.rb index bb0f68043fa..ddf68c4cf78 100644 --- a/spec/lib/gitlab/template/merge_request_template_spec.rb +++ b/spec/lib/gitlab/template/merge_request_template_spec.rb @@ -10,7 +10,7 @@ describe Gitlab::Template::MergeRequestTemplate do let(:file_path_3) { '.gitlab/merge_request_templates/feature_proposal.md' } before do - project.team.add_user(user, Gitlab::Access::MASTER) + 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) @@ -53,7 +53,7 @@ describe Gitlab::Template::MergeRequestTemplate do context 'when repo is bare or empty' do let(:empty_project) { create(:empty_project) } - before { empty_project.team.add_user(user, Gitlab::Access::MASTER) } + before { empty_project.add_user(user, Gitlab::Access::MASTER) } it "returns empty array" do templates = subject.by_category('', empty_project) @@ -78,7 +78,7 @@ describe Gitlab::Template::MergeRequestTemplate do context "when repo is empty" do let(:empty_project) { create(:empty_project) } - before { empty_project.team.add_user(user, Gitlab::Access::MASTER) } + before { empty_project.add_user(user, Gitlab::Access::MASTER) } it "raises file not found" do issue_template = subject.new('.gitlab/merge_request_templates/not_existent.md', empty_project) diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 0363bc74939..0f69119e82e 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -492,21 +492,22 @@ describe Notify do end end - def invite_to_project(project:, email:, inviter:) - Member.add_user( - project.project_members, - 'toto@example.com', - Gitlab::Access::DEVELOPER, - current_user: inviter + def invite_to_project(project, inviter:) + create( + :project_member, + :developer, + project: project, + invite_token: '1234', + invite_email: 'toto@example.com', + user: nil, + created_by: inviter ) - - project.project_members.invite.last end describe 'project invitation' do let(:project) { create(:project) } let(:master) { create(:user).tap { |u| project.team << [u, :master] } } - let(:project_member) { invite_to_project(project: project, email: 'toto@example.com', inviter: master) } + let(:project_member) { invite_to_project(project, inviter: master) } subject { Notify.member_invited_email('project', project_member.id, project_member.invite_token) } @@ -525,10 +526,10 @@ describe Notify do describe 'project invitation accepted' do let(:project) { create(:project) } - let(:invited_user) { create(:user) } + let(:invited_user) { create(:user, name: 'invited user') } let(:master) { create(:user).tap { |u| project.team << [u, :master] } } let(:project_member) do - invitee = invite_to_project(project: project, email: 'toto@example.com', inviter: master) + invitee = invite_to_project(project, inviter: master) invitee.accept_invite!(invited_user) invitee end @@ -552,7 +553,7 @@ describe Notify do let(:project) { create(:project) } let(:master) { create(:user).tap { |u| project.team << [u, :master] } } let(:project_member) do - invitee = invite_to_project(project: project, email: 'toto@example.com', inviter: master) + invitee = invite_to_project(project, inviter: master) invitee.decline_invite! invitee end @@ -744,21 +745,22 @@ describe Notify do end end - def invite_to_group(group:, email:, inviter:) - Member.add_user( - group.group_members, - 'toto@example.com', - Gitlab::Access::DEVELOPER, - current_user: inviter + def invite_to_group(group, inviter:) + create( + :group_member, + :developer, + group: group, + invite_token: '1234', + invite_email: 'toto@example.com', + user: nil, + created_by: inviter ) - - group.group_members.invite.last end describe 'group invitation' do let(:group) { create(:group) } let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } } - let(:group_member) { invite_to_group(group: group, email: 'toto@example.com', inviter: owner) } + let(:group_member) { invite_to_group(group, inviter: owner) } subject { Notify.member_invited_email('group', group_member.id, group_member.invite_token) } @@ -777,10 +779,10 @@ describe Notify do describe 'group invitation accepted' do let(:group) { create(:group) } - let(:invited_user) { create(:user) } + let(:invited_user) { create(:user, name: 'invited user') } let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } } let(:group_member) do - invitee = invite_to_group(group: group, email: 'toto@example.com', inviter: owner) + invitee = invite_to_group(group, inviter: owner) invitee.accept_invite!(invited_user) invitee end @@ -804,7 +806,7 @@ describe Notify do let(:group) { create(:group) } let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } } let(:group_member) do - invitee = invite_to_group(group: group, email: 'toto@example.com', inviter: owner) + invitee = invite_to_group(group, inviter: owner) invitee.decline_invite! invitee end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 3259f795296..3b8b743af2d 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -494,7 +494,7 @@ describe Issue, models: true do context 'with an admin user' do let(:project) { create(:empty_project) } - let(:user) { create(:user, admin: true) } + let(:user) { create(:admin) } it 'returns true for a regular issue' do issue = build(:issue, project: project) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 0b1634f654a..a9d3fcc6587 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -74,22 +74,17 @@ describe Member, models: true do @blocked_master = project.members.find_by(user_id: @blocked_user.id, access_level: Gitlab::Access::MASTER) @blocked_developer = project.members.find_by(user_id: @blocked_user.id, access_level: Gitlab::Access::DEVELOPER) - Member.add_user( - project.members, - 'toto1@example.com', - Gitlab::Access::DEVELOPER, - current_user: @master_user - ) - @invited_member = project.members.invite.find_by_invite_email('toto1@example.com') + @invited_member = create(:project_member, :developer, + project: project, + invite_token: '1234', + invite_email: 'toto1@example.com') accepted_invite_user = build(:user, state: :active) - Member.add_user( - project.members, - 'toto2@example.com', - Gitlab::Access::DEVELOPER, - current_user: @master_user - ) - @accepted_invite_member = project.members.invite.find_by_invite_email('toto2@example.com').tap { |u| u.accept_invite!(accepted_invite_user) } + @accepted_invite_member = create(:project_member, :developer, + project: project, + invite_token: '1234', + invite_email: 'toto2@example.com'). + tap { |u| u.accept_invite!(accepted_invite_user) } requested_user = create(:user).tap { |u| project.request_access(u) } @requested_member = project.requesters.find_by(user_id: requested_user.id) @@ -176,39 +171,209 @@ describe Member, models: true do it { is_expected.to respond_to(:user_email) } end - describe ".add_user" do - let!(:user) { create(:user) } - let(:project) { create(:project) } + describe '.add_user' do + %w[project group].each do |source_type| + context "when source is a #{source_type}" do + let!(:source) { create(source_type) } + let!(:user) { create(:user) } + let!(:admin) { create(:admin) } - context "when called with a user id" do - it "adds the user as a member" do - Member.add_user(project.project_members, user.id, ProjectMember::MASTER) + it 'returns a Member object' do + member = described_class.add_user(source, user, :master) - expect(project.users).to include(user) - end - end + expect(member).to be_a "#{source_type.classify}Member".constantize + expect(member).to be_persisted + end - context "when called with a user object" do - it "adds the user as a member" do - Member.add_user(project.project_members, user, ProjectMember::MASTER) + it 'sets members.created_by to the given current_user' do + member = described_class.add_user(source, user, :master, current_user: admin) - expect(project.users).to include(user) - end - end + expect(member.created_by).to eq(admin) + end - context "when called with a known user email" do - it "adds the user as a member" do - Member.add_user(project.project_members, user.email, ProjectMember::MASTER) + it 'sets members.expires_at to the given expires_at' do + member = described_class.add_user(source, user, :master, expires_at: Date.new(2016, 9, 22)) - expect(project.users).to include(user) - end - end + expect(member.expires_at).to eq(Date.new(2016, 9, 22)) + end + + described_class.access_levels.each do |sym_key, int_access_level| + it "accepts the :#{sym_key} symbol as access level" do + expect(source.users).not_to include(user) + + member = described_class.add_user(source, user.id, sym_key) + + expect(member.access_level).to eq(int_access_level) + expect(source.users.reload).to include(user) + end + + it "accepts the #{int_access_level} integer as access level" do + expect(source.users).not_to include(user) + + member = described_class.add_user(source, user.id, int_access_level) + + expect(member.access_level).to eq(int_access_level) + expect(source.users.reload).to include(user) + end + end + + context 'with no current_user' do + context 'when called with a known user id' do + it 'adds the user as a member' do + expect(source.users).not_to include(user) + + described_class.add_user(source, user.id, :master) + + expect(source.users.reload).to include(user) + end + end + + context 'when called with an unknown user id' do + it 'adds the user as a member' do + expect(source.users).not_to include(user) + + described_class.add_user(source, 42, :master) + + expect(source.users.reload).not_to include(user) + end + end + + context 'when called with a user object' do + it 'adds the user as a member' do + expect(source.users).not_to include(user) + + described_class.add_user(source, user, :master) + + expect(source.users.reload).to include(user) + end + end + + context 'when called with a requester user object' do + before do + source.request_access(user) + end + + it 'adds the requester as a member' do + expect(source.users).not_to include(user) + expect(source.requesters.exists?(user_id: user)).to be_truthy + + expect { described_class.add_user(source, user, :master) }. + to raise_error(Gitlab::Access::AccessDeniedError) + + expect(source.users.reload).not_to include(user) + expect(source.requesters.reload.exists?(user_id: user)).to be_truthy + end + end + + context 'when called with a known user email' do + it 'adds the user as a member' do + expect(source.users).not_to include(user) + + described_class.add_user(source, user.email, :master) + + expect(source.users.reload).to include(user) + end + end + + context 'when called with an unknown user email' do + it 'creates an invited member' do + expect(source.users).not_to include(user) + + described_class.add_user(source, 'user@example.com', :master) + + expect(source.members.invite.pluck(:invite_email)).to include('user@example.com') + end + end + end + + context 'when current_user can update member' do + it 'creates the member' do + expect(source.users).not_to include(user) + + described_class.add_user(source, user, :master, current_user: admin) + + expect(source.users.reload).to include(user) + end + + context 'when called with a requester user object' do + before do + source.request_access(user) + end + + it 'adds the requester as a member' do + expect(source.users).not_to include(user) + expect(source.requesters.exists?(user_id: user)).to be_truthy + + described_class.add_user(source, user, :master, current_user: admin) + + expect(source.users.reload).to include(user) + expect(source.requesters.reload.exists?(user_id: user)).to be_falsy + end + end + end + + context 'when current_user cannot update member' do + it 'does not create the member' do + expect(source.users).not_to include(user) + + member = described_class.add_user(source, user, :master, current_user: user) + + expect(source.users.reload).not_to include(user) + expect(member).not_to be_persisted + end + + context 'when called with a requester user object' do + before do + source.request_access(user) + end + + it 'does not destroy the requester' do + expect(source.users).not_to include(user) + expect(source.requesters.exists?(user_id: user)).to be_truthy + + described_class.add_user(source, user, :master, current_user: user) + + expect(source.users.reload).not_to include(user) + expect(source.requesters.exists?(user_id: user)).to be_truthy + end + end + end + + context 'when member already exists' do + before do + source.add_user(user, :developer) + end + + context 'with no current_user' do + it 'updates the member' do + expect(source.users).to include(user) + + described_class.add_user(source, user, :master) + + expect(source.members.find_by(user_id: user).access_level).to eq(Gitlab::Access::MASTER) + end + end + + context 'when current_user can update member' do + it 'updates the member' do + expect(source.users).to include(user) + + described_class.add_user(source, user, :master, current_user: admin) + + expect(source.members.find_by(user_id: user).access_level).to eq(Gitlab::Access::MASTER) + end + end + + context 'when current_user cannot update member' do + it 'does not update the member' do + expect(source.users).to include(user) - context "when called with an unknown user email" do - it "adds a member invite" do - Member.add_user(project.project_members, "user@example.com", ProjectMember::MASTER) + described_class.add_user(source, user, :master, current_user: user) - expect(project.project_members.invite.pluck(:invite_email)).to include("user@example.com") + expect(source.members.find_by(user_id: user).access_level).to eq(Gitlab::Access::DEVELOPER) + end + end + end end end end diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb index 56fa7fa6134..370aeb9e0a9 100644 --- a/spec/models/members/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -1,6 +1,33 @@ require 'spec_helper' describe GroupMember, models: true do + describe '.access_level_roles' do + it 'returns Gitlab::Access.options_with_owner' do + expect(described_class.access_level_roles).to eq(Gitlab::Access.options_with_owner) + end + end + + describe '.access_levels' do + it 'returns Gitlab::Access.options_with_owner' do + expect(described_class.access_levels).to eq(Gitlab::Access.sym_options_with_owner) + end + end + + describe '.add_users_to_group' do + it 'adds the given users to the given group' do + group = create(:group) + users = create_list(:user, 2) + + described_class.add_users_to_group( + group, + [users.first.id, users.second], + described_class::MASTER + ) + + expect(group.users).to include(users.first, users.second) + end + end + describe 'notifications' do describe "#after_create" do it "sends email to user" do diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index 805c15a4e5e..d85a1c1e3b2 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -15,6 +15,26 @@ describe ProjectMember, models: true do it { is_expected.to include_module(Gitlab::ShellAdapter) } end + describe '.access_level_roles' do + it 'returns Gitlab::Access.options' do + expect(described_class.access_level_roles).to eq(Gitlab::Access.options) + end + end + + describe '.add_user' do + context 'when called with the project owner' do + it 'adds the user as a member' do + project = create(:empty_project) + + expect(project.users).not_to include(project.owner) + + described_class.add_user(project, project.owner, :master, current_user: project.owner) + + expect(project.users.reload).to include(project.owner) + end + end + end + describe '#real_source_type' do subject { create(:project_member).real_source_type } @@ -50,7 +70,7 @@ describe ProjectMember, models: true do end end - describe :import_team do + describe '.import_team' do before do @project_1 = create :project @project_2 = create :project @@ -81,25 +101,21 @@ describe ProjectMember, models: true do end describe '.add_users_to_projects' do - before do - @project_1 = create :project - @project_2 = create :project + it 'adds the given users to the given projects' do + projects = create_list(:empty_project, 2) + users = create_list(:user, 2) - @user_1 = create :user - @user_2 = create :user - - ProjectMember.add_users_to_projects( - [@project_1.id, @project_2.id], - [@user_1.id, @user_2.id], - ProjectMember::MASTER - ) - end + described_class.add_users_to_projects( + [projects.first.id, projects.second], + [users.first.id, users.second], + described_class::MASTER) - it { expect(@project_1.users).to include(@user_1) } - it { expect(@project_1.users).to include(@user_2) } + expect(projects.first.users).to include(users.first) + expect(projects.first.users).to include(users.second) - it { expect(@project_2.users).to include(@user_1) } - it { expect(@project_2.users).to include(@user_2) } + expect(projects.second.users).to include(users.first) + expect(projects.second.users).to include(users.second) + end end describe '.truncate_teams' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 83f61f0af0a..50423d027ac 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -836,7 +836,7 @@ describe Project, models: true do describe 'when a user has access to a project' do before do - project.team.add_user(user, Gitlab::Access::MASTER) + project.add_user(user, Gitlab::Access::MASTER) end it { is_expected.to eq([project]) } diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index a7930c59df9..b813ee967f8 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -15,7 +15,7 @@ describe API::API, api: true do let(:milestone) { create(:milestone, title: '1.0.0', project: project) } before do - project.team << [user, :reporters] + project.team << [user, :reporter] end describe "GET /projects/:id/merge_requests" do @@ -299,7 +299,7 @@ describe API::API, api: true do let!(:unrelated_project) { create(:project, namespace: create(:user).namespace, creator_id: user2.id) } before :each do |each| - fork_project.team << [user2, :reporters] + fork_project.team << [user2, :reporter] end it "returns merge_request" do -- cgit v1.2.1 From edbbbe3a2777c273b3dea1b40aa23b1b7847ca4f Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 10 Nov 2015 23:23:49 +0200 Subject: Fix grammar and typos in Runners pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/runners_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index a5ed3595b0a..0e1cc9a0f73 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -60,7 +60,7 @@ describe "Runners" do it "removes specific runner for project if this is last project for that runners" do within ".activated-specific-runners" do - click_on "Remove runner" + click_on "Remove Runner" end expect(Ci::Runner.exists?(id: @specific_runner)).to be_falsey @@ -75,7 +75,7 @@ describe "Runners" do end it "enables shared runners" do - click_on "Enable shared runners" + click_on "Enable shared Runners" expect(@project.reload.shared_runners_enabled).to be_truthy end end -- cgit v1.2.1 From 93d849beaebb00dc4dcb6cb5ffa4721883e0da51 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 22 Sep 2016 17:31:18 -0300 Subject: Expose project share expiration_date field on API --- spec/requests/api/projects_spec.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 192c7d14c13..4a0d727faea 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -761,13 +761,16 @@ describe API::API, api: true do let(:group) { create(:group) } it "shares project with group" do + expires_at = 10.days.from_now.to_date + expect do - post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER + post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: Gitlab::Access::DEVELOPER, expires_at: expires_at end.to change { ProjectGroupLink.count }.by(1) expect(response.status).to eq 201 - expect(json_response['group_id']).to eq group.id - expect(json_response['group_access']).to eq Gitlab::Access::DEVELOPER + expect(json_response['group_id']).to eq(group.id) + expect(json_response['group_access']).to eq(Gitlab::Access::DEVELOPER) + expect(json_response['expires_at']).to eq(expires_at.to_s) end it "returns a 400 error when group id is not given" do -- cgit v1.2.1 From adab5dba43660a22118ea77038ef03fe0ded19f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 27 Sep 2016 11:29:06 +0200 Subject: Fix permission for setting an issue's due date MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../issues/user_uses_slash_commands_spec.rb | 72 +++++- spec/services/issues/create_service_spec.rb | 36 ++- spec/services/issues/update_service_spec.rb | 97 +++++--- .../slash_commands/interpret_service_spec.rb | 71 +++++- .../issuable_slash_commands_shared_examples.rb | 261 +++++++++++++++++++++ ...reate_service_slash_commands_shared_examples.rb | 83 ------- .../issuable_slash_commands_shared_examples.rb | 261 --------------------- ...reate_service_slash_commands_shared_examples.rb | 83 +++++++ 8 files changed, 556 insertions(+), 408 deletions(-) create mode 100644 spec/support/features/issuable_slash_commands_shared_examples.rb delete mode 100644 spec/support/issuable_create_service_slash_commands_shared_examples.rb delete mode 100644 spec/support/issuable_slash_commands_shared_examples.rb create mode 100644 spec/support/services/issuable_create_service_slash_commands_shared_examples.rb (limited to 'spec') diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index 105629c485a..bf2b93c92fb 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -25,32 +25,78 @@ feature 'Issues > User uses slash commands', feature: true, js: true do describe 'adding a due date from note' do let(:issue) { create(:issue, project: project) } - it 'does not create a note, and sets the due date accordingly' do - write_note("/due 2016-08-28") + context 'when the current user can update the due date' do + it 'does not create a note, and sets the due date accordingly' do + write_note("/due 2016-08-28") - expect(page).not_to have_content '/due 2016-08-28' - expect(page).to have_content 'Your commands have been executed!' + expect(page).not_to have_content '/due 2016-08-28' + expect(page).to have_content 'Your commands have been executed!' - issue.reload + issue.reload - expect(issue.due_date).to eq Date.new(2016, 8, 28) + expect(issue.due_date).to eq Date.new(2016, 8, 28) + end + end + + context 'when the current user cannot update the due date' do + let(:guest) { create(:user) } + before do + project.team << [guest, :guest] + logout + login_with(guest) + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'does not create a note, and sets the due date accordingly' do + write_note("/due 2016-08-28") + + expect(page).to have_content '/due 2016-08-28' + expect(page).not_to have_content 'Your commands have been executed!' + + issue.reload + + expect(issue.due_date).to be_nil + end end end describe 'removing a due date from note' do let(:issue) { create(:issue, project: project, due_date: Date.new(2016, 8, 28)) } - it 'does not create a note, and removes the due date accordingly' do - expect(issue.due_date).to eq Date.new(2016, 8, 28) + context 'when the current user can update the due date' do + it 'does not create a note, and removes the due date accordingly' do + expect(issue.due_date).to eq Date.new(2016, 8, 28) + + write_note("/remove_due_date") + + expect(page).not_to have_content '/remove_due_date' + expect(page).to have_content 'Your commands have been executed!' + + issue.reload + + expect(issue.due_date).to be_nil + end + end + + context 'when the current user cannot update the due date' do + let(:guest) { create(:user) } + before do + project.team << [guest, :guest] + logout + login_with(guest) + visit namespace_project_issue_path(project.namespace, project, issue) + end - write_note("/remove_due_date") + it 'does not create a note, and sets the due date accordingly' do + write_note("/remove_due_date") - expect(page).not_to have_content '/remove_due_date' - expect(page).to have_content 'Your commands have been executed!' + expect(page).to have_content '/remove_due_date' + expect(page).not_to have_content 'Your commands have been executed!' - issue.reload + issue.reload - expect(issue.due_date).to be_nil + expect(issue.due_date).to eq Date.new(2016, 8, 28) + end end end end diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 58569ba96c3..1050502fa19 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -20,16 +20,38 @@ describe Issues::CreateService, services: true do let(:opts) do { title: 'Awesome issue', description: 'please fix', - assignee: assignee, + assignee_id: assignee.id, label_ids: labels.map(&:id), - milestone_id: milestone.id } + milestone_id: milestone.id, + due_date: Date.tomorrow } end - it { expect(issue).to be_valid } - it { expect(issue.title).to eq('Awesome issue') } - it { expect(issue.assignee).to eq assignee } - it { expect(issue.labels).to match_array labels } - it { expect(issue.milestone).to eq milestone } + it 'creates the issue with the given params' do + expect(issue).to be_persisted + expect(issue.title).to eq('Awesome issue') + expect(issue.assignee).to eq assignee + expect(issue.labels).to match_array labels + expect(issue.milestone).to eq milestone + expect(issue.due_date).to eq Date.tomorrow + end + + context 'when current user cannot admin issues in the project' do + let(:guest) { create(:user) } + before do + project.team << [guest, :guest] + end + + it 'filters out params that cannot be set without the :admin_issue permission' do + issue = described_class.new(project, guest, opts).execute + + expect(issue).to be_persisted + expect(issue.title).to eq('Awesome issue') + expect(issue.assignee).to be_nil + expect(issue.labels).to be_empty + expect(issue.milestone).to be_nil + expect(issue.due_date).to be_nil + end + end it 'creates a pending todo for new assignee' do attributes = { diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 4f5375a3583..1638a46ed51 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -32,55 +32,84 @@ describe Issues::UpdateService, services: true do described_class.new(project, user, opts).execute(issue) end - context "valid params" do - before do - opts = { + context 'valid params' do + let(:opts) do + { title: 'New title', description: 'Also please fix', assignee_id: user2.id, state_event: 'close', - label_ids: [label.id] + label_ids: [label.id], + due_date: Date.tomorrow } - - perform_enqueued_jobs do - update_issue(opts) - end end - it { expect(issue).to be_valid } - it { expect(issue.title).to eq('New title') } - it { expect(issue.assignee).to eq(user2) } - it { expect(issue).to be_closed } - it { expect(issue.labels.count).to eq(1) } - it { expect(issue.labels.first.title).to eq(label.name) } - - it 'sends email to user2 about assign of new issue and email to user3 about issue unassignment' do - deliveries = ActionMailer::Base.deliveries - email = deliveries.last - recipients = deliveries.last(2).map(&:to).flatten - expect(recipients).to include(user2.email, user3.email) - expect(email.subject).to include(issue.title) + it 'updates the issue with the given params' do + update_issue(opts) + + expect(issue).to be_valid + expect(issue.title).to eq 'New title' + expect(issue.description).to eq 'Also please fix' + expect(issue.assignee).to eq user2 + expect(issue).to be_closed + expect(issue.labels).to match_array [label] + expect(issue.due_date).to eq Date.tomorrow end - it 'creates system note about issue reassign' do - note = find_note('Reassigned to') + context 'when current user cannot admin issues in the project' do + let(:guest) { create(:user) } + before do + project.team << [guest, :guest] + end - expect(note).not_to be_nil - expect(note.note).to include "Reassigned to \@#{user2.username}" + it 'filters out params that cannot be set without the :admin_issue permission' do + described_class.new(project, guest, opts).execute(issue) + + expect(issue).to be_valid + expect(issue.title).to eq 'New title' + expect(issue.description).to eq 'Also please fix' + expect(issue.assignee).to eq user3 + expect(issue.labels).to be_empty + expect(issue.milestone).to be_nil + expect(issue.due_date).to be_nil + end end - it 'creates system note about issue label edit' do - note = find_note('Added ~') + context 'with background jobs processed' do + before do + perform_enqueued_jobs do + update_issue(opts) + end + end + + it 'sends email to user2 about assign of new issue and email to user3 about issue unassignment' do + deliveries = ActionMailer::Base.deliveries + email = deliveries.last + recipients = deliveries.last(2).map(&:to).flatten + expect(recipients).to include(user2.email, user3.email) + expect(email.subject).to include(issue.title) + end - expect(note).not_to be_nil - expect(note.note).to include "Added ~#{label.id} label" - end + it 'creates system note about issue reassign' do + note = find_note('Reassigned to') - it 'creates system note about title change' do - note = find_note('Changed title:') + expect(note).not_to be_nil + expect(note.note).to include "Reassigned to \@#{user2.username}" + end - expect(note).not_to be_nil - expect(note.note).to eq 'Changed title: **{-Old-} title** → **{+New+} title**' + it 'creates system note about issue label edit' do + note = find_note('Added ~') + + expect(note).not_to be_nil + expect(note.note).to include "Added ~#{label.id} label" + end + + it 'creates system note about title change' do + note = find_note('Changed title:') + + expect(note).not_to be_nil + expect(note.note).to eq 'Changed title: **{-Old-} title** → **{+New+} title**' + end end end diff --git a/spec/services/slash_commands/interpret_service_spec.rb b/spec/services/slash_commands/interpret_service_spec.rb index a616275e883..5b1edba87a1 100644 --- a/spec/services/slash_commands/interpret_service_spec.rb +++ b/spec/services/slash_commands/interpret_service_spec.rb @@ -1,19 +1,19 @@ require 'spec_helper' describe SlashCommands::InterpretService, services: true do - let(:project) { create(:project) } - let(:user) { create(:user) } + let(:project) { create(:empty_project, :public) } + let(:developer) { create(:user) } let(:issue) { create(:issue, project: project) } let(:milestone) { create(:milestone, project: project, title: '9.10') } let(:inprogress) { create(:label, project: project, title: 'In Progress') } let(:bug) { create(:label, project: project, title: 'Bug') } before do - project.team << [user, :developer] + project.team << [developer, :developer] end describe '#execute' do - let(:service) { described_class.new(project, user) } + let(:service) { described_class.new(project, developer) } let(:merge_request) { create(:merge_request, source_project: project) } shared_examples 'reopen command' do @@ -45,13 +45,13 @@ describe SlashCommands::InterpretService, services: true do it 'fetches assignee and populates assignee_id if content contains /assign' do _, updates = service.execute(content, issuable) - expect(updates).to eq(assignee_id: user.id) + expect(updates).to eq(assignee_id: developer.id) end end shared_examples 'unassign command' do it 'populates assignee_id: nil if content contains /unassign' do - issuable.update(assignee_id: user.id) + issuable.update(assignee_id: developer.id) _, updates = service.execute(content, issuable) expect(updates).to eq(assignee_id: nil) @@ -124,7 +124,7 @@ describe SlashCommands::InterpretService, services: true do shared_examples 'done command' do it 'populates todo_event: "done" if content contains /done' do - TodoService.new.mark_todo(issuable, user) + TodoService.new.mark_todo(issuable, developer) _, updates = service.execute(content, issuable) expect(updates).to eq(todo_event: 'done') @@ -141,7 +141,7 @@ describe SlashCommands::InterpretService, services: true do shared_examples 'unsubscribe command' do it 'populates subscription_event: "unsubscribe" if content contains /unsubscribe' do - issuable.subscribe(user) + issuable.subscribe(developer) _, updates = service.execute(content, issuable) expect(updates).to eq(subscription_event: 'unsubscribe') @@ -209,12 +209,12 @@ describe SlashCommands::InterpretService, services: true do end it_behaves_like 'assign command' do - let(:content) { "/assign @#{user.username}" } + let(:content) { "/assign @#{developer.username}" } let(:issuable) { issue } end it_behaves_like 'assign command' do - let(:content) { "/assign @#{user.username}" } + let(:content) { "/assign @#{developer.username}" } let(:issuable) { merge_request } end @@ -380,5 +380,56 @@ describe SlashCommands::InterpretService, services: true do let(:content) { '/remove_due_date' } let(:issuable) { merge_request } end + + context 'when current_user cannot :admin_issue' do + let(:visitor) { create(:user) } + let(:issue) { create(:issue, project: project, author: visitor) } + let(:service) { described_class.new(project, visitor) } + + it_behaves_like 'empty command' do + let(:content) { "/assign @#{developer.username}" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/unassign' } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { "/milestone %#{milestone.title}" } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/remove_milestone' } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { %(/label ~"#{inprogress.title}" ~#{bug.title} ~unknown) } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { %(/unlabel ~"#{inprogress.title}") } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { %(/relabel ~"#{inprogress.title}") } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/due tomorrow' } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/remove_due_date' } + let(:issuable) { issue } + end + end end end diff --git a/spec/support/features/issuable_slash_commands_shared_examples.rb b/spec/support/features/issuable_slash_commands_shared_examples.rb new file mode 100644 index 00000000000..5e3b8f2b23e --- /dev/null +++ b/spec/support/features/issuable_slash_commands_shared_examples.rb @@ -0,0 +1,261 @@ +# Specifications for behavior common to all objects with executable attributes. +# It takes a `issuable_type`, and expect an `issuable`. + +shared_examples 'issuable record that supports slash commands in its description and notes' do |issuable_type| + include SlashCommandsHelpers + include WaitForAjax + + let(:master) { create(:user) } + let(:assignee) { create(:user, username: 'bob') } + let(:guest) { create(:user) } + let(:project) { create(:project, :public) } + let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } + let!(:label_bug) { create(:label, project: project, title: 'bug') } + let!(:label_feature) { create(:label, project: project, title: 'feature') } + let(:new_url_opts) { {} } + + before do + project.team << [master, :master] + project.team << [assignee, :developer] + project.team << [guest, :guest] + login_with(master) + end + + after do + # Ensure all outstanding Ajax requests are complete to avoid database deadlocks + wait_for_ajax + end + + describe "new #{issuable_type}" do + context 'with commands in the description' do + it "creates the #{issuable_type} and interpret commands accordingly" do + visit public_send("new_namespace_project_#{issuable_type}_path", project.namespace, project, new_url_opts) + fill_in "#{issuable_type}_title", with: 'bug 345' + fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug\n/milestone %\"ASAP\"" + click_button "Submit #{issuable_type}".humanize + + issuable = project.public_send(issuable_type.to_s.pluralize).first + + expect(issuable.description).to eq "bug description" + expect(issuable.labels).to eq [label_bug] + expect(issuable.milestone).to eq milestone + expect(page).to have_content 'bug 345' + expect(page).to have_content 'bug description' + end + end + end + + describe "note on #{issuable_type}" do + before do + visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) + end + + context 'with a note containing commands' do + it 'creates a note without the commands and interpret the commands accordingly' do + write_note("Awesome!\n/assign @bob\n/label ~bug\n/milestone %\"ASAP\"") + + expect(page).to have_content 'Awesome!' + expect(page).not_to have_content '/assign @bob' + expect(page).not_to have_content '/label ~bug' + expect(page).not_to have_content '/milestone %"ASAP"' + + issuable.reload + note = issuable.notes.user.first + + expect(note.note).to eq "Awesome!" + expect(issuable.assignee).to eq assignee + expect(issuable.labels).to eq [label_bug] + expect(issuable.milestone).to eq milestone + end + end + + context 'with a note containing only commands' do + it 'does not create a note but interpret the commands accordingly' do + write_note("/assign @bob\n/label ~bug\n/milestone %\"ASAP\"") + + expect(page).not_to have_content '/assign @bob' + expect(page).not_to have_content '/label ~bug' + expect(page).not_to have_content '/milestone %"ASAP"' + expect(page).to have_content 'Your commands have been executed!' + + issuable.reload + + expect(issuable.notes.user).to be_empty + expect(issuable.assignee).to eq assignee + expect(issuable.labels).to eq [label_bug] + expect(issuable.milestone).to eq milestone + end + end + + context "with a note closing the #{issuable_type}" do + before do + expect(issuable).to be_open + end + + context "when current user can close #{issuable_type}" do + it "closes the #{issuable_type}" do + write_note("/close") + + expect(page).not_to have_content '/close' + expect(page).to have_content 'Your commands have been executed!' + + expect(issuable.reload).to be_closed + end + end + + context "when current user cannot close #{issuable_type}" do + before do + logout + login_with(guest) + visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) + end + + it "does not close the #{issuable_type}" do + write_note("/close") + + expect(page).not_to have_content '/close' + expect(page).not_to have_content 'Your commands have been executed!' + + expect(issuable).to be_open + end + end + end + + context "with a note reopening the #{issuable_type}" do + before do + issuable.close + expect(issuable).to be_closed + end + + context "when current user can reopen #{issuable_type}" do + it "reopens the #{issuable_type}" do + write_note("/reopen") + + expect(page).not_to have_content '/reopen' + expect(page).to have_content 'Your commands have been executed!' + + expect(issuable.reload).to be_open + end + end + + context "when current user cannot reopen #{issuable_type}" do + before do + logout + login_with(guest) + visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) + end + + it "does not reopen the #{issuable_type}" do + write_note("/reopen") + + expect(page).not_to have_content '/reopen' + expect(page).not_to have_content 'Your commands have been executed!' + + expect(issuable).to be_closed + end + end + end + + context "with a note changing the #{issuable_type}'s title" do + context "when current user can change title of #{issuable_type}" do + it "reopens the #{issuable_type}" do + write_note("/title Awesome new title") + + expect(page).not_to have_content '/title' + expect(page).to have_content 'Your commands have been executed!' + + expect(issuable.reload.title).to eq 'Awesome new title' + end + end + + context "when current user cannot change title of #{issuable_type}" do + before do + logout + login_with(guest) + visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) + end + + it "does not reopen the #{issuable_type}" do + write_note("/title Awesome new title") + + expect(page).not_to have_content '/title' + expect(page).not_to have_content 'Your commands have been executed!' + + expect(issuable.reload.title).not_to eq 'Awesome new title' + end + end + end + + context "with a note marking the #{issuable_type} as todo" do + it "creates a new todo for the #{issuable_type}" do + write_note("/todo") + + expect(page).not_to have_content '/todo' + expect(page).to have_content 'Your commands have been executed!' + + todos = TodosFinder.new(master).execute + todo = todos.first + + expect(todos.size).to eq 1 + expect(todo).to be_pending + expect(todo.target).to eq issuable + expect(todo.author).to eq master + expect(todo.user).to eq master + end + end + + context "with a note marking the #{issuable_type} as done" do + before do + TodoService.new.mark_todo(issuable, master) + end + + it "creates a new todo for the #{issuable_type}" do + todos = TodosFinder.new(master).execute + todo = todos.first + + expect(todos.size).to eq 1 + expect(todos.first).to be_pending + expect(todo.target).to eq issuable + expect(todo.author).to eq master + expect(todo.user).to eq master + + write_note("/done") + + expect(page).not_to have_content '/done' + expect(page).to have_content 'Your commands have been executed!' + + expect(todo.reload).to be_done + end + end + + context "with a note subscribing to the #{issuable_type}" do + it "creates a new todo for the #{issuable_type}" do + expect(issuable.subscribed?(master)).to be_falsy + + write_note("/subscribe") + + expect(page).not_to have_content '/subscribe' + expect(page).to have_content 'Your commands have been executed!' + + expect(issuable.subscribed?(master)).to be_truthy + end + end + + context "with a note unsubscribing to the #{issuable_type} as done" do + before do + issuable.subscribe(master) + end + + it "creates a new todo for the #{issuable_type}" do + expect(issuable.subscribed?(master)).to be_truthy + + write_note("/unsubscribe") + + expect(page).not_to have_content '/unsubscribe' + expect(page).to have_content 'Your commands have been executed!' + + expect(issuable.subscribed?(master)).to be_falsy + end + end + end +end diff --git a/spec/support/issuable_create_service_slash_commands_shared_examples.rb b/spec/support/issuable_create_service_slash_commands_shared_examples.rb deleted file mode 100644 index 5f9645ed44f..00000000000 --- a/spec/support/issuable_create_service_slash_commands_shared_examples.rb +++ /dev/null @@ -1,83 +0,0 @@ -# Specifications for behavior common to all objects with executable attributes. -# It can take a `default_params`. - -shared_examples 'new issuable record that supports slash commands' do - let!(:project) { create(:project) } - let(:user) { create(:user).tap { |u| project.team << [u, :master] } } - let(:assignee) { create(:user) } - let!(:milestone) { create(:milestone, project: project) } - let!(:labels) { create_list(:label, 3, project: project) } - let(:base_params) { { title: FFaker::Lorem.sentence(3) } } - let(:params) { base_params.merge(defined?(default_params) ? default_params : {}).merge(example_params) } - let(:issuable) { described_class.new(project, user, params).execute } - - context 'with labels in command only' do - let(:example_params) do - { - description: "/label ~#{labels.first.name} ~#{labels.second.name}\n/unlabel ~#{labels.third.name}" - } - end - - it 'attaches labels to issuable' do - expect(issuable).to be_persisted - expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id]) - end - end - - context 'with labels in params and command' do - let(:example_params) do - { - label_ids: [labels.second.id], - description: "/label ~#{labels.first.name}\n/unlabel ~#{labels.third.name}" - } - end - - it 'attaches all labels to issuable' do - expect(issuable).to be_persisted - expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id]) - end - end - - context 'with assignee and milestone in command only' do - let(:example_params) do - { - description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}") - } - end - - it 'assigns and sets milestone to issuable' do - expect(issuable).to be_persisted - expect(issuable.assignee).to eq(assignee) - expect(issuable.milestone).to eq(milestone) - end - end - - context 'with assignee and milestone in params and command' do - let(:example_params) do - { - assignee: build_stubbed(:user), - milestone_id: double(:milestone), - description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}") - } - end - - it 'assigns and sets milestone to issuable from command' do - expect(issuable).to be_persisted - expect(issuable.assignee).to eq(assignee) - expect(issuable.milestone).to eq(milestone) - end - end - - describe '/close' do - let(:example_params) do - { - description: '/close' - } - end - - it 'returns an open issue' do - expect(issuable).to be_persisted - expect(issuable).to be_open - end - end -end diff --git a/spec/support/issuable_slash_commands_shared_examples.rb b/spec/support/issuable_slash_commands_shared_examples.rb deleted file mode 100644 index 5e3b8f2b23e..00000000000 --- a/spec/support/issuable_slash_commands_shared_examples.rb +++ /dev/null @@ -1,261 +0,0 @@ -# Specifications for behavior common to all objects with executable attributes. -# It takes a `issuable_type`, and expect an `issuable`. - -shared_examples 'issuable record that supports slash commands in its description and notes' do |issuable_type| - include SlashCommandsHelpers - include WaitForAjax - - let(:master) { create(:user) } - let(:assignee) { create(:user, username: 'bob') } - let(:guest) { create(:user) } - let(:project) { create(:project, :public) } - let!(:milestone) { create(:milestone, project: project, title: 'ASAP') } - let!(:label_bug) { create(:label, project: project, title: 'bug') } - let!(:label_feature) { create(:label, project: project, title: 'feature') } - let(:new_url_opts) { {} } - - before do - project.team << [master, :master] - project.team << [assignee, :developer] - project.team << [guest, :guest] - login_with(master) - end - - after do - # Ensure all outstanding Ajax requests are complete to avoid database deadlocks - wait_for_ajax - end - - describe "new #{issuable_type}" do - context 'with commands in the description' do - it "creates the #{issuable_type} and interpret commands accordingly" do - visit public_send("new_namespace_project_#{issuable_type}_path", project.namespace, project, new_url_opts) - fill_in "#{issuable_type}_title", with: 'bug 345' - fill_in "#{issuable_type}_description", with: "bug description\n/label ~bug\n/milestone %\"ASAP\"" - click_button "Submit #{issuable_type}".humanize - - issuable = project.public_send(issuable_type.to_s.pluralize).first - - expect(issuable.description).to eq "bug description" - expect(issuable.labels).to eq [label_bug] - expect(issuable.milestone).to eq milestone - expect(page).to have_content 'bug 345' - expect(page).to have_content 'bug description' - end - end - end - - describe "note on #{issuable_type}" do - before do - visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) - end - - context 'with a note containing commands' do - it 'creates a note without the commands and interpret the commands accordingly' do - write_note("Awesome!\n/assign @bob\n/label ~bug\n/milestone %\"ASAP\"") - - expect(page).to have_content 'Awesome!' - expect(page).not_to have_content '/assign @bob' - expect(page).not_to have_content '/label ~bug' - expect(page).not_to have_content '/milestone %"ASAP"' - - issuable.reload - note = issuable.notes.user.first - - expect(note.note).to eq "Awesome!" - expect(issuable.assignee).to eq assignee - expect(issuable.labels).to eq [label_bug] - expect(issuable.milestone).to eq milestone - end - end - - context 'with a note containing only commands' do - it 'does not create a note but interpret the commands accordingly' do - write_note("/assign @bob\n/label ~bug\n/milestone %\"ASAP\"") - - expect(page).not_to have_content '/assign @bob' - expect(page).not_to have_content '/label ~bug' - expect(page).not_to have_content '/milestone %"ASAP"' - expect(page).to have_content 'Your commands have been executed!' - - issuable.reload - - expect(issuable.notes.user).to be_empty - expect(issuable.assignee).to eq assignee - expect(issuable.labels).to eq [label_bug] - expect(issuable.milestone).to eq milestone - end - end - - context "with a note closing the #{issuable_type}" do - before do - expect(issuable).to be_open - end - - context "when current user can close #{issuable_type}" do - it "closes the #{issuable_type}" do - write_note("/close") - - expect(page).not_to have_content '/close' - expect(page).to have_content 'Your commands have been executed!' - - expect(issuable.reload).to be_closed - end - end - - context "when current user cannot close #{issuable_type}" do - before do - logout - login_with(guest) - visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) - end - - it "does not close the #{issuable_type}" do - write_note("/close") - - expect(page).not_to have_content '/close' - expect(page).not_to have_content 'Your commands have been executed!' - - expect(issuable).to be_open - end - end - end - - context "with a note reopening the #{issuable_type}" do - before do - issuable.close - expect(issuable).to be_closed - end - - context "when current user can reopen #{issuable_type}" do - it "reopens the #{issuable_type}" do - write_note("/reopen") - - expect(page).not_to have_content '/reopen' - expect(page).to have_content 'Your commands have been executed!' - - expect(issuable.reload).to be_open - end - end - - context "when current user cannot reopen #{issuable_type}" do - before do - logout - login_with(guest) - visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) - end - - it "does not reopen the #{issuable_type}" do - write_note("/reopen") - - expect(page).not_to have_content '/reopen' - expect(page).not_to have_content 'Your commands have been executed!' - - expect(issuable).to be_closed - end - end - end - - context "with a note changing the #{issuable_type}'s title" do - context "when current user can change title of #{issuable_type}" do - it "reopens the #{issuable_type}" do - write_note("/title Awesome new title") - - expect(page).not_to have_content '/title' - expect(page).to have_content 'Your commands have been executed!' - - expect(issuable.reload.title).to eq 'Awesome new title' - end - end - - context "when current user cannot change title of #{issuable_type}" do - before do - logout - login_with(guest) - visit public_send("namespace_project_#{issuable_type}_path", project.namespace, project, issuable) - end - - it "does not reopen the #{issuable_type}" do - write_note("/title Awesome new title") - - expect(page).not_to have_content '/title' - expect(page).not_to have_content 'Your commands have been executed!' - - expect(issuable.reload.title).not_to eq 'Awesome new title' - end - end - end - - context "with a note marking the #{issuable_type} as todo" do - it "creates a new todo for the #{issuable_type}" do - write_note("/todo") - - expect(page).not_to have_content '/todo' - expect(page).to have_content 'Your commands have been executed!' - - todos = TodosFinder.new(master).execute - todo = todos.first - - expect(todos.size).to eq 1 - expect(todo).to be_pending - expect(todo.target).to eq issuable - expect(todo.author).to eq master - expect(todo.user).to eq master - end - end - - context "with a note marking the #{issuable_type} as done" do - before do - TodoService.new.mark_todo(issuable, master) - end - - it "creates a new todo for the #{issuable_type}" do - todos = TodosFinder.new(master).execute - todo = todos.first - - expect(todos.size).to eq 1 - expect(todos.first).to be_pending - expect(todo.target).to eq issuable - expect(todo.author).to eq master - expect(todo.user).to eq master - - write_note("/done") - - expect(page).not_to have_content '/done' - expect(page).to have_content 'Your commands have been executed!' - - expect(todo.reload).to be_done - end - end - - context "with a note subscribing to the #{issuable_type}" do - it "creates a new todo for the #{issuable_type}" do - expect(issuable.subscribed?(master)).to be_falsy - - write_note("/subscribe") - - expect(page).not_to have_content '/subscribe' - expect(page).to have_content 'Your commands have been executed!' - - expect(issuable.subscribed?(master)).to be_truthy - end - end - - context "with a note unsubscribing to the #{issuable_type} as done" do - before do - issuable.subscribe(master) - end - - it "creates a new todo for the #{issuable_type}" do - expect(issuable.subscribed?(master)).to be_truthy - - write_note("/unsubscribe") - - expect(page).not_to have_content '/unsubscribe' - expect(page).to have_content 'Your commands have been executed!' - - expect(issuable.subscribed?(master)).to be_falsy - end - end - end -end diff --git a/spec/support/services/issuable_create_service_slash_commands_shared_examples.rb b/spec/support/services/issuable_create_service_slash_commands_shared_examples.rb new file mode 100644 index 00000000000..5f9645ed44f --- /dev/null +++ b/spec/support/services/issuable_create_service_slash_commands_shared_examples.rb @@ -0,0 +1,83 @@ +# Specifications for behavior common to all objects with executable attributes. +# It can take a `default_params`. + +shared_examples 'new issuable record that supports slash commands' do + let!(:project) { create(:project) } + let(:user) { create(:user).tap { |u| project.team << [u, :master] } } + let(:assignee) { create(:user) } + let!(:milestone) { create(:milestone, project: project) } + let!(:labels) { create_list(:label, 3, project: project) } + let(:base_params) { { title: FFaker::Lorem.sentence(3) } } + let(:params) { base_params.merge(defined?(default_params) ? default_params : {}).merge(example_params) } + let(:issuable) { described_class.new(project, user, params).execute } + + context 'with labels in command only' do + let(:example_params) do + { + description: "/label ~#{labels.first.name} ~#{labels.second.name}\n/unlabel ~#{labels.third.name}" + } + end + + it 'attaches labels to issuable' do + expect(issuable).to be_persisted + expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id]) + end + end + + context 'with labels in params and command' do + let(:example_params) do + { + label_ids: [labels.second.id], + description: "/label ~#{labels.first.name}\n/unlabel ~#{labels.third.name}" + } + end + + it 'attaches all labels to issuable' do + expect(issuable).to be_persisted + expect(issuable.label_ids).to match_array([labels.first.id, labels.second.id]) + end + end + + context 'with assignee and milestone in command only' do + let(:example_params) do + { + description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}") + } + end + + it 'assigns and sets milestone to issuable' do + expect(issuable).to be_persisted + expect(issuable.assignee).to eq(assignee) + expect(issuable.milestone).to eq(milestone) + end + end + + context 'with assignee and milestone in params and command' do + let(:example_params) do + { + assignee: build_stubbed(:user), + milestone_id: double(:milestone), + description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}") + } + end + + it 'assigns and sets milestone to issuable from command' do + expect(issuable).to be_persisted + expect(issuable.assignee).to eq(assignee) + expect(issuable.milestone).to eq(milestone) + end + end + + describe '/close' do + let(:example_params) do + { + description: '/close' + } + end + + it 'returns an open issue' do + expect(issuable).to be_persisted + expect(issuable).to be_open + end + end +end -- cgit v1.2.1 From ee02856d59bcf7998041eaf0bb3d69643203ca35 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 2 Sep 2016 19:42:42 +0100 Subject: Added soft wrap logic and button to editor Added tests Added awesomeeeeee icons --- .../projects/files/edit_file_soft_wrap_spec.rb | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 spec/features/projects/files/edit_file_soft_wrap_spec.rb (limited to 'spec') diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb new file mode 100644 index 00000000000..7ad90b4a89c --- /dev/null +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +feature 'User uses soft wrap whilst editing file', feature: true, js: true do + before do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as user + visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'test_file-name') + editor = find('.file-editor.code') + editor.click + editor.send_keys 'Touch water with paw then recoil in horror chase dog then + run away chase the pig around the house eat owner\'s food, and knock + dish off table head butt cant eat out of my own dish. Cat is love, cat + is life rub face on everything poop on grasses so meow. Playing with + balls of wool flee in terror at cucumber discovered on floor run in + circles tuxedo cats always looking dapper, but attack dog, run away + and pretend to be victim so all of a sudden cat goes crazy, yet chase + laser. Make muffins sit in window and stare ooo, a bird! yum lick yarn + hanging out of own butt jump off balcony, onto stranger\'s head yet + chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish + end + + let(:toggle_button) { find('.soft-wrap-toggle') } + + scenario 'user clicks the "No wrap" button and then "Soft wrap" button' do + wrapped_content_width = get_content_width + toggle_button.click + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + toggle_button.click + expect(toggle_button).to have_content 'No wrap' + expect(get_content_width).to be < unwrapped_content_width + end + + scenario 'user adds a ".js" extension and then changes to a ".md" extension' do + wrapped_content_width = get_content_width + + fill_in 'file_name', with: 'test_file-name.js' + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + fill_in 'file_name', with: 'test_file-name.md' + expect(toggle_button).to have_content 'No wrap' + expect(get_content_width).to be < unwrapped_content_width + end + + scenario 'user clicks "No wrap" and then changes to a ".md" extension' do + wrapped_content_width = get_content_width + + toggle_button.click + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + fill_in 'file_name', with: 'test_file-name.md' + expect(toggle_button).to have_content 'Soft wrap' + expect(unwrapped_content_width).to be == get_content_width + end + + def get_content_width + find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/) + end +end -- cgit v1.2.1 From 2772109ac15bed2bd199294f8d770f49a749b4bd Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 28 Sep 2016 11:02:31 -0500 Subject: Handle LFS token creation and retrieval in the same method, and in the same Redis connection. Reset expiry time of token, if token is retrieved again before it expires. --- spec/lib/gitlab/auth_spec.rb | 4 ++-- spec/lib/gitlab/lfs_token_spec.rb | 8 ++++---- spec/requests/api/internal_spec.rb | 4 ++-- spec/requests/lfs_http_spec.rb | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 745fbc0df45..c9d64e99f88 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -64,7 +64,7 @@ describe Gitlab::Auth, lib: true do it 'recognizes user lfs tokens' do user = create(:user) ip = 'ip' - token = Gitlab::LfsToken.new(user).generate + 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)) @@ -73,7 +73,7 @@ describe Gitlab::Auth, lib: true do it 'recognizes deploy key lfs tokens' do key = create(:deploy_key) ip = 'ip' - token = Gitlab::LfsToken.new(key).generate + 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)) diff --git a/spec/lib/gitlab/lfs_token_spec.rb b/spec/lib/gitlab/lfs_token_spec.rb index 9f04f67e0a8..e9c1163e22a 100644 --- a/spec/lib/gitlab/lfs_token_spec.rb +++ b/spec/lib/gitlab/lfs_token_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' describe Gitlab::LfsToken, lib: true do - describe '#generate and #value' do + describe '#token' do shared_examples 'an LFS token generator' do it 'returns a randomly generated token' do - token = handler.generate + token = handler.token expect(token).not_to be_nil expect(token).to be_a String @@ -12,9 +12,9 @@ describe Gitlab::LfsToken, lib: true do end it 'returns the correct token based on the key' do - token = handler.generate + token = handler.token - expect(handler.value).to eq(token) + expect(handler.token).to eq(token) end end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 46e8e6f1169..f0f590b0331 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -111,7 +111,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response['username']).to eq(user.username) - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).token) expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end @@ -131,7 +131,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response['username']).to eq("lfs+deploy-key-#{key.id}") - expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value) + expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).token) expect(json_response['repository_http_path']).to eq(project.http_url_to_repo) end end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index a84be1b7c9e..dbdf83a0dff 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -1133,11 +1133,11 @@ describe 'Git LFS API and storage' do end def authorize_deploy_key - ActionController::HttpAuthentication::Basic.encode_credentials("lfs+deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate) + ActionController::HttpAuthentication::Basic.encode_credentials("lfs+deploy-key-#{key.id}", Gitlab::LfsToken.new(key).token) end def authorize_user_key - ActionController::HttpAuthentication::Basic.encode_credentials(user.username, Gitlab::LfsToken.new(user).generate) + ActionController::HttpAuthentication::Basic.encode_credentials(user.username, Gitlab::LfsToken.new(user).token) end def fork_project(project, user, object = nil) -- cgit v1.2.1 From d754b2ce763818c397eef852fd5641f8ba8f1c13 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Thu, 29 Sep 2016 00:56:30 +0000 Subject: Revert "Merge branch '18297-i-would-like-text-to-wrap-when-in-edit-mode-on-web-app' into 'master'" This reverts merge request !6188 --- .../projects/files/edit_file_soft_wrap_spec.rb | 67 ---------------------- 1 file changed, 67 deletions(-) delete mode 100644 spec/features/projects/files/edit_file_soft_wrap_spec.rb (limited to 'spec') diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb deleted file mode 100644 index 7ad90b4a89c..00000000000 --- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' - -feature 'User uses soft wrap whilst editing file', feature: true, js: true do - before do - user = create(:user) - project = create(:project) - project.team << [user, :master] - login_as user - visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'test_file-name') - editor = find('.file-editor.code') - editor.click - editor.send_keys 'Touch water with paw then recoil in horror chase dog then - run away chase the pig around the house eat owner\'s food, and knock - dish off table head butt cant eat out of my own dish. Cat is love, cat - is life rub face on everything poop on grasses so meow. Playing with - balls of wool flee in terror at cucumber discovered on floor run in - circles tuxedo cats always looking dapper, but attack dog, run away - and pretend to be victim so all of a sudden cat goes crazy, yet chase - laser. Make muffins sit in window and stare ooo, a bird! yum lick yarn - hanging out of own butt jump off balcony, onto stranger\'s head yet - chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish - end - - let(:toggle_button) { find('.soft-wrap-toggle') } - - scenario 'user clicks the "No wrap" button and then "Soft wrap" button' do - wrapped_content_width = get_content_width - toggle_button.click - expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - toggle_button.click - expect(toggle_button).to have_content 'No wrap' - expect(get_content_width).to be < unwrapped_content_width - end - - scenario 'user adds a ".js" extension and then changes to a ".md" extension' do - wrapped_content_width = get_content_width - - fill_in 'file_name', with: 'test_file-name.js' - expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - fill_in 'file_name', with: 'test_file-name.md' - expect(toggle_button).to have_content 'No wrap' - expect(get_content_width).to be < unwrapped_content_width - end - - scenario 'user clicks "No wrap" and then changes to a ".md" extension' do - wrapped_content_width = get_content_width - - toggle_button.click - expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - fill_in 'file_name', with: 'test_file-name.md' - expect(toggle_button).to have_content 'Soft wrap' - expect(unwrapped_content_width).to be == get_content_width - end - - def get_content_width - find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/) - end -end -- cgit v1.2.1 From e80e4cb8b97a3865b7e3c551a856a53d98cccf75 Mon Sep 17 00:00:00 2001 From: Guilherme Salazar Date: Fri, 23 Sep 2016 20:43:57 -0300 Subject: expose pipeline data in builds API add pipeline ref, sha, and status to the build API response add tests of build API (pipeline data) change API documentation for builds API log change to builds API in CHANGELOG CHANGELOG: add reference to pull request and contributor's name --- spec/requests/api/builds_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index ee0b61e2ca4..95c7bbf99c9 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -30,6 +30,15 @@ describe API::API, api: true do expect(json_response.first['commit']['id']).to eq project.commit.id end + it 'returns pipeline data' do + json_build = json_response.first + expect(json_build['pipeline']).not_to be_empty + expect(json_build['pipeline']['id']).to eq build.pipeline.id + expect(json_build['pipeline']['ref']).to eq build.pipeline.ref + expect(json_build['pipeline']['sha']).to eq build.pipeline.sha + expect(json_build['pipeline']['status']).to eq build.pipeline.status + end + context 'filter project with one scope element' do let(:query) { 'scope=pending' } @@ -91,6 +100,15 @@ describe API::API, api: true do expect(json_response).to be_an Array expect(json_response.size).to eq 2 end + + it 'returns pipeline data' do + json_build = json_response.first + expect(json_build['pipeline']).not_to be_empty + expect(json_build['pipeline']['id']).to eq build.pipeline.id + expect(json_build['pipeline']['ref']).to eq build.pipeline.ref + expect(json_build['pipeline']['sha']).to eq build.pipeline.sha + expect(json_build['pipeline']['status']).to eq build.pipeline.status + end end context 'when pipeline has no builds' do @@ -133,6 +151,15 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response['name']).to eq('test') end + + it 'returns pipeline data' do + json_build = json_response + expect(json_build['pipeline']).not_to be_empty + expect(json_build['pipeline']['id']).to eq build.pipeline.id + expect(json_build['pipeline']['ref']).to eq build.pipeline.ref + expect(json_build['pipeline']['sha']).to eq build.pipeline.sha + expect(json_build['pipeline']['status']).to eq build.pipeline.status + end end context 'unauthorized user' do -- cgit v1.2.1 From 6e6f34bffb641ae698177055b8f3528ec41fb7c8 Mon Sep 17 00:00:00 2001 From: Dimitris Karakasilis Date: Mon, 26 Sep 2016 18:34:56 +0300 Subject: Notify current_user about automatic merge after successful build Fixes: https://gitlab.com/gitlab-org/gitlab-ce/issues/14409 --- spec/services/notification_service_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'spec') diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 0d152534c38..d820646ebdf 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -962,6 +962,20 @@ describe NotificationService, services: true do should_not_email(@u_lazy_participant) end + it "notifies the merger when merge_when_build_succeeds is true" do + merge_request.merge_when_build_succeeds = true + notification.merge_mr(merge_request, @u_watcher) + + should_email(@u_watcher) + end + + it "does not notify the merger when merge_when_build_succeeds is false" do + merge_request.merge_when_build_succeeds = false + notification.merge_mr(merge_request, @u_watcher) + + should_not_email(@u_watcher) + end + context 'participating' do context 'by assignee' do before do -- cgit v1.2.1 From 29141ed3ea6157a60d9748921782015626a17f9e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 23 Sep 2016 09:42:07 +0200 Subject: fix broken repo 500 errors in UI and added relevant specs --- spec/controllers/projects_controller_spec.rb | 22 ++++++++++++++++++++++ spec/factories/projects.rb | 15 +++++++++++++++ spec/services/projects/import_service_spec.rb | 10 ++++++++++ 3 files changed, 47 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index b0f740f48f7..da0fdce39db 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -63,6 +63,28 @@ describe ProjectsController do end end + context "project with broken repo" do + let(:empty_project) { create(:project_broken_repo, :public) } + + before { sign_in(user) } + + User.project_views.keys.each do |project_view| + context "with #{project_view} view set" do + before do + user.update_attributes(project_view: project_view) + + get :show, namespace_id: empty_project.namespace.path, id: empty_project.path + end + + it "renders the empty project view" do + allow(Project).to receive(:repo).and_raise(Gitlab::Git::Repository::NoRepository) + + expect(response).to render_template('projects/no_repo') + end + end + end + end + context "rendering default project view" do render_views diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index e61b1fd9647..873d3fcb5af 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -27,6 +27,14 @@ FactoryGirl.define do end end + trait :broken_repo do + after(:create) do |project| + project.create_repository + + FileUtils.rm_r(File.join(project.repository_storage_path, "#{project.path_with_namespace}.git", 'refs')) + end + end + # Nest Project Feature attributes transient do wiki_access_level ProjectFeature::ENABLED @@ -56,6 +64,13 @@ FactoryGirl.define do empty_repo end + # Project with broken repository + # + # Project with an invalid repository state + factory :project_broken_repo, parent: :empty_project do + broken_repo + end + # Project with test repository # # Test repository source can be found at diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb index d5d4d7c56ef..ed1384798ab 100644 --- a/spec/services/projects/import_service_spec.rb +++ b/spec/services/projects/import_service_spec.rb @@ -108,6 +108,16 @@ describe Projects::ImportService, services: true do expect(result[:status]).to eq :error expect(result[:message]).to eq 'Github: failed to connect API' end + + it 'expires existence cache after error' do + allow_any_instance_of(Project).to receive(:repository_exists?).and_return(true) + + expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.repository_storage_path, project.path_with_namespace, project.import_url).and_raise(Gitlab::Shell::Error.new('Failed to import the repository')) + expect_any_instance_of(Repository).to receive(:expire_emptiness_caches).and_call_original + expect_any_instance_of(Repository).to receive(:expire_exists_cache).and_call_original + + subject.execute + end end def stub_github_omniauth_provider -- cgit v1.2.1 From 59157c0423d34c1f20c446548df540d103bda939 Mon Sep 17 00:00:00 2001 From: DJ Mountney Date: Tue, 27 Sep 2016 17:56:02 -0700 Subject: Expose the Koding application settings in the API This will allow the Koding app to enable the integration itself once is has authorized an admin user using the application secrets. --- spec/requests/api/settings_spec.rb | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 54d096e8b7f..f4903d8e0be 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -14,22 +14,38 @@ describe API::API, 'Settings', api: true do expect(json_response['default_projects_limit']).to eq(42) expect(json_response['signin_enabled']).to be_truthy expect(json_response['repository_storage']).to eq('default') + expect(json_response['koding_enabled']).to be_falsey + expect(json_response['koding_url']).to be_nil end end describe "PUT /application/settings" do - before do - storages = { 'custom' => 'tmp/tests/custom_repositories' } - allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + context "custom repository storage type set in the config" do + before do + storages = { 'custom' => 'tmp/tests/custom_repositories' } + allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) + end + + it "updates application settings" do + put api("/application/settings", admin), + default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com' + expect(response).to have_http_status(200) + expect(json_response['default_projects_limit']).to eq(3) + expect(json_response['signin_enabled']).to be_falsey + expect(json_response['repository_storage']).to eq('custom') + expect(json_response['koding_enabled']).to be_truthy + expect(json_response['koding_url']).to eq('http://koding.example.com') + end end - it "updates application settings" do - put api("/application/settings", admin), - default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom' - expect(response).to have_http_status(200) - expect(json_response['default_projects_limit']).to eq(3) - expect(json_response['signin_enabled']).to be_falsey - expect(json_response['repository_storage']).to eq('custom') + context "missing koding_url value when koding_enabled is true" do + it "returns a blank parameter error message" do + put api("/application/settings", admin), koding_enabled: true + + expect(response).to have_http_status(400) + expect(json_response['message']).to have_key('koding_url') + expect(json_response['message']['koding_url']).to include "can't be blank" + end end end end -- cgit v1.2.1 From 6d49fcf439c88492ff599432818d1c302e509997 Mon Sep 17 00:00:00 2001 From: Tony Gambone Date: Thu, 22 Sep 2016 17:30:37 -0400 Subject: Close todos when accepting a MR via the API. --- spec/services/merge_requests/merge_service_spec.rb | 24 ++++++++++++++++++++++ .../merge_requests/refresh_service_spec.rb | 12 +++++------ 2 files changed, 30 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 159f6817e8d..31167675d07 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -38,6 +38,30 @@ describe MergeRequests::MergeService, services: true do end end + context 'closes related todos' do + let(:merge_request) { create(:merge_request, assignee: user, author: user) } + let(:project) { merge_request.project } + let(:service) { MergeRequests::MergeService.new(project, user, commit_message: 'Awesome message') } + let!(:todo) do + create(:todo, :assigned, + project: project, + author: user, + user: user, + target: merge_request) + end + + before do + allow(service).to receive(:execute_hooks) + + perform_enqueued_jobs do + service.execute(merge_request) + todo.reload + end + end + + it { expect(todo).to be_done } + end + context 'remove source branch by author' do let(:service) do merge_request.merge_params['force_remove_source_branch'] = '1' diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index a162df5fc34..59d3912018a 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -79,8 +79,8 @@ describe MergeRequests::RefreshService, services: true do it { expect(@merge_request).to be_merged } it { expect(@fork_merge_request).to be_merged } it { expect(@fork_merge_request.notes.last.note).to include('changed to merged') } - it { expect(@build_failed_todo).to be_pending } - it { expect(@fork_build_failed_todo).to be_pending } + it { expect(@build_failed_todo).to be_done } + it { expect(@fork_build_failed_todo).to be_done } end context 'manual merge of source branch' do @@ -99,8 +99,8 @@ describe MergeRequests::RefreshService, services: true do it { expect(@merge_request.diffs.size).to be > 0 } it { expect(@fork_merge_request).to be_merged } it { expect(@fork_merge_request.notes.last.note).to include('changed to merged') } - it { expect(@build_failed_todo).to be_pending } - it { expect(@fork_build_failed_todo).to be_pending } + it { expect(@build_failed_todo).to be_done } + it { expect(@fork_build_failed_todo).to be_done } end context 'push to fork repo source branch' do @@ -149,8 +149,8 @@ describe MergeRequests::RefreshService, services: true do it { expect(@merge_request).to be_merged } it { expect(@fork_merge_request).to be_open } it { expect(@fork_merge_request.notes).to be_empty } - it { expect(@build_failed_todo).to be_pending } - it { expect(@fork_build_failed_todo).to be_pending } + it { expect(@build_failed_todo).to be_done } + it { expect(@fork_build_failed_todo).to be_done } end context 'push new branch that exists in a merge request' do -- cgit v1.2.1 From 385c602bd0e45418ccc10893f8f472584ba95551 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 30 Sep 2016 03:41:22 +0800 Subject: Less confusing name --- spec/services/ci/process_pipeline_service_spec.rb | 38 +++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'spec') diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index 8326e5cd313..e55daabe5a7 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -18,7 +18,7 @@ describe Ci::ProcessPipelineService, services: true do all_builds.where.not(status: [:created, :skipped]) end - def create_builds + def process_pipeline described_class.new(pipeline.project, user).execute(pipeline) end @@ -36,26 +36,26 @@ describe Ci::ProcessPipelineService, services: true do end it 'processes a pipeline' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy succeed_pending expect(builds.success.count).to eq(2) - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy succeed_pending expect(builds.success.count).to eq(4) - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy succeed_pending expect(builds.success.count).to eq(5) - expect(create_builds).to be_falsey + expect(process_pipeline).to be_falsey end it 'does not process pipeline if existing stage is running' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pending.count).to eq(2) - expect(create_builds).to be_falsey + expect(process_pipeline).to be_falsey expect(builds.pending.count).to eq(2) end end @@ -67,7 +67,7 @@ describe Ci::ProcessPipelineService, services: true do end it 'automatically triggers a next stage when build finishes' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:status)).to contain_exactly('pending') pipeline.builds.running_or_pending.each(&:drop) @@ -88,7 +88,7 @@ describe Ci::ProcessPipelineService, services: true do context 'when builds are successful' do it 'properly creates builds' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:name)).to contain_exactly('build') expect(builds.pluck(:status)).to contain_exactly('pending') pipeline.builds.running_or_pending.each(&:success) @@ -113,7 +113,7 @@ describe Ci::ProcessPipelineService, services: true do context 'when test job fails' do it 'properly creates builds' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:name)).to contain_exactly('build') expect(builds.pluck(:status)).to contain_exactly('pending') pipeline.builds.running_or_pending.each(&:success) @@ -138,7 +138,7 @@ describe Ci::ProcessPipelineService, services: true do context 'when test and test_failure jobs fail' do it 'properly creates builds' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:name)).to contain_exactly('build') expect(builds.pluck(:status)).to contain_exactly('pending') pipeline.builds.running_or_pending.each(&:success) @@ -164,7 +164,7 @@ describe Ci::ProcessPipelineService, services: true do context 'when deploy job fails' do it 'properly creates builds' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:name)).to contain_exactly('build') expect(builds.pluck(:status)).to contain_exactly('pending') pipeline.builds.running_or_pending.each(&:success) @@ -189,7 +189,7 @@ describe Ci::ProcessPipelineService, services: true do context 'when build is canceled in the second stage' do it 'does not schedule builds after build has been canceled' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:name)).to contain_exactly('build') expect(builds.pluck(:status)).to contain_exactly('pending') pipeline.builds.running_or_pending.each(&:success) @@ -208,7 +208,7 @@ describe Ci::ProcessPipelineService, services: true do context 'when listing manual actions' do it 'returns only for skipped builds' do # currently all builds are created - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(manual_actions).to be_empty # succeed stage build @@ -242,7 +242,7 @@ describe Ci::ProcessPipelineService, services: true do end it 'does trigger builds in the next stage' do - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pluck(:name)).to contain_exactly('build:1', 'build:2') pipeline.builds.running_or_pending.each(&:success) @@ -297,14 +297,14 @@ describe Ci::ProcessPipelineService, services: true do expect(all_builds.count).to eq(2) # Create builds will mark the created as pending - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.count).to eq(2) expect(all_builds.count).to eq(2) # When we builds succeed we will create a rest of pipeline from .gitlab-ci.yml # We will have 2 succeeded, 2 pending (from stage test), total 5 (one more build from deploy) succeed_pending - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.success.count).to eq(2) expect(builds.pending.count).to eq(2) expect(all_builds.count).to eq(5) @@ -312,14 +312,14 @@ describe Ci::ProcessPipelineService, services: true do # When we succeed the 2 pending from stage test, # We will queue a deploy stage, no new builds will be created succeed_pending - expect(create_builds).to be_truthy + expect(process_pipeline).to be_truthy expect(builds.pending.count).to eq(1) expect(builds.success.count).to eq(4) expect(all_builds.count).to eq(5) # When we succeed last pending build, we will have a total of 5 succeeded builds, no new builds will be created succeed_pending - expect(create_builds).to be_falsey + expect(process_pipeline).to be_falsey expect(builds.success.count).to eq(5) expect(all_builds.count).to eq(5) end -- cgit v1.2.1 From 6053acf5e6cee3ceceb1010ed77f1ce71099d5e1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 30 Sep 2016 03:41:38 +0800 Subject: We consider skipped = success, fixes #22598 --- spec/services/ci/process_pipeline_service_spec.rb | 49 +++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'spec') diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index e55daabe5a7..b6c23002dda 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -230,6 +230,55 @@ describe Ci::ProcessPipelineService, services: true do end end + context 'when there are manual jobs in earlier stages' do + before do + builds + process_pipeline + builds.each(&:reload) + end + + context 'when first stage has only manual jobs' do + let(:builds) do + [create_build('build', 0, 'manual'), + create_build('check', 1), + create_build('test', 2)] + end + + it 'starts from the second stage' do + expect(builds.map(&:status)).to contain_exactly( + 'skipped', 'pending', 'created') + end + end + + context 'when second stage has only manual jobs' do + let(:builds) do + [create_build('check', 0), + create_build('build', 1, 'manual'), + create_build('test', 2)] + end + + it 'skips second stage and continues on third stage' do + expect(builds.map(&:status)).to contain_exactly( + 'pending', 'created', 'created') + + builds.first.success + builds.each(&:reload) + + expect(builds.map(&:status)).to contain_exactly( + 'success', 'skipped', 'pending') + end + end + + def create_build(name, stage_idx, when_value = nil) + create(:ci_build, + :created, + pipeline: pipeline, + name: name, + stage_idx: stage_idx, + when: when_value) + end + end + context 'when failed build in the middle stage is retried' do context 'when failed build is the only unsuccessful build in the stage' do before do -- cgit v1.2.1 From ec82cecf3c54cb2cd1ab7b72f77e787be1bf1264 Mon Sep 17 00:00:00 2001 From: Matthew Dodds Date: Thu, 29 Sep 2016 21:51:33 -0400 Subject: Add link to comparison from system note, update changelog --- spec/services/system_note_service_spec.rb | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 3d854a959f3..16e345501d9 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -40,21 +40,35 @@ describe SystemNoteService, services: true do describe 'note body' do let(:note_lines) { subject.note.split("\n").reject(&:blank?) } + describe 'comparison diff link line' do + it 'adds the comparison link' do + link = Gitlab::Routing.url_helpers.diffs_namespace_project_merge_request_url( + project.namespace, + project, + noteable.iid, + diff_id: noteable.merge_request_diff.id, + start_sha: oldrev + ) + + expect(note_lines[0]).to eq "[Compare with previous version](#{link})" + end + end + context 'without existing commits' do it 'adds a message header' do - expect(note_lines[0]).to eq "Added #{new_commits.size} commits:" + expect(note_lines[1]).to eq "Added #{new_commits.size} commits:" end it 'adds a message line for each commit' do new_commits.each_with_index do |commit, i| # Skip the header - expect(note_lines[i + 1]).to eq "* #{commit.short_id} - #{commit.title}" + expect(note_lines[i + 2]).to eq "* #{commit.short_id} - #{commit.title}" end end end describe 'summary line for existing commits' do - let(:summary_line) { note_lines[1] } + let(:summary_line) { note_lines[2] } context 'with one existing commit' do let(:old_commits) { [noteable.commits.last] } -- cgit v1.2.1 From 82b13a21a6ab71027fb21b4555a207cfd398dafb Mon Sep 17 00:00:00 2001 From: Makoto Scott-Hinkle Date: Mon, 26 Sep 2016 16:47:34 -0700 Subject: Allowing ">" to be used for Milestone models's title and storing the value in db as unescaped. Updating test value for milestone title Adding API test for title with reserved HTML characters. Updating changelog Adding the MR number for fixing bug #22452. removing duplicate line Updating MR number. --- spec/models/milestone_spec.rb | 4 ++-- spec/requests/api/milestones_spec.rb | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index d64d6cde2b5..33fe22dd98c 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -20,10 +20,10 @@ describe Milestone, models: true do let(:user) { create(:user) } describe "#title" do - let(:milestone) { create(:milestone, title: "test") } + let(:milestone) { create(:milestone, title: "foo & bar -> 2.2") } it "sanitizes title" do - expect(milestone.title).to eq("test") + expect(milestone.title).to eq("foo & bar -> 2.2") end end diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index b89dac01040..dd192bea432 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -104,6 +104,14 @@ describe API::API, api: true do expect(response).to have_http_status(400) end + + it 'creates a new project with reserved html characters' do + post api("/projects/#{project.id}/milestones", user), title: 'foo & bar 1.1 -> 2.2' + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq('foo & bar 1.1 -> 2.2') + expect(json_response['description']).to be_nil + end end describe 'PUT /projects/:id/milestones/:milestone_id' do -- cgit v1.2.1 From 25edb0709ccfae340817dc2f414cc8207899a2e0 Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Thu, 22 Sep 2016 15:49:53 +0200 Subject: Close merge request if open without source project --- spec/views/projects/merge_requests/show.html.haml_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'spec') diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb index 68fbb4585c1..842b53344c1 100644 --- a/spec/views/projects/merge_requests/show.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb @@ -41,4 +41,17 @@ describe 'projects/merge_requests/show.html.haml' do expect(rendered).to have_css('a', visible: false, text: 'Close') end end + + context 'when the merge request is open' do + it 'closes open merge request' do + closed_merge_request.update_attributes(state: 'open') + fork_project.destroy + + render + + expect(closed_merge_request.reload.state).to eq('closed') + expect(rendered).to have_css('a', visible: false, text: 'Reopen') + expect(rendered).to have_css('a', visible: false, text: 'Close') + end + end end -- cgit v1.2.1 From 1b547cfba8e0e7b0fb9eef5c2fcc8a9606c83f4d Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Fri, 23 Sep 2016 10:18:54 +0200 Subject: Improve grammar --- spec/views/projects/merge_requests/show.html.haml_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb index 842b53344c1..33cabd14913 100644 --- a/spec/views/projects/merge_requests/show.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb @@ -43,7 +43,7 @@ describe 'projects/merge_requests/show.html.haml' do end context 'when the merge request is open' do - it 'closes open merge request' do + it 'closes the merge request if the source project does not exist' do closed_merge_request.update_attributes(state: 'open') fork_project.destroy -- cgit v1.2.1 From 9b361a3f44eec7a301565318ce86742f2f139a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 23 Sep 2016 15:16:11 +0200 Subject: Take filters in account in issuable counters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/dashboard_issues_spec.rb | 15 +++ spec/features/issues/filter_by_labels_spec.rb | 133 ++++++--------------- spec/features/issues/filter_issues_spec.rb | 56 ++++++++- .../merge_requests/filter_by_milestone_spec.rb | 15 +++ 4 files changed, 117 insertions(+), 102 deletions(-) (limited to 'spec') diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index 3fb1cb37544..4dccf645454 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -21,6 +21,11 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'No Milestone' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_selector('.issue', count: 1) end @@ -29,6 +34,11 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'Any Milestone' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end expect(page).to have_selector('.issue', count: 2) end @@ -39,6 +49,11 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link milestone.title end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_selector('.issue', count: 1) end end diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index 908b18e5339..a615174c00e 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' -feature 'Issue filtering by Labels', feature: true do +feature 'Issue filtering by Labels', feature: true, js: true do include WaitForAjax let(:project) { create(:project, :public) } - let!(:user) { create(:user)} + let!(:user) { create(:user) } let!(:label) { create(:label, project: project) } before do @@ -28,156 +28,85 @@ feature 'Issue filtering by Labels', feature: true do visit namespace_project_issues_path(project.namespace, project) end - context 'filter by label bug', js: true do + context 'filter by label bug' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"bug\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('bug') end - it 'shows issue "Bugfix1" and "Bugfix2" in issues list' do + it 'apply the filter' do expect(page).to have_content "Bugfix1" expect(page).to have_content "Bugfix2" - end - - it 'does not show "Feature1" in issues list' do expect(page).not_to have_content "Feature1" - end - - it 'shows label "bug" in filtered-labels' do expect(find('.filtered-labels')).to have_content "bug" - end - - it 'does not show label "feature" and "enhancement" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "feature" expect(find('.filtered-labels')).not_to have_content "enhancement" - end - it 'removes label "bug"' do find('.js-label-filter-remove').click wait_for_ajax expect(find('.filtered-labels', visible: false)).to have_no_content "bug" end end - context 'filter by label feature', js: true do + context 'filter by label feature' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"feature\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('feature') end - it 'shows issue "Feature1" in issues list' do + it 'applies the filter' do expect(page).to have_content "Feature1" - end - - it 'does not show "Bugfix1" and "Bugfix2" in issues list' do expect(page).not_to have_content "Bugfix2" expect(page).not_to have_content "Bugfix1" - end - - it 'shows label "feature" in filtered-labels' do expect(find('.filtered-labels')).to have_content "feature" - end - - it 'does not show label "bug" and "enhancement" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "bug" expect(find('.filtered-labels')).not_to have_content "enhancement" end end - context 'filter by label enhancement', js: true do + context 'filter by label enhancement' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"enhancement\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('enhancement') end - it 'shows issue "Bugfix2" in issues list' do + it 'applies the filter' do expect(page).to have_content "Bugfix2" - end - - it 'does not show "Feature1" and "Bugfix1" in issues list' do expect(page).not_to have_content "Feature1" expect(page).not_to have_content "Bugfix1" - end - - it 'shows label "enhancement" in filtered-labels' do expect(find('.filtered-labels')).to have_content "enhancement" - end - - it 'does not show label "feature" and "bug" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "bug" expect(find('.filtered-labels')).not_to have_content "feature" end end - context 'filter by label enhancement or feature', js: true do + context 'filter by label enhancement and bug in issues list' do before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"enhancement\") a').click()") - execute_script("$('.dropdown-menu-labels li:contains(\"feature\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax + select_labels('bug', 'enhancement') end - it 'does not show "Bugfix1" or "Feature1" in issues list' do - expect(page).not_to have_content "Bugfix1" + it 'applies the filters' do + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end + expect(page).to have_content "Bugfix2" expect(page).not_to have_content "Feature1" - end - - it 'shows label "enhancement" and "feature" in filtered-labels' do + expect(find('.filtered-labels')).to have_content "bug" expect(find('.filtered-labels')).to have_content "enhancement" - expect(find('.filtered-labels')).to have_content "feature" - end - - it 'does not show label "bug" in filtered-labels' do - expect(find('.filtered-labels')).not_to have_content "bug" - end + expect(find('.filtered-labels')).not_to have_content "feature" - it 'removes label "enhancement"' do find('.js-label-filter-remove', match: :first).click wait_for_ajax - expect(find('.filtered-labels')).to have_no_content "enhancement" - end - end - context 'filter by label enhancement and bug in issues list', js: true do - before do - page.find('.js-label-select').click - wait_for_ajax - execute_script("$('.dropdown-menu-labels li:contains(\"enhancement\") a').click()") - execute_script("$('.dropdown-menu-labels li:contains(\"bug\") a').click()") - page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click - wait_for_ajax - end - - it 'shows issue "Bugfix2" in issues list' do expect(page).to have_content "Bugfix2" - end - - it 'does not show "Feature1"' do expect(page).not_to have_content "Feature1" - end - - it 'shows label "bug" and "enhancement" in filtered-labels' do - expect(find('.filtered-labels')).to have_content "bug" + expect(page).not_to have_content "Bugfix1" + expect(find('.filtered-labels')).not_to have_content "bug" expect(find('.filtered-labels')).to have_content "enhancement" - end - - it 'does not show label "feature" in filtered-labels' do expect(find('.filtered-labels')).not_to have_content "feature" end end - context 'remove filtered labels', js: true do + context 'remove filtered labels' do before do page.within '.labels-filter' do click_button 'Label' @@ -200,7 +129,7 @@ feature 'Issue filtering by Labels', feature: true do end end - context 'dropdown filtering', js: true do + context 'dropdown filtering' do it 'filters by label name' do page.within '.labels-filter' do click_button 'Label' @@ -214,4 +143,14 @@ feature 'Issue filtering by Labels', feature: true do end end end + + def select_labels(*labels) + page.find('.js-label-select').click + wait_for_ajax + labels.each do |label| + execute_script("$('.dropdown-menu-labels li:contains(\"#{label}\") a').click()") + end + page.first('.labels-filter .dropdown-title .dropdown-menu-close-icon').click + wait_for_ajax + end end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index d1501c9791a..8fd67acff69 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -7,15 +7,15 @@ describe 'Filter issues', feature: true do let!(:user) { create(:user)} let!(:milestone) { create(:milestone, project: project) } let!(:label) { create(:label, project: project) } - let!(:issue1) { create(:issue, project: project) } let!(:wontfix) { create(:label, project: project, title: "Won't fix") } before do project.team << [user, :master] login_as(user) + create(:issue, project: project) end - describe 'Filter issues for assignee from issues#index' do + describe 'for assignee from issues#index' do before do visit namespace_project_issues_path(project.namespace, project) @@ -45,7 +45,7 @@ describe 'Filter issues', feature: true do end end - describe 'Filter issues for milestone from issues#index' do + describe 'for milestone from issues#index' do before do visit namespace_project_issues_path(project.namespace, project) @@ -75,7 +75,7 @@ describe 'Filter issues', feature: true do end end - describe 'Filter issues for label from issues#index', js: true do + describe 'for label from issues#index', js: true do before do visit namespace_project_issues_path(project.namespace, project) find('.js-label-select').click @@ -115,6 +115,7 @@ describe 'Filter issues', feature: true do expect(page).to have_content wontfix.title click_link wontfix.title end + expect(find('.js-label-select .dropdown-toggle-text')).to have_content(wontfix.title) end @@ -146,7 +147,7 @@ describe 'Filter issues', feature: true do end end - describe 'Filter issues for assignee and label from issues#index' do + describe 'for assignee and label from issues#index' do before do visit namespace_project_issues_path(project.namespace, project) @@ -226,6 +227,11 @@ describe 'Filter issues', feature: true do it 'filters by text and label' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -236,6 +242,11 @@ describe 'Filter issues', feature: true do end find('.dropdown-menu-close-icon').click + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -244,6 +255,11 @@ describe 'Filter issues', feature: true do it 'filters by text and milestone' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -253,6 +269,11 @@ describe 'Filter issues', feature: true do click_link '8' end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -261,6 +282,11 @@ describe 'Filter issues', feature: true do it 'filters by text and assignee' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -270,6 +296,11 @@ describe 'Filter issues', feature: true do click_link user.name end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -278,6 +309,11 @@ describe 'Filter issues', feature: true do it 'filters by text and author' do fill_in 'issuable_search', with: 'Bug' + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -287,6 +323,11 @@ describe 'Filter issues', feature: true do click_link user.name end + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -315,6 +356,11 @@ describe 'Filter issues', feature: true do find('.dropdown-menu-close-icon').click wait_for_ajax + page.within '.issues-state-filters' do + expect(page).to have_content('Open 2') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 2') + end page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb index bb0bb590a46..3d5d9614fb6 100644 --- a/spec/features/merge_requests/filter_by_milestone_spec.rb +++ b/spec/features/merge_requests/filter_by_milestone_spec.rb @@ -17,6 +17,11 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(Milestone::None.title) + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_css('.merge-request', count: 1) end @@ -39,6 +44,11 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(Milestone::Upcoming.title) + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_css('.merge-request', count: 1) end @@ -61,6 +71,11 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(milestone.title) + page.within '.issues-state-filters' do + expect(page).to have_content('Open 1') + expect(page).to have_content('Closed 0') + expect(page).to have_content('All 1') + end expect(page).to have_css('.merge-request', count: 1) end -- cgit v1.2.1 From 383dafdf31adaded392664cba9ba8b7262505dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 26 Sep 2016 19:12:16 +0200 Subject: Cache the issuable counters for 2 minutes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/helpers/issuables_helper_spec.rb | 97 ++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 2dd2eab0524..5effb7ea36c 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe IssuablesHelper do +describe IssuablesHelper do let(:label) { build_stubbed(:label) } let(:label2) { build_stubbed(:label) } - context 'label tooltip' do + describe '#issuable_labels_tooltip' do it 'returns label text' do expect(issuable_labels_tooltip([label])).to eq(label.title) end @@ -13,4 +13,97 @@ describe IssuablesHelper do expect(issuable_labels_tooltip([label, label2], limit: 1)).to eq("#{label.title}, and 1 more") end end + + describe '#issuables_state_counter_text' do + let(:user) { create(:user) } + + describe 'state text' do + before do + allow(helper).to receive(:issuables_count_for_state).and_return(42) + end + + it 'returns "Open" when state is :opened' do + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + end + + it 'returns "Closed" when state is :closed' do + expect(helper.issuables_state_counter_text(:issues, :closed)). + to eq('Closed 42') + end + + it 'returns "Merged" when state is :merged' do + expect(helper.issuables_state_counter_text(:merge_requests, :merged)). + to eq('Merged 42') + end + + it 'returns "All" when state is :all' do + expect(helper.issuables_state_counter_text(:merge_requests, :all)). + to eq('All 42') + end + end + + describe 'counter caching based on issuable type and params', :caching do + let(:params) do + { + 'scope' => 'created-by-me', + 'state' => 'opened', + 'utf8' => '✓', + 'author_id' => '11', + 'assignee_id' => '18', + 'label_name' => ['bug', 'discussion', 'documentation'], + 'milestone_title' => 'v4.0', + 'sort' => 'due_date_asc', + 'namespace_id' => 'gitlab-org', + 'project_id' => 'gitlab-ce', + 'page' => 2 + } + end + + it 'returns the cached value when called for the same issuable type & with the same params' do + expect(helper).to receive(:params).twice.and_return(params) + expect(helper).to receive(:issuables_count_for_state).with(:issues, :opened).and_return(42) + + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + + expect(helper).not_to receive(:issuables_count_for_state) + + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + end + + describe 'keys not taken in account in the cache key' do + %w[state sort utf8 page].each do |param| + it "does not take in account params['#{param}'] in the cache key" do + expect(helper).to receive(:params).and_return('author_id' => '11', param => 'foo') + expect(helper).to receive(:issuables_count_for_state).with(:issues, :opened).and_return(42) + + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + + expect(helper).to receive(:params).and_return('author_id' => '11', param => 'bar') + expect(helper).not_to receive(:issuables_count_for_state) + + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + end + end + end + + it 'does not take params order in acount in the cache key' do + expect(helper).to receive(:params).and_return('author_id' => '11', 'state' => 'opened') + expect(helper).to receive(:issuables_count_for_state).with(:issues, :opened).and_return(42) + + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + + expect(helper).to receive(:params).and_return('state' => 'opened', 'author_id' => '11') + expect(helper).not_to receive(:issuables_count_for_state) + + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') + end + end + end end -- cgit v1.2.1 From 56259155d5a0ecfbbafb7319651495582504cfb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 29 Sep 2016 16:55:55 +0200 Subject: Small improvements thanks to Robert's feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/dashboard_issues_spec.rb | 18 ++----- spec/features/issues/filter_by_labels_spec.rb | 6 +-- spec/features/issues/filter_issues_spec.rb | 54 ++++--------------- .../merge_requests/filter_by_milestone_spec.rb | 18 ++----- spec/helpers/issuables_helper_spec.rb | 60 ++++++++++++---------- spec/support/matchers/have_issuable_counts.rb | 21 ++++++++ 6 files changed, 71 insertions(+), 106 deletions(-) create mode 100644 spec/support/matchers/have_issuable_counts.rb (limited to 'spec') diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index 4dccf645454..9b54b5301e5 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -21,11 +21,7 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'No Milestone' - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_selector('.issue', count: 1) end @@ -34,11 +30,7 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link 'Any Milestone' - page.within '.issues-state-filters' do - expect(page).to have_content('Open 2') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 2') - end + expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) expect(page).to have_selector('.issue', count: 2) end @@ -49,11 +41,7 @@ describe "Dashboard Issues filtering", feature: true, js: true do click_link milestone.title end - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_selector('.issue', count: 1) end end diff --git a/spec/features/issues/filter_by_labels_spec.rb b/spec/features/issues/filter_by_labels_spec.rb index a615174c00e..0253629f753 100644 --- a/spec/features/issues/filter_by_labels_spec.rb +++ b/spec/features/issues/filter_by_labels_spec.rb @@ -83,11 +83,7 @@ feature 'Issue filtering by Labels', feature: true, js: true do end it 'applies the filters' do - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_content "Bugfix2" expect(page).not_to have_content "Feature1" expect(find('.filtered-labels')).to have_content "bug" diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 8fd67acff69..8d19198efd3 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -227,11 +227,7 @@ describe 'Filter issues', feature: true do it 'filters by text and label' do fill_in 'issuable_search', with: 'Bug' - page.within '.issues-state-filters' do - expect(page).to have_content('Open 2') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 2') - end + expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -242,11 +238,7 @@ describe 'Filter issues', feature: true do end find('.dropdown-menu-close-icon').click - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -255,11 +247,7 @@ describe 'Filter issues', feature: true do it 'filters by text and milestone' do fill_in 'issuable_search', with: 'Bug' - page.within '.issues-state-filters' do - expect(page).to have_content('Open 2') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 2') - end + expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -269,11 +257,7 @@ describe 'Filter issues', feature: true do click_link '8' end - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -282,11 +266,7 @@ describe 'Filter issues', feature: true do it 'filters by text and assignee' do fill_in 'issuable_search', with: 'Bug' - page.within '.issues-state-filters' do - expect(page).to have_content('Open 2') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 2') - end + expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -296,11 +276,7 @@ describe 'Filter issues', feature: true do click_link user.name end - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -309,11 +285,7 @@ describe 'Filter issues', feature: true do it 'filters by text and author' do fill_in 'issuable_search', with: 'Bug' - page.within '.issues-state-filters' do - expect(page).to have_content('Open 2') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 2') - end + expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end @@ -323,11 +295,7 @@ describe 'Filter issues', feature: true do click_link user.name end - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 1) end @@ -356,11 +324,7 @@ describe 'Filter issues', feature: true do find('.dropdown-menu-close-icon').click wait_for_ajax - page.within '.issues-state-filters' do - expect(page).to have_content('Open 2') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 2') - end + expect(page).to have_issuable_counts(open: 2, closed: 0, all: 2) page.within '.issues-list' do expect(page).to have_selector('.issue', count: 2) end diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb index 3d5d9614fb6..d917d5950ec 100644 --- a/spec/features/merge_requests/filter_by_milestone_spec.rb +++ b/spec/features/merge_requests/filter_by_milestone_spec.rb @@ -17,11 +17,7 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(Milestone::None.title) - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) end @@ -44,11 +40,7 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(Milestone::Upcoming.title) - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) end @@ -71,11 +63,7 @@ feature 'Merge Request filtering by Milestone', feature: true do visit_merge_requests(project) filter_by_milestone(milestone.title) - page.within '.issues-state-filters' do - expect(page).to have_content('Open 1') - expect(page).to have_content('Closed 0') - expect(page).to have_content('All 1') - end + expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_css('.merge-request', count: 1) end diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 5effb7ea36c..62cc10f579a 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -46,18 +46,18 @@ describe IssuablesHelper do describe 'counter caching based on issuable type and params', :caching do let(:params) do { - 'scope' => 'created-by-me', - 'state' => 'opened', - 'utf8' => '✓', - 'author_id' => '11', - 'assignee_id' => '18', - 'label_name' => ['bug', 'discussion', 'documentation'], - 'milestone_title' => 'v4.0', - 'sort' => 'due_date_asc', - 'namespace_id' => 'gitlab-org', - 'project_id' => 'gitlab-ce', - 'page' => 2 - } + scope: 'created-by-me', + state: 'opened', + utf8: '✓', + author_id: '11', + assignee_id: '18', + label_name: ['bug', 'discussion', 'documentation'], + milestone_title: 'v4.0', + sort: 'due_date_asc', + namespace_id: 'gitlab-org', + project_id: 'gitlab-ce', + page: 2 + }.with_indifferent_access end it 'returns the cached value when called for the same issuable type & with the same params' do @@ -73,25 +73,33 @@ describe IssuablesHelper do to eq('Open 42') end - describe 'keys not taken in account in the cache key' do - %w[state sort utf8 page].each do |param| - it "does not take in account params['#{param}'] in the cache key" do - expect(helper).to receive(:params).and_return('author_id' => '11', param => 'foo') - expect(helper).to receive(:issuables_count_for_state).with(:issues, :opened).and_return(42) + it 'does not take some keys into account in the cache key' do + expect(helper).to receive(:params).and_return({ + author_id: '11', + state: 'foo', + sort: 'foo', + utf8: 'foo', + page: 'foo' + }.with_indifferent_access) + expect(helper).to receive(:issuables_count_for_state).with(:issues, :opened).and_return(42) - expect(helper.issuables_state_counter_text(:issues, :opened)). - to eq('Open 42') + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') - expect(helper).to receive(:params).and_return('author_id' => '11', param => 'bar') - expect(helper).not_to receive(:issuables_count_for_state) + expect(helper).to receive(:params).and_return({ + author_id: '11', + state: 'bar', + sort: 'bar', + utf8: 'bar', + page: 'bar' + }.with_indifferent_access) + expect(helper).not_to receive(:issuables_count_for_state) - expect(helper.issuables_state_counter_text(:issues, :opened)). - to eq('Open 42') - end - end + expect(helper.issuables_state_counter_text(:issues, :opened)). + to eq('Open 42') end - it 'does not take params order in acount in the cache key' do + it 'does not take params order into account in the cache key' do expect(helper).to receive(:params).and_return('author_id' => '11', 'state' => 'opened') expect(helper).to receive(:issuables_count_for_state).with(:issues, :opened).and_return(42) diff --git a/spec/support/matchers/have_issuable_counts.rb b/spec/support/matchers/have_issuable_counts.rb new file mode 100644 index 00000000000..02605d6b70e --- /dev/null +++ b/spec/support/matchers/have_issuable_counts.rb @@ -0,0 +1,21 @@ +RSpec::Matchers.define :have_issuable_counts do |opts| + match do |actual| + expected_counts = opts.map do |state, count| + "#{state.to_s.humanize} #{count}" + end + + actual.within '.issues-state-filters' do + expected_counts.each do |expected_count| + expect(actual).to have_content(expected_count) + end + end + end + + description do + "displays the following issuable counts: #{expected_counts.inspect}" + end + + failure_message do + "expected the following issuable counts: #{expected_counts.inspect} to be displayed" + end +end -- cgit v1.2.1 From b13502ef825ec6f105ab47a29e7d397636c4d03b Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Fri, 9 Sep 2016 14:43:43 +0200 Subject: Add test for linter values visibility --- spec/views/ci/lints/show.html.haml_spec.rb | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 spec/views/ci/lints/show.html.haml_spec.rb (limited to 'spec') diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/ci/lints/show.html.haml_spec.rb new file mode 100644 index 00000000000..f1d91eab356 --- /dev/null +++ b/spec/views/ci/lints/show.html.haml_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe 'ci/lints/show' do + let(:content) do + { build_template: { + script: './build.sh', + tags: ['dotnet'], + only: ['test@dude/repo'], + except: ['deploy'], + environment: 'testing' + } + } + end + let(:config_processor) { Ci::GitlabCiYamlProcessor.new(YAML.dump(content)) } + + context 'when content is valid' do + before do + assign(:status, true) + assign(:builds, config_processor.builds) + assign(:stages, config_processor.stages) + end + + it 'shows correct values' do + render + + expect(rendered).to have_content('Tag list: dotnet') + expect(rendered).to have_content('Refs only: test@dude/repo') + expect(rendered).to have_content('Refs except: deploy') + expect(rendered).to have_content('Environment: testing') + expect(rendered).to have_content('When: on_success') + end + end +end -- cgit v1.2.1 From 3efbf92e34eb8328817c64fda7ea73357128a61d Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Mon, 12 Sep 2016 08:47:35 +0200 Subject: Improve tests grammar --- spec/views/ci/lints/show.html.haml_spec.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/ci/lints/show.html.haml_spec.rb index f1d91eab356..be41134d12a 100644 --- a/spec/views/ci/lints/show.html.haml_spec.rb +++ b/spec/views/ci/lints/show.html.haml_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe 'ci/lints/show' do let(:content) do - { build_template: { + { + build_template: { script: './build.sh', tags: ['dotnet'], only: ['test@dude/repo'], @@ -11,16 +12,17 @@ describe 'ci/lints/show' do } } end + let(:config_processor) { Ci::GitlabCiYamlProcessor.new(YAML.dump(content)) } - context 'when content is valid' do + context 'when the content is valid' do before do assign(:status, true) assign(:builds, config_processor.builds) assign(:stages, config_processor.stages) end - it 'shows correct values' do + it 'shows the correct values' do render expect(rendered).to have_content('Tag list: dotnet') -- cgit v1.2.1 From 52ebeb5a89927058e1eba5bda777852011f001eb Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Tue, 13 Sep 2016 12:26:44 +0200 Subject: Build attributes with hash, fix gitlab yaml processor tests --- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 6dedd25e9d3..317259f0c27 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -26,7 +26,9 @@ module Ci allow_failure: false, when: "on_success", environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) end @@ -443,7 +445,9 @@ module Ci allow_failure: false, when: "on_success", environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) end @@ -471,7 +475,9 @@ module Ci allow_failure: false, when: "on_success", environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) end end @@ -716,7 +722,9 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) end @@ -859,7 +867,9 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) end end @@ -904,7 +914,9 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) expect(subject.second).to eq({ stage: "build", @@ -916,7 +928,9 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [] + yaml_variables: [], + only: nil, + except: nil }) end end -- cgit v1.2.1 From 7dfb204ef9d343888e2fd8327c5a5348b98a76ce Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Tue, 20 Sep 2016 15:19:55 +0200 Subject: Expose jobs to view --- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 28 +++++++--------------------- spec/views/ci/lints/show.html.haml_spec.rb | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 21 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 317259f0c27..6dedd25e9d3 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -26,9 +26,7 @@ module Ci allow_failure: false, when: "on_success", environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) end @@ -445,9 +443,7 @@ module Ci allow_failure: false, when: "on_success", environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) end @@ -475,9 +471,7 @@ module Ci allow_failure: false, when: "on_success", environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) end end @@ -722,9 +716,7 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) end @@ -867,9 +859,7 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) end end @@ -914,9 +904,7 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) expect(subject.second).to eq({ stage: "build", @@ -928,9 +916,7 @@ module Ci when: "on_success", allow_failure: false, environment: nil, - yaml_variables: [], - only: nil, - except: nil + yaml_variables: [] }) end end diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/ci/lints/show.html.haml_spec.rb index be41134d12a..620fb0e4821 100644 --- a/spec/views/ci/lints/show.html.haml_spec.rb +++ b/spec/views/ci/lints/show.html.haml_spec.rb @@ -20,6 +20,7 @@ describe 'ci/lints/show' do assign(:status, true) assign(:builds, config_processor.builds) assign(:stages, config_processor.stages) + assign(:jobs, config_processor.jobs) end it 'shows the correct values' do @@ -32,4 +33,19 @@ describe 'ci/lints/show' do expect(rendered).to have_content('When: on_success') end end + + context 'when the content is invalid' do + before do + assign(:status, false) + assign(:error, 'Undefined error') + end + + it 'shows error message' do + render + + expect(rendered).to have_content('Status: syntax is incorrec') + expect(rendered).to have_content('Error: Undefined error') + expect(rendered).not_to have_content('Tag list:') + end + end end -- cgit v1.2.1 From 3ef515f3f111e7b470dbb29ba1c75479aee8dc7b Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Tue, 20 Sep 2016 17:28:54 +0200 Subject: Refactor fields in view --- spec/views/ci/lints/show.html.haml_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/ci/lints/show.html.haml_spec.rb index 620fb0e4821..793b747e7eb 100644 --- a/spec/views/ci/lints/show.html.haml_spec.rb +++ b/spec/views/ci/lints/show.html.haml_spec.rb @@ -43,7 +43,7 @@ describe 'ci/lints/show' do it 'shows error message' do render - expect(rendered).to have_content('Status: syntax is incorrec') + expect(rendered).to have_content('Status: syntax is incorrect') expect(rendered).to have_content('Error: Undefined error') expect(rendered).not_to have_content('Tag list:') end -- cgit v1.2.1 From 958d9f11e80633f7120a782900fe1f78b3dbebea Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 29 Sep 2016 17:17:22 +0200 Subject: fix export project file permissions issue --- spec/features/projects/import_export/export_file_spec.rb | 2 ++ spec/support/import_export/export_file_helper.rb | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'spec') diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index 27c986c5187..52d08982c7a 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -47,6 +47,8 @@ feature 'Import/Export - project export integration test', feature: true, js: tr expect(page).to have_content('Download export') + expect(file_permissions(project.export_path)).to eq(0700) + in_directory_with_expanded_export(project) do |exit_status, tmpdir| expect(exit_status).to eq(0) diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb index be0772d6a4a..1b0a4583f5c 100644 --- a/spec/support/import_export/export_file_helper.rb +++ b/spec/support/import_export/export_file_helper.rb @@ -130,4 +130,8 @@ module ExportFileHelper (parsed_model_attributes - parent.keys - excluded_attributes).empty? end + + def file_permissions(file) + File.stat(file).mode & 0777 + end end -- cgit v1.2.1 From 0c0b6f438ee5ac12f9975fb1c3b1dc93f6447015 Mon Sep 17 00:00:00 2001 From: Matthew Dodds Date: Fri, 30 Sep 2016 11:00:03 -0400 Subject: Refactor url_helpers for system note service and remove duplication of logic in spec --- spec/services/system_note_service_spec.rb | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 16e345501d9..b16840a1238 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -41,34 +41,26 @@ describe SystemNoteService, services: true do let(:note_lines) { subject.note.split("\n").reject(&:blank?) } describe 'comparison diff link line' do - it 'adds the comparison link' do - link = Gitlab::Routing.url_helpers.diffs_namespace_project_merge_request_url( - project.namespace, - project, - noteable.iid, - diff_id: noteable.merge_request_diff.id, - start_sha: oldrev - ) - - expect(note_lines[0]).to eq "[Compare with previous version](#{link})" + it 'adds the comparison text' do + expect(note_lines[2]).to match "[Compare with previous version]" end end context 'without existing commits' do it 'adds a message header' do - expect(note_lines[1]).to eq "Added #{new_commits.size} commits:" + expect(note_lines[0]).to eq "Added #{new_commits.size} commits:" end it 'adds a message line for each commit' do new_commits.each_with_index do |commit, i| # Skip the header - expect(note_lines[i + 2]).to eq "* #{commit.short_id} - #{commit.title}" + expect(note_lines[i + 1]).to eq "* #{commit.short_id} - #{commit.title}" end end end describe 'summary line for existing commits' do - let(:summary_line) { note_lines[2] } + let(:summary_line) { note_lines[1] } context 'with one existing commit' do let(:old_commits) { [noteable.commits.last] } -- cgit v1.2.1 From 61afa65d4e5e1ea908d90e45364fbb4e0bcfeb56 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 2 Sep 2016 19:42:42 +0100 Subject: Added soft wrap logic and button to editor Added tests Added awesomeeeeee icons --- .../projects/files/edit_file_soft_wrap_spec.rb | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 spec/features/projects/files/edit_file_soft_wrap_spec.rb (limited to 'spec') diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb new file mode 100644 index 00000000000..7ad90b4a89c --- /dev/null +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +feature 'User uses soft wrap whilst editing file', feature: true, js: true do + before do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as user + visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'test_file-name') + editor = find('.file-editor.code') + editor.click + editor.send_keys 'Touch water with paw then recoil in horror chase dog then + run away chase the pig around the house eat owner\'s food, and knock + dish off table head butt cant eat out of my own dish. Cat is love, cat + is life rub face on everything poop on grasses so meow. Playing with + balls of wool flee in terror at cucumber discovered on floor run in + circles tuxedo cats always looking dapper, but attack dog, run away + and pretend to be victim so all of a sudden cat goes crazy, yet chase + laser. Make muffins sit in window and stare ooo, a bird! yum lick yarn + hanging out of own butt jump off balcony, onto stranger\'s head yet + chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish + end + + let(:toggle_button) { find('.soft-wrap-toggle') } + + scenario 'user clicks the "No wrap" button and then "Soft wrap" button' do + wrapped_content_width = get_content_width + toggle_button.click + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + toggle_button.click + expect(toggle_button).to have_content 'No wrap' + expect(get_content_width).to be < unwrapped_content_width + end + + scenario 'user adds a ".js" extension and then changes to a ".md" extension' do + wrapped_content_width = get_content_width + + fill_in 'file_name', with: 'test_file-name.js' + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + fill_in 'file_name', with: 'test_file-name.md' + expect(toggle_button).to have_content 'No wrap' + expect(get_content_width).to be < unwrapped_content_width + end + + scenario 'user clicks "No wrap" and then changes to a ".md" extension' do + wrapped_content_width = get_content_width + + toggle_button.click + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + fill_in 'file_name', with: 'test_file-name.md' + expect(toggle_button).to have_content 'Soft wrap' + expect(unwrapped_content_width).to be == get_content_width + end + + def get_content_width + find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/) + end +end -- cgit v1.2.1 From 70f7d2446a4ba9e301d0f7151a95a52e127f2423 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 27 Sep 2016 22:08:05 +0100 Subject: Review changes Updated tests --- .../projects/files/edit_file_soft_wrap_spec.rb | 32 ++-------------------- 1 file changed, 3 insertions(+), 29 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb index 7ad90b4a89c..012befa7990 100644 --- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -23,42 +23,16 @@ feature 'User uses soft wrap whilst editing file', feature: true, js: true do let(:toggle_button) { find('.soft-wrap-toggle') } - scenario 'user clicks the "No wrap" button and then "Soft wrap" button' do + scenario 'user clicks the "Soft wrap" button and then "No wrap" button' do wrapped_content_width = get_content_width - toggle_button.click - expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - toggle_button.click expect(toggle_button).to have_content 'No wrap' - expect(get_content_width).to be < unwrapped_content_width - end - - scenario 'user adds a ".js" extension and then changes to a ".md" extension' do - wrapped_content_width = get_content_width - - fill_in 'file_name', with: 'test_file-name.js' - expect(toggle_button).to have_content 'Soft wrap' unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - fill_in 'file_name', with: 'test_file-name.md' - expect(toggle_button).to have_content 'No wrap' - expect(get_content_width).to be < unwrapped_content_width - end - - scenario 'user clicks "No wrap" and then changes to a ".md" extension' do - wrapped_content_width = get_content_width + expect(unwrapped_content_width).to be < wrapped_content_width toggle_button.click expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - fill_in 'file_name', with: 'test_file-name.md' - expect(toggle_button).to have_content 'Soft wrap' - expect(unwrapped_content_width).to be == get_content_width + expect(get_content_width).to be > unwrapped_content_width end def get_content_width -- cgit v1.2.1 From 4a23d7f49150c9292f643b6f1c4fdb3494868de7 Mon Sep 17 00:00:00 2001 From: Jared Deckard Date: Fri, 30 Sep 2016 17:14:39 -0500 Subject: Remove the task_list test since it is patched upstream --- spec/lib/banzai/filter/task_list_filter_spec.rb | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 spec/lib/banzai/filter/task_list_filter_spec.rb (limited to 'spec') diff --git a/spec/lib/banzai/filter/task_list_filter_spec.rb b/spec/lib/banzai/filter/task_list_filter_spec.rb deleted file mode 100644 index 569cbc885c7..00000000000 --- a/spec/lib/banzai/filter/task_list_filter_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -describe Banzai::Filter::TaskListFilter, lib: true do - include FilterSpecHelper - - it 'does not apply `task-list` class to non-task lists' do - exp = act = %(
  • Item
) - expect(filter(act).to_html).to eq exp - end - - it 'applies `task-list` to single-item task lists' do - act = filter('
  • [ ] Task 1
') - - expect(act.to_html).to start_with '
    ' - end -end -- cgit v1.2.1 From dd01f3a748ea8be2af75ef03ff203efe1b8f5962 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 1 Oct 2016 13:56:41 +0800 Subject: Should use eq because we want orders --- spec/services/ci/process_pipeline_service_spec.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index b6c23002dda..95bdb43db05 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -245,8 +245,7 @@ describe Ci::ProcessPipelineService, services: true do end it 'starts from the second stage' do - expect(builds.map(&:status)).to contain_exactly( - 'skipped', 'pending', 'created') + expect(builds.map(&:status)).to eq(%w[skipped pending created]) end end @@ -258,14 +257,12 @@ describe Ci::ProcessPipelineService, services: true do end it 'skips second stage and continues on third stage' do - expect(builds.map(&:status)).to contain_exactly( - 'pending', 'created', 'created') + expect(builds.map(&:status)).to eq(%w[pending created created]) builds.first.success builds.each(&:reload) - expect(builds.map(&:status)).to contain_exactly( - 'success', 'skipped', 'pending') + expect(builds.map(&:status)).to eq(%w[success skipped pending]) end end -- cgit v1.2.1 From f0002da09c0f8ae4fb9f732c2e225c9affd98b04 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 1 Oct 2016 14:38:39 +0800 Subject: Add a test for on_failure jobs in the middle --- spec/services/ci/process_pipeline_service_spec.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index 95bdb43db05..ff113efd916 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -230,7 +230,7 @@ describe Ci::ProcessPipelineService, services: true do end end - context 'when there are manual jobs in earlier stages' do + context 'when there are manual/on_failure jobs in earlier stages' do before do builds process_pipeline @@ -266,6 +266,23 @@ describe Ci::ProcessPipelineService, services: true do end end + context 'when second stage has only on_failure jobs' do + let(:builds) do + [create_build('check', 0), + create_build('build', 1, 'on_failure'), + create_build('test', 2)] + end + + it 'skips second stage and continues on third stage' do + expect(builds.map(&:status)).to eq(%w[pending created created]) + + builds.first.success + builds.each(&:reload) + + expect(builds.map(&:status)).to eq(%w[success skipped pending]) + end + end + def create_build(name, stage_idx, when_value = nil) create(:ci_build, :created, -- cgit v1.2.1 From 6d1cd0e2085d8654dbcfeac61825b7b2cf5f1f15 Mon Sep 17 00:00:00 2001 From: Matthew Dodds Date: Sat, 1 Oct 2016 03:32:21 -0400 Subject: Add a spec to verify comparison context inclusion in path when a version is chosen to compare against --- .../merge_requests/merge_request_versions_spec.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_request_versions_spec.rb b/spec/features/merge_requests/merge_request_versions_spec.rb index 22d9e42119d..32b0b65fbac 100644 --- a/spec/features/merge_requests/merge_request_versions_spec.rb +++ b/spec/features/merge_requests/merge_request_versions_spec.rb @@ -1,12 +1,13 @@ require 'spec_helper' feature 'Merge Request versions', js: true, feature: true do + let(:merge_request) { create(:merge_request, importing: true) } + let(:project) { merge_request.source_project } + before do login_as :admin - merge_request = create(:merge_request, importing: true) merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') - project = merge_request.source_project visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) end @@ -47,6 +48,16 @@ feature 'Merge Request versions', js: true, feature: true do end end + it 'has a path with comparison context' do + expect(page).to have_current_path diffs_namespace_project_merge_request_path( + project.namespace, + project, + merge_request.iid, + diff_id: 2, + start_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' + ) + end + it 'should have correct value in the compare dropdown' do page.within '.mr-version-compare-dropdown' do expect(page).to have_content 'version 1' -- cgit v1.2.1 From f8349e320770fe8e0498439719d33e0ef80d1d06 Mon Sep 17 00:00:00 2001 From: Matthew Dodds Date: Sat, 1 Oct 2016 03:33:20 -0400 Subject: Remove duplicate test --- spec/features/merge_requests/merge_request_versions_spec.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_request_versions_spec.rb b/spec/features/merge_requests/merge_request_versions_spec.rb index 32b0b65fbac..23cee891bac 100644 --- a/spec/features/merge_requests/merge_request_versions_spec.rb +++ b/spec/features/merge_requests/merge_request_versions_spec.rb @@ -72,10 +72,6 @@ feature 'Merge Request versions', js: true, feature: true do expect(page).to have_content '4 changed files with 15 additions and 6 deletions' end - it 'show diff between new and old version' do - expect(page).to have_content '4 changed files with 15 additions and 6 deletions' - end - it 'should return to latest version when "Show latest version" button is clicked' do click_link 'Show latest version' page.within '.mr-version-dropdown' do -- cgit v1.2.1 From 89e663122b1c114f9b7566cd42c5bbee4873430a Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Sat, 1 Oct 2016 12:18:44 -0500 Subject: Changed zero padded days to no padded days in date_format --- spec/features/calendar_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index f52682f229c..7fa0c95cae2 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -5,7 +5,9 @@ feature 'Contributions Calendar', js: true, feature: true do let(:contributed_project) { create(:project, :public) } - date_format = '%A %b %d, %Y' + # Ex/ Sunday Jan 1, 2016 + date_format = '%A %b %-d, %Y' + issue_title = 'Bug in old browser' issue_params = { title: issue_title } -- cgit v1.2.1 From 0b38e213a735994628a5ceabaf7ff51eeef38eae Mon Sep 17 00:00:00 2001 From: secustor Date: Fri, 30 Sep 2016 23:03:30 +0200 Subject: Changed Slack service user referencing from full name to username --- .../project_services/slack_service/issue_message_spec.rb | 6 +++--- .../project_services/slack_service/merge_message_spec.rb | 6 +++--- .../project_services/slack_service/note_message_spec.rb | 10 +++++----- .../project_services/slack_service/push_message_spec.rb | 12 ++++++------ .../project_services/slack_service/wiki_page_message_spec.rb | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/slack_service/issue_message_spec.rb b/spec/models/project_services/slack_service/issue_message_spec.rb index 0f8889bdf3c..98c36ec088d 100644 --- a/spec/models/project_services/slack_service/issue_message_spec.rb +++ b/spec/models/project_services/slack_service/issue_message_spec.rb @@ -7,7 +7,7 @@ describe SlackService::IssueMessage, models: true do { user: { name: 'Test User', - username: 'Test User' + username: 'test.user' }, project_name: 'project_name', project_url: 'somewhere.com', @@ -40,7 +40,7 @@ describe SlackService::IssueMessage, models: true do context 'open' do it 'returns a message regarding opening of issues' do expect(subject.pretext).to eq( - '] Issue opened by Test User') + '] Issue opened by test.user') expect(subject.attachments).to eq([ { title: "#100 Issue title", @@ -60,7 +60,7 @@ describe SlackService::IssueMessage, models: true do it 'returns a message regarding closing of issues' do expect(subject.pretext). to eq( - '] Issue closed by Test User') + '] Issue closed by test.user') expect(subject.attachments).to be_empty end end diff --git a/spec/models/project_services/slack_service/merge_message_spec.rb b/spec/models/project_services/slack_service/merge_message_spec.rb index 224c7ceabe8..c5c052d9af1 100644 --- a/spec/models/project_services/slack_service/merge_message_spec.rb +++ b/spec/models/project_services/slack_service/merge_message_spec.rb @@ -7,7 +7,7 @@ describe SlackService::MergeMessage, models: true do { user: { name: 'Test User', - username: 'Test User' + username: 'test.user' }, project_name: 'project_name', project_url: 'somewhere.com', @@ -31,7 +31,7 @@ describe SlackService::MergeMessage, models: true do context 'open' do it 'returns a message regarding opening of merge requests' do expect(subject.pretext).to eq( - 'Test User opened '\ + 'test.user opened '\ 'in : *Issue title*') expect(subject.attachments).to be_empty end @@ -43,7 +43,7 @@ describe SlackService::MergeMessage, models: true do end it 'returns a message regarding closing of merge requests' do expect(subject.pretext).to eq( - 'Test User closed '\ + 'test.user closed '\ 'in : *Issue title*') expect(subject.attachments).to be_empty end diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb index 41b93f08050..38cfe4ad3e3 100644 --- a/spec/models/project_services/slack_service/note_message_spec.rb +++ b/spec/models/project_services/slack_service/note_message_spec.rb @@ -7,7 +7,7 @@ describe SlackService::NoteMessage, models: true do @args = { user: { name: 'Test User', - username: 'username', + username: 'test.user', avatar_url: 'http://fakeavatar' }, project_name: 'project_name', @@ -37,7 +37,7 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on commits' do message = SlackService::NoteMessage.new(@args) - expect(message.pretext).to eq("Test User commented on " \ + expect(message.pretext).to eq("test.user commented on " \ " in : " \ "*Added a commit message*") expected_attachments = [ @@ -63,7 +63,7 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on a merge request' do message = SlackService::NoteMessage.new(@args) - expect(message.pretext).to eq("Test User commented on " \ + expect(message.pretext).to eq("test.user commented on " \ " in : " \ "*merge request title*") expected_attachments = [ @@ -90,7 +90,7 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on an issue' do message = SlackService::NoteMessage.new(@args) expect(message.pretext).to eq( - "Test User commented on " \ + "test.user commented on " \ " in : " \ "*issue title*") expected_attachments = [ @@ -115,7 +115,7 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on a project snippet' do message = SlackService::NoteMessage.new(@args) - expect(message.pretext).to eq("Test User commented on " \ + expect(message.pretext).to eq("test.user commented on " \ " in : " \ "*snippet title*") expected_attachments = [ diff --git a/spec/models/project_services/slack_service/push_message_spec.rb b/spec/models/project_services/slack_service/push_message_spec.rb index cda9ee670b0..17cd05e24f1 100644 --- a/spec/models/project_services/slack_service/push_message_spec.rb +++ b/spec/models/project_services/slack_service/push_message_spec.rb @@ -9,7 +9,7 @@ describe SlackService::PushMessage, models: true do before: 'before', project_name: 'project_name', ref: 'refs/heads/master', - user_name: 'user_name', + user_name: 'test.user', project_url: 'url' } end @@ -26,7 +26,7 @@ describe SlackService::PushMessage, models: true do it 'returns a message regarding pushes' do expect(subject.pretext).to eq( - 'user_name pushed to branch of '\ + 'test.user pushed to branch of '\ ' ()' ) expect(subject.attachments).to eq([ @@ -46,13 +46,13 @@ describe SlackService::PushMessage, models: true do before: Gitlab::Git::BLANK_SHA, project_name: 'project_name', ref: 'refs/tags/new_tag', - user_name: 'user_name', + user_name: 'test.user', project_url: 'url' } end it 'returns a message regarding pushes' do - expect(subject.pretext).to eq('user_name pushed new tag ' \ + expect(subject.pretext).to eq('test.user pushed new tag ' \ ' to ' \ '') expect(subject.attachments).to be_empty @@ -66,7 +66,7 @@ describe SlackService::PushMessage, models: true do it 'returns a message regarding a new branch' do expect(subject.pretext).to eq( - 'user_name pushed new branch to '\ + 'test.user pushed new branch to '\ '' ) expect(subject.attachments).to be_empty @@ -80,7 +80,7 @@ describe SlackService::PushMessage, models: true do it 'returns a message regarding a removed branch' do expect(subject.pretext).to eq( - 'user_name removed branch master from ' + 'test.user removed branch master from ' ) expect(subject.attachments).to be_empty end diff --git a/spec/models/project_services/slack_service/wiki_page_message_spec.rb b/spec/models/project_services/slack_service/wiki_page_message_spec.rb index 13aea0b0600..093911598b0 100644 --- a/spec/models/project_services/slack_service/wiki_page_message_spec.rb +++ b/spec/models/project_services/slack_service/wiki_page_message_spec.rb @@ -7,7 +7,7 @@ describe SlackService::WikiPageMessage, models: true do { user: { name: 'Test User', - username: 'Test User' + username: 'test.user' }, project_name: 'project_name', project_url: 'somewhere.com', @@ -25,7 +25,7 @@ describe SlackService::WikiPageMessage, models: true do it 'returns a message that a new wiki page was created' do expect(subject.pretext).to eq( - 'Test User created in : '\ + 'test.user created in : '\ '*Wiki page title*') end end @@ -35,7 +35,7 @@ describe SlackService::WikiPageMessage, models: true do it 'returns a message that a wiki page was updated' do expect(subject.pretext).to eq( - 'Test User edited in : '\ + 'test.user edited in : '\ '*Wiki page title*') end end -- cgit v1.2.1 From ddbe676dc318b87c3d656a08bbf5d75485ad544b Mon Sep 17 00:00:00 2001 From: Thomas Balthazar Date: Thu, 8 Sep 2016 11:18:41 +0200 Subject: Add a /wip slash command It toggles the 'WIP' prefix in the MR title. --- .../projects/merge_requests_controller_spec.rb | 14 ++++++ .../issues/user_uses_slash_commands_spec.rb | 10 ++++ .../user_uses_slash_commands_spec.rb | 55 ++++++++++++++++++++-- spec/models/merge_request_spec.rb | 40 ++++++++++++++++ .../slash_commands/interpret_service_spec.rb | 27 +++++++++++ 5 files changed, 141 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 94c9edc91fe..742edd8ba3d 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -644,6 +644,20 @@ describe Projects::MergeRequestsController do end end + context 'POST remove_wip' do + it 'removes the wip status' do + merge_request.title = merge_request.wip_title + merge_request.save + + post :remove_wip, + namespace_id: merge_request.project.namespace.to_param, + project_id: merge_request.project.to_param, + id: merge_request.iid + + expect(merge_request.reload.title).to eq(merge_request.wipless_title) + end + end + context 'POST resolve_conflicts' do let(:json_response) { JSON.parse(response.body) } let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha } diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index bf2b93c92fb..3f2da1c380c 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -99,5 +99,15 @@ feature 'Issues > User uses slash commands', feature: true, js: true do end end end + + describe 'toggling the WIP prefix from the title from note' do + let(:issue) { create(:issue, project: project) } + + it 'does not recognize the command nor create a note' do + write_note("/wip") + + expect(page).not_to have_content '/wip' + end + end end end diff --git a/spec/features/merge_requests/user_uses_slash_commands_spec.rb b/spec/features/merge_requests/user_uses_slash_commands_spec.rb index 22d9d1b9fd5..cb3cea3fd51 100644 --- a/spec/features/merge_requests/user_uses_slash_commands_spec.rb +++ b/spec/features/merge_requests/user_uses_slash_commands_spec.rb @@ -14,21 +14,66 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do let(:new_url_opts) { { merge_request: { source_branch: 'feature' } } } end - describe 'adding a due date from note' do + describe 'merge-request-only commands' do before do project.team << [user, :master] login_with(user) visit namespace_project_merge_request_path(project.namespace, project, merge_request) end - + after do wait_for_ajax end - it 'does not recognize the command nor create a note' do - write_note("/due 2016-08-28") + describe 'toggling the WIP prefix in the title from note' do + context 'when the current user can toggle the WIP prefix' do + it 'adds the WIP: prefix to the title' do + write_note("/wip") + + expect(page).not_to have_content '/wip' + expect(page).to have_content 'Your commands have been executed!' + + expect(merge_request.reload.work_in_progress?).to eq true + end + + it 'removes the WIP: prefix from the title' do + merge_request.title = merge_request.wip_title + merge_request.save + write_note("/wip") + + expect(page).not_to have_content '/wip' + expect(page).to have_content 'Your commands have been executed!' + + expect(merge_request.reload.work_in_progress?).to eq false + end + end + + context 'when the current user cannot toggle the WIP prefix' do + let(:guest) { create(:user) } + before do + project.team << [guest, :guest] + logout + login_with(guest) + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'does not change the WIP prefix' do + write_note("/wip") + + expect(page).not_to have_content '/wip' + expect(page).not_to have_content 'Your commands have been executed!' + + expect(merge_request.reload.work_in_progress?).to eq false + end + end + end + + describe 'adding a due date from note' do + it 'does not recognize the command nor create a note' do + write_note('/due 2016-08-28') - expect(page).not_to have_content '/due 2016-08-28' + expect(page).not_to have_content '/due 2016-08-28' + end end end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 580a3235127..9d7be2429ed 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -287,6 +287,46 @@ describe MergeRequest, models: true do end end + describe "#wipless_title" do + ['WIP ', 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP [WIP] WIP: WIP '].each do |wip_prefix| + it "removes the '#{wip_prefix}' prefix" do + wipless_title = subject.title + subject.title = "#{wip_prefix}#{subject.title}" + + expect(subject.wipless_title).to eq wipless_title + end + + it "is satisfies the #work_in_progress? method" do + subject.title = "#{wip_prefix}#{subject.title}" + subject.title = subject.wipless_title + + expect(subject.work_in_progress?).to eq false + end + end + end + + describe "#wip_title" do + it "adds the WIP: prefix to the title" do + wip_title = "WIP: #{subject.title}" + + expect(subject.wip_title).to eq wip_title + end + + it "does not add the WIP: prefix multiple times" do + wip_title = "WIP: #{subject.title}" + subject.title = subject.wip_title + subject.title = subject.wip_title + + expect(subject.wip_title).to eq wip_title + end + + it "is satisfies the #work_in_progress? method" do + subject.title = subject.wip_title + + expect(subject.work_in_progress?).to eq true + end + end + describe '#can_remove_source_branch?' do let(:user) { create(:user) } let(:user2) { create(:user) } diff --git a/spec/services/slash_commands/interpret_service_spec.rb b/spec/services/slash_commands/interpret_service_spec.rb index 5b1edba87a1..ae4d286d250 100644 --- a/spec/services/slash_commands/interpret_service_spec.rb +++ b/spec/services/slash_commands/interpret_service_spec.rb @@ -165,6 +165,23 @@ describe SlashCommands::InterpretService, services: true do end end + shared_examples 'wip command' do + it 'returns wip_event: "wip" if content contains /wip' do + _, updates = service.execute(content, issuable) + + expect(updates).to eq(wip_event: 'wip') + end + end + + shared_examples 'unwip command' do + it 'returns wip_event: "unwip" if content contains /wip' do + issuable.update(title: issuable.wip_title) + _, updates = service.execute(content, issuable) + + expect(updates).to eq(wip_event: 'unwip') + end + end + shared_examples 'empty command' do it 'populates {} if content contains an unsupported command' do _, updates = service.execute(content, issuable) @@ -376,6 +393,16 @@ describe SlashCommands::InterpretService, services: true do let(:issuable) { issue } end + it_behaves_like 'wip command' do + let(:content) { '/wip' } + let(:issuable) { merge_request } + end + + it_behaves_like 'unwip command' do + let(:content) { '/wip' } + let(:issuable) { merge_request } + end + it_behaves_like 'empty command' do let(:content) { '/remove_due_date' } let(:issuable) { merge_request } -- cgit v1.2.1 From 72da67485ff7ca430d8f09b7d7f28b4f54d33215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 3 Oct 2016 10:01:02 +0200 Subject: Members::RequestAccessService is tricter on permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortunately, only specs needed to be fixed, so that's good! Signed-off-by: Rémy Coutable --- spec/finders/access_requests_finder_spec.rb | 4 ++-- spec/models/member_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/finders/access_requests_finder_spec.rb b/spec/finders/access_requests_finder_spec.rb index 6cc90299417..626513200e4 100644 --- a/spec/finders/access_requests_finder_spec.rb +++ b/spec/finders/access_requests_finder_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe AccessRequestsFinder, services: true do let(:user) { create(:user) } let(:access_requester) { create(:user) } - let(:project) { create(:project) } - let(:group) { create(:group) } + let(:project) { create(:project, :public) } + let(:group) { create(:group, :public) } before do project.request_access(access_requester) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index bda23eaed43..485121701af 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -174,7 +174,7 @@ describe Member, models: true do describe '.add_user' do %w[project group].each do |source_type| context "when source is a #{source_type}" do - let!(:source) { create(source_type) } + let!(:source) { create(source_type, :public) } let!(:user) { create(:user) } let!(:admin) { create(:admin) } -- cgit v1.2.1 From a09e1d3dda57323d8932b498a711928c98404005 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 29 Aug 2016 09:46:05 +0200 Subject: Enable import/export back for non-admins --- spec/features/projects/import_export/import_file_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 09cd6369881..f32834801a0 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -86,14 +86,14 @@ feature 'Import/Export - project import integration test', feature: true, js: tr login_as(normal_user) end - scenario 'non-admin user is not allowed to import a project' do + scenario 'non-admin user is allowed to import a project' do expect(Project.all.count).to be_zero visit new_project_path fill_in :project_path, with: 'test-project-path', visible: true - expect(page).not_to have_content('GitLab export') + expect(page).to have_content('GitLab export') end end -- cgit v1.2.1 From 4c5c5ab31479b0f3e1b7c3830cae250417d02f43 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 14 Sep 2016 19:22:36 +0100 Subject: Added test for due date --- spec/features/todos/todos_spec.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb index fc555a74f30..bf93c1d1251 100644 --- a/spec/features/todos/todos_spec.rb +++ b/spec/features/todos/todos_spec.rb @@ -4,7 +4,7 @@ describe 'Dashboard Todos', feature: true do let(:user) { create(:user) } let(:author) { create(:user) } let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } - let(:issue) { create(:issue) } + let(:issue) { create(:issue, due_date: Date.today) } describe 'GET /dashboard/todos' do context 'User does not have todos' do @@ -28,6 +28,12 @@ describe 'Dashboard Todos', feature: true do expect(page).to have_selector('.todos-list .todo', count: 1) end + it 'shows due date as today' do + page.within first('.todo') do + expect(page).to have_content 'Due today' + end + end + describe 'deleting the todo' do before do first('.done-todo').click -- cgit v1.2.1 From ef2ed380f3af1a198761f5bd547b360165fa7a82 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 2 Oct 2016 17:00:41 +0200 Subject: Convert "SSH Keys" Spinach features to RSpec --- spec/features/profiles/keys_spec.rb | 47 +++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index 3b20d38c520..eb1050d21c6 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -1,18 +1,57 @@ require 'rails_helper' -describe 'Profile > SSH Keys', feature: true do +feature 'Profile > SSH Keys', feature: true do let(:user) { create(:user) } before do login_as(user) - visit profile_keys_path end - describe 'User adds an SSH key' do - it 'auto-populates the title', js: true do + describe 'User adds a key' do + before do + visit profile_keys_path + end + + scenario 'auto-populates the title', js: true do fill_in('Key', with: attributes_for(:key).fetch(:key)) expect(find_field('Title').value).to eq 'dummy@gitlab.com' end + + scenario 'saves the new key' do + attrs = attributes_for(:key) + + fill_in('Key', with: attrs[:key]) + fill_in('Title', with: attrs[:title]) + click_button('Add key') + + expect(page).to have_content("Title: #{attrs[:title]}") + expect(page).to have_content(attrs[:key]) + end + end + + scenario 'User sees their keys' do + key = create(:key, user: user) + visit profile_keys_path + + expect(page).to have_content(key.title) + end + + scenario 'User removes a key via the key index' do + create(:key, user: user) + visit profile_keys_path + + click_link('Remove') + + expect(page).to have_content('Your SSH keys (0)') + end + + scenario 'User removes a key via its details page' do + key = create(:key, user: user) + visit profile_key_path(key) + + click_link('Remove') + + expect(page).to have_content('Your SSH keys (0)') end end -- cgit v1.2.1 From bf3b8d1c1d3d854311a638ebeaf87991367e4052 Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Fri, 30 Sep 2016 14:53:37 +0200 Subject: Fix test, add author attribute to all tests --- spec/lib/banzai/filter/user_reference_filter_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb index fdbdb21eac1..4b1ea6403cc 100644 --- a/spec/lib/banzai/filter/user_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/user_reference_filter_spec.rb @@ -31,13 +31,16 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do end it 'supports a special @all mention' do + project.team << [user, :developer] doc = reference_filter("Hey #{reference}", author: user) + expect(doc.css('a').length).to eq 1 expect(doc.css('a').first.attr('href')) .to eq urls.namespace_project_url(project.namespace, project) end it 'includes a data-author attribute when there is an author' do + project.team << [user, :developer] doc = reference_filter(reference, author: user) expect(doc.css('a').first.attr('data-author')).to eq(user.id.to_s) @@ -48,6 +51,12 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do expect(doc.css('a').first.has_attribute?('data-author')).to eq(false) end + + it 'ignores reference to all when user is not a project member' do + doc = reference_filter("Hey #{reference}", author: user) + + expect(doc.css('a').length).to eq 0 + end end context 'mentioning a user' do -- cgit v1.2.1 From fd8c30d1d7da92b45732e532890453b277428588 Mon Sep 17 00:00:00 2001 From: Katarzyna Kobierska Date: Sat, 1 Oct 2016 11:17:56 +0200 Subject: Imrove grammar --- spec/lib/banzai/filter/user_reference_filter_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb index 4b1ea6403cc..729e77fd43f 100644 --- a/spec/lib/banzai/filter/user_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/user_reference_filter_spec.rb @@ -52,7 +52,7 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do expect(doc.css('a').first.has_attribute?('data-author')).to eq(false) end - it 'ignores reference to all when user is not a project member' do + it 'ignores reference to all when the user is not a project member' do doc = reference_filter("Hey #{reference}", author: user) expect(doc.css('a').length).to eq 0 -- cgit v1.2.1 From 74c8e091f40c29a59b99bf7864b9fee303c68e50 Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Fri, 2 Sep 2016 16:57:08 +0800 Subject: add configurable email subject suffix --- spec/mailers/shared/notify.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 5c9851f14c7..de1d8995534 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -2,6 +2,7 @@ shared_context 'gitlab email notification' do let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name } let(:gitlab_sender) { Gitlab.config.gitlab.email_from } let(:gitlab_sender_reply_to) { Gitlab.config.gitlab.email_reply_to } + let(:gitlab_subject_suffix) { Gitlab.config.gitlab.email_subject_suffix } let(:recipient) { create(:user, email: 'recipient@example.com') } let(:project) { create(:project) } let(:new_user_address) { 'newguy@example.com' } @@ -31,6 +32,9 @@ shared_examples 'an email sent from GitLab' do sender = subject.header[:from].addrs[0] expect(sender.display_name).to eq(gitlab_sender_display_name) expect(sender.address).to eq(gitlab_sender) + if gitlab_subject_suffix.length > 0 + is_expected.to have_subject gitlab_subject_suffix + end end it 'has a Reply-To address' do -- cgit v1.2.1 From 785094e201a7d3e7c88f9556da8d9539281a36d5 Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Tue, 27 Sep 2016 01:06:57 +0800 Subject: create new test in `spec/mailers/notify_spec.rb` --- spec/mailers/notify_spec.rb | 11 +++++++++++ spec/mailers/shared/notify.rb | 4 ---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index cd8578b6f49..03e0bfd3614 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -1094,4 +1094,15 @@ describe Notify do is_expected.to have_body_text /#{diff_path}/ end end + + describe 'email has correct subject' do + let(:gitlab_subject_suffix) { Gitlab.config.gitlab.email_subject_suffix } + + it 'has correct suffix' do + if gitlab_subject_suffix.length > 0 + is_expected.to have_subject gitlab_subject_suffix + end + end + end + end diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index de1d8995534..5c9851f14c7 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -2,7 +2,6 @@ shared_context 'gitlab email notification' do let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name } let(:gitlab_sender) { Gitlab.config.gitlab.email_from } let(:gitlab_sender_reply_to) { Gitlab.config.gitlab.email_reply_to } - let(:gitlab_subject_suffix) { Gitlab.config.gitlab.email_subject_suffix } let(:recipient) { create(:user, email: 'recipient@example.com') } let(:project) { create(:project) } let(:new_user_address) { 'newguy@example.com' } @@ -32,9 +31,6 @@ shared_examples 'an email sent from GitLab' do sender = subject.header[:from].addrs[0] expect(sender.display_name).to eq(gitlab_sender_display_name) expect(sender.address).to eq(gitlab_sender) - if gitlab_subject_suffix.length > 0 - is_expected.to have_subject gitlab_subject_suffix - end end it 'has a Reply-To address' do -- cgit v1.2.1 From 89dc70df4614daf95a2284d8171db2a9115ec46e Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Tue, 27 Sep 2016 19:03:24 +0800 Subject: remove empty line at block body end --- spec/mailers/notify_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 03e0bfd3614..3585432ec75 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -1104,5 +1104,4 @@ describe Notify do end end end - end -- cgit v1.2.1 From 2a438f452c920e57545add519ed7b7a2c15e660e Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Tue, 27 Sep 2016 20:18:10 +0800 Subject: stub config settings in spec --- spec/mailers/notify_spec.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 3585432ec75..8dc5e0b34d2 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -1096,12 +1096,9 @@ describe Notify do end describe 'email has correct subject' do - let(:gitlab_subject_suffix) { Gitlab.config.gitlab.email_subject_suffix } - it 'has correct suffix' do - if gitlab_subject_suffix.length > 0 - is_expected.to have_subject gitlab_subject_suffix - end + stub_config_setting(email_subject_suffix: 'A Nice Suffix') + is_expected.to have_subject /\| A Nice Suffix$/ end end end -- cgit v1.2.1 From 048f124a0851a51c449881814dbfd2f2fc2dd32d Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Wed, 28 Sep 2016 16:14:47 +0800 Subject: move spec back into shared example `an email sent from GitLab` --- spec/mailers/notify_spec.rb | 7 ------- spec/mailers/shared/notify.rb | 10 ++++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 8dc5e0b34d2..cd8578b6f49 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -1094,11 +1094,4 @@ describe Notify do is_expected.to have_body_text /#{diff_path}/ end end - - describe 'email has correct subject' do - it 'has correct suffix' do - stub_config_setting(email_subject_suffix: 'A Nice Suffix') - is_expected.to have_subject /\| A Nice Suffix$/ - end - end end diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 5c9851f14c7..33d1075c739 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -37,6 +37,16 @@ shared_examples 'an email sent from GitLab' do reply_to = subject.header[:reply_to].addresses expect(reply_to).to eq([gitlab_sender_reply_to]) end + + context 'when custom suffix for email subject is set' do + before do + stub_config_setting(email_subject_suffix: 'A Nice Suffix') + end + + it 'ends the subject with the suffix' do + is_expected.to have_subject (/ \| A Nice Suffix$/) + end + end end shared_examples 'an email that contains a header with author username' do -- cgit v1.2.1 From 064eb2caa671cdd18cd051e49ff2086d004e5516 Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Thu, 29 Sep 2016 16:11:40 +0800 Subject: follow the styleguide: Don't use parentheses around a literal --- spec/mailers/shared/notify.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 33d1075c739..3956d05060b 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -44,7 +44,7 @@ shared_examples 'an email sent from GitLab' do end it 'ends the subject with the suffix' do - is_expected.to have_subject (/ \| A Nice Suffix$/) + is_expected.to have_subject /\ \| A Nice Suffix$/ end end end -- cgit v1.2.1 From 76463c2cb460099559b8544396cf1a6656895e8d Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Fri, 30 Sep 2016 17:46:37 +0800 Subject: override subject method in devise mailer --- spec/mailers/notify_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index cd8578b6f49..0e4130e8a3a 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -831,6 +831,7 @@ describe Notify do let(:user) { create(:user, email: 'old-email@mail.com') } before do + stub_config_setting(email_subject_suffix: 'A Nice Suffix') perform_enqueued_jobs do user.email = "new-email@mail.com" user.save @@ -847,7 +848,7 @@ describe Notify do end it 'has the correct subject' do - is_expected.to have_subject "Confirmation instructions" + is_expected.to have_subject /^Confirmation instructions/ end it 'includes a link to the site' do -- cgit v1.2.1 From aa1ab8aa1786517544d0a5c1a4217f98d37ea58f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 3 Oct 2016 11:49:17 +0200 Subject: Add some tests for updating ci runner information --- spec/requests/ci/api/builds_spec.rb | 43 +++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'spec') diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index df97f1bf7b6..7b7d62feb2c 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -35,18 +35,24 @@ describe Ci::API::API do end end - it "starts a build" do - register_builds info: { platform: :darwin } - - expect(response).to have_http_status(201) - expect(json_response['sha']).to eq(build.sha) - expect(runner.reload.platform).to eq("darwin") - expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] }) - expect(json_response["variables"]).to include( - { "key" => "CI_BUILD_NAME", "value" => "spinach", "public" => true }, - { "key" => "CI_BUILD_STAGE", "value" => "test", "public" => true }, - { "key" => "DB_NAME", "value" => "postgres", "public" => true } - ) + context 'when there is a pending build' do + it 'starts a build' do + register_builds info: { platform: :darwin } + + expect(response).to have_http_status(201) + expect(json_response['sha']).to eq(build.sha) + expect(runner.reload.platform).to eq("darwin") + expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] }) + expect(json_response["variables"]).to include( + { "key" => "CI_BUILD_NAME", "value" => "spinach", "public" => true }, + { "key" => "CI_BUILD_STAGE", "value" => "test", "public" => true }, + { "key" => "DB_NAME", "value" => "postgres", "public" => true } + ) + end + + it 'updates runner info' do + expect { register_builds }.to change { runner.reload.contacted_at } + end end context 'when builds are finished' do @@ -159,13 +165,18 @@ describe Ci::API::API do end context 'when runner is paused' do - let(:inactive_runner) { create(:ci_runner, :inactive, token: "InactiveRunner") } + let(:runner) { create(:ci_runner, :inactive, token: 'InactiveRunner') } - before do - register_builds inactive_runner.token + it 'responds with 404' do + register_builds + + expect(response).to have_http_status 404 end - it { expect(response).to have_http_status 404 } + it 'does not update runner info' do + expect { register_builds } + .not_to change { runner.reload.contacted_at } + end end def register_builds(token = runner.token, **params) -- cgit v1.2.1 From 8dfec32d2bac661313f62b338b6d991b3fa25b98 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 3 Oct 2016 18:22:51 +0800 Subject: Rename ignored to failed_but_allowed, introduce exclude_ignored which merges previous exclude_ignored_jobs and failed_but_allowed, so that we don't treat ignored a special case in HasStatus. --- spec/models/build_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index e7864b7ad33..ae185de9ca3 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -39,8 +39,8 @@ describe Ci::Build, models: true do end end - describe '#ignored?' do - subject { build.ignored? } + describe '#failed_but_allowed?' do + subject { build.failed_but_allowed? } context 'when build is not allowed to fail' do before do -- cgit v1.2.1 From 752a4cce514f04e0f364f615b817e64e9f40879b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 3 Oct 2016 18:56:32 +0800 Subject: Add test for CommitStatus.exclude_ignored --- spec/models/commit_status_spec.rb | 55 ++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 2f1baff5d66..80c2a1bc7a9 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -7,7 +7,11 @@ describe CommitStatus, models: true do create(:ci_pipeline, project: project, sha: project.commit.id) end - let(:commit_status) { create(:commit_status, pipeline: pipeline) } + let(:commit_status) { create_status } + + def create_status(args = {}) + create(:commit_status, args.merge(pipeline: pipeline)) + end it { is_expected.to belong_to(:pipeline) } it { is_expected.to belong_to(:user) } @@ -125,32 +129,53 @@ describe CommitStatus, models: true do describe '.latest' do subject { CommitStatus.latest.order(:id) } - before do - @commit1 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'bb', status: 'running' - @commit2 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'cc', ref: 'cc', status: 'pending' - @commit3 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'cc', status: 'success' - @commit4 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'cc', ref: 'bb', status: 'success' - @commit5 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'bb', status: 'success' + let(:statuses) do + [create_status(name: 'aa', ref: 'bb', status: 'running'), + create_status(name: 'cc', ref: 'cc', status: 'pending'), + create_status(name: 'aa', ref: 'cc', status: 'success'), + create_status(name: 'cc', ref: 'bb', status: 'success'), + create_status(name: 'aa', ref: 'bb', status: 'success')] end it 'returns unique statuses' do - is_expected.to eq([@commit4, @commit5]) + is_expected.to eq(statuses.values_at(3, 4)) end end describe '.running_or_pending' do subject { CommitStatus.running_or_pending.order(:id) } - before do - @commit1 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: 'bb', status: 'running' - @commit2 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'cc', ref: 'cc', status: 'pending' - @commit3 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'aa', ref: nil, status: 'success' - @commit4 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'dd', ref: nil, status: 'failed' - @commit5 = FactoryGirl.create :commit_status, pipeline: pipeline, name: 'ee', ref: nil, status: 'canceled' + let(:statuses) do + [create_status(name: 'aa', ref: 'bb', status: 'running'), + create_status(name: 'cc', ref: 'cc', status: 'pending'), + create_status(name: 'aa', ref: nil, status: 'success'), + create_status(name: 'dd', ref: nil, status: 'failed'), + create_status(name: 'ee', ref: nil, status: 'canceled')] end it 'returns statuses that are running or pending' do - is_expected.to eq([@commit1, @commit2]) + is_expected.to eq(statuses.values_at(0, 1)) + end + end + + describe '.exclude_ignored' do + subject { CommitStatus.exclude_ignored.order(:id) } + + let(:statuses) do + [create_status(when: 'manual', status: 'skipped'), + create_status(when: 'manual', status: 'success'), + create_status(when: 'manual', status: 'failed'), + create_status(when: 'on_failure', status: 'skipped'), + create_status(when: 'on_failure', status: 'success'), + create_status(when: 'on_failure', status: 'failed'), + create_status(allow_failure: true, status: 'success'), + create_status(allow_failure: true, status: 'failed'), + create_status(allow_failure: false, status: 'success'), + create_status(allow_failure: false, status: 'failed')] + end + + it 'returns statuses without what we want to ignore' do + is_expected.to eq(statuses.values_at(1, 2, 4, 5, 6, 8, 9)) end end -- cgit v1.2.1 From afc0ae5cbef721dad867c2fca9734fa9748b02f2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 3 Oct 2016 19:35:53 +0800 Subject: Fix tests. Check 'success' first (default status) --- spec/models/concerns/has_status_spec.rb | 43 +++++++++++++++------------------ 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb index e118432d098..87bffbdc54e 100644 --- a/spec/models/concerns/has_status_spec.rb +++ b/spec/models/concerns/has_status_spec.rb @@ -1,26 +1,17 @@ require 'spec_helper' describe HasStatus do - before do - @object = Object.new - @object.extend(HasStatus::ClassMethods) - end - describe '.status' do - before do - allow(@object).to receive(:all).and_return(CommitStatus.where(id: statuses)) - end - - subject { @object.status } + subject { CommitStatus.status } shared_examples 'build status summary' do context 'all successful' do - let(:statuses) { Array.new(2) { create(type, status: :success) } } + let!(:statuses) { Array.new(2) { create(type, status: :success) } } it { is_expected.to eq 'success' } end context 'at least one failed' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :failed)] end @@ -28,7 +19,7 @@ describe HasStatus do end context 'at least one running' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :running)] end @@ -36,7 +27,7 @@ describe HasStatus do end context 'at least one pending' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :pending)] end @@ -44,7 +35,7 @@ describe HasStatus do end context 'success and failed but allowed to fail' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :failed, allow_failure: true)] end @@ -53,12 +44,15 @@ describe HasStatus do end context 'one failed but allowed to fail' do - let(:statuses) { [create(type, status: :failed, allow_failure: true)] } + let!(:statuses) do + [create(type, status: :failed, allow_failure: true)] + end + it { is_expected.to eq 'success' } end context 'success and canceled' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :canceled)] end @@ -66,7 +60,7 @@ describe HasStatus do end context 'one failed and one canceled' do - let(:statuses) do + let!(:statuses) do [create(type, status: :failed), create(type, status: :canceled)] end @@ -74,7 +68,7 @@ describe HasStatus do end context 'one failed but allowed to fail and one canceled' do - let(:statuses) do + let!(:statuses) do [create(type, status: :failed, allow_failure: true), create(type, status: :canceled)] end @@ -83,7 +77,7 @@ describe HasStatus do end context 'one running one canceled' do - let(:statuses) do + let!(:statuses) do [create(type, status: :running), create(type, status: :canceled)] end @@ -91,14 +85,15 @@ describe HasStatus do end context 'all canceled' do - let(:statuses) do + let!(:statuses) do [create(type, status: :canceled), create(type, status: :canceled)] end + it { is_expected.to eq 'canceled' } end context 'success and canceled but allowed to fail' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :canceled, allow_failure: true)] end @@ -107,7 +102,7 @@ describe HasStatus do end context 'one finished and second running but allowed to fail' do - let(:statuses) do + let!(:statuses) do [create(type, status: :success), create(type, status: :running, allow_failure: true)] end @@ -118,11 +113,13 @@ describe HasStatus do context 'ci build statuses' do let(:type) { :ci_build } + it_behaves_like 'build status summary' end context 'generic commit statuses' do let(:type) { :generic_commit_status } + it_behaves_like 'build status summary' end end -- cgit v1.2.1 From 4a191c83d1db31aac16241dbf99ac45088efb99a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 3 Oct 2016 16:09:57 +0200 Subject: Enable Lint/StringConversionInInterpolation cop and autocorrect offenses --- spec/finders/access_requests_finder_spec.rb | 2 +- spec/lib/gitlab/import_export/attribute_configuration_spec.rb | 2 +- spec/services/members/approve_access_request_service_spec.rb | 2 +- spec/services/members/request_access_service_spec.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/finders/access_requests_finder_spec.rb b/spec/finders/access_requests_finder_spec.rb index 626513200e4..8cfea9659cb 100644 --- a/spec/finders/access_requests_finder_spec.rb +++ b/spec/finders/access_requests_finder_spec.rb @@ -16,7 +16,7 @@ describe AccessRequestsFinder, services: true do access_requesters = described_class.new(source).public_send(method_name, user) expect(access_requesters.size).to eq(1) - expect(access_requesters.first).to be_a "#{source.class.to_s}Member".constantize + expect(access_requesters.first).to be_a "#{source.class}Member".constantize expect(access_requesters.first.user).to eq(access_requester) end end diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 2ba344092ce..2e19d590d83 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -27,7 +27,7 @@ describe 'Import/Export attribute configuration', lib: true do relation_names.each do |relation_name| relation_class = relation_class_for_name(relation_name) - expect(safe_model_attributes[relation_class.to_s]).not_to be_nil, "Expected exported class #{relation_class.to_s} to exist in safe_model_attributes" + expect(safe_model_attributes[relation_class.to_s]).not_to be_nil, "Expected exported class #{relation_class} to exist in safe_model_attributes" current_attributes = parsed_attributes(relation_name, relation_class.attribute_names) safe_attributes = safe_model_attributes[relation_class.to_s] diff --git a/spec/services/members/approve_access_request_service_spec.rb b/spec/services/members/approve_access_request_service_spec.rb index 6fca80b5613..03e296259f9 100644 --- a/spec/services/members/approve_access_request_service_spec.rb +++ b/spec/services/members/approve_access_request_service_spec.rb @@ -26,7 +26,7 @@ describe Members::ApproveAccessRequestService, services: true do it 'returns a Member' do member = described_class.new(source, user, params).execute - expect(member).to be_a "#{source.class.to_s}Member".constantize + expect(member).to be_a "#{source.class}Member".constantize expect(member.requested_at).to be_nil end diff --git a/spec/services/members/request_access_service_spec.rb b/spec/services/members/request_access_service_spec.rb index dff5b4917ae..0d2d5f03199 100644 --- a/spec/services/members/request_access_service_spec.rb +++ b/spec/services/members/request_access_service_spec.rb @@ -19,7 +19,7 @@ describe Members::RequestAccessService, services: true do it 'returns a Member' do member = described_class.new(source, user).execute - expect(member).to be_a "#{source.class.to_s}Member".constantize + expect(member).to be_a "#{source.class}Member".constantize expect(member.requested_at).to be_present end end -- cgit v1.2.1 From 3158f57dba6dcef3e586ae8fced7deb6fdbd6dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 28 Jul 2016 19:31:17 +0200 Subject: Improve Members::DestroyService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/access_requests_spec.rb | 14 +++- spec/services/members/destroy_service_spec.rb | 112 +++++++++++++++++--------- 2 files changed, 84 insertions(+), 42 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb index 905a7311372..b7e5c2af82a 100644 --- a/spec/requests/api/access_requests_spec.rb +++ b/spec/requests/api/access_requests_spec.rb @@ -195,7 +195,7 @@ describe API::AccessRequests, api: true do end context 'when authenticated as the access requester' do - it 'returns 200' do + it 'deletes the access requester' do expect do delete api("/#{source_type.pluralize}/#{source.id}/access_requests/#{access_requester.id}", access_requester) @@ -205,7 +205,7 @@ describe API::AccessRequests, api: true do end context 'when authenticated as a master/owner' do - it 'returns 200' do + it 'deletes the access requester' do expect do delete api("/#{source_type.pluralize}/#{source.id}/access_requests/#{access_requester.id}", master) @@ -213,6 +213,16 @@ describe API::AccessRequests, api: true do end.to change { source.requesters.count }.by(-1) end + context 'user_id matches a member' do + it 'returns 404' do + expect do + delete api("/#{source_type.pluralize}/#{source.id}/access_requests/#{developer.id}", master) + + expect(response).to have_http_status(404) + end.not_to change { source.requesters.count } + end + end + context 'user_id does not match an existing access requester' do it 'returns 404' do expect do diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb index 2395445e7fd..06a6b0083c9 100644 --- a/spec/services/members/destroy_service_spec.rb +++ b/spec/services/members/destroy_service_spec.rb @@ -2,70 +2,102 @@ require 'spec_helper' describe Members::DestroyService, services: true do let(:user) { create(:user) } - let(:project) { create(:project) } - let!(:member) { create(:project_member, source: project) } + let(:member_user) { create(:user) } + let(:project) { create(:project, :public) } + let(:group) { create(:group, :public) } - context 'when member is nil' do - before do - project.team << [user, :developer] + shared_examples 'a service raising ActiveRecord::RecordNotFound' do + it 'raises ActiveRecord::RecordNotFound' do + expect { described_class.new(source, user, params).execute }.to raise_error(ActiveRecord::RecordNotFound) end + end - it 'does not destroy the member' do - expect { destroy_member(nil, user) }.to raise_error(Gitlab::Access::AccessDeniedError) + shared_examples 'a service raising Gitlab::Access::AccessDeniedError' do + it 'raises Gitlab::Access::AccessDeniedError' do + expect { described_class.new(source, user, params).execute }.to raise_error(Gitlab::Access::AccessDeniedError) end end - context 'when current user cannot destroy the given member' do - before do - project.team << [user, :developer] + shared_examples 'a service destroying a member' do + it 'destroys the member' do + expect { described_class.new(source, user, params).execute }.to change { source.members.count }.by(-1) end - it 'does not destroy the member' do - expect { destroy_member(member, user) }.to raise_error(Gitlab::Access::AccessDeniedError) + context 'when the given member is an access requester' do + before do + source.members.find_by(user_id: member_user).destroy + source.request_access(member_user) + end + let(:access_requester) { source.requesters.find_by(user_id: member_user) } + + it_behaves_like 'a service raising ActiveRecord::RecordNotFound' + + %i[requesters all].each do |scope| + context "and #{scope} scope is passed" do + it 'destroys the access requester' do + expect { described_class.new(source, user, params).execute(scope) }.to change { source.requesters.count }.by(-1) + end + + it 'calls Member#after_decline_request' do + expect_any_instance_of(NotificationService).to receive(:decline_access_request).with(access_requester) + + described_class.new(source, user, params).execute(scope) + end + + context 'when current user is the member' do + it 'does not call Member#after_decline_request' do + expect_any_instance_of(NotificationService).not_to receive(:decline_access_request).with(access_requester) + + described_class.new(source, member_user, params).execute(scope) + end + end + end + end end end - context 'when current user can destroy the given member' do - before do - project.team << [user, :master] + context 'when no member are found' do + let(:params) { { user_id: 42 } } + + it_behaves_like 'a service raising ActiveRecord::RecordNotFound' do + let(:source) { project } end - it 'destroys the member' do - destroy_member(member, user) + it_behaves_like 'a service raising ActiveRecord::RecordNotFound' do + let(:source) { group } + end + end - expect(member).to be_destroyed + context 'when a member is found' do + before do + project.team << [member_user, :developer] + group.add_developer(member_user) end + let(:params) { { user_id: member_user.id } } - context 'when the given member is a requester' do - before do - member.update_column(:requested_at, Time.now) + context 'when current user cannot destroy the given member' do + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { project } end - it 'calls Member#after_decline_request' do - expect_any_instance_of(NotificationService).to receive(:decline_access_request).with(member) - - destroy_member(member, user) + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { group } end + end - context 'when current user is the member' do - it 'does not call Member#after_decline_request' do - expect_any_instance_of(NotificationService).not_to receive(:decline_access_request).with(member) - - destroy_member(member, member.user) - end + context 'when current user can destroy the given member' do + before do + project.team << [user, :master] + group.add_owner(user) end - context 'when current user is the member and ' do - it 'does not call Member#after_decline_request' do - expect_any_instance_of(NotificationService).not_to receive(:decline_access_request).with(member) + it_behaves_like 'a service destroying a member' do + let(:source) { project } + end - destroy_member(member, member.user) - end + it_behaves_like 'a service destroying a member' do + let(:source) { group } end end end - - def destroy_member(member, user) - Members::DestroyService.new(member, user).execute - end end -- cgit v1.2.1 From c8b1311934935c7ac7fd901558e19ac496fbad2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 9 Sep 2016 18:51:31 +0200 Subject: Fix a few things after the initial improvment to Members::DestroyService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/groups/group_members_controller_spec.rb | 4 ++-- spec/controllers/projects/project_members_controller_spec.rb | 4 ++-- spec/services/members/destroy_service_spec.rb | 9 +++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index 92b97bf3d0c..a0870891cf4 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -87,10 +87,10 @@ describe Groups::GroupMembersController do context 'when member is not found' do before { sign_in(user) } - it 'returns 403' do + it 'returns 404' do delete :leave, group_id: group - expect(response).to have_http_status(403) + expect(response).to have_http_status(404) end end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 5e2a8cf3849..074f85157de 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -135,11 +135,11 @@ describe Projects::ProjectMembersController do context 'when member is not found' do before { sign_in(user) } - it 'returns 403' do + it 'returns 404' do delete :leave, namespace_id: project.namespace, project_id: project - expect(response).to have_http_status(403) + expect(response).to have_http_status(404) end end diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb index 06a6b0083c9..9995f3488af 100644 --- a/spec/services/members/destroy_service_spec.rb +++ b/spec/services/members/destroy_service_spec.rb @@ -98,6 +98,15 @@ describe Members::DestroyService, services: true do it_behaves_like 'a service destroying a member' do let(:source) { group } end + + context 'when given a :id' do + let(:params) { { id: project.members.find_by!(user_id: user.id).id } } + + it 'destroys the member' do + expect { described_class.new(project, user, params).execute }. + to change { project.members.count }.by(-1) + end + end end end end -- cgit v1.2.1 From e9d7b4f765605cfe25c2c4d8729e3d34cf5a979b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 16 Sep 2016 13:37:21 +0200 Subject: Invert method's naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/access_requests_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb index b7e5c2af82a..b467890a403 100644 --- a/spec/requests/api/access_requests_spec.rb +++ b/spec/requests/api/access_requests_spec.rb @@ -213,7 +213,7 @@ describe API::AccessRequests, api: true do end.to change { source.requesters.count }.by(-1) end - context 'user_id matches a member' do + context 'user_id matches a member, not an access requester' do it 'returns 404' do expect do delete api("/#{source_type.pluralize}/#{source.id}/access_requests/#{developer.id}", master) -- cgit v1.2.1 From 735731a565e593fa8df445b3bb2ac2f768fb1fae Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 3 Oct 2016 16:24:00 +0100 Subject: Tests update --- spec/features/issues/filter_issues_spec.rb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 32aaa0f1037..78208aed46d 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -110,30 +110,37 @@ describe 'Filter issues', feature: true do end it "filters by `won't fix` and another label" do - find('.dropdown-menu-labels a', text: label.title).click page.within '.labels-filter' do - expect(page).to have_content wontfix.title click_link wontfix.title + expect(page).to have_content wontfix.title + click_link label.title end - expect(find('.js-label-select .dropdown-toggle-text')).to have_content(wontfix.title) + expect(find('.js-label-select .dropdown-toggle-text')).to have_content("#{wontfix.title} +1 more") end it "filters by `won't fix` label followed by another label after page load" do - find('.dropdown-menu-labels a', text: wontfix.title).click - # Close label dropdown to load + page.within '.labels-filter' do + click_link wontfix.title + expect(page).to have_content wontfix.title + end + find('body').click + expect(find('.filtered-labels')).to have_content(wontfix.title) find('.js-label-select').click wait_for_ajax find('.dropdown-menu-labels a', text: label.title).click - # Close label dropdown to load + find('body').click + + expect(find('.filtered-labels')).to have_content(wontfix.title) expect(find('.filtered-labels')).to have_content(label.title) find('.js-label-select').click wait_for_ajax + expect(find('.dropdown-menu-labels li', text: wontfix.title)).to have_css('.is-active') expect(find('.dropdown-menu-labels li', text: label.title)).to have_css('.is-active') end -- cgit v1.2.1 From ad2b6cae0b299868eba9f8acf76bafe919408ccd Mon Sep 17 00:00:00 2001 From: Joseph Frazier <1212jtraceur@gmail.com> Date: Thu, 1 Sep 2016 07:58:09 -0400 Subject: Append issue template to existing description Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/21733 Add two newlines before the template if the existing description isn't empty. This makes it easier to see where the template begins. Don't append the template when "Reset template" is selected, of course. Don't append template if it equals the existing description. This makes it so that selecting a template twice doesn't duplicate it. --- spec/features/projects/issuable_templates_spec.rb | 30 +++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index f76c4fe8b57..cd79c4f512d 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -26,7 +26,7 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "bug" template' do select_template 'bug' wait_for_ajax - preview_template + preview_template(template_content) save_changes end @@ -42,6 +42,26 @@ feature 'issuable templates', feature: true, js: true do end end + context 'user creates an issue using templates, with a prior description' do + let(:prior_description) { 'test issue description' } + let(:template_content) { 'this is a test "bug" template' } + 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) + 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 + end + + scenario 'user selects "bug" template' do + select_template 'bug' + wait_for_ajax + preview_template("#{prior_description}\n\n#{template_content}") + save_changes + end + end + context 'user creates a merge request using templates' do let(:template_content) { 'this is a test "feature-proposal" template' } let(:merge_request) { create(:merge_request, :with_diffs, source_project: project) } @@ -55,7 +75,7 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "feature-proposal" template' do select_template 'feature-proposal' wait_for_ajax - preview_template + preview_template(template_content) save_changes end end @@ -82,16 +102,16 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects template' do select_template 'feature-proposal' wait_for_ajax - preview_template + preview_template(template_content) save_changes end end end end - def preview_template + def preview_template(expected_content) click_link 'Preview' - expect(page).to have_content template_content + expect(page).to have_content expected_content end def save_changes -- cgit v1.2.1 From 0cc3fc562738b88875e9ab2e871fdd64cc616705 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 4 Oct 2016 04:16:14 +0800 Subject: Add pipeline_email_service. Fixes: https://gitlab.com/gitlab-org/gitlab-ce/builds/4710913 --- spec/lib/gitlab/import_export/all_models.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 006569254a6..9002c6bc6da 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -125,6 +125,7 @@ project: - drone_ci_service - emails_on_push_service - builds_email_service +- pipelines_email_service - irker_service - pivotaltracker_service - hipchat_service @@ -184,4 +185,4 @@ project: - project_feature award_emoji: - awardable -- user \ No newline at end of file +- user -- cgit v1.2.1 From 45bfadbcbf0eec5bf7c691b13751f684e3c62c5c Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 30 Sep 2016 11:53:44 -0300 Subject: Fix bug when trying to cache closed issues from external issue trackers --- spec/models/merge_request_spec.rb | 24 +++++++++++++++ spec/services/merge_requests/merge_service_spec.rb | 36 ++++++++++++++++++++++ 2 files changed, 60 insertions(+) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 9d7be2429ed..556b4c1efc3 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -86,6 +86,30 @@ describe MergeRequest, models: true do end end + describe '#cache_merge_request_closes_issues!' do + before do + subject.project.team << [subject.author, :developer] + subject.target_branch = subject.project.default_branch + end + + it 'caches closed issues' do + issue = create :issue, project: subject.project + commit = double('commit1', safe_message: "Fixes #{issue.to_reference}") + allow(subject).to receive(:commits).and_return([commit]) + + expect { subject.cache_merge_request_closes_issues! }.to change(subject.merge_requests_closing_issues, :count).by(1) + end + + it 'does not cache issues from external trackers' do + subject.project.update_attribute(:has_external_issue_tracker, true) + issue = ExternalIssue.new('JIRA-123', subject.project) + commit = double('commit1', safe_message: "Fixes #{issue.to_reference}") + allow(subject).to receive(:commits).and_return([commit]) + + expect { subject.cache_merge_request_closes_issues! }.not_to change(subject.merge_requests_closing_issues, :count) + end + end + describe '#source_branch_sha' do let(:last_branch_commit) { subject.source_project.repository.commit(subject.source_branch) } diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 31167675d07..e49a0d5e553 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -38,6 +38,42 @@ describe MergeRequests::MergeService, services: true do end end + context 'closes related issues' do + let(:service) { described_class.new(project, user, commit_message: 'Awesome message') } + + before do + allow(project).to receive(:default_branch).and_return(merge_request.target_branch) + end + + it 'closes GitLab issue tracker issues' do + issue = create :issue, project: project + commit = double('commit', safe_message: "Fixes #{issue.to_reference}") + allow(merge_request).to receive(:commits).and_return([commit]) + + service.execute(merge_request) + + expect(issue.reload.closed?).to be_truthy + end + + context 'with JIRA integration' do + include JiraServiceHelper + + let(:jira_tracker) { project.create_jira_service } + + before { jira_service_settings } + + it 'closes issues on JIRA issue tracker' do + jira_issue = ExternalIssue.new('JIRA-123', project) + commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}") + allow(merge_request).to receive(:commits).and_return([commit]) + + expect_any_instance_of(JiraService).to receive(:close_issue).with(merge_request, jira_issue).once + + service.execute(merge_request) + end + end + end + context 'closes related todos' do let(:merge_request) { create(:merge_request, assignee: user, author: user) } let(:project) { merge_request.project } -- cgit v1.2.1 From 901c994b7a4481437f8fe91583d2ed3f19e4775e Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 3 Oct 2016 15:39:12 +0200 Subject: deployment refs in own folder, new method for creating refs --- spec/models/repository_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index db29f4d353b..98c64c079b9 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -320,6 +320,16 @@ describe Repository, models: true do end end + describe '#create_ref' do + it 'redirects the call to fetch_ref' do + ref, ref_path = '1', '2' + + expect(repository).to receive(:fetch_ref).with(repository.path_to_repo, ref, ref_path) + + repository.create_ref(ref, ref_path) + end + end + describe "#changelog" do before do repository.send(:cache).expire(:changelog) -- cgit v1.2.1 From 912d7f7b68d5c75d801299a8c9363a257030e142 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 4 Oct 2016 10:01:32 +0200 Subject: Fix issues importing services via Import/Export --- spec/models/service_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'spec') diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 05056a4bb47..ed1bc9271ae 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -203,6 +203,23 @@ describe Service, models: true do end end + describe 'initialize service with no properties' do + let(:service) do + GitlabIssueTrackerService.create( + project: create(:project), + title: 'random title' + ) + end + + it 'does not raise error' do + expect { service }.not_to raise_error + end + + it 'creates the properties' do + expect(service.properties).to eq({ "title" => "random title" }) + end + end + describe "callbacks" do let(:project) { create(:project) } let!(:service) do -- cgit v1.2.1 From 4ff345c488c993e9f67f34ad271bc98a1f3ffa61 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Thu, 29 Sep 2016 16:28:45 +0200 Subject: Simplify Mentionable concern instance methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We remove some arguments that are rarely used or used just to simplify setups on specs. Modified Mentionable#create_new_cross_references method we don’t need to calculate previous references to avoid the duplication because we do that at database level when creating references extracted from the current entity state. MergeRequests won’t create cross_references for commits that are included so we change a spec to use a different merge request to make references to commits to other branches --- spec/models/concerns/mentionable_spec.rb | 22 +++++++++++++++------- spec/models/merge_request_spec.rb | 2 +- spec/support/mentionable_shared_examples.rb | 4 +++- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb index 549b0042038..132858950d5 100644 --- a/spec/models/concerns/mentionable_spec.rb +++ b/spec/models/concerns/mentionable_spec.rb @@ -1,18 +1,27 @@ require 'spec_helper' describe Mentionable do - include Mentionable + class Example + include Mentionable - def author - nil + attr_accessor :project, :message + attr_mentionable :message + + def author + nil + end end describe 'references' do let(:project) { create(:project) } + let(:mentionable) { Example.new } it 'excludes JIRA references' do allow(project).to receive_messages(jira_tracker?: true) - expect(referenced_mentionables(project, 'JIRA-123')).to be_empty + + mentionable.project = project + mentionable.message = 'JIRA-123' + expect(mentionable.referenced_mentionables).to be_empty end end end @@ -39,9 +48,8 @@ describe Issue, "Mentionable" do let(:user) { create(:user) } def referenced_issues(current_user) - text = "#{private_issue.to_reference(project)} and #{public_issue.to_reference}" - - issue.referenced_mentionables(current_user, text) + issue.title = "#{private_issue.to_reference(project)} and #{public_issue.to_reference}" + issue.referenced_mentionables(current_user) end context 'when the current user can see the issue' do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 9d7be2429ed..c29364466f0 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -522,7 +522,7 @@ describe MergeRequest, models: true do end it_behaves_like 'an editable mentionable' do - subject { create(:merge_request) } + subject { create(:merge_request, :simple) } let(:backref_text) { "merge request #{subject.to_reference}" } let(:set_mentionable_text) { ->(txt){ subject.description = txt } } diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb index e876d44c166..f57c82809a6 100644 --- a/spec/support/mentionable_shared_examples.rb +++ b/spec/support/mentionable_shared_examples.rb @@ -9,7 +9,7 @@ shared_context 'mentionable context' do let(:author) { subject.author } let(:mentioned_issue) { create(:issue, project: project) } - let!(:mentioned_mr) { create(:merge_request, :simple, source_project: project) } + let!(:mentioned_mr) { create(:merge_request, source_project: project) } let(:mentioned_commit) { project.commit("HEAD~1") } let(:ext_proj) { create(:project, :public) } @@ -100,6 +100,7 @@ shared_examples 'an editable mentionable' do it 'creates new cross-reference notes when the mentionable text is edited' do subject.save + subject.create_cross_references! new_text = <<-MSG.strip_heredoc These references already existed: @@ -131,6 +132,7 @@ shared_examples 'an editable mentionable' do end # These two issues are new and should receive reference notes + # In the case of MergeRequests remember that cannot mention commits included in the MergeRequest new_issues.each do |newref| expect(SystemNoteService).to receive(:cross_reference). with(newref, subject.local_reference, author) -- cgit v1.2.1 From ebeee31100cb142dfc74ec02928d3c5433eab8d7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 3 Oct 2016 16:32:12 +0200 Subject: Fix pipeline fixtures and calls to removed method --- spec/features/projects/badges/coverage_spec.rb | 2 +- spec/lib/gitlab/badge/coverage/report_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb index 5972e7f31c2..01a95bf49ac 100644 --- a/spec/features/projects/badges/coverage_spec.rb +++ b/spec/features/projects/badges/coverage_spec.rb @@ -59,7 +59,7 @@ feature 'test coverage badge' do create(:ci_pipeline, opts).tap do |pipeline| yield pipeline - pipeline.build_updated + pipeline.update_status end end diff --git a/spec/lib/gitlab/badge/coverage/report_spec.rb b/spec/lib/gitlab/badge/coverage/report_spec.rb index ab0cce6e091..1547bd3228c 100644 --- a/spec/lib/gitlab/badge/coverage/report_spec.rb +++ b/spec/lib/gitlab/badge/coverage/report_spec.rb @@ -100,7 +100,7 @@ describe Gitlab::Badge::Coverage::Report do create(:ci_pipeline, opts).tap do |pipeline| yield pipeline - pipeline.build_updated + pipeline.update_status end end end -- cgit v1.2.1 From 5ce5abdc1dc53e97cff88f5abfe0edd10211bf9c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 4 Oct 2016 12:30:57 +0200 Subject: Fix hipchat service specs after changes in pipeline --- spec/models/project_services/hipchat_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index cf713684463..26dd95bdfec 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -283,7 +283,7 @@ describe HipchatService, models: true do context 'build events' do let(:pipeline) { create(:ci_empty_pipeline) } let(:build) { create(:ci_build, pipeline: pipeline) } - let(:data) { Gitlab::DataBuilder::Build.build(build) } + let(:data) { Gitlab::DataBuilder::Build.build(build.reload) } context 'for failed' do before { build.drop } -- cgit v1.2.1 From 4e4640b10bfae9bfa1da265775ede57ea72c358c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 4 Oct 2016 13:27:48 +0200 Subject: Add specs for new async ci pipeline workers --- spec/workers/process_pipeline_worker_spec.rb | 22 ++++++++++++++++++++++ spec/workers/update_pipeline_worker_spec.rb | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 spec/workers/process_pipeline_worker_spec.rb create mode 100644 spec/workers/update_pipeline_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/process_pipeline_worker_spec.rb b/spec/workers/process_pipeline_worker_spec.rb new file mode 100644 index 00000000000..7b5f98d5763 --- /dev/null +++ b/spec/workers/process_pipeline_worker_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe ProcessPipelineWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline) } + + it 'processes pipeline' do + expect_any_instance_of(Ci::Pipeline).to receive(:process!) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end diff --git a/spec/workers/update_pipeline_worker_spec.rb b/spec/workers/update_pipeline_worker_spec.rb new file mode 100644 index 00000000000..fadc42b22f0 --- /dev/null +++ b/spec/workers/update_pipeline_worker_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe UpdatePipelineWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline) } + + it 'updates pipeline status' do + expect_any_instance_of(Ci::Pipeline).to receive(:update_status) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 138e26b1fad6730aa048b8cc91f92a597e323162 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 4 Oct 2016 14:06:44 +0100 Subject: Adds v-pre to code blocks in comments Closes #22911 --- spec/features/notes_on_merge_requests_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index f1c522155d3..5d7247e2a62 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -240,6 +240,18 @@ describe 'Comments', feature: true do is_expected.to have_css('.notes_holder .note', count: 1) is_expected.to have_button('Reply...') end + + it 'adds code to discussion' do + click_button 'Reply...' + + page.within(first('.js-discussion-note-form')) do + fill_in 'note[note]', with: '```{{ test }}```' + + click_button('Comment') + end + + expect(page).to have_content('{{ test }}') + end end end end -- cgit v1.2.1 From 194fbc3c3d4b068f191fca75488b986df88c5333 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 2 Sep 2016 14:30:19 +0100 Subject: Restrict failed login attempts for users with 2FA Copy logic from `Devise::Models::Lockable#valid_for_authentication?`, as our custom login flow with two pages doesn't call this method. This will increment the failed login counter, and lock the user's account once they exceed the number of failed attempts. Also ensure that users who are locked can't continue to submit 2FA codes. --- spec/controllers/sessions_controller_spec.rb | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'spec') diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 8f27e616c3e..48d69377461 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -109,6 +109,44 @@ describe SessionsController do end end + context 'when the user is on their last attempt' do + before do + user.update(failed_attempts: User.maximum_attempts.pred) + end + + context 'when OTP is valid' do + it 'authenticates correctly' do + authenticate_2fa(otp_attempt: user.current_otp) + + expect(subject.current_user).to eq user + end + end + + context 'when OTP is invalid' do + before { authenticate_2fa(otp_attempt: 'invalid') } + + it 'does not authenticate' do + expect(subject.current_user).not_to eq user + end + + it 'warns about invalid login' do + expect(response).to set_flash.now[:alert] + .to /Invalid Login or password/ + end + + it 'locks the user' do + expect(user.reload).to be_access_locked + end + + it 'keeps the user locked on future login attempts' do + post(:create, user: { login: user.username, password: user.password }) + + expect(response) + .to set_flash.now[:alert].to /Invalid Login or password/ + end + end + end + context 'when another user does not have 2FA enabled' do let(:another_user) { create(:user) } -- cgit v1.2.1 From f377f82651998dc56301cc6540867b5120da43f2 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 4 Oct 2016 16:13:55 +0100 Subject: Fixed banzai test failures --- spec/lib/banzai/filter/syntax_highlight_filter_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb index b1370bca833..d265d29ee86 100644 --- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb +++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb @@ -6,21 +6,21 @@ describe Banzai::Filter::SyntaxHighlightFilter, lib: true do context "when no language is specified" do it "highlights as plaintext" do result = filter('
    def fun end
    ') - expect(result.to_html).to eq('
    def fun end
    ') + expect(result.to_html).to eq('
    def fun end
    ') end end context "when a valid language is specified" do it "highlights as that language" do result = filter('
    def fun end
    ') - expect(result.to_html).to eq('
    def fun end
    ') + expect(result.to_html).to eq('
    def fun end
    ') end end context "when an invalid language is specified" do it "highlights as plaintext" do result = filter('
    This is a test
    ') - expect(result.to_html).to eq('
    This is a test
    ') + expect(result.to_html).to eq('
    This is a test
    ') end end @@ -31,7 +31,7 @@ describe Banzai::Filter::SyntaxHighlightFilter, lib: true do it "highlights as plaintext" do result = filter('
    This is a test
    ') - expect(result.to_html).to eq('
    This is a test
    ') + expect(result.to_html).to eq('
    This is a test
    ') end end end -- cgit v1.2.1 From b5f954177825fbea9245149805541cffb2e0de05 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 4 Oct 2016 02:40:03 -0300 Subject: Skip wiki creation when GitHub project has wiki enabled If the GitHub project repository has wiki, we should not create the default wiki. Otherwise the GitHub importer will fail because the wiki repository already exist. This bug was introduced here https://gitlab.com/gitlab-org/gitlab-ce/commit/892dea67717c0efbd6a28f763 9f34535ec0a8747 --- .../gitlab/github_import/project_creator_spec.rb | 24 ++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/project_creator_spec.rb b/spec/lib/gitlab/github_import/project_creator_spec.rb index ab06b7bc5bb..a73b1f4ff5d 100644 --- a/spec/lib/gitlab/github_import/project_creator_spec.rb +++ b/spec/lib/gitlab/github_import/project_creator_spec.rb @@ -33,7 +33,7 @@ describe Gitlab::GithubImport::ProjectCreator, lib: true do expect(project.import_data.credentials).to eq(user: 'asdffg', password: nil) end - context 'when Github project is private' do + context 'when GitHub project is private' do it 'sets project visibility to private' do repo.private = true @@ -43,7 +43,7 @@ describe Gitlab::GithubImport::ProjectCreator, lib: true do end end - context 'when Github project is public' do + context 'when GitHub project is public' do before do allow_any_instance_of(ApplicationSetting).to receive(:default_project_visibility).and_return(Gitlab::VisibilityLevel::INTERNAL) end @@ -56,5 +56,25 @@ describe Gitlab::GithubImport::ProjectCreator, lib: true do expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL) end end + + context 'when GitHub project has wiki' do + it 'does not create the wiki repository' do + allow(repo).to receive(:has_wiki?).and_return(true) + + project = service.execute + + expect(project.wiki.repository_exists?).to eq false + end + end + + context 'when GitHub project does not have wiki' do + it 'creates the wiki repository' do + allow(repo).to receive(:has_wiki?).and_return(false) + + project = service.execute + + expect(project.wiki.repository_exists?).to eq true + end + end end end -- cgit v1.2.1 From e956a24dfd45baaafe93a520df61015bba40a4da Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 23 Aug 2016 15:23:56 -0400 Subject: api: add /projects/visible API endpoint FIxes #19361, #3119. --- spec/requests/api/projects_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 4a0d727faea..5bf8b64b84b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -175,6 +175,17 @@ describe API::API, api: true do end end + describe 'GET /projects/visible' do + let(:public_project) { create(:project, :public) } + + it 'returns the projects viewable by the user' do + get api('/projects/visible', user3) + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.map { |project| project['id'] }).to contain_exactly(project.id, project2.id, project4.id) + end + end + describe 'GET /projects/starred' do let(:public_project) { create(:project, :public) } -- cgit v1.2.1 From 706737a004b67303f15ccbd1f8630b0d80f481e9 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 4 Oct 2016 13:21:26 +0200 Subject: Exclude system notes from Project.trending Having many system notes isn't really an indication of a project being trending. Including these notes would lead to projects with lots of commit cross references (for example) showing up in the trending projects list. --- spec/models/project_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index ef854a25321..1a316176f63 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -826,6 +826,14 @@ describe Project, models: true do expect(subject).to eq([project2, project1]) end end + + it 'does not take system notes into account' do + 10.times do + create(:note_on_commit, project: project2, system: true) + end + + expect(described_class.trending.to_a).to eq([project1, project2]) + end end describe '.visible_to_user' do -- cgit v1.2.1 From 42cb659726822d500086ce09f712b858228f4caa Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 4 Oct 2016 17:46:08 +0100 Subject: Update API docs and specs for /projects/visible --- spec/requests/api/projects_spec.rb | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5bf8b64b84b..fafceb6ecfa 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -178,11 +178,30 @@ describe API::API, api: true do describe 'GET /projects/visible' do let(:public_project) { create(:project, :public) } + before do + public_project + project + project2 + project3 + project4 + end + it 'returns the projects viewable by the user' do - get api('/projects/visible', user3) + get api('/projects/visible', user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.map { |project| project['id'] }). + to contain_exactly(public_project.id, project.id, project2.id, project3.id) + end + + it 'shows only public projects when the user only has access to those' do + get api('/projects/visible', user2) + expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.map { |project| project['id'] }).to contain_exactly(project.id, project2.id, project4.id) + expect(json_response.map { |project| project['id'] }). + to contain_exactly(public_project.id) end end -- cgit v1.2.1 From c9bcfc631a79db97203d51d7c221a7549ba65adf Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 4 Oct 2016 17:22:58 +0200 Subject: Remove lease from Event#reset_project_activity Per GitLab.com's performance metrics this method could take up to 5 seconds of wall time to complete, while only taking 1-2 milliseconds of CPU time. Removing the Redis lease in favour of conditional updates allows us to work around this. A slight drawback is that this allows for multiple threads/processes to try and update the same row. However, only a single thread/process will ever win since the UPDATE query uses a WHERE condition to only update rows that were not updated in the last hour. Fixes gitlab-org/gitlab-ce#22473 --- spec/models/event_spec.rb | 8 +++----- spec/models/project_spec.rb | 4 +--- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 8600eb4d2c4..af5002487cc 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -173,13 +173,11 @@ describe Event, models: true do it 'updates the project' do project.update(last_activity_at: 1.year.ago) - expect_any_instance_of(Gitlab::ExclusiveLease). - to receive(:try_obtain).and_return(true) + create_event(project, project.owner) - expect(project).to receive(:update_column). - with(:last_activity_at, a_kind_of(Time)) + project.reload - create_event(project, project.owner) + project.last_activity_at <= 1.minute.ago end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index ef854a25321..3ab5ac78bba 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -308,8 +308,7 @@ describe Project, models: true do end describe 'last_activity methods' do - let(:timestamp) { Time.now - 2.hours } - let(:project) { create(:project, created_at: timestamp, updated_at: timestamp) } + let(:project) { create(:project, last_activity_at: 2.hours.ago) } describe 'last_activity' do it 'alias last_activity to last_event' do @@ -321,7 +320,6 @@ describe Project, models: true do describe 'last_activity_date' do it 'returns the creation date of the project\'s last event if present' do - expect_any_instance_of(Event).to receive(:try_obtain_lease).and_return(true) new_event = create(:event, project: project, created_at: Time.now) expect(project.last_activity_at.to_i).to eq(new_event.created_at.to_i) -- cgit v1.2.1 From fea80aa12d6a0b55513e497b2b8e5d0aa86a7d76 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 4 Oct 2016 20:53:15 -0700 Subject: Fix project deletion when feature visibility is set to private Projects that are destroyed are put in the pending_delete state. The ProjectDestroyWorker checks whether the current user has access, but since the ProjectFeature class uses the default scope of the Project, it will not be able to find the right project. This was a regression in 8.12 that caused the following stack trace: ``` NoMethodError: undefined method `team' for nil:NilClass from app/models/project_feature.rb:62:in `get_permission' from app/models/project_feature.rb:34:in `feature_available?' from app/models/project.rb:21:in `feature_available?' from app/policies/project_policy.rb:170:in `disabled_features!' from app/policies/project_policy.rb:29:in `rules' from app/policies/base_policy.rb:82:in `block in abilities' from app/policies/base_policy.rb:113:in `collect_rules' from app/policies/base_policy.rb:82:in `abilities' from app/policies/base_policy.rb:50:in `abilities' from app/models/ability.rb:64:in `uncached_allowed' from app/models/ability.rb:58:in `allowed' from app/models/ability.rb:49:in `allowed?' from app/services/base_service.rb:11:in `can?' from lib/gitlab/metrics/instrumentation.rb:155:in `block in can?' from lib/gitlab/metrics/method_call.rb:23:in `measure' from lib/gitlab/metrics/instrumentation.rb:155:in `can?' from app/services/projects/destroy_service.rb:18:in `execute' ``` Closes #22948 --- spec/services/projects/destroy_service_spec.rb | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index 29341c5e57e..7dcd03496bb 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -5,6 +5,7 @@ describe Projects::DestroyService, services: true do let!(:project) { create(:project, namespace: user.namespace) } let!(:path) { project.repository.path_to_repo } let!(:remove_path) { path.sub(/\.git\Z/, "+#{project.id}+deleted.git") } + let!(:async) { false } # execute or async_execute context 'Sidekiq inline' do before do @@ -28,6 +29,22 @@ describe Projects::DestroyService, services: true do it { expect(Dir.exist?(remove_path)).to be_truthy } end + context 'async delete of project with private issue visibility' do + let!(:async) { true } + + before do + project.project_feature.update_attribute("issues_access_level", ProjectFeature::PRIVATE) + # Run sidekiq immediately to check that renamed repository will be removed + Sidekiq::Testing.inline! { destroy_project(project, user, {}) } + end + + it 'deletes the project' do + expect(Project.all).not_to include(project) + expect(Dir.exist?(path)).to be_falsey + expect(Dir.exist?(remove_path)).to be_falsey + end + end + context 'container registry' do before do stub_container_registry_config(enabled: true) @@ -52,6 +69,10 @@ describe Projects::DestroyService, services: true do end def destroy_project(project, user, params) - Projects::DestroyService.new(project, user, params).execute + if async + Projects::DestroyService.new(project, user, params).async_execute + else + Projects::DestroyService.new(project, user, params).execute + end end end -- cgit v1.2.1 From 35ced4dae480d61ddc4d73eb4695626ecc419e9c Mon Sep 17 00:00:00 2001 From: barthc Date: Thu, 1 Sep 2016 18:23:39 +0100 Subject: fix group links 404 --- .../projects/group_links_controller_spec.rb | 37 +++++++++++++++++++++- spec/requests/api/groups_spec.rb | 10 ++++++ 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb index fbe8758dda7..b9d9117c928 100644 --- a/spec/controllers/projects/group_links_controller_spec.rb +++ b/spec/controllers/projects/group_links_controller_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' describe Projects::GroupLinksController do - let(:project) { create(:project, :private) } let(:group) { create(:group, :private) } + let(:group2) { create(:group, :private) } + let(:project) { create(:project, :private, group: group2) } let(:user) { create(:user) } before do @@ -46,5 +47,39 @@ describe Projects::GroupLinksController do expect(group.shared_projects).not_to include project end end + + context 'when project group id equal link group id' do + before do + post(:create, namespace_id: project.namespace.to_param, + project_id: project.to_param, + link_group_id: group2.id, + link_group_access: ProjectGroupLink.default_access) + end + + it 'does not share project with selected group' do + expect(group2.shared_projects).not_to include project + end + + it 'redirects to project group links page' do + expect(response).to redirect_to( + namespace_project_group_links_path(project.namespace, project) + ) + end + end + + context 'when link group id is not present' do + before do + post(:create, namespace_id: project.namespace.to_param, + project_id: project.to_param, + link_group_access: ProjectGroupLink.default_access) + end + + it 'redirects to project group links page' do + expect(response).to redirect_to( + namespace_project_group_links_path(project.namespace, project) + ) + expect(flash[:alert]).to eq('Please select a group.') + end + end end end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 1f68ef1af8f..3ba257256a0 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -45,6 +45,16 @@ describe API::API, api: true do expect(json_response.length).to eq(2) end end + + context "when using skip_groups in request" do + it "returns all groups excluding skipped groups" do + get api("/groups", admin), skip_groups: [group2.id] + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + end + end end describe "GET /groups/:id" do -- cgit v1.2.1 From 84b7dd763bd6a9a55b2a59039c57af588cc2519f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 29 Jul 2016 16:02:35 +0200 Subject: Use Grape DSL to document methods and their params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/members_spec.rb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index 92032f09b17..d22e0595788 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -97,7 +97,10 @@ describe API::Members, api: true do shared_examples 'POST /:sources/:id/members' do |source_type| context "with :sources == #{source_type.pluralize}" do it_behaves_like 'a 404 response when source is private' do - let(:route) { post api("/#{source_type.pluralize}/#{source.id}/members", stranger) } + let(:route) do + post api("/#{source_type.pluralize}/#{source.id}/members", stranger), + user_id: access_requester.id, access_level: Member::MASTER + end end context 'when authenticated as a non-member or member with insufficient rights' do @@ -105,7 +108,8 @@ describe API::Members, api: true do context "as a #{type}" do it 'returns 403' do user = public_send(type) - post api("/#{source_type.pluralize}/#{source.id}/members", user) + post api("/#{source_type.pluralize}/#{source.id}/members", user), + user_id: access_requester.id, access_level: Member::MASTER expect(response).to have_http_status(403) end @@ -174,7 +178,10 @@ describe API::Members, api: true do shared_examples 'PUT /:sources/:id/members/:user_id' do |source_type| context "with :sources == #{source_type.pluralize}" do it_behaves_like 'a 404 response when source is private' do - let(:route) { put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger) } + let(:route) do + put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", stranger), + access_level: Member::MASTER + end end context 'when authenticated as a non-member or member with insufficient rights' do @@ -182,7 +189,8 @@ describe API::Members, api: true do context "as a #{type}" do it 'returns 403' do user = public_send(type) - put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user) + put api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", user), + access_level: Member::MASTER expect(response).to have_http_status(403) end -- cgit v1.2.1 From 47217666194d5767cab4e5c7ba3e0aaaae10f943 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 27 Sep 2016 12:47:58 +0200 Subject: Fix test for SearchAutocomplete. --- spec/javascripts/search_autocomplete_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index 00d9fc1302a..4470fbcb099 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -112,7 +112,7 @@ fixture.preload('search_autocomplete.html'); beforeEach(function() { fixture.load('search_autocomplete.html'); - return widget = new SearchAutocomplete; + return widget = new gl.SearchAutocomplete; }); it('should show Dashboard specific dropdown menu', function() { var list; -- cgit v1.2.1 From f11ebb9556612f663264868a24ee8b774babda32 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 5 Oct 2016 18:08:16 +0800 Subject: Add a view test for showing source commits --- .../merge_requests/_commits.html.haml_spec.rb | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/views/projects/merge_requests/_commits.html.haml_spec.rb (limited to 'spec') diff --git a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb new file mode 100644 index 00000000000..6f70b3daf8e --- /dev/null +++ b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe 'projects/merge_requests/show/_commits.html.haml' do + include Devise::Test::ControllerHelpers + + let(:user) { create(:user) } + let(:target_project) { create(:project) } + + let(:source_project) do + create(:project, forked_from_project: target_project) + end + + let(:merge_request) do + create(:merge_request, :simple, + source_project: source_project, + target_project: target_project, + author: user) + end + + before do + controller.prepend_view_path('app/views/projects') + + assign(:merge_request, merge_request) + assign(:commits, merge_request.commits) + end + + it 'shows commits from source project' do + render + + commit = source_project.commit(merge_request.source_branch) + href = namespace_project_commit_path( + source_project.namespace, + source_project, + commit) + + expect(rendered).to have_link(Commit.truncate_sha(commit.sha), href: href) + end +end -- cgit v1.2.1 From 16ed9b6129daf51a296d4576580c5f232d043db6 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 4 Oct 2016 18:03:10 +0200 Subject: Refactor Gitlab::Identifier This refactors Gitlab::Identifier so it uses fewer queries and is actually tested. Queries are reduced by caching the output as well as using 1 query (instead of 2) to find a user using an SSH key. --- spec/lib/gitlab/identifier_spec.rb | 123 +++++++++++++++++++++++++++++++++++++ spec/models/user_spec.rb | 17 +++++ spec/workers/post_receive_spec.rb | 4 +- 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 spec/lib/gitlab/identifier_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/identifier_spec.rb b/spec/lib/gitlab/identifier_spec.rb new file mode 100644 index 00000000000..47d6f1007d1 --- /dev/null +++ b/spec/lib/gitlab/identifier_spec.rb @@ -0,0 +1,123 @@ +require 'spec_helper' + +describe Gitlab::Identifier do + let(:identifier) do + Class.new { include Gitlab::Identifier }.new + end + + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:key) { create(:key, user: user) } + + describe '#identify' do + context 'without an identifier' do + it 'identifies the user using a commit' do + expect(identifier).to receive(:identify_using_commit). + with(project, '123') + + identifier.identify('', project, '123') + end + end + + context 'with a user identifier' do + it 'identifies the user using a user ID' do + expect(identifier).to receive(:identify_using_user). + with("user-#{user.id}") + + identifier.identify("user-#{user.id}", project, '123') + end + end + + context 'with an SSH key identifier' do + it 'identifies the user using an SSH key ID' do + expect(identifier).to receive(:identify_using_ssh_key). + with("key-#{key.id}") + + identifier.identify("key-#{key.id}", project, '123') + end + end + end + + describe '#identify_using_commit' do + it "returns the User for an existing commit author's Email address" do + commit = double(:commit, author_email: user.email) + + expect(project).to receive(:commit).with('123').and_return(commit) + + expect(identifier.identify_using_commit(project, '123')).to eq(user) + end + + it 'returns nil when no user could be found' do + allow(project).to receive(:commit).with('123').and_return(nil) + + expect(identifier.identify_using_commit(project, '123')).to be_nil + end + + it 'returns nil when the commit does not have an author Email' do + commit = double(:commit, author_email: nil) + + expect(project).to receive(:commit).with('123').and_return(commit) + + expect(identifier.identify_using_commit(project, '123')).to be_nil + end + + it 'caches the found users per Email' do + commit = double(:commit, author_email: user.email) + + expect(project).to receive(:commit).with('123').twice.and_return(commit) + expect(User).to receive(:find_by).once.and_call_original + + 2.times do + expect(identifier.identify_using_commit(project, '123')).to eq(user) + end + end + end + + describe '#identify_using_user' do + it 'returns the User for an existing ID in the identifier' do + found = identifier.identify_using_user("user-#{user.id}") + + expect(found).to eq(user) + end + + it 'returns nil for a non existing user ID' do + found = identifier.identify_using_user('user--1') + + expect(found).to be_nil + end + + it 'caches the found users per ID' do + expect(User).to receive(:find_by).once.and_call_original + + 2.times do + found = identifier.identify_using_user("user-#{user.id}") + + expect(found).to eq(user) + end + end + end + + describe '#identify_using_ssh_key' do + it 'returns the User for an existing SSH key' do + found = identifier.identify_using_ssh_key("key-#{key.id}") + + expect(found).to eq(user) + end + + it 'returns nil for an invalid SSH key' do + found = identifier.identify_using_ssh_key('key--1') + + expect(found).to be_nil + end + + it 'caches the found users per key' do + expect(User).to receive(:find_by_ssh_key_id).once.and_call_original + + 2.times do + found = identifier.identify_using_ssh_key("key-#{key.id}") + + expect(found).to eq(user) + end + end + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a1770d96f83..65b2896930a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -610,6 +610,23 @@ describe User, models: true do end end + describe '.find_by_ssh_key_id' do + context 'using an existing SSH key ID' do + let(:user) { create(:user) } + let(:key) { create(:key, user: user) } + + it 'returns the corresponding User' do + expect(described_class.find_by_ssh_key_id(key.id)).to eq(user) + end + end + + context 'using an invalid SSH key ID' do + it 'returns nil' do + expect(described_class.find_by_ssh_key_id(-1)).to be_nil + end + end + end + describe '.by_login' do let(:username) { 'John' } let!(:user) { create(:user, username: username) } diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 1d2cf7acddd..ffeaafe654a 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -79,7 +79,9 @@ describe PostReceive do end it "does not run if the author is not in the project" do - allow(Key).to receive(:find_by).with(hash_including(id: anything())) { nil } + allow_any_instance_of(Gitlab::GitPostReceive). + to receive(:identify_using_ssh_key). + and_return(nil) expect(project).not_to receive(:execute_hooks) -- cgit v1.2.1 From 154253cab55491d54dfe264fa946acb9c399398a Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 4 Oct 2016 14:09:54 +0200 Subject: Refactor TrendingProjectsFinder to support caching == Public Projects This finder class now _only_ returns public projects. Previously this finder would also return private and internal projects. Including these projects makes caching data much harder and less efficient. Meanwhile including this data isn't very useful as very few users would be interested in seeing projects they have access to as trending. That is, the feature is more useful when you want to see what _other_ popular projects there are. == Caching The data returned by TrendingProjectsFinder is now cached for a day based on the number of months the data should be restricted to. The cache is not flushed explicitly, instead it's rebuilt whenever it expires. == Timings To measure the impact I changed the finder code to use the last 24 months instead of the last month. I then executed and measured 10 requests to the explore page. On the current "master" branch (commit 88fa5916ffa0aea491cd339272ed7437c3f52dc7) this would take an average of 2.43 seconds. Using the changes of this commit this was reduced to around 1.7 seconds. Fixes gitlab-org/gitlab-ce#22164 --- spec/finders/trending_projects_finder_spec.rb | 53 ++++++++++++++++----------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'spec') diff --git a/spec/finders/trending_projects_finder_spec.rb b/spec/finders/trending_projects_finder_spec.rb index a49cbfd5160..cfe15b9defa 100644 --- a/spec/finders/trending_projects_finder_spec.rb +++ b/spec/finders/trending_projects_finder_spec.rb @@ -1,39 +1,48 @@ require 'spec_helper' describe TrendingProjectsFinder do - let(:user) { build(:user) } + let(:user) { create(:user) } + let(:public_project1) { create(:empty_project, :public) } + let(:public_project2) { create(:empty_project, :public) } + let(:private_project) { create(:empty_project, :private) } + let(:internal_project) { create(:empty_project, :internal) } + + before do + 3.times do + create(:note_on_commit, project: public_project1) + end - describe '#execute' do - describe 'without an explicit start date' do - subject { described_class.new } + 2.times do + create(:note_on_commit, project: public_project2, created_at: 5.weeks.ago) + end - it 'returns the trending projects' do - relation = double(:ar_relation) + create(:note_on_commit, project: private_project) + create(:note_on_commit, project: internal_project) + end - allow(subject).to receive(:projects_for) - .with(user) - .and_return(relation) + describe '#execute', caching: true do + context 'without an explicit time range' do + it 'returns public trending projects' do + projects = described_class.new.execute - allow(relation).to receive(:trending) - .with(an_instance_of(ActiveSupport::TimeWithZone)) + expect(projects).to eq([public_project1]) end end - describe 'with an explicit start date' do - let(:date) { 2.months.ago } + context 'with an explicit time range' do + it 'returns public trending projects' do + projects = described_class.new.execute(2) - subject { described_class.new } + expect(projects).to eq([public_project1, public_project2]) + end + end - it 'returns the trending projects' do - relation = double(:ar_relation) + it 'caches the list of projects' do + projects = described_class.new - allow(subject).to receive(:projects_for) - .with(user) - .and_return(relation) + expect(Project).to receive(:trending).once - allow(relation).to receive(:trending) - .with(date) - end + 2.times { projects.execute } end end end -- cgit v1.2.1 From 41d70ea300efb73a05f4753ddd3e0c3730e96e0a Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 3 Oct 2016 00:12:59 -0300 Subject: Added Issue Board API support - Includes documentation and tests --- spec/requests/api/boards_spec.rb | 192 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 spec/requests/api/boards_spec.rb (limited to 'spec') diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb new file mode 100644 index 00000000000..f4b04445c6c --- /dev/null +++ b/spec/requests/api/boards_spec.rb @@ -0,0 +1,192 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:non_member) { create(:user) } + let(:guest) { create(:user) } + let(:admin) { create(:user, :admin) } + let!(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) } + + let!(:dev_label) do + create(:label, title: 'Development', color: '#FFAABB', project: project) + end + + let!(:test_label) do + create(:label, title: 'Testing', color: '#FFAACC', project: project) + end + + let!(:ux_label) do + create(:label, title: 'UX', color: '#FF0000', project: project) + end + + let!(:dev_list) do + create(:list, label: dev_label, position: 1) + end + + let!(:test_list) do + create(:list, label: test_label, position: 2) + end + + let!(:board) do + create(:board, project: project, lists: [dev_list, test_list]) + end + + before do + project.team << [user, :reporter] + project.team << [guest, :guest] + end + + describe "GET /projects/:id/boards" do + let(:base_url) { "/projects/#{project.id}/boards" } + + context "when unauthenticated" do + it "returns authentication error" do + get api(base_url) + + expect(response).to have_http_status(401) + end + end + + context "when authenticated" do + it "returns the project issue board" do + get api(base_url, user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(board.id) + expect(json_response.first['lists']).to be_an Array + expect(json_response.first['lists'].length).to eq(2) + expect(json_response.first['lists'].last).to have_key('position') + end + end + end + + describe "GET /projects/:id/boards/:board_id/lists" do + let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" } + + it 'returns issue board lists' do + get api(base_url, user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + expect(json_response.first['label']['name']).to eq(dev_label.title) + end + + it 'returns 404 if board not found' do + get api("/projects/#{project.id}/boards/22343/lists", user) + + expect(response).to have_http_status(404) + end + end + + describe "GET /projects/:id/boards/:board_id/lists/:list_id" do + let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" } + + it 'returns a list' do + get api("#{base_url}/#{dev_list.id}", user) + + expect(response).to have_http_status(200) + expect(json_response['id']).to eq(dev_list.id) + expect(json_response['label']['name']).to eq(dev_label.title) + expect(json_response['position']).to eq(1) + end + + it 'returns 404 if list not found' do + get api("#{base_url}/5324", user) + + expect(response).to have_http_status(404) + end + end + + describe "POST /projects/:id/board/lists" do + let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" } + + it 'creates a new issue board list' do + post api(base_url, user), + label_id: ux_label.id + + expect(response).to have_http_status(201) + expect(json_response['label']['name']).to eq(ux_label.title) + expect(json_response['position']).to eq(3) + end + + it 'returns 400 when creating a new list if label_id is invalid' do + post api(base_url, user), + label_id: 23423 + + expect(response).to have_http_status(400) + end + + it "returns 403 for project members with guest role" do + put api("#{base_url}/#{test_list.id}", guest), + position: 1 + + expect(response).to have_http_status(403) + end + end + + describe "PUT /projects/:id/boards/:board_id/lists/:list_id to update only position" do + let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" } + + it "updates a list" do + put api("#{base_url}/#{test_list.id}", user), + position: 1 + + expect(response).to have_http_status(200) + expect(json_response['position']).to eq(1) + end + + it "returns 404 error if list id not found" do + put api("#{base_url}/44444", user), + position: 1 + + expect(response).to have_http_status(404) + end + + it "returns 403 for project members with guest role" do + put api("#{base_url}/#{test_list.id}", guest), + position: 1 + + expect(response).to have_http_status(403) + end + end + + describe "DELETE /projects/:id/board/lists/:list_id" do + let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" } + + it "rejects a non member from deleting a list" do + delete api("#{base_url}/#{dev_list.id}", non_member) + + expect(response).to have_http_status(403) + end + + it "rejects a user with guest role from deleting a list" do + delete api("#{base_url}/#{dev_list.id}", guest) + + expect(response).to have_http_status(403) + end + + it "returns 404 error if list id not found" do + delete api("#{base_url}/44444", user) + + expect(response).to have_http_status(404) + end + + context "when the user is project owner" do + let(:owner) { create(:user) } + let(:project) { create(:project, namespace: owner.namespace) } + + it "deletes the list if an admin requests it" do + delete api("#{base_url}/#{dev_list.id}", owner) + + expect(response).to have_http_status(200) + expect(json_response['position']).to eq(1) + end + end + end +end -- cgit v1.2.1 From 6b9671388d523a03b058e1cc467de77d805fc7a2 Mon Sep 17 00:00:00 2001 From: Linus G Thiel Date: Wed, 5 Oct 2016 18:13:49 +0200 Subject: Respond with 404 Not Found for non-existent tags Non-existent tags should be handled with 404 Not Found. --- spec/controllers/projects/tags_controller_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb index a6995145cc1..5e661c2c41d 100644 --- a/spec/controllers/projects/tags_controller_spec.rb +++ b/spec/controllers/projects/tags_controller_spec.rb @@ -17,4 +17,18 @@ describe Projects::TagsController do expect(assigns(:releases)).not_to include(invalid_release) end end + + describe 'GET show' do + before { get :show, namespace_id: project.namespace.to_param, project_id: project.to_param, id: id } + + context "valid tag" do + let(:id) { 'v1.0.0' } + it { is_expected.to respond_with(:success) } + end + + context "invalid tag" do + let(:id) { 'latest' } + it { is_expected.to respond_with(:not_found) } + end + end end -- cgit v1.2.1 From a1ee8cf5ad07256807f15590bdb5f56152d55553 Mon Sep 17 00:00:00 2001 From: Marc Siegfriedt Date: Mon, 29 Aug 2016 23:58:32 +0000 Subject: multi-file commit add docs and tests - add additional validation allow move without content updated response --- spec/requests/api/commits_spec.rb | 273 ++++++++++++++++++++++++++++- spec/services/files/update_service_spec.rb | 4 +- 2 files changed, 269 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 10f772c5b1a..aa610557056 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -5,7 +5,7 @@ describe API::API, api: true do include ApiHelpers let(:user) { create(:user) } let(:user2) { create(:user) } - let!(:project) { create(:project, creator_id: user.id) } + let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let!(:master) { create(:project_member, :master, user: user, project: project) } let!(:guest) { create(:project_member, :guest, user: user2, project: project) } let!(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') } @@ -13,7 +13,7 @@ describe API::API, api: true do before { project.team << [user, :reporter] } - describe "GET /projects/:id/repository/commits" do + describe "List repository commits" do context "authorized user" do before { project.team << [user2, :reporter] } @@ -69,7 +69,268 @@ describe API::API, api: true do end end - describe "GET /projects:id/repository/commits/:sha" do + describe "Create a commit with multiple files and actions" do + let!(:url) { "/projects/#{project.id}/repository/commits" } + + it 'returns a 403 unauthorized for user without permissions' do + post api(url, user2) + + expect(response).to have_http_status(403) + end + + it 'returns a 400 bad request if no params are given' do + post api(url, user) + + expect(response).to have_http_status(400) + end + + context :create do + let(:message) { 'Created file' } + let!(:invalid_c_params) do + { + branch_name: 'master', + commit_message: message, + actions: [ + { + action: 'create', + file_path: 'files/ruby/popen.rb', + content: 'puts 8' + } + ] + } + end + let!(:valid_c_params) do + { + branch_name: 'master', + commit_message: message, + actions: [ + { + action: 'create', + file_path: 'foo/bar/baz.txt', + content: 'puts 8' + } + ] + } + end + + it 'a new file in project repo' do + post api(url, user), valid_c_params + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq(message) + end + + it 'returns a 400 bad request if file exists' do + post api(url, user), invalid_c_params + + expect(response).to have_http_status(400) + end + end + + context :delete do + let(:message) { 'Deleted file' } + let!(:invalid_d_params) do + { + branch_name: 'markdown', + commit_message: message, + actions: [ + { + action: 'delete', + file_path: 'doc/api/projects.md' + } + ] + } + end + let!(:valid_d_params) do + { + branch_name: 'markdown', + commit_message: message, + actions: [ + { + action: 'delete', + file_path: 'doc/api/users.md' + } + ] + } + end + + it 'an existing file in project repo' do + post api(url, user), valid_d_params + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq(message) + end + + it 'returns a 400 bad request if file does not exist' do + post api(url, user), invalid_d_params + + expect(response).to have_http_status(400) + end + end + + context :move do + let(:message) { 'Moved file' } + let!(:invalid_m_params) do + { + branch_name: 'feature', + commit_message: message, + actions: [ + { + action: 'move', + file_path: 'CHANGELOG', + previous_path: 'VERSION', + content: '6.7.0.pre' + } + ] + } + end + let!(:valid_m_params) do + { + branch_name: 'feature', + commit_message: message, + actions: [ + { + action: 'move', + file_path: 'VERSION.txt', + previous_path: 'VERSION', + content: '6.7.0.pre' + } + ] + } + end + + it 'an existing file in project repo' do + post api(url, user), valid_m_params + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq(message) + end + + it 'returns a 400 bad request if file does not exist' do + post api(url, user), invalid_m_params + + expect(response).to have_http_status(400) + end + end + + context :update do + let(:message) { 'Updated file' } + let!(:invalid_u_params) do + { + branch_name: 'master', + commit_message: message, + actions: [ + { + action: 'update', + file_path: 'foo/bar.baz', + content: 'puts 8' + } + ] + } + end + let!(:valid_u_params) do + { + branch_name: 'master', + commit_message: message, + actions: [ + { + action: 'update', + file_path: 'files/ruby/popen.rb', + content: 'puts 8' + } + ] + } + end + + it 'an existing file in project repo' do + post api(url, user), valid_u_params + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq(message) + end + + it 'returns a 400 bad request if file does not exist' do + post api(url, user), invalid_u_params + + expect(response).to have_http_status(400) + end + end + + context "multiple operations" do + let(:message) { 'Multiple actions' } + let!(:invalid_mo_params) do + { + branch_name: 'master', + commit_message: message, + actions: [ + { + action: 'create', + file_path: 'files/ruby/popen.rb', + content: 'puts 8' + }, + { + action: 'delete', + file_path: 'doc/api/projects.md' + }, + { + action: 'move', + file_path: 'CHANGELOG', + previous_path: 'VERSION', + content: '6.7.0.pre' + }, + { + action: 'update', + file_path: 'foo/bar.baz', + content: 'puts 8' + } + ] + } + end + let!(:valid_mo_params) do + { + branch_name: 'master', + commit_message: message, + actions: [ + { + action: 'create', + file_path: 'foo/bar/baz.txt', + content: 'puts 8' + }, + { + action: 'delete', + file_path: 'Gemfile.zip' + }, + { + action: 'move', + file_path: 'VERSION.txt', + previous_path: 'VERSION', + content: '6.7.0.pre' + }, + { + action: 'update', + file_path: 'files/ruby/popen.rb', + content: 'puts 8' + } + ] + } + end + + it 'are commited as one in project repo' do + post api(url, user), valid_mo_params + + expect(response).to have_http_status(201) + expect(json_response['title']).to eq(message) + end + + it 'return a 400 bad request if there are any issues' do + post api(url, user), invalid_mo_params + + expect(response).to have_http_status(400) + end + end + end + + describe "Get a single commit" do context "authorized user" do it "returns a commit by sha" do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user) @@ -122,7 +383,7 @@ describe API::API, api: true do end end - describe "GET /projects:id/repository/commits/:sha/diff" do + describe "Get the diff of a commit" do context "authorized user" do before { project.team << [user2, :reporter] } @@ -149,7 +410,7 @@ describe API::API, api: true do end end - describe 'GET /projects:id/repository/commits/:sha/comments' do + describe 'Get the comments of a commit' do context 'authorized user' do it 'returns merge_request comments' do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user) @@ -174,7 +435,7 @@ describe API::API, api: true do end end - describe 'POST /projects:id/repository/commits/:sha/comments' do + describe 'Post comment to commit' do context 'authorized user' do it 'returns comment' do post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment' diff --git a/spec/services/files/update_service_spec.rb b/spec/services/files/update_service_spec.rb index d019e50649f..d3c37c7820f 100644 --- a/spec/services/files/update_service_spec.rb +++ b/spec/services/files/update_service_spec.rb @@ -41,7 +41,7 @@ describe Files::UpdateService do it "returns a hash with the :success status " do results = subject.execute - expect(results).to match({ status: :success }) + expect(results[:status]).to match(:success) end it "updates the file with the new contents" do @@ -69,7 +69,7 @@ describe Files::UpdateService do it "returns a hash with the :success status " do results = subject.execute - expect(results).to match({ status: :success }) + expect(results[:status]).to match(:success) end it "updates the file with the new contents" do -- cgit v1.2.1 From b4d614bdbcb50f506c56eaa180d7b3f3055884a8 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Mon, 29 Aug 2016 12:09:33 -0500 Subject: Fix inconsistent highlighting of already selected activity nav-links --- spec/javascripts/activities_spec.js.es6 | 61 ++++++++++++++++++++++++ spec/javascripts/fixtures/event_filter.html.haml | 21 ++++++++ spec/lib/event_filter_spec.rb | 49 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 spec/javascripts/activities_spec.js.es6 create mode 100644 spec/javascripts/fixtures/event_filter.html.haml create mode 100644 spec/lib/event_filter_spec.rb (limited to 'spec') diff --git a/spec/javascripts/activities_spec.js.es6 b/spec/javascripts/activities_spec.js.es6 new file mode 100644 index 00000000000..743b15460c6 --- /dev/null +++ b/spec/javascripts/activities_spec.js.es6 @@ -0,0 +1,61 @@ +/*= require jquery.cookie.js */ +/*= require jquery.endless-scroll.js */ +/*= require pager */ +/*= require activities */ + +(() => { + window.gon || (window.gon = {}); + const fixtureTemplate = 'event_filter.html'; + const filters = [ + { + id: 'all', + }, { + id: 'push', + name: 'push events', + }, { + id: 'merged', + name: 'merge events', + }, { + id: 'comments', + },{ + id: 'team', + }]; + + function getEventName(index) { + let filter = filters[index]; + return filter.hasOwnProperty('name') ? filter.name : filter.id; + } + + function getSelector(index) { + let filter = filters[index]; + return `#${filter.id}_event_filter` + } + + describe('Activities', () => { + beforeEach(() => { + fixture.load(fixtureTemplate); + new Activities(); + }); + + for(let i = 0; i < filters.length; i++) { + ((i) => { + describe(`when selecting ${getEventName(i)}`, () => { + beforeEach(() => { + $(getSelector(i)).click(); + }); + + for(let x = 0; x < filters.length; x++) { + ((x) => { + let shouldHighlight = i === x; + let testName = shouldHighlight ? 'should highlight' : 'should not highlight'; + + it(`${testName} ${getEventName(x)}`, () => { + expect($(getSelector(x)).parent().hasClass('active')).toEqual(shouldHighlight); + }); + })(x); + } + }); + })(i); + } + }); +})(); diff --git a/spec/javascripts/fixtures/event_filter.html.haml b/spec/javascripts/fixtures/event_filter.html.haml new file mode 100644 index 00000000000..95e248cadf8 --- /dev/null +++ b/spec/javascripts/fixtures/event_filter.html.haml @@ -0,0 +1,21 @@ +%ul.nav-links.event-filter.scrolling-tabs + %li.active + %a.event-filter-link{ id: "all_event_filter", title: "Filter by all", href: "/dashboard/activity"} + %span + All + %li + %a.event-filter-link{ id: "push_event_filter", title: "Filter by push events", href: "/dashboard/activity"} + %span + Push events + %li + %a.event-filter-link{ id: "merged_event_filter", title: "Filter by merge events", href: "/dashboard/activity"} + %span + Merge events + %li + %a.event-filter-link{ id: "comments_event_filter", title: "Filter by comments", href: "/dashboard/activity"} + %span + Comments + %li + %a.event-filter-link{ id: "team_event_filter", title: "Filter by team", href: "/dashboard/activity"} + %span + Team \ No newline at end of file diff --git a/spec/lib/event_filter_spec.rb b/spec/lib/event_filter_spec.rb new file mode 100644 index 00000000000..a6d8e6927e0 --- /dev/null +++ b/spec/lib/event_filter_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe EventFilter, lib: true do + describe '#apply_filter' do + let(:source_user) { create(:user) } + let!(:public_project) { create(:project, :public) } + + let!(:push_event) { create(:event, action: Event::PUSHED, project: public_project, target: public_project, author: source_user) } + let!(:merged_event) { create(:event, action: Event::MERGED, project: public_project, target: public_project, author: source_user) } + let!(:comments_event) { create(:event, action: Event::COMMENTED, project: public_project, target: public_project, author: source_user) } + let!(:joined_event) { create(:event, action: Event::JOINED, project: public_project, target: public_project, author: source_user) } + let!(:left_event) { create(:event, action: Event::LEFT, project: public_project, target: public_project, author: source_user) } + + it 'applies push filter' do + events = EventFilter.new(EventFilter.push).apply_filter(Event.all) + expect(events).to contain_exactly(push_event) + end + + it 'applies merged filter' do + events = EventFilter.new(EventFilter.merged).apply_filter(Event.all) + expect(events).to contain_exactly(merged_event) + end + + it 'applies comments filter' do + events = EventFilter.new(EventFilter.comments).apply_filter(Event.all) + expect(events).to contain_exactly(comments_event) + end + + it 'applies team filter' do + events = EventFilter.new(EventFilter.team).apply_filter(Event.all) + expect(events).to contain_exactly(joined_event, left_event) + end + + it 'applies all filter' do + events = EventFilter.new(EventFilter.all).apply_filter(Event.all) + expect(events).to contain_exactly(push_event, merged_event, comments_event, joined_event, left_event) + end + + it 'applies no filter' do + events = EventFilter.new(nil).apply_filter(Event.all) + expect(events).to contain_exactly(push_event, merged_event, comments_event, joined_event, left_event) + end + + it 'applies unknown filter' do + events = EventFilter.new('').apply_filter(Event.all) + expect(events).to contain_exactly(push_event, merged_event, comments_event, joined_event, left_event) + end + end +end -- cgit v1.2.1 From 640a4c88341f790ede78f845d29a37634030581f Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Mon, 3 Oct 2016 16:42:02 +0200 Subject: Use higher size on Gitlab::Redis connection pool on Sidekiq servers --- spec/lib/gitlab/redis_spec.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/redis_spec.rb b/spec/lib/gitlab/redis_spec.rb index cb54c020b31..74ff85e132a 100644 --- a/spec/lib/gitlab/redis_spec.rb +++ b/spec/lib/gitlab/redis_spec.rb @@ -88,6 +88,34 @@ describe Gitlab::Redis do end end + describe '.with' do + before { clear_pool } + after { clear_pool } + + context 'when running not on sidekiq workers' do + before { allow(Sidekiq).to receive(:server?).and_return(false) } + + it 'instantiates a connection pool with size 5' do + expect(ConnectionPool).to receive(:new).with(size: 5).and_call_original + + described_class.with { |_redis| true } + end + end + + context 'when running on sidekiq workers' do + before do + allow(Sidekiq).to receive(:server?).and_return(true) + allow(Sidekiq).to receive(:options).and_return({ concurrency: 18 }) + end + + it 'instantiates a connection pool with a size based on the concurrency of the worker' do + expect(ConnectionPool).to receive(:new).with(size: 18 + 5).and_call_original + + described_class.with { |_redis| true } + end + end + end + describe '#raw_config_hash' do it 'returns default redis url when no config file is present' do expect(subject).to receive(:fetch_config) { false } @@ -114,4 +142,10 @@ describe Gitlab::Redis do rescue NameError # raised if @_raw_config was not set; ignore end + + def clear_pool + described_class.remove_instance_variable(:@pool) + rescue NameError + # raised if @pool was not set; ignore + end end -- cgit v1.2.1 From c65ea7a5c30ee44c859ac711f1054dab734bdb89 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 16 Sep 2016 10:45:23 +0100 Subject: Merge request tabs stick when scrolling page Closes #20548 --- spec/features/merge_requests/sticky_tabs_spec.rb | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 spec/features/merge_requests/sticky_tabs_spec.rb (limited to 'spec') diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb new file mode 100644 index 00000000000..6f8c3dc55f4 --- /dev/null +++ b/spec/features/merge_requests/sticky_tabs_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +feature 'Merge request tabs', js: true, feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } + + before do + project.team << [user, :master] + login_as user + visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'affixes to top of page when scrolling' do + page.execute_script "window.scrollBy(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') + end + + it 'removes affix when scrolling to top' do + page.execute_script "window.scrollBy(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') + + page.execute_script "window.scrollBy(0,-10000)" + expect(page).to have_selector('.js-tabs-affix.affix-top') + end +end -- cgit v1.2.1 From 8962a3359c4282c755fff0fa08deeb64d74543a0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 16 Sep 2016 11:21:45 +0100 Subject: Fixed merge request tab JS spec --- spec/javascripts/merge_request_tabs_spec.js | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js index 395032a7416..96ee5235acf 100644 --- a/spec/javascripts/merge_request_tabs_spec.js +++ b/spec/javascripts/merge_request_tabs_spec.js @@ -1,5 +1,6 @@ /*= require merge_request_tabs */ +//= require breakpoints (function() { describe('MergeRequestTabs', function() { -- cgit v1.2.1 From 97dc95b18e5a5c29daab84e0d65522b3d3158dc1 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 16 Sep 2016 14:32:43 +0100 Subject: Fixed tests --- spec/features/merge_requests/sticky_tabs_spec.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb index 6f8c3dc55f4..e78f3f134d5 100644 --- a/spec/features/merge_requests/sticky_tabs_spec.rb +++ b/spec/features/merge_requests/sticky_tabs_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' feature 'Merge request tabs', js: true, feature: true do + include WaitForAjax + let(:user) { create(:user) } let(:project) { create(:project, :public) } let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } @@ -9,18 +11,20 @@ feature 'Merge request tabs', js: true, feature: true do project.team << [user, :master] login_as user visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + + wait_for_ajax end it 'affixes to top of page when scrolling' do - page.execute_script "window.scrollBy(0,10000)" + page.execute_script "window.scroll(0,10000)" expect(page).to have_selector('.js-tabs-affix.affix') end it 'removes affix when scrolling to top' do - page.execute_script "window.scrollBy(0,10000)" + page.execute_script "window.scroll(0,10000)" expect(page).to have_selector('.js-tabs-affix.affix') - page.execute_script "window.scrollBy(0,-10000)" + page.execute_script "window.scroll(0,-10000)" expect(page).to have_selector('.js-tabs-affix.affix-top') end end -- cgit v1.2.1 From ef1b5988af68a2811c079f785351e30fa8afd347 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 3 Oct 2016 09:50:50 +0100 Subject: Tests update --- spec/features/merge_requests/sticky_tabs_spec.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'spec') diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb index e78f3f134d5..3e8bd768324 100644 --- a/spec/features/merge_requests/sticky_tabs_spec.rb +++ b/spec/features/merge_requests/sticky_tabs_spec.rb @@ -17,14 +17,17 @@ feature 'Merge request tabs', js: true, feature: true do it 'affixes to top of page when scrolling' do page.execute_script "window.scroll(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') end it 'removes affix when scrolling to top' do page.execute_script "window.scroll(0,10000)" + expect(page).to have_selector('.js-tabs-affix.affix') page.execute_script "window.scroll(0,-10000)" + expect(page).to have_selector('.js-tabs-affix.affix-top') end end -- cgit v1.2.1 From 284af578f37ffb9ec7bcc44ae9d8897be6e68d2f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 4 Oct 2016 12:53:39 +0100 Subject: Added tests --- spec/features/boards/new_issue_spec.rb | 80 ++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 spec/features/boards/new_issue_spec.rb (limited to 'spec') diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb new file mode 100644 index 00000000000..c046e6b8d79 --- /dev/null +++ b/spec/features/boards/new_issue_spec.rb @@ -0,0 +1,80 @@ +require 'rails_helper' + +describe 'Issue Boards new issue', feature: true, js: true do + include WaitForAjax + include WaitForVueResource + + let(:project) { create(:project_with_board, :public) } + let(:user) { create(:user) } + + context 'authorized user' do + before do + project.team << [user, :master] + + login_as(user) + + visit namespace_project_board_path(project.namespace, project) + wait_for_vue_resource + + expect(page).to have_selector('.board', count: 3) + end + + it 'displays new issue button' do + expect(page).to have_selector('.board-issue-count-holder .btn', count: 1) + end + + it 'does not display new issue button in done list' do + page.within('.board:nth-child(3)') do + expect(page).not_to have_selector('.board-issue-count-holder .btn') + end + end + + it 'shows form when clicking button' do + page.within(first('.board')) do + find('.board-issue-count-holder .btn').click + + expect(page).to have_selector('.board-new-issue-form') + end + end + + it 'hides form when clicking cancel' do + page.within(first('.board')) do + find('.board-issue-count-holder .btn').click + + expect(page).to have_selector('.board-new-issue-form') + + click_button 'Cancel' + + expect(page).to have_selector('.board-new-issue-form', visible: false) + end + end + + it 'creates new issue' do + page.within(first('.board')) do + find('.board-issue-count-holder .btn').click + end + + page.within(first('.board-new-issue-form')) do + find('.form-control').set('bug') + click_button 'Submit issue' + end + + wait_for_vue_resource + + page.within(first('.board .board-issue-count')) do + expect(page).to have_content('1') + end + end + end + + context 'unauthorized user' do + before do + visit namespace_project_board_path(project.namespace, project) + wait_for_vue_resource + end + + it 'does not display new issue button' do + expect(page).to have_selector('.board-issue-count-holder .btn', count: 0) + end + end +end -- cgit v1.2.1 From 97ec0c05f66e40a6de6620efcf5c92b7c2979f95 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 4 Oct 2016 17:41:00 -0300 Subject: Add service to create a new issue in a board list --- spec/services/boards/issues/create_service_spec.rb | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 spec/services/boards/issues/create_service_spec.rb (limited to 'spec') diff --git a/spec/services/boards/issues/create_service_spec.rb b/spec/services/boards/issues/create_service_spec.rb new file mode 100644 index 00000000000..33e10e79f6d --- /dev/null +++ b/spec/services/boards/issues/create_service_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe Boards::Issues::CreateService, services: true do + describe '#execute' do + let(:project) { create(:project_with_board) } + let(:board) { project.board } + let(:user) { create(:user) } + let(:label) { create(:label, project: project, name: 'in-progress') } + let!(:list) { create(:list, board: board, label: label, position: 0) } + + subject(:service) { described_class.new(project, user, title: 'New issue') } + + before do + project.team << [user, :developer] + end + + it 'delegates the create proceedings to Issues::CreateService' do + expect_any_instance_of(Issues::CreateService).to receive(:execute).once + + service.execute(list) + end + + it 'creates a new issue' do + expect { service.execute(list) }.to change(project.issues, :count).by(1) + end + + it 'adds the label of the list to the issue' do + issue = service.execute(list) + + expect(issue.labels).to eq [label] + end + end +end -- cgit v1.2.1 From fe3f1657ab88cbb60281681771c4b9dd870b65c6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 4 Oct 2016 17:41:24 -0300 Subject: Add tests to Projects::Boards::IssuesController#create action --- .../projects/boards/issues_controller_spec.rb | 64 +++++++++++++++++++--- 1 file changed, 57 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index 2896636db5a..566658b508d 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' describe Projects::Boards::IssuesController do let(:project) { create(:project_with_board) } let(:user) { create(:user) } + let(:guest) { create(:user) } let(:planning) { create(:label, project: project, name: 'Planning') } let(:development) { create(:label, project: project, name: 'Development') } @@ -12,6 +13,7 @@ describe Projects::Boards::IssuesController do before do project.team << [user, :master] + project.team << [guest, :guest] end describe 'GET index' do @@ -61,6 +63,60 @@ describe Projects::Boards::IssuesController do end end + describe 'POST create' do + context 'with valid params' do + it 'returns a successful 200 response' do + create_issue user: user, list: list1, title: 'New issue' + + expect(response).to have_http_status(200) + end + + it 'returns the created issue' do + create_issue user: user, list: list1, title: 'New issue' + + expect(response).to match_response_schema('issue') + end + end + + context 'with invalid params' do + context 'when title is nil' do + it 'returns an unprocessable entity 422 response' do + create_issue user: user, list: list1, title: nil + + expect(response).to have_http_status(422) + end + end + + context 'when list does not belongs to project board' do + it 'returns a not found 404 response' do + list = create(:list) + + create_issue user: user, list: list, title: 'New issue' + + expect(response).to have_http_status(404) + end + end + end + + context 'with unauthorized user' do + it 'returns a forbidden 403 response' do + create_issue user: guest, list: list1, title: 'New issue' + + expect(response).to have_http_status(403) + end + end + + def create_issue(user:, list:, title:) + sign_in(user) + + post :create, namespace_id: project.namespace.to_param, + project_id: project.to_param, + list_id: list.to_param, + issue: { title: title }, + format: :json + end + end + describe 'PATCH update' do let(:issue) { create(:labeled_issue, project: project, labels: [planning]) } @@ -93,13 +149,7 @@ describe Projects::Boards::IssuesController do end context 'with unauthorized user' do - let(:guest) { create(:user) } - - before do - project.team << [guest, :guest] - end - - it 'returns a successful 403 response' do + it 'returns a forbidden 403 response' do move user: guest, issue: issue, from_list_id: list1.id, to_list_id: list2.id expect(response).to have_http_status(403) -- cgit v1.2.1 From 9824a69c8a4028b757a3d13d7ed4251589d20589 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 6 Oct 2016 12:19:50 +0200 Subject: Fix tests and code for MWBS event move to pipeline --- .../merge_when_build_succeeds_service_spec.rb | 48 +++++++++++----------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb index 520e906b21f..df8f8b61df5 100644 --- a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb @@ -58,42 +58,44 @@ describe MergeRequests::MergeWhenBuildSucceedsService do end describe "#trigger" do - context 'build with ref' do - let(:build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch, status: "success") } + let(:merge_request_ref) { mr_merge_if_green_enabled.source_branch } + let(:merge_request_head) do + project.commit(mr_merge_if_green_enabled.source_branch).id + end - it "merges all merge requests with merge when build succeeds enabled" do - allow_any_instance_of(MergeRequest).to receive(:pipeline).and_return(pipeline) - allow(pipeline).to receive(:success?).and_return(true) + context 'when triggered by pipeline with valid ref and sha' do + let(:triggering_pipeline) do + create(:ci_pipeline, project: project, ref: merge_request_ref, + sha: merge_request_head, status: 'success') + end + it "merges all merge requests with merge when build succeeds enabled" do expect(MergeWorker).to receive(:perform_async) - service.trigger(build) + service.trigger(triggering_pipeline) end end - context 'triggered by an old build' do - let(:old_build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch, status: "success") } - let(:build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch, status: "success") } - - it "merges all merge requests with merge when build succeeds enabled" do - allow_any_instance_of(MergeRequest).to receive(:pipeline).and_return(pipeline) - allow(pipeline).to receive(:success?).and_return(true) - allow(old_build).to receive(:sha).and_return('1234abcdef') + context 'when triggered by an old pipeline' do + let(:old_pipeline) do + create(:ci_pipeline, project: project, ref: merge_request_ref, + sha: '1234abcdef', status: 'success') + end + it 'it does not merge merge request' do expect(MergeWorker).not_to receive(:perform_async) - service.trigger(old_build) + service.trigger(old_pipeline) end end - context 'commit status without ref' do - let(:commit_status) { create(:generic_commit_status, status: 'success') } - - before { mr_merge_if_green_enabled } - - it "doesn't merge a requests for status on other branch" do - allow(project.repository).to receive(:branch_names_contains).with(commit_status.sha).and_return([]) + context 'when triggered by pipeline from a different branch' do + let(:unrelated_pipeline) do + create(:ci_pipeline, project: project, ref: 'feature', + sha: merge_request_head, status: 'success') + end + it 'does not merge request' do expect(MergeWorker).not_to receive(:perform_async) - service.trigger(commit_status) + service.trigger(unrelated_pipeline) end it 'discovers branches and merges all merge requests when status is success' do -- cgit v1.2.1 From cd58410811564130e6975c62fe77d2c9fccce46f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 6 Oct 2016 12:31:39 +0200 Subject: Remove support for branch-less builds in MWBS See !6675#note_16580143 --- .../merge_when_build_succeeds_service_spec.rb | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb index df8f8b61df5..03345ed9c15 100644 --- a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb @@ -97,20 +97,9 @@ describe MergeRequests::MergeWhenBuildSucceedsService do expect(MergeWorker).not_to receive(:perform_async) service.trigger(unrelated_pipeline) end - - it 'discovers branches and merges all merge requests when status is success' do - allow(project.repository).to receive(:branch_names_contains). - with(commit_status.sha).and_return([mr_merge_if_green_enabled.source_branch]) - allow(pipeline).to receive(:success?).and_return(true) - allow_any_instance_of(MergeRequest).to receive(:pipeline).and_return(pipeline) - allow(pipeline).to receive(:success?).and_return(true) - - expect(MergeWorker).to receive(:perform_async) - service.trigger(commit_status) - end end - context 'properly handles multiple stages' do + context 'when there are multiple stages in the pipeline' do let(:ref) { mr_merge_if_green_enabled.source_branch } let!(:build) { create(:ci_build, :created, pipeline: pipeline, ref: ref, name: 'build', stage: 'build') } let!(:test) { create(:ci_build, :created, pipeline: pipeline, ref: ref, name: 'test', stage: 'test') } -- cgit v1.2.1 From f82d6c180d171d09d6822aaffb447b4c048749a6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 4 Oct 2016 22:33:37 +0100 Subject: Updates failing test --- spec/features/environments_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 4309a726917..3b38a7f5007 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -175,12 +175,12 @@ feature 'Environments', feature: true do before do visit namespace_project_environment_path(project.namespace, project, environment) end - + context 'when logged as master' do given(:role) { :master } - scenario 'does delete environment' do - click_link 'Destroy' + scenario 'does close environment' do + click_link 'Close' expect(page).not_to have_link(environment.name) end end @@ -188,8 +188,8 @@ feature 'Environments', feature: true do context 'when logged as developer' do given(:role) { :developer } - scenario 'does not have a Destroy link' do - expect(page).not_to have_link('Destroy') + scenario 'does not have a Close link' do + expect(page).not_to have_link('Close') end end end -- cgit v1.2.1 From 492b4332a46fa0ae7d6547fe7417977f34c77b99 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 8 Aug 2016 23:30:01 +0100 Subject: Added link to bulk assign issues to MR author. (Issue #18876) --- .../projects/merge_requests_controller_spec.rb | 31 +++++++++++++ spec/features/merge_requests/assign_issues_spec.rb | 51 ++++++++++++++++++++++ .../merge_requests/assign_issues_service_spec.rb | 49 +++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 spec/features/merge_requests/assign_issues_spec.rb create mode 100644 spec/services/merge_requests/assign_issues_service_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 742edd8ba3d..18041bce482 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -708,4 +708,35 @@ describe Projects::MergeRequestsController do end end end + + describe 'POST assign_related_issues' do + let(:issue1) { create(:issue, project: project) } + let(:issue2) { create(:issue, project: project) } + + def post_assign_issues + merge_request.update!(description: "Closes #{issue1.to_reference} and #{issue2.to_reference}", + author: user, + source_branch: 'feature', + target_branch: 'master') + + post :assign_related_issues, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: merge_request.iid + end + + it 'shows a flash message on success' do + post_assign_issues + + expect(flash[:notice]).to eq '2 issues have been assigned to you' + end + + it 'correctly pluralizes flash message on success' do + issue2.update!(assignee: user) + + post_assign_issues + + expect(flash[:notice]).to eq '1 issue has been assigned to you' + end + end end diff --git a/spec/features/merge_requests/assign_issues_spec.rb b/spec/features/merge_requests/assign_issues_spec.rb new file mode 100644 index 00000000000..43cc6f2a2a7 --- /dev/null +++ b/spec/features/merge_requests/assign_issues_spec.rb @@ -0,0 +1,51 @@ +require 'rails_helper' + +feature 'Merge request issue assignment', js: true, feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue1) { create(:issue, project: project) } + let(:issue2) { create(:issue, project: project) } + let(:merge_request) { create(:merge_request, :simple, source_project: project, author: user, description: "fixes #{issue1.to_reference} and #{issue2.to_reference}") } + let(:service) { MergeRequests::AssignIssuesService.new(merge_request, user, user, project) } + + before do + project.team << [user, :developer] + end + + def visit_merge_request(current_user = nil) + login_as(current_user || user) + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + context 'logged in as author' do + scenario 'updates related issues' do + visit_merge_request + click_link "Assign yourself to these issues" + + expect(page).to have_content "2 issues have been assigned to you" + end + + it 'returns user to the merge request' do + visit_merge_request + click_link "Assign yourself to these issues" + + expect(page).to have_content merge_request.description + end + + it "doesn't display if related issues are already assigned" do + [issue1, issue2].each { |issue| issue.update!(assignee: user) } + + visit_merge_request + + expect(page).not_to have_content "Assign yourself" + end + end + + context 'not MR author' do + it "doesn't not show assignment link" do + visit_merge_request(create(:user)) + + expect(page).not_to have_content "Assign yourself" + end + end +end diff --git a/spec/services/merge_requests/assign_issues_service_spec.rb b/spec/services/merge_requests/assign_issues_service_spec.rb new file mode 100644 index 00000000000..7aeb95a15ea --- /dev/null +++ b/spec/services/merge_requests/assign_issues_service_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe MergeRequests::AssignIssuesService, services: true do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project) } + let(:merge_request) { create(:merge_request, :simple, source_project: project, author: user, description: "fixes #{issue.to_reference}") } + let(:service) { described_class.new(project, user, merge_request: merge_request) } + + before do + project.team << [user, :developer] + end + + it 'finds unassigned issues fixed in merge request' do + expect(service.assignable_issues.map(&:id)).to include(issue.id) + end + + it 'ignores issues already assigned to any user' do + issue.update!(assignee: create(:user)) + + expect(service.assignable_issues).to be_empty + end + + it 'ignores issues the user cannot update assignee on' do + project.team.truncate + + expect(service.assignable_issues).to be_empty + end + + it 'ignores all issues unless current_user is merge_request.author' do + merge_request.update!(author: create(:user)) + + expect(service.assignable_issues).to be_empty + end + + it 'accepts precomputed data for closes_issues' do + issue2 = create(:issue, project: project) + service2 = described_class.new(project, + user, + merge_request: merge_request, + closes_issues: [issue, issue2]) + + expect(service2.assignable_issues.count).to eq 2 + end + + it 'assigns these to the merge request owner' do + expect { service.execute }.to change { issue.reload.assignee }.to(user) + end +end -- cgit v1.2.1 From a43baa056e69827c342e705e2d5ea8cfc67bfd9c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 6 Oct 2016 14:52:00 +0200 Subject: Rename pipeline workers to match current convention --- spec/workers/pipeline_proccess_worker_spec.rb | 22 ++++++++++++++++++++++ spec/workers/pipeline_update_worker_spec.rb | 22 ++++++++++++++++++++++ spec/workers/process_pipeline_worker_spec.rb | 22 ---------------------- spec/workers/update_pipeline_worker_spec.rb | 22 ---------------------- 4 files changed, 44 insertions(+), 44 deletions(-) create mode 100644 spec/workers/pipeline_proccess_worker_spec.rb create mode 100644 spec/workers/pipeline_update_worker_spec.rb delete mode 100644 spec/workers/process_pipeline_worker_spec.rb delete mode 100644 spec/workers/update_pipeline_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/pipeline_proccess_worker_spec.rb b/spec/workers/pipeline_proccess_worker_spec.rb new file mode 100644 index 00000000000..86e9d7f6684 --- /dev/null +++ b/spec/workers/pipeline_proccess_worker_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe PipelineProcessWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline) } + + it 'processes pipeline' do + expect_any_instance_of(Ci::Pipeline).to receive(:process!) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end diff --git a/spec/workers/pipeline_update_worker_spec.rb b/spec/workers/pipeline_update_worker_spec.rb new file mode 100644 index 00000000000..0b456cfd0da --- /dev/null +++ b/spec/workers/pipeline_update_worker_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe PipelineUpdateWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline) } + + it 'updates pipeline status' do + expect_any_instance_of(Ci::Pipeline).to receive(:update_status) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end diff --git a/spec/workers/process_pipeline_worker_spec.rb b/spec/workers/process_pipeline_worker_spec.rb deleted file mode 100644 index 7b5f98d5763..00000000000 --- a/spec/workers/process_pipeline_worker_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec_helper' - -describe ProcessPipelineWorker do - describe '#perform' do - context 'when pipeline exists' do - let(:pipeline) { create(:ci_pipeline) } - - it 'processes pipeline' do - expect_any_instance_of(Ci::Pipeline).to receive(:process!) - - described_class.new.perform(pipeline.id) - end - end - - context 'when pipeline does not exist' do - it 'does not raise exception' do - expect { described_class.new.perform(123) } - .not_to raise_error - end - end - end -end diff --git a/spec/workers/update_pipeline_worker_spec.rb b/spec/workers/update_pipeline_worker_spec.rb deleted file mode 100644 index fadc42b22f0..00000000000 --- a/spec/workers/update_pipeline_worker_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec_helper' - -describe UpdatePipelineWorker do - describe '#perform' do - context 'when pipeline exists' do - let(:pipeline) { create(:ci_pipeline) } - - it 'updates pipeline status' do - expect_any_instance_of(Ci::Pipeline).to receive(:update_status) - - described_class.new.perform(pipeline.id) - end - end - - context 'when pipeline does not exist' do - it 'does not raise exception' do - expect { described_class.new.perform(123) } - .not_to raise_error - end - end - end -end -- cgit v1.2.1 From f8da5eb8ef7cb757b88fd1c8d3c2dea7671e7daa Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 11:10:03 -0300 Subject: Revert "Label list shows all issues (opened or closed) with that label" --- spec/services/boards/issues/list_service_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index e65da15aca8..5b9f454fd2d 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -30,7 +30,7 @@ describe Boards::Issues::ListService, services: true do let!(:closed_issue1) { create(:labeled_issue, :closed, project: project, labels: [bug]) } let!(:closed_issue2) { create(:labeled_issue, :closed, project: project, labels: [p3]) } let!(:closed_issue3) { create(:issue, :closed, project: project) } - let!(:closed_issue4) { create(:labeled_issue, :closed, project: project, labels: [p1, development]) } + let!(:closed_issue4) { create(:labeled_issue, :closed, project: project, labels: [p1]) } before do project.team << [user, :developer] @@ -58,15 +58,15 @@ describe Boards::Issues::ListService, services: true do issues = described_class.new(project, user, params).execute - expect(issues).to eq [closed_issue2, closed_issue3, closed_issue1] + expect(issues).to eq [closed_issue4, closed_issue2, closed_issue3, closed_issue1] end - it 'returns opened/closed issues that have label list applied when listing issues from a label list' do + it 'returns opened issues that have label list applied when listing issues from a label list' do params = { id: list1.id } issues = described_class.new(project, user, params).execute - expect(issues).to eq [closed_issue4, list1_issue3, list1_issue1, list1_issue2] + expect(issues).to eq [list1_issue3, list1_issue1, list1_issue2] end end end -- cgit v1.2.1 From fe46e4eb35dd6728a8a5ebcee9cc05a4613effbf Mon Sep 17 00:00:00 2001 From: Justin DiPierro Date: Thu, 29 Sep 2016 12:46:54 -0400 Subject: Load Github::Shell's secret token from file on initialization instead of every request. --- spec/lib/gitlab/backend/shell_spec.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index 07407f212aa..c9c7ef8f479 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -22,15 +22,14 @@ describe Gitlab::Shell, lib: true do it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") } - describe 'generate_and_link_secret_token' do + describe 'memoized secret_token' do let(:secret_file) { 'tmp/tests/.secret_shell_test' } let(:link_file) { 'tmp/tests/shell-secret-test/.gitlab_shell_secret' } before do - allow(Gitlab.config.gitlab_shell).to receive(:path).and_return('tmp/tests/shell-secret-test') allow(Gitlab.config.gitlab_shell).to receive(:secret_file).and_return(secret_file) + allow(Gitlab.config.gitlab_shell).to receive(:path).and_return('tmp/tests/shell-secret-test') FileUtils.mkdir('tmp/tests/shell-secret-test') - gitlab_shell.generate_and_link_secret_token end after do @@ -39,7 +38,10 @@ describe Gitlab::Shell, lib: true do end it 'creates and links the secret token file' do + secret_token = Gitlab::Shell.secret_token + expect(File.exist?(secret_file)).to be(true) + expect(File.read(secret_file).chomp).to eq(secret_token) expect(File.symlink?(link_file)).to be(true) expect(File.readlink(link_file)).to eq(secret_file) end -- cgit v1.2.1 From 67b85665777c7ee4d808a58bff8fbe199cfdbab2 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 6 Oct 2016 15:37:25 +0100 Subject: Try tmpfs for repository storage, etc --- spec/spec_helper.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'spec') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b19f5824236..f313bd4f249 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -50,6 +50,11 @@ RSpec.configure do |config| example.run Rails.cache = caching_store end + + config.after(:each) do + FileUtils.rm_rf("tmp/tests/repositories") + FileUtils.mkdir_p("tmp/tests/repositories") + end end FactoryGirl::SyntaxRunner.class_eval do -- cgit v1.2.1 From 6b90ccb9fd57401912e1978cbad28cc693a2e0a1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 6 Oct 2016 15:14:24 +0300 Subject: Change user & group landing page routing from /u/:name & /groups/:name to /:name Signed-off-by: Dmitriy Zaporozhets --- spec/features/users_spec.rb | 22 ++++++++++++++++++ spec/helpers/projects_helper_spec.rb | 2 +- .../constraints/namespace_url_constrainer_spec.rb | 26 ++++++++++++++++++++++ spec/routing/routing_spec.rb | 4 +++- spec/services/system_note_service_spec.rb | 2 +- 5 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 spec/lib/constraints/namespace_url_constrainer_spec.rb (limited to 'spec') diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index b5a94fe0383..f2c0aa7784a 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -40,6 +40,23 @@ feature 'Users', feature: true do expect(number_of_errors_on_page(page)).to be(1), 'errors on page:\n #{errors_on_page page}' end + describe 'redirect alias routes' do + before { user } + + scenario '/u/user1 redirects to user page' do + visit '/u/user1' + + expect_user_show_page + end + + + scenario '/users/user1 redirects to user page' do + visit '/users/user1' + + expect_user_show_page + end + end + def errors_on_page(page) page.find('#error_explanation').find('ul').all('li').map{ |item| item.text }.join("\n") end @@ -47,4 +64,9 @@ feature 'Users', feature: true do def number_of_errors_on_page(page) page.find('#error_explanation').find('ul').all('li').count end + + def expect_user_show_page + expect(current_path).to eq user_path(user) + expect(page).to have_text(user.name) + end end diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index bcd53440cb4..8113742923b 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -72,7 +72,7 @@ describe ProjectsHelper do it 'returns an HTML link to the user' do link = helper.link_to_member(project, user) - expect(link).to match(%r{/u/#{user.username}}) + expect(link).to match(%r{/#{user.username}}) end end end diff --git a/spec/lib/constraints/namespace_url_constrainer_spec.rb b/spec/lib/constraints/namespace_url_constrainer_spec.rb new file mode 100644 index 00000000000..8940fd6b94e --- /dev/null +++ b/spec/lib/constraints/namespace_url_constrainer_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe NamespaceUrlConstrainer, lib: true do + let!(:group) { create(:group, path: 'gitlab') } + subject { NamespaceUrlConstrainer.new } + + describe '#matches?' do + context 'existing namespace' do + it { expect(subject.matches?(request '/gitlab')).to be_truthy } + it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } + it { expect(subject.matches?(request '/gitlab/')).to be_truthy } + it { expect(subject.matches?(request '//gitlab/')).to be_truthy } + end + + context 'non-existing namespace' do + it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } + it { expect(subject.matches?(request '/gitlab.ce')).to be_falsey } + it { expect(subject.matches?(request '/g/gitlab')).to be_falsey } + it { expect(subject.matches?(request '/.gitlab')).to be_falsey } + end + end + + def request(path) + OpenStruct.new(path: path) + end +end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 4bc3cddd9c2..3608aa70f65 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -9,7 +9,9 @@ require 'spec_helper' # user_calendar_activities GET /u/:username/calendar_activities(.:format) describe UsersController, "routing" do it "to #show" do - expect(get("/u/User")).to route_to('users#show', username: 'User') + allow(User).to receive(:find_by_username).and_return(true) + + expect(get("/User")).to route_to('users#show', username: 'User') end it "to #groups" do diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index c22dd9ab77a..d1a47ea9b6f 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -561,7 +561,7 @@ describe SystemNoteService, services: true do describe "existing reference" do before do - message = %Q{[#{author.name}|http://localhost/u/#{author.username}] mentioned this issue in [a commit of #{project.path_with_namespace}|http://localhost/#{project.path_with_namespace}/commit/#{commit.id}]:\\n'#{commit.title}'} + message = %Q{[#{author.name}|http://localhost/#{author.username}] mentioned this issue in [a commit of #{project.path_with_namespace}|http://localhost/#{project.path_with_namespace}/commit/#{commit.id}]:\\n'#{commit.title}'} WebMock.stub_request(:get, jira_api_comment_url).to_return(body: %Q({"comments":[{"body":"#{message}"}]})) end -- cgit v1.2.1 From 105260314899303de4c70a1125b5ab69fb50e6d9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 6 Oct 2016 15:34:30 +0300 Subject: Fix users feature spec Signed-off-by: Dmitriy Zaporozhets --- spec/features/users_spec.rb | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index f2c0aa7784a..6498b7317b4 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -46,14 +46,8 @@ feature 'Users', feature: true do scenario '/u/user1 redirects to user page' do visit '/u/user1' - expect_user_show_page - end - - - scenario '/users/user1 redirects to user page' do - visit '/users/user1' - - expect_user_show_page + expect(current_path).to eq user_path(user) + expect(page).to have_text(user.name) end end @@ -64,9 +58,4 @@ feature 'Users', feature: true do def number_of_errors_on_page(page) page.find('#error_explanation').find('ul').all('li').count end - - def expect_user_show_page - expect(current_path).to eq user_path(user) - expect(page).to have_text(user.name) - end end -- cgit v1.2.1 From 42c6555bab47eb042749be1f24d486797eb8d8ee Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 6 Oct 2016 16:59:22 +0300 Subject: Make user constrainer lookup same as controller and add more constrainer tests Signed-off-by: Dmitriy Zaporozhets --- spec/lib/constraints/group_url_constrainer_spec.rb | 10 ++++++++++ spec/lib/constraints/namespace_url_constrainer_spec.rb | 1 - spec/lib/constraints/user_url_constrainer_spec.rb | 10 ++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 spec/lib/constraints/group_url_constrainer_spec.rb create mode 100644 spec/lib/constraints/user_url_constrainer_spec.rb (limited to 'spec') diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb new file mode 100644 index 00000000000..f0b75a664f2 --- /dev/null +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe GroupUrlConstrainer, lib: true do + let!(:username) { create(:group, path: 'gitlab-org') } + + describe '#find_resource' do + it { expect(!!subject.find_resource('gitlab-org')).to be_truthy } + it { expect(!!subject.find_resource('gitlab-com')).to be_falsey } + end +end diff --git a/spec/lib/constraints/namespace_url_constrainer_spec.rb b/spec/lib/constraints/namespace_url_constrainer_spec.rb index 8940fd6b94e..a5feaacb8ee 100644 --- a/spec/lib/constraints/namespace_url_constrainer_spec.rb +++ b/spec/lib/constraints/namespace_url_constrainer_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' describe NamespaceUrlConstrainer, lib: true do let!(:group) { create(:group, path: 'gitlab') } - subject { NamespaceUrlConstrainer.new } describe '#matches?' do context 'existing namespace' do diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb new file mode 100644 index 00000000000..4b26692672f --- /dev/null +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe UserUrlConstrainer, lib: true do + let!(:username) { create(:user, username: 'dz') } + + describe '#find_resource' do + it { expect(!!subject.find_resource('dz')).to be_truthy } + it { expect(!!subject.find_resource('john')).to be_falsey } + end +end -- cgit v1.2.1 From b356c7ddad1ada1d78136386536f6676ca8b1df4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 6 Oct 2016 18:08:29 +0300 Subject: Update user routing spec after constrainer logic changed Signed-off-by: Dmitriy Zaporozhets --- spec/routing/routing_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 3608aa70f65..0dd00af878d 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -9,7 +9,7 @@ require 'spec_helper' # user_calendar_activities GET /u/:username/calendar_activities(.:format) describe UsersController, "routing" do it "to #show" do - allow(User).to receive(:find_by_username).and_return(true) + allow(User).to receive(:find_by).and_return(true) expect(get("/User")).to route_to('users#show', username: 'User') end -- cgit v1.2.1 From 8443cee049068d8d69633e57df5e15e6d999f073 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 6 Oct 2016 18:10:18 +0100 Subject: Fixes external_url link Adds tests for: - external_url link in environmnets list - must show deployment internal id in environments list - must show build name and id in environments list --- spec/features/environments_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 4309a726917..d4ecccf5f12 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -44,6 +44,10 @@ feature 'Environments', feature: true do scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) end + + scenario 'does show deployment internal id' do + expect(page).to have_content(deployment.iid) + end context 'with build and manual actions' do given(:pipeline) { create(:ci_pipeline, project: project) } @@ -61,6 +65,20 @@ feature 'Environments', feature: true do expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end + + scenario 'does show build name and id' do + expect(page).to have_link("#{build.name} (##{build.id})") + end + + context 'with external_url' do + given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show an external link button' do + expect(page).to have_selector('.btn.external-url') + end + end end end end -- cgit v1.2.1 From f415a32eceabe07e125cc2c26d922b618aef89e9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 6 Oct 2016 18:13:42 +0100 Subject: Adds test for external link in environment details --- spec/features/environments_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index d4ecccf5f12..a4d2460f595 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -140,6 +140,16 @@ feature 'Environments', feature: true do expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end + + context 'with external_url' do + given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show an external link button' do + expect(page).to have_selector('.btn.external-url') + end + end end end end -- cgit v1.2.1 From 1d35c5b3aed565f1da0fc696f078642540584ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Wed, 21 Sep 2016 02:09:31 -0300 Subject: Improve project policy spec --- spec/policies/project_policy_spec.rb | 147 +++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 16 deletions(-) (limited to 'spec') diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index a7a06744428..43c8d884a47 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -1,20 +1,68 @@ require 'spec_helper' describe ProjectPolicy, models: true do - let(:project) { create(:empty_project, :public) } let(:guest) { create(:user) } let(:reporter) { create(:user) } let(:dev) { create(:user) } let(:master) { create(:user) } let(:owner) { create(:user) } - let(:admin) { create(:admin) } + let(:project) { create(:empty_project, :public, namespace: owner.namespace) } - let(:users_ordered_by_permissions) do - [nil, guest, reporter, dev, master, owner, admin] + let(:guest_permissions) do + [ + :read_project, :read_board, :read_list, :read_wiki, :read_issue, :read_label, + :read_milestone, :read_project_snippet, :read_project_member, + :read_merge_request, :read_note, :create_project, :create_issue, :create_note, + :upload_file + ] end - let(:users_permissions) do - users_ordered_by_permissions.map { |u| Ability.allowed(u, project).size } + let(:reporter_permissions) do + [ + :download_code, :fork_project, :create_project_snippet, :update_issue, + :admin_issue, :admin_label, :admin_list, :read_commit_status, :read_build, + :read_container_image, :read_pipeline, :read_environment, :read_deployment + ] + end + + let(:team_member_reporter_permissions) do + [ + :build_download_code, :build_read_container_image + ] + end + + let(:developer_permissions) do + [ + :admin_merge_request, :update_merge_request, :create_commit_status, + :update_commit_status, :create_build, :update_build, :create_pipeline, + :update_pipeline, :create_merge_request, :create_wiki, :push_code, + :resolve_note, :create_container_image, :update_container_image, + :create_environment, :create_deployment + ] + end + + let(:master_permissions) do + [ + :push_code_to_protected_branches, :update_project_snippet, :update_environment, + :update_deployment, :admin_milestone, :admin_project_snippet, + :admin_project_member, :admin_note, :admin_wiki, :admin_project, + :admin_commit_status, :admin_build, :admin_container_image, + :admin_pipeline, :admin_environment, :admin_deployment + ] + end + + let(:public_permissions) do + [ + :download_code, :fork_project, :read_commit_status, :read_pipeline, + :read_container_image, :build_download_code, :build_read_container_image + ] + end + + let(:owner_permissions) do + [ + :change_namespace, :change_visibility_level, :rename_project, :remove_project, + :archive_project, :remove_fork_project, :destroy_merge_request, :destroy_issue + ] end before do @@ -22,16 +70,6 @@ describe ProjectPolicy, models: true do project.team << [master, :master] project.team << [dev, :developer] project.team << [reporter, :reporter] - - group = create(:group) - project.project_group_links.create( - group: group, - group_access: Gitlab::Access::MASTER) - group.add_owner(owner) - end - - it 'returns increasing permissions for each level' do - expect(users_permissions).to eq(users_permissions.sort.uniq) end it 'does not include the read_issue permission when the issue author is not a member of the private project' do @@ -46,4 +84,81 @@ describe ProjectPolicy, models: true do expect(Ability.allowed?(user, :read_issue, project)).to be_falsy end + + context 'abilities for non-public projects' do + let(:project) { create(:empty_project, namespace: owner.namespace) } + + subject { described_class.abilities(current_user, project).to_set } + + context 'with no user' do + let(:current_user) { nil } + + it { is_expected.to be_empty } + end + + context 'guests' do + let(:current_user) { guest } + + it do + is_expected.to include(*guest_permissions) + is_expected.not_to include(*reporter_permissions) + is_expected.not_to include(*team_member_reporter_permissions) + is_expected.not_to include(*developer_permissions) + is_expected.not_to include(*master_permissions) + is_expected.not_to include(*owner_permissions) + end + end + + context 'reporter' do + let(:current_user) { reporter } + + it do + is_expected.to include(*guest_permissions) + is_expected.to include(*reporter_permissions) + is_expected.to include(*team_member_reporter_permissions) + is_expected.not_to include(*developer_permissions) + is_expected.not_to include(*master_permissions) + is_expected.not_to include(*owner_permissions) + end + end + + context 'developer' do + let(:current_user) { dev } + + it do + is_expected.to include(*guest_permissions) + is_expected.to include(*reporter_permissions) + is_expected.to include(*team_member_reporter_permissions) + is_expected.to include(*developer_permissions) + is_expected.not_to include(*master_permissions) + is_expected.not_to include(*owner_permissions) + end + end + + context 'master' do + let(:current_user) { master } + + it do + is_expected.to include(*guest_permissions) + is_expected.to include(*reporter_permissions) + is_expected.to include(*team_member_reporter_permissions) + is_expected.to include(*developer_permissions) + is_expected.to include(*master_permissions) + is_expected.not_to include(*owner_permissions) + end + end + + context 'owner' do + let(:current_user) { owner } + + it do + is_expected.to include(*guest_permissions) + is_expected.to include(*reporter_permissions) + is_expected.not_to include(*team_member_reporter_permissions) + is_expected.to include(*developer_permissions) + is_expected.to include(*master_permissions) + is_expected.to include(*owner_permissions) + end + end + end end -- cgit v1.2.1 From 35e231b5cce463c793a76cf1961e23bf63f82c7c Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Thu, 6 Oct 2016 09:46:07 -0500 Subject: Update issue board spec --- spec/features/boards/boards_spec.rb | 4 ++-- spec/services/boards/lists/generate_service_spec.rb | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 26ea06e002b..470e2bdbb9b 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -34,14 +34,14 @@ describe 'Issue Boards', feature: true, js: true do end it 'creates default lists' do - lists = ['Backlog', 'Development', 'Testing', 'Production', 'Ready', 'Done'] + lists = ['Backlog', 'To Do', 'Doing', 'Done'] page.within(find('.board-blank-state')) do click_button('Add default lists') end wait_for_vue_resource - expect(page).to have_selector('.board', count: 6) + expect(page).to have_selector('.board', count: 4) page.all('.board').each_with_index do |list, i| expect(list.find('.board-title')).to have_content(lists[i]) diff --git a/spec/services/boards/lists/generate_service_spec.rb b/spec/services/boards/lists/generate_service_spec.rb index 9fd39122737..4171e4d816c 100644 --- a/spec/services/boards/lists/generate_service_spec.rb +++ b/spec/services/boards/lists/generate_service_spec.rb @@ -10,7 +10,7 @@ describe Boards::Lists::GenerateService, services: true do context 'when board lists is empty' do it 'creates the default lists' do - expect { service.execute }.to change(board.lists, :count).by(4) + expect { service.execute }.to change(board.lists, :count).by(2) end end @@ -24,16 +24,15 @@ describe Boards::Lists::GenerateService, services: true do context 'when project labels does not contains any list label' do it 'creates labels' do - expect { service.execute }.to change(project.labels, :count).by(4) + expect { service.execute }.to change(project.labels, :count).by(2) end end context 'when project labels contains some of list label' do it 'creates the missing labels' do - create(:label, project: project, name: 'Development') - create(:label, project: project, name: 'Ready') + create(:label, project: project, name: 'Doing') - expect { service.execute }.to change(project.labels, :count).by(2) + expect { service.execute }.to change(project.labels, :count).by(1) end end end -- cgit v1.2.1 From e94cd6fdfe43d9128d37a539cf84f4388c5cf970 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 6 Oct 2016 22:17:11 +0100 Subject: Add markdown cache columns to the database, but don't use them yet This commit adds a number of _html columns and, with the exception of Note, starts updating them whenever the content of their partner fields changes. Note has a collision with the note_html attr_accessor; that will be fixed later A background worker for clearing these cache columns is also introduced - use `rake cache:clear` to set it off. You can clear the database or Redis caches separately by running `rake cache:clear:db` or `rake cache:clear:redis`, respectively. --- spec/factories/projects.rb | 7 + spec/lib/banzai/renderer_spec.rb | 74 +++++++++ .../import_export/attribute_configuration_spec.rb | 3 +- spec/models/abuse_report_spec.rb | 4 + spec/models/concerns/cache_markdown_field_spec.rb | 181 +++++++++++++++++++++ spec/models/project_spec.rb | 2 +- spec/models/service_spec.rb | 2 +- spec/models/snippet_spec.rb | 7 + spec/requests/api/projects_spec.rb | 4 +- spec/services/git_push_service_spec.rb | 2 + spec/services/merge_requests/merge_service_spec.rb | 5 +- spec/services/system_note_service_spec.rb | 12 +- 12 files changed, 287 insertions(+), 16 deletions(-) create mode 100644 spec/lib/banzai/renderer_spec.rb create mode 100644 spec/models/concerns/cache_markdown_field_spec.rb (limited to 'spec') diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 873d3fcb5af..331172445e4 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -9,6 +9,9 @@ FactoryGirl.define do namespace creator + # Behaves differently to nil due to cache_has_external_issue_tracker + has_external_issue_tracker false + trait :public do visibility_level Gitlab::VisibilityLevel::PUBLIC end @@ -92,6 +95,8 @@ FactoryGirl.define do end factory :redmine_project, parent: :project do + has_external_issue_tracker true + after :create do |project| project.create_redmine_service( active: true, @@ -105,6 +110,8 @@ FactoryGirl.define do end factory :jira_project, parent: :project do + has_external_issue_tracker true + after :create do |project| project.create_jira_service( active: true, diff --git a/spec/lib/banzai/renderer_spec.rb b/spec/lib/banzai/renderer_spec.rb new file mode 100644 index 00000000000..aaa6b12e67e --- /dev/null +++ b/spec/lib/banzai/renderer_spec.rb @@ -0,0 +1,74 @@ +require 'spec_helper' + +describe Banzai::Renderer do + def expect_render(project = :project) + expected_context = { project: project } + expect(renderer).to receive(:cacheless_render) { :html }.with(:markdown, expected_context) + end + + def expect_cache_update + expect(object).to receive(:update_column).with("field_html", :html) + end + + def fake_object(*features) + markdown = :markdown if features.include?(:markdown) + html = :html if features.include?(:html) + + object = double( + "object", + banzai_render_context: { project: :project }, + field: markdown, + field_html: html + ) + + allow(object).to receive(:markdown_cache_field_for).with(:field).and_return("field_html") + allow(object).to receive(:new_record?).and_return(features.include?(:new)) + allow(object).to receive(:destroyed?).and_return(features.include?(:destroyed)) + + object + end + + describe "#render_field" do + let(:renderer) { Banzai::Renderer } + let(:subject) { renderer.render_field(object, :field) } + + context "with an empty cache" do + let(:object) { fake_object(:markdown) } + it "caches and returns the result" do + expect_render + expect_cache_update + expect(subject).to eq(:html) + end + end + + context "with a filled cache" do + let(:object) { fake_object(:markdown, :html) } + + it "uses the cache" do + expect_render.never + expect_cache_update.never + should eq(:html) + end + end + + context "new object" do + let(:object) { fake_object(:new, :markdown) } + + it "doesn't cache the result" do + expect_render + expect_cache_update.never + expect(subject).to eq(:html) + end + end + + context "destroyed object" do + let(:object) { fake_object(:destroyed, :markdown) } + + it "doesn't cache the result" do + expect_render + expect_cache_update.never + expect(subject).to eq(:html) + end + end + end +end diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 2e19d590d83..ea65a5dfed1 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -26,10 +26,11 @@ describe 'Import/Export attribute configuration', lib: true do it 'has no new columns' do relation_names.each do |relation_name| relation_class = relation_class_for_name(relation_name) + relation_attributes = relation_class.new.attributes.keys expect(safe_model_attributes[relation_class.to_s]).not_to be_nil, "Expected exported class #{relation_class} to exist in safe_model_attributes" - current_attributes = parsed_attributes(relation_name, relation_class.attribute_names) + current_attributes = parsed_attributes(relation_name, relation_attributes) safe_attributes = safe_model_attributes[relation_class.to_s] new_attributes = current_attributes - safe_attributes diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index 305f8bc88cc..c4486a32082 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -9,6 +9,10 @@ RSpec.describe AbuseReport, type: :model do describe 'associations' do it { is_expected.to belong_to(:reporter).class_name('User') } it { is_expected.to belong_to(:user) } + + it "aliases reporter to author" do + expect(subject.author).to be(subject.reporter) + end end describe 'validations' do diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb new file mode 100644 index 00000000000..15cd3a7ed70 --- /dev/null +++ b/spec/models/concerns/cache_markdown_field_spec.rb @@ -0,0 +1,181 @@ +require 'spec_helper' + +describe CacheMarkdownField do + CacheMarkdownField::CACHING_CLASSES << "ThingWithMarkdownFields" + + # The minimum necessary ActiveModel to test this concern + class ThingWithMarkdownFields + include ActiveModel::Model + include ActiveModel::Dirty + + include ActiveModel::Serialization + + class_attribute :attribute_names + self.attribute_names = [] + + def attributes + attribute_names.each_with_object({}) do |name, hsh| + hsh[name.to_s] = send(name) + end + end + + extend ActiveModel::Callbacks + define_model_callbacks :save + + include CacheMarkdownField + cache_markdown_field :foo + cache_markdown_field :baz, pipeline: :single_line + + def self.add_attr(attr_name) + self.attribute_names += [attr_name] + define_attribute_methods(attr_name) + attr_reader(attr_name) + define_method("#{attr_name}=") do |val| + send("#{attr_name}_will_change!") unless val == send(attr_name) + instance_variable_set("@#{attr_name}", val) + end + end + + [:foo, :foo_html, :bar, :baz, :baz_html].each do |attr_name| + add_attr(attr_name) + end + + def initialize(*) + super + + # Pretend new is load + clear_changes_information + end + + def save + run_callbacks :save do + changes_applied + end + end + end + + CacheMarkdownField::CACHING_CLASSES.delete("ThingWithMarkdownFields") + + def thing_subclass(new_attr) + Class.new(ThingWithMarkdownFields) { add_attr(new_attr) } + end + + let(:markdown) { "`Foo`" } + let(:html) { "

    Foo

    " } + + let(:updated_markdown) { "`Bar`" } + let(:updated_html) { "

    Bar

    " } + + subject { ThingWithMarkdownFields.new(foo: markdown, foo_html: html) } + + describe ".attributes" do + it "excludes cache attributes" do + expect(thing_subclass(:qux).new.attributes.keys.sort).to eq(%w[bar baz foo qux]) + end + end + + describe ".cache_markdown_field" do + it "refuses to allow untracked classes" do + expect { thing_subclass(:qux).__send__(:cache_markdown_field, :qux) }.to raise_error(RuntimeError) + end + end + + context "an unchanged markdown field" do + before do + subject.foo = subject.foo + subject.save + end + + it { expect(subject.foo).to eq(markdown) } + it { expect(subject.foo_html).to eq(html) } + it { expect(subject.foo_html_changed?).not_to be_truthy } + end + + context "a changed markdown field" do + before do + subject.foo = updated_markdown + subject.save + end + + it { expect(subject.foo_html).to eq(updated_html) } + end + + context "a non-markdown field changed" do + before do + subject.bar = "OK" + subject.save + end + + it { expect(subject.bar).to eq("OK") } + it { expect(subject.foo).to eq(markdown) } + it { expect(subject.foo_html).to eq(html) } + end + + describe '#banzai_render_context' do + it "sets project to nil if the object lacks a project" do + context = subject.banzai_render_context(:foo) + expect(context).to have_key(:project) + expect(context[:project]).to be_nil + end + + it "excludes author if the object lacks an author" do + context = subject.banzai_render_context(:foo) + expect(context).not_to have_key(:author) + end + + it "raises if the context for an unrecognised field is requested" do + expect{subject.banzai_render_context(:not_found)}.to raise_error(ArgumentError) + end + + it "includes the pipeline" do + context = subject.banzai_render_context(:baz) + expect(context[:pipeline]).to eq(:single_line) + end + + it "returns copies of the context template" do + template = subject.cached_markdown_fields[:baz] + copy = subject.banzai_render_context(:baz) + expect(copy).not_to be(template) + end + + context "with a project" do + subject { thing_subclass(:project).new(foo: markdown, foo_html: html, project: :project) } + + it "sets the project in the context" do + context = subject.banzai_render_context(:foo) + expect(context).to have_key(:project) + expect(context[:project]).to eq(:project) + end + + it "invalidates the cache when project changes" do + subject.project = :new_project + allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html) + + subject.save + + expect(subject.foo_html).to eq(updated_html) + expect(subject.baz_html).to eq(updated_html) + end + end + + context "with an author" do + subject { thing_subclass(:author).new(foo: markdown, foo_html: html, author: :author) } + + it "sets the author in the context" do + context = subject.banzai_render_context(:foo) + expect(context).to have_key(:author) + expect(context[:author]).to eq(:author) + end + + it "invalidates the cache when author changes" do + subject.author = :new_author + allow(Banzai::Renderer).to receive(:cacheless_render_field).and_return(updated_html) + + subject.save + + expect(subject.foo_html).to eq(updated_html) + expect(subject.baz_html).to eq(updated_html) + end + end + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index e52d4aaf884..381d14ed21a 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -518,7 +518,7 @@ describe Project, models: true do end describe '#cache_has_external_issue_tracker' do - let(:project) { create(:project) } + let(:project) { create(:project, has_external_issue_tracker: nil) } it 'stores true if there is any external_issue_tracker' do services = double(:service, external_issue_trackers: [RedmineService.new]) diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index ed1bc9271ae..43937a54b2c 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -238,7 +238,7 @@ describe Service, models: true do it "updates the has_external_issue_tracker boolean" do expect do service.save! - end.to change { service.project.has_external_issue_tracker }.from(nil).to(true) + end.to change { service.project.has_external_issue_tracker }.from(false).to(true) end end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index e6bc5296398..f62f6bacbaa 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -46,6 +46,13 @@ describe Snippet, models: true do end end + describe "#content_html_invalidated?" do + let(:snippet) { create(:snippet, content: "md", content_html: "html", file_name: "foo.md") } + it "invalidates the HTML cache of content when the filename changes" do + expect { snippet.file_name = "foo.rb" }.to change { snippet.content_html_invalidated? }.from(false).to(true) + end + end + describe '.search' do let(:snippet) { create(:snippet) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 4a0d727faea..861eb12b94c 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -232,7 +232,7 @@ describe API::API, api: true do post api('/projects', user), project project.each_pair do |k, v| - next if %i{ issues_enabled merge_requests_enabled wiki_enabled }.include?(k) + next if %i[has_external_issue_tracker issues_enabled merge_requests_enabled wiki_enabled].include?(k) expect(json_response[k.to_s]).to eq(v) end @@ -360,7 +360,7 @@ describe API::API, api: true do post api("/projects/user/#{user.id}", admin), project project.each_pair do |k, v| - next if k == :path + next if %i[has_external_issue_tracker path].include?(k) expect(json_response[k.to_s]).to eq(v) end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 22991c5bc86..8e3e12114f2 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -448,6 +448,8 @@ describe GitPushService, services: true do let(:jira_tracker) { project.create_jira_service if project.jira_service.nil? } before do + # project.create_jira_service doesn't seem to invalidate the cache here + project.has_external_issue_tracker = true jira_service_settings WebMock.stub_request(:post, jira_api_transition_url) diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index e49a0d5e553..ee53e110aee 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -60,7 +60,10 @@ describe MergeRequests::MergeService, services: true do let(:jira_tracker) { project.create_jira_service } - before { jira_service_settings } + before do + project.update_attributes!(has_external_issue_tracker: true) + jira_service_settings + end it 'closes issues on JIRA issue tracker' do jira_issue = ExternalIssue.new('JIRA-123', project) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index d1a47ea9b6f..304d4e62396 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -531,12 +531,12 @@ describe SystemNoteService, services: true do include JiraServiceHelper describe 'JIRA integration' do - let(:project) { create(:project) } + let(:project) { create(:jira_project) } let(:author) { create(:user) } let(:issue) { create(:issue, project: project) } let(:mergereq) { create(:merge_request, :simple, target_project: project, source_project: project) } let(:jira_issue) { ExternalIssue.new("JIRA-1", project)} - let(:jira_tracker) { project.create_jira_service if project.jira_service.nil? } + let(:jira_tracker) { project.jira_service } let(:commit) { project.commit } context 'in JIRA issue tracker' do @@ -545,10 +545,6 @@ describe SystemNoteService, services: true do WebMock.stub_request(:post, jira_api_comment_url) end - after do - jira_tracker.destroy! - end - describe "new reference" do before do WebMock.stub_request(:get, jira_api_comment_url).to_return(body: jira_issue_comments) @@ -578,10 +574,6 @@ describe SystemNoteService, services: true do WebMock.stub_request(:get, jira_api_comment_url).to_return(body: jira_issue_comments) end - after do - jira_tracker.destroy! - end - subject { described_class.cross_reference(jira_issue, issue, author) } it { is_expected.to eq(jira_status_message) } -- cgit v1.2.1 From 109816c42fbe44fca108b52308a5fa4366876216 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 6 Oct 2016 22:52:44 +0100 Subject: Use CacheMarkdownField for notes --- spec/lib/banzai/note_renderer_spec.rb | 3 +- spec/lib/banzai/object_renderer_spec.rb | 62 ++++++++++++--------------------- 2 files changed, 24 insertions(+), 41 deletions(-) (limited to 'spec') diff --git a/spec/lib/banzai/note_renderer_spec.rb b/spec/lib/banzai/note_renderer_spec.rb index 98f76f36fd5..49556074278 100644 --- a/spec/lib/banzai/note_renderer_spec.rb +++ b/spec/lib/banzai/note_renderer_spec.rb @@ -12,8 +12,7 @@ describe Banzai::NoteRenderer do with(project, user, requested_path: 'foo', project_wiki: wiki, - ref: 'bar', - pipeline: :note). + ref: 'bar'). and_call_original expect_any_instance_of(Banzai::ObjectRenderer). diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index bcdb95250ca..f5ff236105e 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -4,10 +4,18 @@ describe Banzai::ObjectRenderer do let(:project) { create(:empty_project) } let(:user) { project.owner } + def fake_object(attrs = {}) + object = double(attrs.merge("new_record?": true, "destroyed?": true)) + allow(object).to receive(:markdown_cache_field_for).with(:note).and_return(:note_html) + allow(object).to receive(:banzai_render_context).with(:note).and_return(project: nil, author: nil) + allow(object).to receive(:update_column).with(:note_html, anything).and_return(true) + object + end + describe '#render' do it 'renders and redacts an Array of objects' do renderer = described_class.new(project, user) - object = double(:object, note: 'hello', note_html: nil) + object = fake_object(note: 'hello', note_html: nil) expect(renderer).to receive(:render_objects).with([object], :note). and_call_original @@ -16,7 +24,7 @@ describe Banzai::ObjectRenderer do with(an_instance_of(Array)). and_call_original - expect(object).to receive(:note_html=).with('

    hello

    ') + expect(object).to receive(:redacted_note_html=).with('

    hello

    ') expect(object).to receive(:user_visible_reference_count=).with(0) renderer.render([object], :note) @@ -25,7 +33,7 @@ describe Banzai::ObjectRenderer do describe '#render_objects' do it 'renders an Array of objects' do - object = double(:object, note: 'hello') + object = fake_object(note: 'hello', note_html: nil) renderer = described_class.new(project, user) @@ -57,49 +65,29 @@ describe Banzai::ObjectRenderer do end describe '#context_for' do - let(:object) { double(:object, note: 'hello') } + let(:object) { fake_object(note: 'hello') } let(:renderer) { described_class.new(project, user) } it 'returns a Hash' do expect(renderer.context_for(object, :note)).to be_an_instance_of(Hash) end - it 'includes the cache key' do + it 'includes the banzai render context for the object' do + expect(object).to receive(:banzai_render_context).with(:note).and_return(foo: :bar) context = renderer.context_for(object, :note) - - expect(context[:cache_key]).to eq([object, :note]) - end - - context 'when the object responds to "author"' do - it 'includes the author in the context' do - expect(object).to receive(:author).and_return('Alice') - - context = renderer.context_for(object, :note) - - expect(context[:author]).to eq('Alice') - end - end - - context 'when the object does not respond to "author"' do - it 'does not include the author in the context' do - context = renderer.context_for(object, :note) - - expect(context.key?(:author)).to eq(false) - end + expect(context).to have_key(:foo) + expect(context[:foo]).to eq(:bar) end end describe '#render_attributes' do it 'renders the attribute of a list of objects' do - objects = [double(:doc, note: 'hello'), double(:doc, note: 'bye')] - renderer = described_class.new(project, user, pipeline: :note) + objects = [fake_object(note: 'hello', note_html: nil), fake_object(note: 'bye', note_html: nil)] + renderer = described_class.new(project, user) - expect(Banzai).to receive(:cache_collection_render). - with([ - { text: 'hello', context: renderer.context_for(objects[0], :note) }, - { text: 'bye', context: renderer.context_for(objects[1], :note) } - ]). - and_call_original + objects.each do |object| + expect(Banzai).to receive(:render_field).with(object, :note).and_call_original + end docs = renderer.render_attributes(objects, :note) @@ -114,17 +102,13 @@ describe Banzai::ObjectRenderer do objects = [] renderer = described_class.new(project, user, pipeline: :note) - expect(Banzai).to receive(:cache_collection_render). - with([]). - and_call_original - expect(renderer.render_attributes(objects, :note)).to eq([]) end end describe '#base_context' do let(:context) do - described_class.new(project, user, pipeline: :note).base_context + described_class.new(project, user, foo: :bar).base_context end it 'returns a Hash' do @@ -132,7 +116,7 @@ describe Banzai::ObjectRenderer do end it 'includes the custom attributes' do - expect(context[:pipeline]).to eq(:note) + expect(context[:foo]).to eq(:bar) end it 'includes the current user' do -- cgit v1.2.1 From 9920551536bb4f78dffeaaf3a194b92f54c34a47 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 6 Oct 2016 23:01:42 +0100 Subject: Enable CacheMarkdownField for the remaining models This commit alters views for the following models to use the markdown cache if present: * AbuseReport * Appearance * ApplicationSetting * BroadcastMessage * Group * Issue * Label * MergeRequest * Milestone * Project At the same time, calls to `escape_once` have been moved into the `single_line` Banzai pipeline, so they can't be missed out by accident and the work is done at save, rather than render, time. --- spec/helpers/broadcast_messages_helper_spec.rb | 4 ++-- spec/lib/banzai/filter/html_entity_filter_spec.rb | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 spec/lib/banzai/filter/html_entity_filter_spec.rb (limited to 'spec') diff --git a/spec/helpers/broadcast_messages_helper_spec.rb b/spec/helpers/broadcast_messages_helper_spec.rb index 157cc4665a2..c6e3c5c2368 100644 --- a/spec/helpers/broadcast_messages_helper_spec.rb +++ b/spec/helpers/broadcast_messages_helper_spec.rb @@ -7,7 +7,7 @@ describe BroadcastMessagesHelper do end it 'includes the current message' do - current = double(message: 'Current Message') + current = BroadcastMessage.new(message: 'Current Message') allow(helper).to receive(:broadcast_message_style).and_return(nil) @@ -15,7 +15,7 @@ describe BroadcastMessagesHelper do end it 'includes custom style' do - current = double(message: 'Current Message') + current = BroadcastMessage.new(message: 'Current Message') allow(helper).to receive(:broadcast_message_style).and_return('foo') diff --git a/spec/lib/banzai/filter/html_entity_filter_spec.rb b/spec/lib/banzai/filter/html_entity_filter_spec.rb new file mode 100644 index 00000000000..6dc4a970071 --- /dev/null +++ b/spec/lib/banzai/filter/html_entity_filter_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe Banzai::Filter::HTMLEntityFilter, lib: true do + include FilterSpecHelper + + let(:unescaped) { 'foo &&&' } + let(:escaped) { 'foo <strike attr="foo">&&&</strike>' } + + it 'converts common entities to their HTML-escaped equivalents' do + output = filter(unescaped) + + expect(output).to eq(escaped) + end +end -- cgit v1.2.1 From 1c462cf7d6d61aebac9b909102f0e794cc9e409a Mon Sep 17 00:00:00 2001 From: Justin DiPierro Date: Thu, 6 Oct 2016 22:40:04 -0400 Subject: Call ensure_secret_token! in secret token test's before block since it would be called in an initializer. --- spec/lib/gitlab/backend/shell_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index c9c7ef8f479..f826d0d1b04 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -30,6 +30,7 @@ describe Gitlab::Shell, lib: true do allow(Gitlab.config.gitlab_shell).to receive(:secret_file).and_return(secret_file) allow(Gitlab.config.gitlab_shell).to receive(:path).and_return('tmp/tests/shell-secret-test') FileUtils.mkdir('tmp/tests/shell-secret-test') + Gitlab::Shell.ensure_secret_token! end after do -- cgit v1.2.1 From 1662640985b56390a4d22dab1fee7fd04ccd5bc8 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 6 Oct 2016 15:50:29 -0700 Subject: Fix Event#reset_project_activity updates !6678 removed the lease from Event#reset_project_activity, but it wasn't actually updating the project's last_activity_at timestamp properly. The WHERE clause would always return no matching projects. The spec passed occasionally because the created_at timestamp was automatically set to last_activity_at. --- spec/models/project_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index e52d4aaf884..67a968aaf11 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -308,7 +308,9 @@ describe Project, models: true do end describe 'last_activity methods' do - let(:project) { create(:project, last_activity_at: 2.hours.ago) } + let(:timestamp) { 2.hours.ago } + # last_activity_at gets set to created_at upon creation + let(:project) { create(:project, created_at: timestamp, updated_at: timestamp) } describe 'last_activity' do it 'alias last_activity to last_event' do @@ -322,6 +324,7 @@ describe Project, models: true do it 'returns the creation date of the project\'s last event if present' do new_event = create(:event, project: project, created_at: Time.now) + project.reload expect(project.last_activity_at.to_i).to eq(new_event.created_at.to_i) end -- cgit v1.2.1 From a98e4081d1b122d001438d17036f395fc82b9d5c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 7 Oct 2016 09:32:29 +0200 Subject: Process MWBS in successful pipeline asynchronously --- spec/workers/pipeline_success_worker_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 spec/workers/pipeline_success_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/pipeline_success_worker_spec.rb b/spec/workers/pipeline_success_worker_spec.rb new file mode 100644 index 00000000000..5e31cc2c8e7 --- /dev/null +++ b/spec/workers/pipeline_success_worker_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe PipelineSuccessWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline, status: 'success') } + + it 'performs "merge when pipeline succeeds"' do + expect_any_instance_of( + MergeRequests::MergeWhenBuildSucceedsService + ).to receive(:trigger) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 2f66969e43d25192017ebbe4ff56df213a2dae3f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 7 Oct 2016 09:49:43 +0200 Subject: Improve merge when builds succeeds specs readability --- .../merge_when_build_succeeds_spec.rb | 44 ++++++++++++++-------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb index 60bc07bd1a0..8b6544269a7 100644 --- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb @@ -2,18 +2,26 @@ require 'spec_helper' feature 'Merge When Build Succeeds', feature: true, js: true do let(:user) { create(:user) } + let(:project) { create(:project, :public) } - let(:project) { create(:project, :public) } - let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } + let(:merge_request) do + create(:merge_request_with_diffs, source_project: project, + author: user, + title: 'Bug NS-04') + end - before do - project.team << [user, :master] - project.enable_ci + let(:pipeline) do + create(:ci_pipeline, project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch) end - context "Active build for Merge Request" do - let!(:pipeline) { create(:ci_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) } - let!(:ci_build) { create(:ci_build, pipeline: pipeline) } + before { project.team << [user, :master] } + + context 'when there is active build for merge request' do + background do + create(:ci_build, pipeline: pipeline) + end before do login_as user @@ -41,21 +49,25 @@ feature 'Merge When Build Succeeds', feature: true, js: true do end end - context 'When it is enabled' do + context 'when merge when build succeeds is enabled' do let(:merge_request) do - create(:merge_request_with_diffs, :simple, source_project: project, author: user, - merge_user: user, title: "MepMep", merge_when_build_succeeds: true) + create(:merge_request_with_diffs, :simple, source_project: project, + author: user, + merge_user: user, + title: 'MepMep', + merge_when_build_succeeds: true) end - let!(:pipeline) { create(:ci_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) } - let!(:ci_build) { create(:ci_build, pipeline: pipeline) } + background do + create(:ci_build, pipeline: pipeline) + end before do login_as user visit_merge_request(merge_request) end - it 'cancels the automatic merge' do + it 'allows to cancel the automatic merge' do click_link "Cancel Automatic Merge" expect(page).to have_button "Merge When Build Succeeds" @@ -72,8 +84,8 @@ feature 'Merge When Build Succeeds', feature: true, js: true do end end - context 'Build is not active' do - it "does not allow for enabling" do + context 'when build is not active' do + it "does not allow to enable merge when build succeeds" do visit_merge_request(merge_request) expect(page).not_to have_link "Merge When Build Succeeds" end -- cgit v1.2.1 From e351ed2d11b611bf06eba8d64d2549fbf60fb605 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 7 Oct 2016 10:10:46 +0200 Subject: Add test that checks actual merge for MWBS feature --- .../merge_requests/merge_when_build_succeeds_spec.rb | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb index 8b6544269a7..bc2b0ff3e2c 100644 --- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb @@ -58,7 +58,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do merge_when_build_succeeds: true) end - background do + let!(:build) do create(:ci_build, pipeline: pipeline) end @@ -72,7 +72,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do expect(page).to have_button "Merge When Build Succeeds" - visit_merge_request(merge_request) # Needed to refresh the page + visit_merge_request(merge_request) # refresh the page expect(page).to have_content "Canceled the automatic merge" end @@ -82,6 +82,17 @@ feature 'Merge When Build Succeeds', feature: true, js: true do click_link "Remove Source Branch When Merged" expect(page).to have_content "The source branch will be removed" end + + context 'when build succeeds' do + background { build.success } + + it 'merges merge request' do + visit_merge_request(merge_request) # refresh the page + + expect(page).to have_content 'The changes were merged' + expect(merge_request.reload).to be_merged + end + end end context 'when build is not active' do -- cgit v1.2.1 From 18607d6c88e820b927d90ca1d247a23a61be8c99 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 6 Oct 2016 14:36:44 +0100 Subject: Added tests --- spec/features/boards/sidebar_spec.rb | 297 +++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 spec/features/boards/sidebar_spec.rb (limited to 'spec') diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb new file mode 100644 index 00000000000..2e754287f3a --- /dev/null +++ b/spec/features/boards/sidebar_spec.rb @@ -0,0 +1,297 @@ +require 'rails_helper' + +describe 'Issue Boards', feature: true, js: true do + include WaitForAjax + include WaitForVueResource + + let(:project) { create(:project_with_board, :public) } + let(:user) { create(:user) } + let!(:label) { create(:label, project: project) } + let!(:label2) { create(:label, project: project) } + let!(:milestone) { create(:milestone, project: project) } + let!(:issue2) { create(:labeled_issue, project: project, assignee: user, milestone: milestone, labels: [label]) } + let!(:issue) { create(:issue, project: project) } + + before do + project.team << [user, :master] + + login_as(user) + + visit namespace_project_board_path(project.namespace, project) + wait_for_vue_resource + end + + it 'shows sidebar when clicking issue' do + page.within(first('.board')) do + first('.card').click + end + + expect(page).to have_selector('.issue-boards-sidebar') + end + + it 'closes sidebar when clicking issue' do + page.within(first('.board')) do + first('.card').click + end + + expect(page).to have_selector('.issue-boards-sidebar') + + page.within(first('.board')) do + first('.card').click + end + + expect(page).not_to have_selector('.issue-boards-sidebar') + end + + it 'closes sidebar when clicking close button' do + page.within(first('.board')) do + first('.card').click + end + + expect(page).to have_selector('.issue-boards-sidebar') + + find('.gutter-toggle').click + + expect(page).not_to have_selector('.issue-boards-sidebar') + end + + it 'shows issue details when sidebar is open' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.issue-boards-sidebar') do + expect(page).to have_content(issue.title) + expect(page).to have_content(issue.to_reference) + end + end + + context 'assignee' do + it 'updates the issues assignee' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.assignee') do + click_link 'Edit' + + wait_for_ajax + + page.within('.dropdown-menu-user') do + click_link user.name + + wait_for_vue_resource + end + + expect(page).to have_content(user.name) + end + + page.within(first('.board')) do + page.within(first('.card')) do + expect(page).to have_selector('.avatar') + end + end + end + + it 'removes the assignee' do + page.within(first('.board')) do + find('.card:nth-child(2)').click + end + + page.within('.assignee') do + click_link 'Edit' + + wait_for_ajax + + page.within('.dropdown-menu-user') do + click_link 'Unassigned' + + wait_for_vue_resource + end + + expect(page).to have_content('No assignee') + end + + page.within(first('.board')) do + page.within(find('.card:nth-child(2)')) do + expect(page).not_to have_selector('.avatar') + end + end + end + + it 'assignees to current user' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.assignee') do + click_link 'assign yourself' + + wait_for_vue_resource + + expect(page).to have_content(user.name) + end + + page.within(first('.board')) do + page.within(first('.card')) do + expect(page).to have_selector('.avatar') + end + end + end + end + + context 'milestone' do + it 'adds a milestone' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.milestone') do + click_link 'Edit' + + wait_for_ajax + + click_link milestone.title + + wait_for_vue_resource + + page.within('.value') do + expect(page).to have_content(milestone.title) + end + end + end + + it 'removes a milestone' do + page.within(first('.board')) do + find('.card:nth-child(2)').click + end + + page.within('.milestone') do + click_link 'Edit' + + wait_for_ajax + + click_link "No Milestone" + + wait_for_vue_resource + + page.within('.value') do + expect(page).not_to have_content(milestone.title) + end + end + end + end + + context 'due date' do + it 'updates due date' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.due_date') do + click_link 'Edit' + + click_link Date.today.day + + wait_for_vue_resource + + expect(page).to have_content(Date.today.to_s(:medium)) + end + end + end + + context 'labels' do + it 'adds a single label' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.labels') do + click_link 'Edit' + + wait_for_ajax + + click_link label.title + + wait_for_vue_resource + + find('.dropdown-menu-close-icon').click + + page.within('.value') do + expect(page).to have_selector('.label', count: 1) + expect(page).to have_content(label.title) + end + end + + page.within(first('.board')) do + page.within(first('.card')) do + expect(page).to have_selector('.label', count: 1) + expect(page).to have_content(label.title) + end + end + end + + it 'adds a multiple labels' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.labels') do + click_link 'Edit' + + wait_for_ajax + + click_link label.title + click_link label2.title + + wait_for_vue_resource + + find('.dropdown-menu-close-icon').click + + page.within('.value') do + expect(page).to have_selector('.label', count: 2) + expect(page).to have_content(label.title) + expect(page).to have_content(label2.title) + end + end + + page.within(first('.board')) do + page.within(first('.card')) do + expect(page).to have_selector('.label', count: 2) + expect(page).to have_content(label.title) + expect(page).to have_content(label2.title) + end + end + end + + it 'removes a label' do + page.within(first('.board')) do + find('.card:nth-child(2)').click + end + + page.within('.labels') do + click_link 'Edit' + + wait_for_ajax + + click_link label.title + + wait_for_vue_resource + + find('.dropdown-menu-close-icon').click + + page.within('.value') do + expect(page).to have_selector('.label', count: 0) + expect(page).not_to have_content(label.title) + end + end + + page.within(first('.board')) do + page.within(find('.card:nth-child(2)')) do + expect(page).not_to have_selector('.label', count: 1) + expect(page).not_to have_content(label.title) + end + end + end + end +end -- cgit v1.2.1 From 0c286d54737f685caf7ec21320d43d8069f2001d Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 6 Oct 2016 11:51:38 -0300 Subject: Fix JSON Schema that validates data returned by board issues endpoint --- spec/controllers/projects/boards/issues_controller_spec.rb | 2 +- spec/fixtures/api/schemas/issue.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index 566658b508d..0eebb5a4624 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -21,7 +21,7 @@ describe Projects::Boards::IssuesController do it 'returns issues that have the list label applied' do johndoe = create(:user, avatar: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) create(:labeled_issue, project: project, labels: [planning]) - create(:labeled_issue, project: project, labels: [development]) + create(:labeled_issue, project: project, labels: [development], due_date: Date.tomorrow) create(:labeled_issue, project: project, labels: [development], assignee: johndoe) list_issues user: user, list_id: list2 diff --git a/spec/fixtures/api/schemas/issue.json b/spec/fixtures/api/schemas/issue.json index 532ebb9640e..6de6618e475 100644 --- a/spec/fixtures/api/schemas/issue.json +++ b/spec/fixtures/api/schemas/issue.json @@ -9,6 +9,7 @@ "iid": { "type": "integer" }, "title": { "type": "string" }, "confidential": { "type": "boolean" }, + "due_date": { "type": ["date", "null"] }, "labels": { "type": "array", "items": { -- cgit v1.2.1 From 7d20a91b2ecf0af89b3a6d3a5d4d8621114687ec Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 7 Oct 2016 09:24:57 +0100 Subject: Restore subscribe status in JSON --- spec/controllers/projects/boards/issues_controller_spec.rb | 2 ++ spec/fixtures/api/schemas/issue.json | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index 0eebb5a4624..75f6e7f54e2 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -20,9 +20,11 @@ describe Projects::Boards::IssuesController do context 'with valid list id' do it 'returns issues that have the list label applied' do johndoe = create(:user, avatar: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) + issue = create(:labeled_issue, project: project, labels: [planning]) create(:labeled_issue, project: project, labels: [planning]) create(:labeled_issue, project: project, labels: [development], due_date: Date.tomorrow) create(:labeled_issue, project: project, labels: [development], assignee: johndoe) + issue.subscribe(johndoe) list_issues user: user, list_id: list2 diff --git a/spec/fixtures/api/schemas/issue.json b/spec/fixtures/api/schemas/issue.json index 6de6618e475..77f2bcee1f3 100644 --- a/spec/fixtures/api/schemas/issue.json +++ b/spec/fixtures/api/schemas/issue.json @@ -43,7 +43,8 @@ "name": { "type": "string" }, "username": { "type": "string" }, "avatar_url": { "type": "uri" } - } + }, + "subscribed": { "type": ["boolean", "null"] } }, "additionalProperties": false } -- cgit v1.2.1 From b602023e95f130e4b24cf2be1817f4a22444bb5b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 7 Oct 2016 09:55:12 +0100 Subject: Added tests for showing sidebar when new issue is saved --- spec/features/boards/new_issue_spec.rb | 15 +++++++++++++++ spec/features/boards/sidebar_spec.rb | 14 ++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'spec') diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index c046e6b8d79..c776c977416 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -65,6 +65,21 @@ describe 'Issue Boards new issue', feature: true, js: true do expect(page).to have_content('1') end end + + it 'shows sidebar when creating new issue' do + page.within(first('.board')) do + find('.board-issue-count-holder .btn').click + end + + page.within(first('.board-new-issue-form')) do + find('.form-control').set('bug') + click_button 'Submit issue' + end + + wait_for_vue_resource + + expect(page).to have_selector('.issue-boards-sidebar') + end end context 'unauthorized user' do diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 2e754287f3a..905d720705d 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -294,4 +294,18 @@ describe 'Issue Boards', feature: true, js: true do end end end + + context 'subscription' do + it 'changes issue subscription' do + page.within(first('.board')) do + first('.card').click + end + + page.within('.subscription') do + click_button 'Subscribe' + + expect(page).to have_content("You're receiving notifications because you're subscribed to this thread.") + end + end + end end -- cgit v1.2.1 From 908b37bc88d9e671b508e064287564cc484d3c29 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 7 Oct 2016 11:48:43 +0100 Subject: Updates test in order to look for link --- spec/features/environments_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index a4d2460f595..05925f93220 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -76,7 +76,7 @@ feature 'Environments', feature: true do given(:deployment) { create(:deployment, environment: environment, deployable: build) } scenario 'does show an external link button' do - expect(page).to have_selector('.btn.external-url') + expect(page).to have_link(nil, href: environment.external_url) end end end @@ -147,9 +147,10 @@ feature 'Environments', feature: true do given(:deployment) { create(:deployment, environment: environment, deployable: build) } scenario 'does show an external link button' do - expect(page).to have_selector('.btn.external-url') + expect(page).to have_link(nil, href: environment.external_url) end end + end end end -- cgit v1.2.1 From 443619300d067a83cbd53872635c2c3cfd1f6655 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 23 Sep 2016 15:18:33 +0100 Subject: Added `issuable_filters_present` to check for active filters before rendering the reset button Added tests --- spec/features/issues/reset_filters_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'spec') diff --git a/spec/features/issues/reset_filters_spec.rb b/spec/features/issues/reset_filters_spec.rb index f4d0f13c3d5..c9a3ecf16ea 100644 --- a/spec/features/issues/reset_filters_spec.rb +++ b/spec/features/issues/reset_filters_spec.rb @@ -75,6 +75,14 @@ feature 'Issues filter reset button', feature: true, js: true do end end + context 'when no filters have been applied' do + it 'the reset link should not be visible' do + visit_issues(project) + expect(page).to have_css('.issue', count: 2) + expect(page).not_to have_css '.reset_filters' + end + end + def reset_filters find('.reset-filters').click end -- cgit v1.2.1 From 9afb2dac5c9f49f9f7943053b50a3808a99fdf6b Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Fri, 7 Oct 2016 11:11:02 +0200 Subject: ExpireBuildArtifactsWorker query builds table without ordering enqueuing one job per build to cleanup We use Sidekiq::Client.push_bulk to avoid Redis round trips --- spec/workers/expire_build_artifacts_worker_spec.rb | 51 +++++----------- .../expire_build_instance_artifacts_worker_spec.rb | 69 ++++++++++++++++++++++ 2 files changed, 83 insertions(+), 37 deletions(-) create mode 100644 spec/workers/expire_build_instance_artifacts_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/expire_build_artifacts_worker_spec.rb b/spec/workers/expire_build_artifacts_worker_spec.rb index 7d6668920c0..73cbadc13d9 100644 --- a/spec/workers/expire_build_artifacts_worker_spec.rb +++ b/spec/workers/expire_build_artifacts_worker_spec.rb @@ -5,65 +5,42 @@ describe ExpireBuildArtifactsWorker do let(:worker) { described_class.new } + before { Sidekiq::Worker.clear_all } + describe '#perform' do before { build } - subject! { worker.perform } + subject! do + Sidekiq::Testing.fake! { worker.perform } + end context 'with expired artifacts' do let(:build) { create(:ci_build, :artifacts, artifacts_expire_at: Time.now - 7.days) } - it 'does expire' do - expect(build.reload.artifacts_expired?).to be_truthy - end - - it 'does remove files' do - expect(build.reload.artifacts_file.exists?).to be_falsey - end - - it 'does nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).to be_nil + it 'enqueues that build' do + expect(jobs_enqueued.size).to eq(1) + expect(jobs_enqueued[0]["args"]).to eq([build.id]) end end context 'with not yet expired artifacts' do let(:build) { create(:ci_build, :artifacts, artifacts_expire_at: Time.now + 7.days) } - it 'does not expire' do - expect(build.reload.artifacts_expired?).to be_falsey - end - - it 'does not remove files' do - expect(build.reload.artifacts_file.exists?).to be_truthy - end - - it 'does not nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).not_to be_nil + it 'does not enqueue that build' do + expect(jobs_enqueued.size).to eq(0) end end context 'without expire date' do let(:build) { create(:ci_build, :artifacts) } - it 'does not expire' do - expect(build.reload.artifacts_expired?).to be_falsey - end - - it 'does not remove files' do - expect(build.reload.artifacts_file.exists?).to be_truthy - end - - it 'does not nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).not_to be_nil + it 'does not enqueue that build' do + expect(jobs_enqueued.size).to eq(0) end end - context 'for expired artifacts' do - let(:build) { create(:ci_build, artifacts_expire_at: Time.now - 7.days) } - - it 'is still expired' do - expect(build.reload.artifacts_expired?).to be_truthy - end + def jobs_enqueued + Sidekiq::Queues.jobs_by_worker['ExpireBuildInstanceArtifactsWorker'] end end end diff --git a/spec/workers/expire_build_instance_artifacts_worker_spec.rb b/spec/workers/expire_build_instance_artifacts_worker_spec.rb new file mode 100644 index 00000000000..2b140f2ba28 --- /dev/null +++ b/spec/workers/expire_build_instance_artifacts_worker_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +describe ExpireBuildInstanceArtifactsWorker do + include RepoHelpers + + let(:worker) { described_class.new } + + describe '#perform' do + before { build } + + subject! { worker.perform(build.id) } + + context 'with expired artifacts' do + let(:build) { create(:ci_build, :artifacts, artifacts_expire_at: Time.now - 7.days) } + + it 'does expire' do + expect(build.reload.artifacts_expired?).to be_truthy + end + + it 'does remove files' do + expect(build.reload.artifacts_file.exists?).to be_falsey + end + + it 'does nullify artifacts_file column' do + expect(build.reload.artifacts_file_identifier).to be_nil + end + end + + context 'with not yet expired artifacts' do + let(:build) { create(:ci_build, :artifacts, artifacts_expire_at: Time.now + 7.days) } + + it 'does not expire' do + expect(build.reload.artifacts_expired?).to be_falsey + end + + it 'does not remove files' do + expect(build.reload.artifacts_file.exists?).to be_truthy + end + + it 'does not nullify artifacts_file column' do + expect(build.reload.artifacts_file_identifier).not_to be_nil + end + end + + context 'without expire date' do + let(:build) { create(:ci_build, :artifacts) } + + it 'does not expire' do + expect(build.reload.artifacts_expired?).to be_falsey + end + + it 'does not remove files' do + expect(build.reload.artifacts_file.exists?).to be_truthy + end + + it 'does not nullify artifacts_file column' do + expect(build.reload.artifacts_file_identifier).not_to be_nil + end + end + + context 'for expired artifacts' do + let(:build) { create(:ci_build, artifacts_expire_at: Time.now - 7.days) } + + it 'is still expired' do + expect(build.reload.artifacts_expired?).to be_truthy + end + end + end +end -- cgit v1.2.1 From 328ca8c47054a6d1d284bc8e16b9b0600a137916 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 6 Oct 2016 20:00:51 +0200 Subject: Optimize the `award_user_list` helper spec According to https://gitlab.com/gitlab-org/gitlab-ce/issues/23034#note_16586657, each test for this helper generated 1,833 queries. Now we only generate stubbed records, and only as many as we need for each test. This also corrects a slight logic bug in the helper itself. When the number of awards was greater than the limit (9 by default), _and_ the current user was one of them, we actually included 10 names, including "You", plus the remaining count. Now we return the correct number regardless. --- spec/helpers/issues_helper_spec.rb | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 67bac782591..abe08d95ece 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -63,28 +63,38 @@ describe IssuesHelper do end describe '#award_user_list' do - let!(:awards) { build_list(:award_emoji, 15) } + it "returns a comma-separated list of the first X users" do + user = build_stubbed(:user, name: 'Joe') + awards = Array.new(3, build_stubbed(:award_emoji, user: user)) - it "returns a comma seperated list of 1-9 users" do - expect(award_user_list(awards.first(9), nil)).to eq(awards.first(9).map { |a| a.user.name }.to_sentence) + expect(award_user_list(awards, nil, limit: 3)) + .to eq('Joe, Joe, and Joe') end it "displays the current user's name as 'You'" do - expect(award_user_list(awards.first(1), awards[0].user)).to eq('You') - end + user = build_stubbed(:user, name: 'Joe') + award = build_stubbed(:award_emoji, user: user) - it "truncates lists of larger than 9 users" do - expect(award_user_list(awards, nil)).to eq(awards.first(9).map { |a| a.user.name }.join(', ') + ", and 6 more.") + expect(award_user_list([award], user)).to eq('You') + expect(award_user_list([award], nil)).to eq 'Joe' end - it "displays the current user in front of 0-9 other users" do - expect(award_user_list(awards, awards[0].user)). - to eq("You, " + awards[1..9].map { |a| a.user.name }.join(', ') + ", and 5 more.") + it "truncates lists" do + user = build_stubbed(:user, name: 'Jane') + awards = Array.new(5, build_stubbed(:award_emoji, user: user)) + + expect(award_user_list(awards, nil, limit: 3)) + .to eq('Jane, Jane, Jane, and 2 more.') end - it "displays the current user in front regardless of position in the list" do - expect(award_user_list(awards, awards[12].user)). - to eq("You, " + awards[0..8].map { |a| a.user.name }.join(', ') + ", and 5 more.") + it "displays the current user in front of other users" do + current_user = build_stubbed(:user) + my_award = build_stubbed(:award_emoji, user: current_user) + award = build_stubbed(:award_emoji, user: build_stubbed(:user, name: 'Jane')) + awards = Array.new(5, award).push(my_award) + + expect(award_user_list(awards, current_user, limit: 2)). + to eq("You, Jane, and 4 more.") end end -- cgit v1.2.1 From 031777339e3f0d07551b2976eb471069f77506e6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 7 Oct 2016 15:56:37 +0100 Subject: Deletes extra empty line breaking the build --- spec/features/environments_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 05925f93220..68ea4eeae31 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -150,7 +150,6 @@ feature 'Environments', feature: true do expect(page).to have_link(nil, href: environment.external_url) end end - end end end -- cgit v1.2.1 From 8d2de73a83b98741dbbbc21fe2cbcdaf7840996d Mon Sep 17 00:00:00 2001 From: James Edwards-Jones Date: Fri, 7 Oct 2016 17:16:42 +0100 Subject: fixup! Added link to bulk assign issues to MR author. (Issue #18876) --- .../projects/merge_requests_controller_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 18041bce482..2a68e5a2c9b 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -738,5 +738,22 @@ describe Projects::MergeRequestsController do expect(flash[:notice]).to eq '1 issue has been assigned to you' end + + it 'calls MergeRequests::AssignIssuesService' do + expect(MergeRequests::AssignIssuesService).to receive(:new). + with(project, user, merge_request: merge_request). + and_return(double(execute: {count: 1})) + + post_assign_issues + end + + it 'is skipped when not signed in' do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + sign_out(:user) + + expect(MergeRequests::AssignIssuesService).not_to receive(:new) + + post_assign_issues + end end end -- cgit v1.2.1 From 4f1de5faacb6824bad2624b75537e9f4ddbb1207 Mon Sep 17 00:00:00 2001 From: Will Starms Date: Thu, 25 Aug 2016 11:48:08 -0500 Subject: Correct namespace validation to forbid bad names #21077 Adds .git and .atom to the master namespace regex Updates existing group tests and adds two new ones Updates path cleaning to also forbid .atom --- spec/features/groups_spec.rb | 32 +++++++++++++++++++++++++++++++- spec/models/namespace_spec.rb | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 2d8b59472e8..c54ec2563ad 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -5,6 +5,12 @@ feature 'Group', feature: true do login_as(:admin) end + matcher :have_namespace_error_message do + match do |page| + page.has_content?("Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-' or end in '.', '.git' or '.atom'.") + end + end + describe 'creating a group with space in group path' do it 'renders new group form with validation errors' do visit new_group_path @@ -13,7 +19,31 @@ feature 'Group', feature: true do click_button 'Create group' expect(current_path).to eq(groups_path) - expect(page).to have_content("Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-' or end in '.'.") + expect(page).to have_namespace_error_message + end + end + + describe 'creating a group with .atom at end of group path' do + it 'renders new group form with validation errors' do + visit new_group_path + fill_in 'Group path', with: 'atom_group.atom' + + click_button 'Create group' + + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end + end + + describe 'creating a group with .git at end of group path' do + it 'renders new group form with validation errors' do + visit new_group_path + fill_in 'Group path', with: 'git_group.git' + + click_button 'Create group' + + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 544920d1824..431b3e4435f 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -114,6 +114,7 @@ describe Namespace, models: true do it "cleans the path and makes sure it's available" do expect(Namespace.clean_path("-john+gitlab-ETC%.git@gmail.com")).to eq("johngitlab-ETC2") + expect(Namespace.clean_path("--%+--valid_*&%name=.git.%.atom.atom.@email.com")).to eq("valid_name") end end end -- cgit v1.2.1 From 720968cc8799f665f4f4392e80bf8dfe88fdd69b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 8 Oct 2016 15:31:26 +0800 Subject: Fix tests for subject updates --- spec/services/ci/send_pipeline_notification_service_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index f6cf1039287..6a32357b72c 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -32,14 +32,14 @@ describe Ci::SendPipelineNotificationService, services: true do context 'with success pipeline' do let(:status) { 'success' } - let(:email_subject) { 'Pipeline succeeded for' } + let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } it_behaves_like 'sending emails' end context 'with failed pipeline' do let(:status) { 'failed' } - let(:email_subject) { 'Pipeline failed for' } + let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } it_behaves_like 'sending emails' end -- cgit v1.2.1 From 4695bb8829679a75f66178b2ebf16059d90f6f33 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 8 Oct 2016 05:17:01 -0700 Subject: Use Hash rocket syntax to maintain Ruby 2.1 compatibility in spec --- spec/lib/banzai/object_renderer_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index f5ff236105e..90da78a67dd 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -5,7 +5,7 @@ describe Banzai::ObjectRenderer do let(:user) { project.owner } def fake_object(attrs = {}) - object = double(attrs.merge("new_record?": true, "destroyed?": true)) + object = double(attrs.merge("new_record?" => true, "destroyed?" => true)) allow(object).to receive(:markdown_cache_field_for).with(:note).and_return(:note_html) allow(object).to receive(:banzai_render_context).with(:note).and_return(project: nil, author: nil) allow(object).to receive(:update_column).with(:note_html, anything).and_return(true) -- cgit v1.2.1 From 04afdb613e2282fc6a2debb301a32dad08427f8a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sat, 8 Oct 2016 20:24:43 +0200 Subject: Improve spec for merge when build succeeds feature --- .../merge_when_build_succeeds_service_spec.rb | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb index 520e906b21f..9a29e400654 100644 --- a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb @@ -110,9 +110,21 @@ describe MergeRequests::MergeWhenBuildSucceedsService do context 'properly handles multiple stages' do let(:ref) { mr_merge_if_green_enabled.source_branch } - let!(:build) { create(:ci_build, :created, pipeline: pipeline, ref: ref, name: 'build', stage: 'build') } - let!(:test) { create(:ci_build, :created, pipeline: pipeline, ref: ref, name: 'test', stage: 'test') } - let(:pipeline) { create(:ci_empty_pipeline, ref: mr_merge_if_green_enabled.source_branch, project: project) } + let(:sha) { project.commit(ref).id } + + let(:pipeline) do + create(:ci_empty_pipeline, ref: ref, sha: sha, project: project) + end + + let!(:build) do + create(:ci_build, :created, pipeline: pipeline, ref: ref, + name: 'build', stage: 'build') + end + + let!(:test) do + create(:ci_build, :created, pipeline: pipeline, ref: ref, + name: 'test', stage: 'test') + end before do # This behavior of MergeRequest: we instantiate a new object @@ -121,14 +133,16 @@ describe MergeRequests::MergeWhenBuildSucceedsService do end end - it "doesn't merge if some stages failed" do + it "doesn't merge if any of stages failed" do expect(MergeWorker).not_to receive(:perform_async) + build.success test.drop end - it 'merge when all stages succeeded' do + it 'merges when all stages succeeded' do expect(MergeWorker).to receive(:perform_async) + build.success test.success end -- cgit v1.2.1 From 40fa1b6e6fa13c859351a6c8b6978d7ca3a4cf58 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Sun, 9 Oct 2016 20:31:28 +0500 Subject: Use user from let instead recreate in before --- spec/controllers/projects/blob_controller_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 9444a50b1ce..52d13fb6f9e 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -5,7 +5,6 @@ describe Projects::BlobController do let(:user) { create(:user) } before do - user = create(:user) project.team << [user, :master] sign_in(user) -- cgit v1.2.1 From ff076d88df70a70f6534faefefdca92b059318bf Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Tue, 27 Sep 2016 16:39:29 +0100 Subject: writes tests to verify the issue is solved and fixes breaking issues. --- spec/models/repository_spec.rb | 16 +++++++++++----- spec/support/test_env.rb | 4 +++- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 98c64c079b9..6dd3f91be17 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -115,10 +115,16 @@ describe Repository, models: true do describe '#merged_to_root_ref?' do context 'merged branch' do - subject { repository.merged_to_root_ref?('improve/awesome') } + subject { repository.merged_to_root_ref?('branch-merged') } it { is_expected.to be_truthy } end + + context 'not merged branch' do + subject { repository.merged_to_root_ref?('not-merged-branch') } + + it { is_expected.to be_falsey } + end end describe '#can_be_merged?' do @@ -316,7 +322,7 @@ describe Repository, models: true do subject { results.first } it { is_expected.to be_an String } - it { expect(subject.lines[2]).to eq("master:CHANGELOG:188: - Feature: Replace teams with group membership\n") } + it { expect(subject.lines[2]).to eq("master:CHANGELOG:190: - Feature: Replace teams with group membership\n") } end end @@ -960,10 +966,10 @@ describe Repository, models: true do context 'cherry-picking a merge commit' do it 'cherry-picks the changes' do - expect(repository.blob_at_branch('master', 'foo/bar/.gitkeep')).to be_nil + expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).to be_nil - repository.cherry_pick(user, pickable_merge, 'master') - expect(repository.blob_at_branch('master', 'foo/bar/.gitkeep')).not_to be_nil + repository.cherry_pick(user, pickable_merge, 'improve/awesome') + expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).not_to be_nil end end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 0097dbf8fad..d56274d0979 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -5,6 +5,8 @@ module TestEnv # When developing the seed repository, comment out the branch you will modify. BRANCH_SHA = { + 'not-merged-branch' => 'b83d6e3', + 'branch-merged' => '498214d', 'empty-branch' => '7efb185', 'ends-with.json' => '98b0d8b', 'flatten-dir' => 'e56497b', @@ -14,7 +16,7 @@ module TestEnv 'improve/awesome' => '5937ac0', 'markdown' => '0ed8c6c', 'lfs' => 'be93687', - 'master' => '5937ac0', + 'master' => 'b83d6e3', "'test'" => 'e56497b', 'orphaned-branch' => '45127a9', 'binary-encoding' => '7b1cf43', -- cgit v1.2.1 From 1cf2b9a6b8ff2359f7fad099dcda5632289854a6 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Mon, 10 Oct 2016 10:11:46 +0200 Subject: Make searching for commits case insensitive. Fixes #21800. --- spec/models/repository_spec.rb | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 98c64c079b9..4641f297465 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -97,12 +97,20 @@ describe Repository, models: true do end describe '#find_commits_by_message' do - subject { repository.find_commits_by_message('submodule').map{ |k| k.id } } + it 'returns commits with messages containing a given string' do + commit_ids = repository.find_commits_by_message('submodule').map(&:id) - it { is_expected.to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e') } - it { is_expected.to include('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } - it { is_expected.to include('cfe32cf61b73a0d5e9f13e774abde7ff789b1660') } - it { is_expected.not_to include('913c66a37b4a45b9769037c55c2d238bd0942d2e') } + expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e') + expect(commit_ids).to include('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') + expect(commit_ids).to include('cfe32cf61b73a0d5e9f13e774abde7ff789b1660') + expect(commit_ids).not_to include('913c66a37b4a45b9769037c55c2d238bd0942d2e') + end + + it 'is case insensitive' do + commit_ids = repository.find_commits_by_message('SUBMODULE').map(&:id) + + expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e') + end end describe '#blob_at' do -- cgit v1.2.1 From f3c55164d21b64de13a75a9004b48005cc7c901a Mon Sep 17 00:00:00 2001 From: Brennan Roberts Date: Sun, 2 Oct 2016 15:11:08 -0700 Subject: Prevent conflict b/w search field and its dropdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop the global search form's default "action" from fighting with dropdown items when using the keyboard to navigate the dropdown. `e.preventDefault()` is now called on the enter key when a dropdown item is already selected. Signed-off-by: Rémy Coutable --- spec/javascripts/search_autocomplete_spec.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index 4470fbcb099..333128782a2 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -5,6 +5,8 @@ /*= require lib/utils/common_utils */ /*= require lib/utils/type_utility */ /*= require fuzzaldrin-plus */ +/*= require turbolinks */ +/*= require jquery.turbolinks */ (function() { var addBodyAttributes, assertLinks, dashboardIssuesPath, dashboardMRsPath, groupIssuesPath, groupMRsPath, groupName, mockDashboardOptions, mockGroupOptions, mockProjectOptions, projectIssuesPath, projectMRsPath, projectName, userId, widget; @@ -138,7 +140,7 @@ list = widget.wrap.find('.dropdown-menu').find('ul'); return assertLinks(list, projectIssuesPath, projectMRsPath); }); - return it('should not show category related menu if there is text in the input', function() { + it('should not show category related menu if there is text in the input', function() { var link, list; addBodyAttributes('project'); mockProjectOptions(); @@ -148,6 +150,23 @@ link = "a[href='" + projectIssuesPath + "/?assignee_id=" + userId + "']"; return expect(list.find(link).length).toBe(0); }); + return it('should not submit the search form when selecting an autocomplete row with the keyboard', function() { + var ENTER = 13; + var DOWN = 40; + addBodyAttributes(); + mockDashboardOptions(true); + var submitSpy = spyOnEvent('form', 'submit'); + widget.searchInput.focus(); + widget.wrap.trigger($.Event('keydown', { which: DOWN })); + var enterKeyEvent = $.Event('keydown', { which: ENTER }); + widget.searchInput.trigger(enterKeyEvent); + // This does not currently catch failing behavior. For security reasons, + // browsers will not trigger default behavior (form submit, in this + // example) on JavaScript-created keypresses. + expect(submitSpy).not.toHaveBeenTriggered(); + // Does a worse job at capturing the intent of the test, but works. + expect(enterKeyEvent.isDefaultPrevented()).toBe(true); + }); }); }).call(this); -- cgit v1.2.1 From 237c8f66e6608420629503280aaea555ee980022 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 7 Oct 2016 15:24:09 +0200 Subject: Precalculate trending projects This commit introduces a Sidekiq worker that precalculates the list of trending projects on a daily basis. The resulting set is stored in a database table that is then queried by Project.trending. This setup means that Unicorn workers no longer _may_ have to calculate the list of trending projects. Furthermore it supports filtering without any complex caching mechanisms. The data in the "trending_projects" table is inserted in the same order as the project ranking. This means that getting the projects in the correct order is simply a matter of: SELECT projects.* FROM projects INNER JOIN trending_projects ON trending_projects.project_id = projects.id ORDER BY trending_projects.id ASC; Such a query will only take a few milliseconds at most (as measured on GitLab.com), opposed to a few seconds for the query used for calculating the project ranks. The migration in this commit does not require downtime and takes care of populating an initial list of trending projects. --- spec/finders/trending_projects_finder_spec.rb | 48 ----------------------- spec/models/project_spec.rb | 26 ++----------- spec/models/trending_project_spec.rb | 56 +++++++++++++++++++++++++++ spec/workers/trending_projects_worker_spec.rb | 11 ++++++ 4 files changed, 71 insertions(+), 70 deletions(-) delete mode 100644 spec/finders/trending_projects_finder_spec.rb create mode 100644 spec/models/trending_project_spec.rb create mode 100644 spec/workers/trending_projects_worker_spec.rb (limited to 'spec') diff --git a/spec/finders/trending_projects_finder_spec.rb b/spec/finders/trending_projects_finder_spec.rb deleted file mode 100644 index cfe15b9defa..00000000000 --- a/spec/finders/trending_projects_finder_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -require 'spec_helper' - -describe TrendingProjectsFinder do - let(:user) { create(:user) } - let(:public_project1) { create(:empty_project, :public) } - let(:public_project2) { create(:empty_project, :public) } - let(:private_project) { create(:empty_project, :private) } - let(:internal_project) { create(:empty_project, :internal) } - - before do - 3.times do - create(:note_on_commit, project: public_project1) - end - - 2.times do - create(:note_on_commit, project: public_project2, created_at: 5.weeks.ago) - end - - create(:note_on_commit, project: private_project) - create(:note_on_commit, project: internal_project) - end - - describe '#execute', caching: true do - context 'without an explicit time range' do - it 'returns public trending projects' do - projects = described_class.new.execute - - expect(projects).to eq([public_project1]) - end - end - - context 'with an explicit time range' do - it 'returns public trending projects' do - projects = described_class.new.execute(2) - - expect(projects).to eq([public_project1, public_project2]) - end - end - - it 'caches the list of projects' do - projects = described_class.new - - expect(Project).to receive(:trending).once - - 2.times { projects.execute } - end - end -end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 8aadfcb439b..dae546a0cdc 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -800,32 +800,14 @@ describe Project, models: true do end create(:note_on_commit, project: project2) - end - - describe 'without an explicit start date' do - subject { described_class.trending.to_a } - it 'sorts Projects by the amount of notes in descending order' do - expect(subject).to eq([project1, project2]) - end + TrendingProject.refresh! end - describe 'with an explicit start date' do - let(:date) { 2.months.ago } + subject { described_class.trending.to_a } - subject { described_class.trending(date).to_a } - - before do - 2.times do - # Little fix for special issue related to Fractional Seconds support for MySQL. - # See: https://github.com/rails/rails/pull/14359/files - create(:note_on_commit, project: project2, created_at: date + 1) - end - end - - it 'sorts Projects by the amount of notes in descending order' do - expect(subject).to eq([project2, project1]) - end + it 'sorts projects by the amount of notes in descending order' do + expect(subject).to eq([project1, project2]) end it 'does not take system notes into account' do diff --git a/spec/models/trending_project_spec.rb b/spec/models/trending_project_spec.rb new file mode 100644 index 00000000000..cc28c6d4004 --- /dev/null +++ b/spec/models/trending_project_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +describe TrendingProject do + let(:user) { create(:user) } + let(:public_project1) { create(:empty_project, :public) } + let(:public_project2) { create(:empty_project, :public) } + let(:public_project3) { create(:empty_project, :public) } + let(:private_project) { create(:empty_project, :private) } + let(:internal_project) { create(:empty_project, :internal) } + + before do + 3.times do + create(:note_on_commit, project: public_project1) + end + + 2.times do + create(:note_on_commit, project: public_project2) + end + + create(:note_on_commit, project: public_project3, created_at: 5.weeks.ago) + create(:note_on_commit, project: private_project) + create(:note_on_commit, project: internal_project) + end + + describe '.refresh!' do + before do + described_class.refresh! + end + + it 'populates the trending projects table' do + expect(described_class.count).to eq(2) + end + + it 'removes existing rows before populating the table' do + described_class.refresh! + + expect(described_class.count).to eq(2) + end + + it 'stores the project IDs for every trending project' do + rows = described_class.order(id: :asc).all + + expect(rows[0].project_id).to eq(public_project1.id) + expect(rows[1].project_id).to eq(public_project2.id) + end + + it 'does not store projects that fall out of the trending time range' do + expect(described_class.where(project_id: public_project3).any?).to eq(false) + end + + it 'stores only public projects' do + expect(described_class.where(project_id: [public_project1.id, public_project2.id]).count).to eq(2) + expect(described_class.where(project_id: [private_project.id, internal_project.id]).count).to eq(0) + end + end +end diff --git a/spec/workers/trending_projects_worker_spec.rb b/spec/workers/trending_projects_worker_spec.rb new file mode 100644 index 00000000000..c3c6fdcf2d5 --- /dev/null +++ b/spec/workers/trending_projects_worker_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe TrendingProjectsWorker do + describe '#perform' do + it 'refreshes the trending projects' do + expect(TrendingProject).to receive(:refresh!) + + described_class.new.perform + end + end +end -- cgit v1.2.1 From 33ce1976451ee8fc0275e0ae012755053d50ec34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 10 Oct 2016 13:35:26 +0200 Subject: API: New /users/:id/events endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/users_spec.rb | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index f4ea3bebb4c..56b2ec6271e 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -895,4 +895,59 @@ describe API::API, api: true do expect{put api("/users/ASDF/block", admin) }.to raise_error(ActionController::RoutingError) end end + + describe 'GET /user/:id/events' do + let(:user) { create(:user) } + let(:lambda_user) { create(:user) } + let(:project) { create(:empty_project) } + let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) } + + before do + project.add_user(user, :developer) + EventCreateService.new.leave_note(note, user) + end + + context "as a user than cannot see the event's project" do + it 'returns no events' do + get api("/users/#{user.id}/events", lambda_user) + + expect(response).to have_http_status(200) + expect(json_response).to be_empty + end + end + + context "as a user than can see the event's project" do + it_behaves_like 'a paginated resources' do + let(:request) { get api("/users/#{user.id}/events", user) } + end + + context 'joined event' do + it 'returns the "joined" event' do + get api("/users/#{user.id}/events", user) + + first_event = json_response.first + + expect(first_event['action_name']).to eq('commented on') + expect(first_event['project_id'].to_i).to eq(project.id) + expect(first_event['author_username']).to eq(user.username) + expect(first_event['note']['id']).to eq(note.id) + expect(first_event['note']['body']).to eq('What an awesome day!') + + last_event = json_response.last + + expect(last_event['action_name']).to eq('joined') + expect(last_event['project_id'].to_i).to eq(project.id) + expect(last_event['author_username']).to eq(user.username) + expect(last_event['author']['name']).to eq(user.name) + end + end + end + + it 'returns a 404 error if not found' do + get api('/users/42/events', user) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 User Not Found') + end + end end -- cgit v1.2.1 From 517895da4c1ca6201f952e443a579e4f2845e6e0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 10 Oct 2016 13:13:07 +0100 Subject: Don't run affix tabs in test env This was messing up other tests --- spec/features/merge_requests/sticky_tabs_spec.rb | 33 ------------------------ 1 file changed, 33 deletions(-) delete mode 100644 spec/features/merge_requests/sticky_tabs_spec.rb (limited to 'spec') diff --git a/spec/features/merge_requests/sticky_tabs_spec.rb b/spec/features/merge_requests/sticky_tabs_spec.rb deleted file mode 100644 index 3e8bd768324..00000000000 --- a/spec/features/merge_requests/sticky_tabs_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'spec_helper' - -feature 'Merge request tabs', js: true, feature: true do - include WaitForAjax - - let(:user) { create(:user) } - let(:project) { create(:project, :public) } - let(:merge_request) { create(:merge_request_with_diffs, source_project: project, author: user, title: "Bug NS-04") } - - before do - project.team << [user, :master] - login_as user - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) - - wait_for_ajax - end - - it 'affixes to top of page when scrolling' do - page.execute_script "window.scroll(0,10000)" - - expect(page).to have_selector('.js-tabs-affix.affix') - end - - it 'removes affix when scrolling to top' do - page.execute_script "window.scroll(0,10000)" - - expect(page).to have_selector('.js-tabs-affix.affix') - - page.execute_script "window.scroll(0,-10000)" - - expect(page).to have_selector('.js-tabs-affix.affix-top') - end -end -- cgit v1.2.1 From 66c32cab1af621caa6ae3cb24b82b344d43512a5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 7 Oct 2016 14:17:06 +0300 Subject: Remove NamespacesController The main purpose of this controller was redirect to group or user page when URL like https://gitlab.com/gitlab-org was used. Now this functionality is handled by contrainers and take user to correct controller right from the start Signed-off-by: Dmitriy Zaporozhets --- spec/controllers/namespaces_controller_spec.rb | 118 ------------------------- 1 file changed, 118 deletions(-) delete mode 100644 spec/controllers/namespaces_controller_spec.rb (limited to 'spec') diff --git a/spec/controllers/namespaces_controller_spec.rb b/spec/controllers/namespaces_controller_spec.rb deleted file mode 100644 index 2b334ed1172..00000000000 --- a/spec/controllers/namespaces_controller_spec.rb +++ /dev/null @@ -1,118 +0,0 @@ -require 'spec_helper' - -describe NamespacesController do - let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } - - describe "GET show" do - context "when the namespace belongs to a user" do - let!(:other_user) { create(:user) } - - it "redirects to the user's page" do - get :show, id: other_user.username - - expect(response).to redirect_to(user_path(other_user)) - end - end - - context "when the namespace belongs to a group" do - let!(:group) { create(:group) } - - context "when the group is public" do - context "when not signed in" do - it "redirects to the group's page" do - get :show, id: group.path - - expect(response).to redirect_to(group_path(group)) - end - end - - context "when signed in" do - before do - sign_in(user) - end - - it "redirects to the group's page" do - get :show, id: group.path - - expect(response).to redirect_to(group_path(group)) - end - end - end - - context "when the group is private" do - before do - group.update_attribute(:visibility_level, Group::PRIVATE) - end - - context "when not signed in" do - it "redirects to the sign in page" do - get :show, id: group.path - expect(response).to redirect_to(new_user_session_path) - end - end - - context "when signed in" do - before do - sign_in(user) - end - - context "when the user has access to the group" do - before do - group.add_developer(user) - end - - context "when the user is blocked" do - before do - user.block - end - - it "redirects to the sign in page" do - get :show, id: group.path - - expect(response).to redirect_to(new_user_session_path) - end - end - - context "when the user isn't blocked" do - it "redirects to the group's page" do - get :show, id: group.path - - expect(response).to redirect_to(group_path(group)) - end - end - end - - context "when the user doesn't have access to the group" do - it "responds with status 404" do - get :show, id: group.path - - expect(response).to have_http_status(404) - end - end - end - end - end - - context "when the namespace doesn't exist" do - context "when signed in" do - before do - sign_in(user) - end - - it "responds with status 404" do - get :show, id: "doesntexist" - - expect(response).to have_http_status(404) - end - end - - context "when not signed in" do - it "redirects to the sign in page" do - get :show, id: "doesntexist" - - expect(response).to redirect_to(new_user_session_path) - end - end - end - end -end -- cgit v1.2.1 From 68ab7047dae98172a0bd8b92956f2ee51b9167a0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 7 Oct 2016 14:53:49 +0300 Subject: Update git over http test to match new routing Signed-off-by: Dmitriy Zaporozhets --- spec/requests/git_http_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index c0c1e62e910..413d06715b3 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -412,10 +412,9 @@ describe 'Git HTTP requests', lib: true do context "when the params are anything else" do let(:params) { { service: 'git-implode-pack' } } - before { get path, params } - it "redirects to the sign-in page" do - expect(response).to redirect_to(new_user_session_path) + it "fails to find a route" do + expect { get(path, params) }.to raise_error(ActionController::RoutingError) end end end -- cgit v1.2.1 From d6cfc0042ed2ce9a33f31a6c44661c136e861b98 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 7 Oct 2016 16:39:57 +0300 Subject: Catch any undefined API routing and return 400 Bad Request Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/users_spec.rb | 4 ++-- spec/routing/routing_spec.rb | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index f4ea3bebb4c..c040000e8bb 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -90,9 +90,9 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns a 404 if invalid ID" do + it "returns a 400 if invalid ID" do get api("/users/1ASDF", user) - expect(response).to have_http_status(404) + expect(response).to have_http_status(400) end end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 0dd00af878d..0ee1c811dfb 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -266,7 +266,9 @@ describe "Groups", "routing" do end it "also display group#show on the short path" do - expect(get('/1')).to route_to('namespaces#show', id: '1') + allow(Group).to receive(:find_by_path).and_return(true) + + expect(get('/1')).to route_to('groups#show', id: '1') end end -- cgit v1.2.1 From fdfc93679d1ca91d4666095ba2ca732fdb273947 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 7 Oct 2016 18:39:04 +0300 Subject: Fix API specs behaviour for invalid routing Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/project_hooks_spec.rb | 5 ++-- spec/requests/api/users_spec.rb | 52 +++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index 765dc8a8f66..5d739802095 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -163,9 +163,10 @@ describe API::API, 'ProjectHooks', api: true do expect(response).to have_http_status(404) end - it "returns a 405 error if hook id not given" do + it "returns a 400 error if hook id not given" do delete api("/projects/#{project.id}/hooks", user) - expect(response).to have_http_status(405) + + expect(response).to have_http_status(400) end it "returns a 404 if a user attempts to delete project hooks he/she does not own" do diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index c040000e8bb..9537b0ec83d 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -92,6 +92,7 @@ describe API::API, api: true do it "returns a 400 if invalid ID" do get api("/users/1ASDF", user) + expect(response).to have_http_status(400) end end @@ -340,8 +341,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "raises error for invalid ID" do - expect{put api("/users/ASDF", admin) }.to raise_error(ActionController::RoutingError) + it "returns a 400 if invalid ID" do + put api("/users/ASDF", admin) + + expect(response).to have_http_status(400) end it 'returns 400 error if user does not validate' do @@ -525,9 +528,10 @@ describe API::API, api: true do expect(json_response.first['email']).to eq(email.email) end - it "raises error for invalid ID" do + it "returns a 400 for invalid ID" do put api("/users/ASDF/emails", admin) - expect(response).to have_http_status(405) + + expect(response).to have_http_status(400) end end end @@ -566,8 +570,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Email Not Found') end - it "raises error for invalid ID" do - expect{delete api("/users/ASDF/emails/bar", admin) }.to raise_error(ActionController::RoutingError) + it "returns a 400 for invalid ID" do + delete api("/users/ASDF/emails/bar", admin) + + expect(response).to have_http_status(400) end end end @@ -600,8 +606,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 User Not Found') end - it "raises error for invalid ID" do - expect{delete api("/users/ASDF", admin) }.to raise_error(ActionController::RoutingError) + it "returns a 400 for invalid ID" do + delete api("/users/ASDF", admin) + + expect(response).to have_http_status(400) end end @@ -667,9 +675,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns 404 for invalid ID" do + it "returns 400 for invalid ID" do get api("/users/keys/ASDF", admin) - expect(response).to have_http_status(404) + + expect(response).to have_http_status(400) end end @@ -727,8 +736,10 @@ describe API::API, api: true do expect(response).to have_http_status(401) end - it "raises error for invalid ID" do - expect{delete api("/users/keys/ASDF", admin) }.to raise_error(ActionController::RoutingError) + it "returns a 400 for invalid ID" do + delete api("/users/keys/ASDF", admin) + + expect(response).to have_http_status(400) end end @@ -776,9 +787,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns 404 for invalid ID" do + it "returns 400 for invalid ID" do get api("/users/emails/ASDF", admin) - expect(response).to have_http_status(404) + + expect(response).to have_http_status(400) end end @@ -825,8 +837,10 @@ describe API::API, api: true do expect(response).to have_http_status(401) end - it "raises error for invalid ID" do - expect{delete api("/users/emails/ASDF", admin) }.to raise_error(ActionController::RoutingError) + it "returns a 400 for invalid ID" do + delete api("/users/emails/ASDF", admin) + + expect(response).to have_http_status(400) end end @@ -891,8 +905,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 User Not Found') end - it "raises error for invalid ID" do - expect{put api("/users/ASDF/block", admin) }.to raise_error(ActionController::RoutingError) + it "returns a 400 for invalid ID" do + put api("/users/ASDF/block", admin) + + expect(response).to have_http_status(400) end end end -- cgit v1.2.1 From 137ebcfb3cb013174f2885776a47264cffd193a6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 7 Oct 2016 20:18:02 +0300 Subject: Replace undefined Grape routing code from 400 to 404 Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/project_hooks_spec.rb | 4 +-- spec/requests/api/users_spec.rb | 50 +++++++++++++++++---------------- 2 files changed, 28 insertions(+), 26 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index 5d739802095..cfcdcad74cd 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -163,10 +163,10 @@ describe API::API, 'ProjectHooks', api: true do expect(response).to have_http_status(404) end - it "returns a 400 error if hook id not given" do + it "returns a 404 error if hook id not given" do delete api("/projects/#{project.id}/hooks", user) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end it "returns a 404 if a user attempts to delete project hooks he/she does not own" do diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 9537b0ec83d..f0dd0592adb 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -90,10 +90,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns a 400 if invalid ID" do + it "returns a 404 for invalid ID" do get api("/users/1ASDF", user) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -341,10 +341,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns a 400 if invalid ID" do + it "returns a 404 if invalid ID" do put api("/users/ASDF", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end it 'returns 400 error if user does not validate' do @@ -410,9 +410,9 @@ describe API::API, api: true do end.to change{ user.keys.count }.by(1) end - it "returns 400 for invalid ID" do + it "returns 404 for invalid ID" do post api("/users/999999/keys", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -496,9 +496,10 @@ describe API::API, api: true do end.to change{ user.emails.count }.by(1) end - it "raises error for invalid ID" do + it "returns a 404 for invalid ID" do post api("/users/999999/emails", admin) - expect(response).to have_http_status(400) + + expect(response).to have_http_status(404) end end @@ -528,10 +529,10 @@ describe API::API, api: true do expect(json_response.first['email']).to eq(email.email) end - it "returns a 400 for invalid ID" do + it "returns a 404 for invalid ID" do put api("/users/ASDF/emails", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end end @@ -570,10 +571,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Email Not Found') end - it "returns a 400 for invalid ID" do + it "returns a 404 for invalid ID" do delete api("/users/ASDF/emails/bar", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end end @@ -606,10 +607,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 User Not Found') end - it "returns a 400 for invalid ID" do + it "returns a 404 for invalid ID" do delete api("/users/ASDF", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -662,6 +663,7 @@ describe API::API, api: true do it "returns 404 Not Found within invalid ID" do get api("/user/keys/42", user) + expect(response).to have_http_status(404) expect(json_response['message']).to eq('404 Not found') end @@ -675,10 +677,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns 400 for invalid ID" do + it "returns 404 for invalid ID" do get api("/users/keys/ASDF", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -736,10 +738,10 @@ describe API::API, api: true do expect(response).to have_http_status(401) end - it "returns a 400 for invalid ID" do + it "returns a 404 for invalid ID" do delete api("/users/keys/ASDF", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -787,10 +789,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end - it "returns 400 for invalid ID" do + it "returns 404 for invalid ID" do get api("/users/emails/ASDF", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -837,10 +839,10 @@ describe API::API, api: true do expect(response).to have_http_status(401) end - it "returns a 400 for invalid ID" do + it "returns a 404 for invalid ID" do delete api("/users/emails/ASDF", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end @@ -905,10 +907,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 User Not Found') end - it "returns a 400 for invalid ID" do + it "returns a 404 for invalid ID" do put api("/users/ASDF/block", admin) - expect(response).to have_http_status(400) + expect(response).to have_http_status(404) end end end -- cgit v1.2.1 From 3e49123dd5f8cb3c04184ce53e95f598e82a9f88 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 7 Oct 2016 21:09:41 +0300 Subject: Fix api users spec for post request with invalid id Signed-off-by: Dmitriy Zaporozhets --- spec/requests/api/users_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index f0dd0592adb..b002949b41b 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -410,9 +410,9 @@ describe API::API, api: true do end.to change{ user.keys.count }.by(1) end - it "returns 404 for invalid ID" do + it "returns 400 for invalid ID" do post api("/users/999999/keys", admin) - expect(response).to have_http_status(404) + expect(response).to have_http_status(400) end end @@ -496,10 +496,10 @@ describe API::API, api: true do end.to change{ user.emails.count }.by(1) end - it "returns a 404 for invalid ID" do + it "returns a 400 for invalid ID" do post api("/users/999999/emails", admin) - expect(response).to have_http_status(404) + expect(response).to have_http_status(400) end end -- cgit v1.2.1 From aac2af5bc42fbca355d7d5f5ab03ef662b876219 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 10 Oct 2016 15:46:26 +0100 Subject: HTMLEntityFilter -> HtmlEntityFilter --- spec/lib/banzai/filter/html_entity_filter_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/banzai/filter/html_entity_filter_spec.rb b/spec/lib/banzai/filter/html_entity_filter_spec.rb index 6dc4a970071..4c68ce6d6e4 100644 --- a/spec/lib/banzai/filter/html_entity_filter_spec.rb +++ b/spec/lib/banzai/filter/html_entity_filter_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Banzai::Filter::HTMLEntityFilter, lib: true do +describe Banzai::Filter::HtmlEntityFilter, lib: true do include FilterSpecHelper let(:unescaped) { 'foo &&&' } -- cgit v1.2.1 From 4917bbd7ffc9e7e67d93a08650d95d02a0a67081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 10 Oct 2016 17:03:34 +0200 Subject: Speed up specs for GET /projects/:id/events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 8.15s to 4.55s by grouping expectations Signed-off-by: Rémy Coutable --- spec/requests/api/projects_spec.rb | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5f19638b460..85717d274aa 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -588,37 +588,39 @@ describe API::API, api: true do before do note = create(:note_on_issue, note: 'What an awesome day!', project: project) EventCreateService.new.leave_note(note, note.author) - get api("/projects/#{project.id}/events", user) end - it { expect(response).to have_http_status(200) } + it 'returns all events' do + get api("/projects/#{project.id}/events", user) - context 'joined event' do - let(:json_event) { json_response[1] } + expect(response).to have_http_status(200) - it { expect(json_event['action_name']).to eq('joined') } - it { expect(json_event['project_id'].to_i).to eq(project.id) } - it { expect(json_event['author_username']).to eq(user3.username) } - it { expect(json_event['author']['name']).to eq(user3.name) } - end + first_event = json_response.first - context 'comment event' do - let(:json_event) { json_response.first } + expect(first_event['action_name']).to eq('commented on') + expect(first_event['note']['body']).to eq('What an awesome day!') - it { expect(json_event['action_name']).to eq('commented on') } - it { expect(json_event['note']['body']).to eq('What an awesome day!') } + last_event = json_response.last + + expect(last_event['action_name']).to eq('joined') + expect(last_event['project_id'].to_i).to eq(project.id) + expect(last_event['author_username']).to eq(user3.username) + expect(last_event['author']['name']).to eq(user3.name) end end it 'returns a 404 error if not found' do get api('/projects/42/events', user) + expect(response).to have_http_status(404) expect(json_response['message']).to eq('404 Project Not Found') end it 'returns a 404 error if user is not a member' do other_user = create(:user) + get api("/projects/#{project.id}/events", other_user) + expect(response).to have_http_status(404) end end -- cgit v1.2.1 From 6606642f8f352267d9f645778a789b79d98a6ca8 Mon Sep 17 00:00:00 2001 From: James Edwards-Jones Date: Mon, 10 Oct 2016 16:19:46 +0100 Subject: fixup! Added link to bulk assign issues to MR author. (Issue #18876) --- spec/controllers/projects/merge_requests_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 2a68e5a2c9b..84298f8bef4 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -742,7 +742,7 @@ describe Projects::MergeRequestsController do it 'calls MergeRequests::AssignIssuesService' do expect(MergeRequests::AssignIssuesService).to receive(:new). with(project, user, merge_request: merge_request). - and_return(double(execute: {count: 1})) + and_return(double(execute: { count: 1 })) post_assign_issues end -- cgit v1.2.1 From d4fab17d7c8c2b233248295755a6277fdee09c9f Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 7 Oct 2016 22:48:23 -0700 Subject: Fix Error 500 when viewing old merge requests with bad diff data Customers running old versions of GitLab may have MergeRequestDiffs with the text ["--broken diff"] due to text generated by gitlab_git 1.0.3. To avoid the Error 500, verify that each element is a type that gitlab_git will accept before attempting to create a DiffCollection. Closes #20776 --- spec/models/merge_request_diff_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 530a7def553..96f1f60dbc0 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -44,6 +44,16 @@ describe MergeRequestDiff, models: true do end end + context 'when the raw diffs have invalid content' do + before { mr_diff.update_attributes(st_diffs: ["--broken-diff"]) } + + it 'returns an empty DiffCollection' do + expect(mr_diff.raw_diffs.to_a).to be_empty + expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection) + expect(mr_diff.raw_diffs).to be_empty + end + end + context 'when the raw diffs exist' do it 'returns the diffs' do expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection) -- cgit v1.2.1 From 594c320851afbf4c8dd1c78600a0195f12d6ce41 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 10 Oct 2016 21:44:29 +0100 Subject: Adds tests to verify if tabs are rendered --- spec/features/environments_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 3b38a7f5007..99246589eae 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -18,11 +18,26 @@ feature 'Environments', feature: true do before do visit namespace_project_environments_path(project.namespace, project) end + + context 'shows two tabs' do + scenario 'does show Available tab with link' do + expect(page).to have_link('Available') + end + + scenario 'does show Stopped tab with link' do + expect(page).to have_link('Stopped') + end + end context 'without environments' do scenario 'does show no environments' do expect(page).to have_content('You don\'t have any environments right now.') end + + scenario 'does show 0 as counter for environments in both tabs' do + expect(page.find('.js-avaibale-environments-count').text).to eq('0') + expect(page.find('.js-stopped-environments-count').text).to eq('0') + end end context 'with environments' do -- cgit v1.2.1 From 0a79e5cd44e1d83f0cd18ffb538da25e6b2deae3 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Mon, 10 Oct 2016 16:21:08 -0500 Subject: Replace generic table with --- spec/features/merge_requests/created_from_fork_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb index 4d5d4aa121a..a506624b30d 100644 --- a/spec/features/merge_requests/created_from_fork_spec.rb +++ b/spec/features/merge_requests/created_from_fork_spec.rb @@ -45,7 +45,7 @@ feature 'Merge request created from fork' do page.within('.merge-request-tabs') { click_link 'Builds' } wait_for_ajax - page.within('table.builds') do + page.within('table.ci-table') do expect(page).to have_content 'rspec' expect(page).to have_content 'spinach' end -- cgit v1.2.1 From 73fff8d9e33d31b0958b7ef889a6ad3ff6dbf4c5 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Tue, 11 Oct 2016 10:58:46 +0500 Subject: Build instead create in label_link model spec --- spec/models/label_link_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb index 5e6f8ca1528..c18ed8574b1 100644 --- a/spec/models/label_link_spec.rb +++ b/spec/models/label_link_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' describe LabelLink, models: true do - let(:label) { create(:label_link) } - it { expect(label).to be_valid } + it { expect(build(:label_link)).to be_valid } it { is_expected.to belong_to(:label) } it { is_expected.to belong_to(:target) } -- cgit v1.2.1 From 85df1bf02dbcd180ad7db0c0e3c609671dac1a11 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Tue, 11 Oct 2016 11:02:53 +0500 Subject: Remove empty describe block on key spec model --- spec/models/key_spec.rb | 3 --- 1 file changed, 3 deletions(-) (limited to 'spec') diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index fd4a2beff58..7fc6ed1dd54 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -5,9 +5,6 @@ describe Key, models: true do it { is_expected.to belong_to(:user) } end - describe "Mass assignment" do - end - describe "Validation" do it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_presence_of(:key) } -- cgit v1.2.1 From ebba49149395ba6fb0f14c3aa9c46a496b234dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 7 Oct 2016 18:35:36 +0200 Subject: Add a new gitlab:users:clear_all_authentication_tokens task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/tasks/gitlab/users_rake_spec.rb | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 spec/tasks/gitlab/users_rake_spec.rb (limited to 'spec') diff --git a/spec/tasks/gitlab/users_rake_spec.rb b/spec/tasks/gitlab/users_rake_spec.rb new file mode 100644 index 00000000000..e6ebef82b78 --- /dev/null +++ b/spec/tasks/gitlab/users_rake_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' +require 'rake' + +describe 'gitlab:users namespace rake task' do + let(:enable_registry) { true } + + before :all do + Rake.application.rake_require 'tasks/gitlab/task_helpers' + Rake.application.rake_require 'tasks/gitlab/users' + + # empty task as env is already loaded + Rake::Task.define_task :environment + end + + def run_rake_task(task_name) + Rake::Task[task_name].reenable + Rake.application.invoke_task task_name + end + + describe 'clear_all_authentication_tokens' do + before do + # avoid writing task output to spec progress + allow($stdout).to receive :write + end + + context 'gitlab version' do + it 'clears the authentication token for all users' do + create_list(:user, 2) + + expect(User.pluck(:authentication_token)).to all(be_present) + + run_rake_task('gitlab:users:clear_all_authentication_tokens') + + expect(User.pluck(:authentication_token)).to all(be_nil) + end + end + end +end -- cgit v1.2.1 From 6c1690fcc03406ad3230cb05ba8701289a25ba28 Mon Sep 17 00:00:00 2001 From: Artem Sidorenko Date: Tue, 13 Sep 2016 23:05:16 +0200 Subject: Allow empty merge requests --- spec/services/merge_requests/build_service_spec.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index 0d586e2216b..3a3f07ddcb9 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -52,12 +52,28 @@ describe MergeRequests::BuildService, services: true do end end - context 'no commits in the diff' do - let(:commits) { [] } + context 'same source and target branch' do + let(:source_branch) { 'master' } it 'forbids the merge request from being created' do expect(merge_request.can_be_created).to eq(false) end + + it 'adds an error message to the merge request' do + expect(merge_request.errors).to contain_exactly('You must select different branches') + end + end + + context 'no commits in the diff' do + let(:commits) { [] } + + it 'allows the merge request to be created' do + expect(merge_request.can_be_created).to eq(true) + end + + it 'adds a WIP prefix to the merge request title' do + expect(merge_request.title).to eq('WIP: Feature branch') + end end context 'one commit in the diff' do -- cgit v1.2.1 From 7d12683de51721e75b314b29272f4f024f7f0655 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 11 Oct 2016 11:03:11 +0100 Subject: Fixes broken tests --- spec/features/environments_spec.rb | 47 ++++++++++++++++++++-- .../merge_when_build_succeeds_spec.rb | 9 +++++ 2 files changed, 53 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 99246589eae..a8244ca89c6 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -46,6 +46,14 @@ feature 'Environments', feature: true do scenario 'does show environment name' do expect(page).to have_link(environment.name) end + + scenario 'does show number of opened environments in Availabe tab' do + expect(page.find('.js-avaibale-environments-count').text).to eq('1') + end + + scenario 'does show number of closed environments in Stopped tab' do + expect(page.find('.js-stopped-environments-count').text).to eq('0') + end context 'without deployments' do scenario 'does show no deployments' do @@ -76,6 +84,16 @@ feature 'Environments', feature: true do expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end + + scenario 'does show close button' do + # TODO: Add test to verify if close button is visible + # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? + end + + scenario 'does allow to close environment' do + # TODO: Add test to verify if close environment works + # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? + end end end end @@ -137,6 +155,16 @@ feature 'Environments', feature: true do expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end + + scenario 'does show close button' do + # TODO: Add test to verify if close button is visible + # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? + end + + scenario 'does allow to close environment' do + # TODO: Add test to verify if close environment works + # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? + end end end end @@ -194,9 +222,22 @@ feature 'Environments', feature: true do context 'when logged as master' do given(:role) { :master } - scenario 'does close environment' do - click_link 'Close' - expect(page).not_to have_link(environment.name) + scenario 'does not have a Close link' do + expect(page).not_to have_link('Close') + end + + context 'when environment is opened and can be closed' do + let(:project) { create(:project) } + let(:environment) { create(:environment, project: project) } + + let!(:deployment) do + create(:deployment, environment: environment, sha: project.commit('master').id) + end + + scenario 'does have a Close link' do + # TODO: Add missing validation. In order to have Close link + # this must be true: last_deployment.try(:close_action) + end end end diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb index 60bc07bd1a0..2c1a45af596 100644 --- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb @@ -79,6 +79,15 @@ feature 'Merge When Build Succeeds', feature: true, js: true do end end + context 'Has Environment' do + let(:environment) { create(:environment, project: project) } + + it 'does show link to close the environment' do + # TODO add test to verify if the button is visible when this condition + # is met: if environment.closeable? + end + end + def visit_merge_request(merge_request) visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) end -- cgit v1.2.1 From 1022456bb15d18b05c14fe344950fb75c7c69f48 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 7 Oct 2016 16:49:48 +0100 Subject: Allow browsing branches that end with '.atom' We need to do two things to support this: 1. Simplify the regex capture in the routing for the CommitsController to not exclude the '.atom' suffix. That's a perfectly valid git branch name, so we shouldn't blow up if we get it. 2. Because Rails now can't automatically detect the request format, add some code to do so in `ExtractPath` when there is no path. This means that, given branches 'foo' and 'foo.atom', the Atom feed for the former is unroutable. To fix this: don't do that! Give the branches different names! --- .../projects/commits_controller_spec.rb | 41 +++++++--- spec/lib/extracts_path_spec.rb | 87 +++++++++++++++++++++- spec/routing/project_routing_spec.rb | 2 +- 3 files changed, 119 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb index 2518a48e336..1ac7e03a2db 100644 --- a/spec/controllers/projects/commits_controller_spec.rb +++ b/spec/controllers/projects/commits_controller_spec.rb @@ -10,15 +10,38 @@ describe Projects::CommitsController do end describe "GET show" do - context "as atom feed" do - it "renders as atom" do - get(:show, - namespace_id: project.namespace.to_param, - project_id: project.to_param, - id: "master", - format: "atom") - expect(response).to be_success - expect(response.content_type).to eq('application/atom+xml') + context "when the ref name ends in .atom" do + render_views + + context "when the ref does not exist with the suffix" do + it "renders as atom" do + get(:show, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: "master.atom") + + expect(response).to be_success + expect(response.content_type).to eq('application/atom+xml') + end + end + + context "when the ref exists with the suffix" do + before do + commit = project.repository.commit('master') + + allow_any_instance_of(Repository).to receive(:commit).and_call_original + allow_any_instance_of(Repository).to receive(:commit).with('master.atom').and_return(commit) + + get(:show, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: "master.atom") + end + + it "renders as HTML" do + expect(response).to be_success + expect(response.content_type).to eq('text/html') + end end end end diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index e10c1f5c547..0e85e302f29 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -6,6 +6,7 @@ describe ExtractsPath, lib: true do include Gitlab::Routing.url_helpers let(:project) { double('project') } + let(:request) { double('request') } before do @project = project @@ -15,9 +16,10 @@ describe ExtractsPath, lib: true do allow(project).to receive(:repository).and_return(repo) allow(project).to receive(:path_with_namespace). and_return('gitlab/gitlab-ci') + allow(request).to receive(:format=) end - describe '#assign_ref' do + describe '#assign_ref_vars' do let(:ref) { sample_commit[:id] } let(:params) { { path: sample_commit[:line_code_path], ref: ref } } @@ -61,6 +63,75 @@ describe ExtractsPath, lib: true do expect(@id).to eq(get_id) end end + + context 'ref only exists without .atom suffix' do + context 'with a path' do + let(:params) { { ref: 'v1.0.0.atom', path: 'README.md' } } + + it 'renders a 404' do + expect(self).to receive(:render_404) + + assign_ref_vars + end + end + + context 'without a path' do + let(:params) { { ref: 'v1.0.0.atom' } } + before { assign_ref_vars } + + it 'sets the un-suffixed version as @ref' do + expect(@ref).to eq('v1.0.0') + end + + it 'sets the request format to Atom' do + expect(request).to have_received(:format=).with(:atom) + end + end + end + + context 'ref exists with .atom suffix' do + context 'with a path' do + let(:params) { { ref: 'master.atom', path: 'README.md' } } + + before do + repository = @project.repository + allow(repository).to receive(:commit).and_call_original + allow(repository).to receive(:commit).with('master.atom').and_return(repository.commit('master')) + + assign_ref_vars + end + + it 'sets the suffixed version as @ref' do + expect(@ref).to eq('master.atom') + end + + it 'does not change the request format' do + expect(request).not_to have_received(:format=) + end + end + + context 'without a path' do + let(:params) { { ref: 'master.atom' } } + + before do + repository = @project.repository + allow(repository).to receive(:commit).and_call_original + allow(repository).to receive(:commit).with('master.atom').and_return(repository.commit('master')) + end + + it 'sets the suffixed version as @ref' do + assign_ref_vars + + expect(@ref).to eq('master.atom') + end + + it 'does not change the request format' do + expect(request).not_to receive(:format=) + + assign_ref_vars + end + end + end end describe '#extract_ref' do @@ -115,4 +186,18 @@ describe ExtractsPath, lib: true do end end end + + describe '#extract_ref_without_atom' do + it 'ignores any matching refs suffixed with atom' do + expect(extract_ref_without_atom('master.atom')).to eq('master') + end + + it 'returns the longest matching ref' do + expect(extract_ref_without_atom('release/app/v1.0.0.atom')).to eq('release/app/v1.0.0') + end + + it 'returns nil if there are no matching refs' do + expect(extract_ref_without_atom('foo.atom')).to eq(nil) + end + end end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 77842057a10..2322430d212 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -337,7 +337,7 @@ describe Projects::CommitsController, 'routing' do end it 'to #show' do - expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'atom') + expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom') end end -- cgit v1.2.1 From 8caf097a162cc43cea59162600bbb1fbc981f0bc Mon Sep 17 00:00:00 2001 From: henrik Date: Tue, 11 Oct 2016 15:41:10 +0200 Subject: Convert unicode emojis to images. --- spec/lib/banzai/filter/emoji_filter_spec.rb | 71 ++++++++++++++++++++++++++++- spec/models/merge_request_diff_spec.rb | 10 ++++ 2 files changed, 79 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/banzai/filter/emoji_filter_spec.rb b/spec/lib/banzai/filter/emoji_filter_spec.rb index b5b38cf0c8c..475160bb5ec 100644 --- a/spec/lib/banzai/filter/emoji_filter_spec.rb +++ b/spec/lib/banzai/filter/emoji_filter_spec.rb @@ -12,11 +12,14 @@ describe Banzai::Filter::EmojiFilter, lib: true do ActionController::Base.asset_host = @original_asset_host end - it 'replaces supported emoji' do + it 'replaces supported name emoji' do doc = filter('

    :heart:

    ') expect(doc.css('img').first.attr('src')).to eq 'https://foo.com/assets/2764.png' end - + it 'replaces supported unicode emoji' do + doc = filter('

    ❤️

    ') + expect(doc.css('img').first.attr('src')).to eq 'https://foo.com/assets/2764.png' + end it 'ignores unsupported emoji' do exp = act = '

    :foo:

    ' doc = filter(act) @@ -28,46 +31,96 @@ describe Banzai::Filter::EmojiFilter, lib: true do expect(doc.css('img').first.attr('src')).to eq 'https://foo.com/assets/1F44D.png' end + it 'correctly encodes unicode to the URL' do + doc = filter('

    👍

    ') + expect(doc.css('img').first.attr('src')).to eq 'https://foo.com/assets/1F44D.png' + end + it 'matches at the start of a string' do doc = filter(':+1:') expect(doc.css('img').size).to eq 1 end + it 'unicode matches at the start of a string' do + doc = filter("'👍'") + expect(doc.css('img').size).to eq 1 + end + it 'matches at the end of a string' do doc = filter('This gets a :-1:') expect(doc.css('img').size).to eq 1 end + it 'unicode matches at the end of a string' do + doc = filter('This gets a 👍') + expect(doc.css('img').size).to eq 1 + end + it 'matches with adjacent text' do doc = filter('+1 (:+1:)') expect(doc.css('img').size).to eq 1 end + it 'unicode matches with adjacent text' do + doc = filter('+1 (👍)') + expect(doc.css('img').size).to eq 1 + end + it 'matches multiple emoji in a row' do doc = filter(':see_no_evil::hear_no_evil::speak_no_evil:') expect(doc.css('img').size).to eq 3 end + it 'unicode matches multiple emoji in a row' do + doc = filter("'🙈🙉🙊'") + expect(doc.css('img').size).to eq 3 + end + + it 'mixed matches multiple emoji in a row' do + doc = filter("'🙈:see_no_evil:🙉:hear_no_evil:🙊:speak_no_evil:'") + expect(doc.css('img').size).to eq 6 + end + it 'has a title attribute' do doc = filter(':-1:') expect(doc.css('img').first.attr('title')).to eq ':-1:' end + it 'unicode has a title attribute' do + doc = filter("'👎'") + expect(doc.css('img').first.attr('title')).to eq ':thumbsdown:' + end + it 'has an alt attribute' do doc = filter(':-1:') expect(doc.css('img').first.attr('alt')).to eq ':-1:' end + it 'unicode has an alt attribute' do + doc = filter("'👎'") + expect(doc.css('img').first.attr('alt')).to eq ':thumbsdown:' + end + it 'has an align attribute' do doc = filter(':8ball:') expect(doc.css('img').first.attr('align')).to eq 'absmiddle' end + it 'unicode has an align attribute' do + doc = filter("'🎱'") + expect(doc.css('img').first.attr('align')).to eq 'absmiddle' + end + it 'has an emoji class' do doc = filter(':cat:') expect(doc.css('img').first.attr('class')).to eq 'emoji' end + it 'unicode has an emoji class' do + doc = filter("'🐱'") + expect(doc.css('img').first.attr('class')).to eq 'emoji' + end + it 'has height and width attributes' do doc = filter(':dog:') img = doc.css('img').first @@ -76,12 +129,26 @@ describe Banzai::Filter::EmojiFilter, lib: true do expect(img.attr('height')).to eq '20' end + it 'unicode has height and width attributes' do + doc = filter("'🐶'") + img = doc.css('img').first + + expect(img.attr('width')).to eq '20' + expect(img.attr('height')).to eq '20' + end + it 'keeps whitespace intact' do doc = filter('This deserves a :+1:, big time.') expect(doc.to_html).to match(/^This deserves a , big time\.\z/) end + it 'unicode keeps whitespace intact' do + doc = filter('This deserves a 🎱, big time.') + + expect(doc.to_html).to match(/^This deserves a , big time\.\z/) + end + it 'uses a custom asset_root context' do root = Gitlab.config.gitlab.url + 'gitlab/root' diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 530a7def553..96f1f60dbc0 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -44,6 +44,16 @@ describe MergeRequestDiff, models: true do end end + context 'when the raw diffs have invalid content' do + before { mr_diff.update_attributes(st_diffs: ["--broken-diff"]) } + + it 'returns an empty DiffCollection' do + expect(mr_diff.raw_diffs.to_a).to be_empty + expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection) + expect(mr_diff.raw_diffs).to be_empty + end + end + context 'when the raw diffs exist' do it 'returns the diffs' do expect(mr_diff.raw_diffs).to be_a(Gitlab::Git::DiffCollection) -- cgit v1.2.1 From b4004488f76d7360acd2f38277d617447c76b888 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 4 Oct 2016 15:52:08 +0300 Subject: Make guests unable to view MRs --- .../projects/guest_navigation_menu_spec.rb | 28 +++++++++++ .../security/project/private_access_spec.rb | 2 +- spec/models/event_spec.rb | 11 +++++ spec/policies/project_policy_spec.rb | 5 +- .../services/merge_requests/update_service_spec.rb | 6 +++ spec/services/notification_service_spec.rb | 57 +++++++++++++++++++++- spec/services/todo_service_spec.rb | 22 ++++++++- 7 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 spec/features/projects/guest_navigation_menu_spec.rb (limited to 'spec') diff --git a/spec/features/projects/guest_navigation_menu_spec.rb b/spec/features/projects/guest_navigation_menu_spec.rb new file mode 100644 index 00000000000..c22441f8929 --- /dev/null +++ b/spec/features/projects/guest_navigation_menu_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe "Guest navigation menu" do + let(:project) { create :empty_project, :private } + let(:guest) { create :user } + + before do + project.team << [guest, :guest] + + login_as(guest) + end + + it "shows allowed tabs only" do + visit namespace_project_path(project.namespace, project) + + within(".nav-links") do + expect(page).to have_content 'Project' + expect(page).to have_content 'Activity' + expect(page).to have_content 'Issues' + expect(page).to have_content 'Wiki' + + expect(page).not_to have_content 'Repository' + expect(page).not_to have_content 'Pipelines' + expect(page).not_to have_content 'Graphs' + expect(page).not_to have_content 'Merge Requests' + end + end +end diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index ccb5c06dab0..79417c769a8 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -203,7 +203,7 @@ describe "Private Project Access", feature: true do it { is_expected.to be_allowed_for master } it { is_expected.to be_allowed_for developer } it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for guest } it { is_expected.to be_denied_for :user } it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index af5002487cc..06cac929bbf 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -135,6 +135,17 @@ describe Event, models: true do it { expect(event.visible_to_user?(member)).to eq true } it { expect(event.visible_to_user?(guest)).to eq true } it { expect(event.visible_to_user?(admin)).to eq true } + + context 'private project' do + let(:project) { create(:project, :private) } + + it { expect(event.visible_to_user?(non_member)).to eq false } + it { expect(event.visible_to_user?(author)).to eq true } + it { expect(event.visible_to_user?(assignee)).to eq true } + it { expect(event.visible_to_user?(member)).to eq true } + it { expect(event.visible_to_user?(guest)).to eq false } + it { expect(event.visible_to_user?(admin)).to eq true } + end end end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 43c8d884a47..658e3c13a73 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -12,7 +12,7 @@ describe ProjectPolicy, models: true do [ :read_project, :read_board, :read_list, :read_wiki, :read_issue, :read_label, :read_milestone, :read_project_snippet, :read_project_member, - :read_merge_request, :read_note, :create_project, :create_issue, :create_note, + :read_note, :create_project, :create_issue, :create_note, :upload_file ] end @@ -21,7 +21,8 @@ describe ProjectPolicy, models: true do [ :download_code, :fork_project, :create_project_snippet, :update_issue, :admin_issue, :admin_label, :admin_list, :read_commit_status, :read_build, - :read_container_image, :read_pipeline, :read_environment, :read_deployment + :read_container_image, :read_pipeline, :read_environment, :read_deployment, + :read_merge_request ] end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 33db34c0f62..fd5f94047c2 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -17,6 +17,7 @@ describe MergeRequests::UpdateService, services: true do before do project.team << [user, :master] project.team << [user2, :developer] + project.team << [user3, :developer] end describe 'execute' do @@ -188,6 +189,11 @@ describe MergeRequests::UpdateService, services: true do let!(:non_subscriber) { create(:user) } let!(:subscriber) { create(:user).tap { |u| label.toggle_subscription(u) } } + before do + project.team << [non_subscriber, :developer] + project.team << [subscriber, :developer] + end + it 'sends notifications for subscribers of newly added labels' do opts = { label_ids: [label.id] } diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index d820646ebdf..699b9925b4e 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -331,7 +331,7 @@ describe NotificationService, services: true do describe '#new_note' do it "records sent notifications" do # Ensure create SentNotification by noteable = merge_request 6 times, not noteable = note - expect(SentNotification).to receive(:record_note).with(note, any_args).exactly(4).times.and_call_original + expect(SentNotification).to receive(:record_note).with(note, any_args).exactly(3).times.and_call_original notification.new_note(note) @@ -1169,6 +1169,61 @@ describe NotificationService, services: true do end end + context 'guest user in private project' do + let(:private_project) { create(:empty_project, :private) } + let(:guest) { create(:user) } + let(:developer) { create(:user) } + let(:assignee) { create(:user) } + let(:merge_request) { create(:merge_request, source_project: private_project, assignee: assignee) } + let(:merge_request1) { create(:merge_request, source_project: private_project, assignee: assignee, description: "cc @#{guest.username}") } + let(:note) { create(:note, noteable: merge_request, project: private_project) } + + before do + private_project.team << [assignee, :developer] + private_project.team << [developer, :developer] + private_project.team << [guest, :guest] + + ActionMailer::Base.deliveries.clear + end + + it 'filters out guests when new note is created' do + expect(SentNotification).to receive(:record).with(merge_request, any_args).exactly(1).times + + notification.new_note(note) + + should_not_email(guest) + should_email(assignee) + end + + it 'filters out guests when new merge request is created' do + notification.new_merge_request(merge_request1, @u_disabled) + + should_not_email(guest) + should_email(assignee) + end + + it 'filters out guests when merge request is closed' do + notification.close_mr(merge_request, developer) + + should_not_email(guest) + should_email(assignee) + end + + it 'filters out guests when merge request is reopened' do + notification.reopen_mr(merge_request, developer) + + should_not_email(guest) + should_email(assignee) + end + + it 'filters out guests when merge request is merged' do + notification.merge_mr(merge_request, developer) + + should_not_email(guest) + should_email(assignee) + end + end + def build_team(project) @u_watcher = create_global_setting_for(create(:user), :watch) @u_participating = create_global_setting_for(create(:user), :participating) diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index b41f6f14fbd..ed55791d24e 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -345,7 +345,7 @@ describe TodoService, services: true do service.new_merge_request(mr_assigned, author) should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED) - should_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) should_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED) @@ -357,7 +357,7 @@ describe TodoService, services: true do service.update_merge_request(mr_assigned, author) should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED) - should_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) should_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) should_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED) @@ -381,6 +381,7 @@ describe TodoService, services: true do should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) should_not_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED) should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED) + should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) end it 'does not raise an error when description not change' do @@ -430,6 +431,11 @@ describe TodoService, services: true do should_create_todo(user: john_doe, target: mr_assigned, author: john_doe, action: Todo::ASSIGNED) end + + it 'does not create a todo for guests' do + service.reassigned_merge_request(mr_assigned, author) + should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) + end end describe '#merge_merge_request' do @@ -441,6 +447,11 @@ describe TodoService, services: true do expect(first_todo.reload).to be_done expect(second_todo.reload).to be_done end + + it 'does not create todo for guests' do + service.merge_merge_request(mr_assigned, john_doe) + should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) + end end describe '#new_award_emoji' do @@ -495,6 +506,13 @@ describe TodoService, services: true do should_create_todo(user: john_doe, target: mr_unassigned, author: author, action: Todo::MENTIONED, note: legacy_diff_note_on_merge_request) end + + it 'does not create todo for guests' do + note_on_merge_request = create :note_on_merge_request, project: project, noteable: mr_assigned, note: mentions + service.new_note(note_on_merge_request, author) + + should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED) + end end end -- cgit v1.2.1 From fb5a4202062d07d2dbca544f4cfb475a65411716 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 11:42:37 -0300 Subject: Allow projects to have many boards --- spec/models/project_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index dae546a0cdc..3748b1c7f5f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -24,7 +24,7 @@ describe Project, models: true do it { is_expected.to have_one(:slack_service).dependent(:destroy) } it { is_expected.to have_one(:pushover_service).dependent(:destroy) } it { is_expected.to have_one(:asana_service).dependent(:destroy) } - it { is_expected.to have_one(:board).dependent(:destroy) } + it { is_expected.to have_many(:boards).dependent(:destroy) } it { is_expected.to have_one(:campfire_service).dependent(:destroy) } it { is_expected.to have_one(:drone_ci_service).dependent(:destroy) } it { is_expected.to have_one(:emails_on_push_service).dependent(:destroy) } -- cgit v1.2.1 From 95a5cc9285a8583988ece697ebdb948730b5db55 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 6 Oct 2016 15:58:28 -0300 Subject: Restrict the number of permitted boards per project to one --- spec/models/project_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 3748b1c7f5f..1b13f1be477 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -94,6 +94,15 @@ describe Project, models: true do end end end + + describe '#boards' do + it 'raises an error when attempting to add more than one board to the project' do + subject.boards.build + + expect { subject.boards.build }.to raise_error(StandardError, 'Number of permitted boards exceeded') + expect(subject.boards.size).to eq 1 + end + end end describe 'modules' do -- cgit v1.2.1 From e46a4aabd925e0182c31976b5d28c38b9a8a0872 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 6 Oct 2016 16:20:21 -0300 Subject: Update Boards::CreateService to handle with the has_many association --- spec/factories/boards.rb | 5 +++++ spec/factories/projects.rb | 8 -------- spec/services/boards/create_service_spec.rb | 22 ++++++++++------------ 3 files changed, 15 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/factories/boards.rb b/spec/factories/boards.rb index 35c4a0b6f08..ec46146d9b5 100644 --- a/spec/factories/boards.rb +++ b/spec/factories/boards.rb @@ -1,5 +1,10 @@ FactoryGirl.define do factory :board do project factory: :empty_project + + after(:create) do |board| + board.lists.create(list_type: :backlog) + board.lists.create(list_type: :done) + end end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 331172445e4..719ef17f57e 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -124,12 +124,4 @@ FactoryGirl.define do ) end end - - factory :project_with_board, parent: :empty_project do - after(:create) do |project| - project.create_board - project.board.lists.create(list_type: :backlog) - project.board.lists.create(list_type: :done) - end - end end diff --git a/spec/services/boards/create_service_spec.rb b/spec/services/boards/create_service_spec.rb index a1a4dd4c57c..fde807cc410 100644 --- a/spec/services/boards/create_service_spec.rb +++ b/spec/services/boards/create_service_spec.rb @@ -2,33 +2,31 @@ require 'spec_helper' describe Boards::CreateService, services: true do describe '#execute' do + let(:project) { create(:empty_project) } + subject(:service) { described_class.new(project, double) } context 'when project does not have a board' do - let(:project) { create(:empty_project, board: nil) } - it 'creates a new board' do expect { service.execute }.to change(Board, :count).by(1) end it 'creates default lists' do - service.execute + board = service.execute - expect(project.board.lists.size).to eq 2 - expect(project.board.lists.first).to be_backlog - expect(project.board.lists.last).to be_done + expect(board.lists.size).to eq 2 + expect(board.lists.first).to be_backlog + expect(board.lists.last).to be_done end end context 'when project has a board' do - let!(:project) { create(:project_with_board) } - - it 'does not create a new board' do - expect { service.execute }.not_to change(Board, :count) + before do + create(:board, project: project) end - it 'does not create board lists' do - expect { service.execute }.not_to change(project.board.lists, :count) + it 'does not create a new board' do + expect { service.execute }.not_to change(project.boards, :count) end end end -- cgit v1.2.1 From a2c485473a142a5aad2f03abefb4bfafed645995 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 13:54:46 -0300 Subject: Add Boards::Lists::ListService to list lists for a specific board --- spec/services/boards/lists/list_service_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 spec/services/boards/lists/list_service_spec.rb (limited to 'spec') diff --git a/spec/services/boards/lists/list_service_spec.rb b/spec/services/boards/lists/list_service_spec.rb new file mode 100644 index 00000000000..4464f80f796 --- /dev/null +++ b/spec/services/boards/lists/list_service_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe Boards::Lists::ListService, services: true do + describe '#execute' do + it "returns board's lists" do + project = create(:empty_project) + board = create(:board, project: project) + label = create(:label, project: project) + backlog_list = create(:backlog_list, board: board) + list = create(:list, board: board, label: label) + done_list = create(:done_list, board: board) + + service = described_class.new(project, double) + + expect(service.execute(board)).to eq [backlog_list, list, done_list] + end + end +end -- cgit v1.2.1 From 9110746370c9759402af5087a612cbcfdf667c3c Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 14:00:18 -0300 Subject: Update Boards::Lists::CreateService to create lists for a specific board --- spec/services/boards/lists/create_service_spec.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/lists/create_service_spec.rb b/spec/services/boards/lists/create_service_spec.rb index bff9c1fd1fe..e7806add916 100644 --- a/spec/services/boards/lists/create_service_spec.rb +++ b/spec/services/boards/lists/create_service_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe Boards::Lists::CreateService, services: true do describe '#execute' do - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } let(:label) { create(:label, project: project, name: 'in-progress') } @@ -11,7 +11,7 @@ describe Boards::Lists::CreateService, services: true do context 'when board lists is empty' do it 'creates a new list at beginning of the list' do - list = service.execute + list = service.execute(board) expect(list.position).to eq 0 end @@ -19,7 +19,7 @@ describe Boards::Lists::CreateService, services: true do context 'when board lists has backlog, and done lists' do it 'creates a new list at beginning of the list' do - list = service.execute + list = service.execute(board) expect(list.position).to eq 0 end @@ -30,7 +30,7 @@ describe Boards::Lists::CreateService, services: true do create(:list, board: board, position: 0) create(:list, board: board, position: 1) - list = service.execute + list = service.execute(board) expect(list.position).to eq 2 end @@ -40,7 +40,7 @@ describe Boards::Lists::CreateService, services: true do it 'creates a new list at end of the label lists' do list1 = create(:list, board: board, position: 0) - list2 = service.execute + list2 = service.execute(board) expect(list1.reload.position).to eq 0 expect(list2.reload.position).to eq 1 @@ -52,7 +52,7 @@ describe Boards::Lists::CreateService, services: true do label = create(:label, name: 'in-development') service = described_class.new(project, user, label_id: label.id) - expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) + expect { service.execute(board) }.to raise_error(ActiveRecord::RecordNotFound) end end end -- cgit v1.2.1 From af87cf7c6ee1778b283ed285cdd7edbaaffc5fa5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 14:06:34 -0300 Subject: Update Boards::Lists::GenerateService to generate for a specific board --- spec/services/boards/lists/generate_service_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/lists/generate_service_spec.rb b/spec/services/boards/lists/generate_service_spec.rb index 4171e4d816c..8b2f5e81338 100644 --- a/spec/services/boards/lists/generate_service_spec.rb +++ b/spec/services/boards/lists/generate_service_spec.rb @@ -2,15 +2,15 @@ require 'spec_helper' describe Boards::Lists::GenerateService, services: true do describe '#execute' do - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } subject(:service) { described_class.new(project, user) } context 'when board lists is empty' do it 'creates the default lists' do - expect { service.execute }.to change(board.lists, :count).by(2) + expect { service.execute(board) }.to change(board.lists, :count).by(2) end end @@ -18,13 +18,13 @@ describe Boards::Lists::GenerateService, services: true do it 'does not creates the default lists' do create(:list, board: board) - expect { service.execute }.not_to change(board.lists, :count) + expect { service.execute(board) }.not_to change(board.lists, :count) end end context 'when project labels does not contains any list label' do it 'creates labels' do - expect { service.execute }.to change(project.labels, :count).by(2) + expect { service.execute(board) }.to change(project.labels, :count).by(2) end end @@ -32,7 +32,7 @@ describe Boards::Lists::GenerateService, services: true do it 'creates the missing labels' do create(:label, project: project, name: 'Doing') - expect { service.execute }.to change(project.labels, :count).by(1) + expect { service.execute(board) }.to change(project.labels, :count).by(1) end end end -- cgit v1.2.1 From 1a4b1e9735c8b3502d54f1e9ecbce0c3f235f5c7 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 14:13:43 -0300 Subject: Update Boards::Lists::MoveService to move lists inside a specific board --- spec/services/boards/lists/move_service_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/lists/move_service_spec.rb b/spec/services/boards/lists/move_service_spec.rb index 102ed67449d..63fa0bb8c5f 100644 --- a/spec/services/boards/lists/move_service_spec.rb +++ b/spec/services/boards/lists/move_service_spec.rb @@ -2,16 +2,16 @@ require 'spec_helper' describe Boards::Lists::MoveService, services: true do describe '#execute' do - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } - let!(:backlog) { project.board.backlog_list } + let!(:backlog) { create(:backlog_list, board: board) } let!(:planning) { create(:list, board: board, position: 0) } let!(:development) { create(:list, board: board, position: 1) } let!(:review) { create(:list, board: board, position: 2) } let!(:staging) { create(:list, board: board, position: 3) } - let!(:done) { project.board.done_list } + let!(:done) { create(:done_list, board: board) } context 'when list type is set to label' do it 'keeps position of lists when new position is nil' do -- cgit v1.2.1 From 1fa3f30811c3599a2f060803b201441046926b87 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 14:26:28 -0300 Subject: Update Boards::Issues::ListService to list issues for a board list --- spec/services/boards/issues/list_service_spec.rb | 31 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index 5b9f454fd2d..cc96fd05189 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -4,7 +4,7 @@ describe Boards::Issues::ListService, services: true do describe '#execute' do let(:user) { create(:user) } let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:board) { create(:board, project: project) } let(:bug) { create(:label, project: project, name: 'Bug') } let(:development) { create(:label, project: project, name: 'Development') } @@ -13,10 +13,10 @@ describe Boards::Issues::ListService, services: true do let(:p2) { create(:label, title: 'P2', project: project, priority: 2) } let(:p3) { create(:label, title: 'P3', project: project, priority: 3) } - let!(:backlog) { project.board.backlog_list } + let!(:backlog) { create(:backlog_list, board: board) } let!(:list1) { create(:list, board: board, label: development, position: 0) } let!(:list2) { create(:list, board: board, label: testing, position: 1) } - let!(:done) { project.board.done_list } + let!(:done) { create(:done_list, board: board) } let!(:opened_issue1) { create(:labeled_issue, project: project, labels: [bug]) } let!(:opened_issue2) { create(:labeled_issue, project: project, labels: [p2]) } @@ -37,7 +37,7 @@ describe Boards::Issues::ListService, services: true do end it 'delegates search to IssuesFinder' do - params = { id: list1.id } + params = { board_id: board.id, id: list1.id } expect_any_instance_of(IssuesFinder).to receive(:execute).once.and_call_original @@ -46,7 +46,7 @@ describe Boards::Issues::ListService, services: true do context 'sets default order to priority' do it 'returns opened issues when listing issues from Backlog' do - params = { id: backlog.id } + params = { board_id: board.id, id: backlog.id } issues = described_class.new(project, user, params).execute @@ -54,7 +54,7 @@ describe Boards::Issues::ListService, services: true do end it 'returns closed issues when listing issues from Done' do - params = { id: done.id } + params = { board_id: board.id, id: done.id } issues = described_class.new(project, user, params).execute @@ -62,12 +62,29 @@ describe Boards::Issues::ListService, services: true do end it 'returns opened issues that have label list applied when listing issues from a label list' do - params = { id: list1.id } + params = { board_id: board.id, id: list1.id } issues = described_class.new(project, user, params).execute expect(issues).to eq [list1_issue3, list1_issue1, list1_issue2] end end + + context 'with list that does not belongs to the board' do + it 'raises an error' do + list = create(:list) + service = described_class.new(project, user, board_id: board.id, id: list.id) + + expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'with invalid list id' do + it 'raises an error' do + service = described_class.new(project, user, board_id: board.id, id: nil) + + expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) + end + end end end -- cgit v1.2.1 From 104c4f88cdc5aaa40334c83112f7c994ff7128c6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 14:32:53 -0300 Subject: Update Boards::Issues::MoveService to move issues on a specific board --- spec/services/boards/issues/move_service_spec.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb index 180f1b08631..9cf5a17e128 100644 --- a/spec/services/boards/issues/move_service_spec.rb +++ b/spec/services/boards/issues/move_service_spec.rb @@ -3,17 +3,17 @@ require 'spec_helper' describe Boards::Issues::MoveService, services: true do describe '#execute' do let(:user) { create(:user) } - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:bug) { create(:label, project: project, name: 'Bug') } let(:development) { create(:label, project: project, name: 'Development') } let(:testing) { create(:label, project: project, name: 'Testing') } - let!(:backlog) { project.board.backlog_list } + let!(:backlog) { create(:backlog_list, board: board) } let!(:list1) { create(:list, board: board, label: development, position: 0) } let!(:list2) { create(:list, board: board, label: testing, position: 1) } - let!(:done) { project.board.done_list } + let!(:done) { create(:done_list, board: board) } before do project.team << [user, :developer] @@ -22,7 +22,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from backlog' do it 'adds the label of the list it goes to' do issue = create(:labeled_issue, project: project, labels: [bug]) - params = { from_list_id: backlog.id, to_list_id: list1.id } + params = { board_id: board.id, from_list_id: backlog.id, to_list_id: list1.id } described_class.new(project, user, params).execute(issue) @@ -33,7 +33,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving to backlog' do it 'removes all list-labels' do issue = create(:labeled_issue, project: project, labels: [bug, development, testing]) - params = { from_list_id: list1.id, to_list_id: backlog.id } + params = { board_id: board.id, from_list_id: list1.id, to_list_id: backlog.id } described_class.new(project, user, params).execute(issue) @@ -44,7 +44,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from backlog to done' do it 'closes the issue' do issue = create(:labeled_issue, project: project, labels: [bug]) - params = { from_list_id: backlog.id, to_list_id: done.id } + params = { board_id: board.id, from_list_id: backlog.id, to_list_id: done.id } described_class.new(project, user, params).execute(issue) issue.reload @@ -56,7 +56,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving an issue between lists' do let(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) } - let(:params) { { from_list_id: list1.id, to_list_id: list2.id } } + let(:params) { { board_id: board.id, from_list_id: list1.id, to_list_id: list2.id } } it 'delegates the label changes to Issues::UpdateService' do expect_any_instance_of(Issues::UpdateService).to receive(:execute).with(issue).once @@ -73,7 +73,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving to done' do let(:issue) { create(:labeled_issue, project: project, labels: [bug, development, testing]) } - let(:params) { { from_list_id: list2.id, to_list_id: done.id } } + let(:params) { { board_id: board.id, from_list_id: list2.id, to_list_id: done.id } } it 'delegates the close proceedings to Issues::CloseService' do expect_any_instance_of(Issues::CloseService).to receive(:execute).with(issue).once @@ -92,7 +92,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from done' do let(:issue) { create(:labeled_issue, :closed, project: project, labels: [bug]) } - let(:params) { { from_list_id: done.id, to_list_id: list2.id } } + let(:params) { { board_id: board.id, from_list_id: done.id, to_list_id: list2.id } } it 'delegates the re-open proceedings to Issues::ReopenService' do expect_any_instance_of(Issues::ReopenService).to receive(:execute).with(issue).once @@ -112,7 +112,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from done to backlog' do it 'reopens the issue' do issue = create(:labeled_issue, :closed, project: project, labels: [bug]) - params = { from_list_id: done.id, to_list_id: backlog.id } + params = { board_id: board.id, from_list_id: done.id, to_list_id: backlog.id } described_class.new(project, user, params).execute(issue) issue.reload @@ -124,7 +124,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving to same list' do let(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) } - let(:params) { { from_list_id: list1.id, to_list_id: list1.id } } + let(:params) { { board_id: board.id, from_list_id: list1.id, to_list_id: list1.id } } it 'returns false' do expect(described_class.new(project, user, params).execute(issue)).to eq false -- cgit v1.2.1 From 8b15e328a60f050d4ff24c0c7203461ae2724a30 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 14:50:44 -0300 Subject: Removes all labels from project boards when moving and issue to done --- spec/services/boards/issues/move_service_spec.rb | 34 +++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb index 9cf5a17e128..c43b2aec490 100644 --- a/spec/services/boards/issues/move_service_spec.rb +++ b/spec/services/boards/issues/move_service_spec.rb @@ -4,16 +4,16 @@ describe Boards::Issues::MoveService, services: true do describe '#execute' do let(:user) { create(:user) } let(:project) { create(:empty_project) } - let(:board) { create(:board, project: project) } + let(:board1) { create(:board, project: project) } let(:bug) { create(:label, project: project, name: 'Bug') } let(:development) { create(:label, project: project, name: 'Development') } let(:testing) { create(:label, project: project, name: 'Testing') } - let!(:backlog) { create(:backlog_list, board: board) } - let!(:list1) { create(:list, board: board, label: development, position: 0) } - let!(:list2) { create(:list, board: board, label: testing, position: 1) } - let!(:done) { create(:done_list, board: board) } + let!(:backlog) { create(:backlog_list, board: board1) } + let!(:list1) { create(:list, board: board1, label: development, position: 0) } + let!(:list2) { create(:list, board: board1, label: testing, position: 1) } + let!(:done) { create(:done_list, board: board1) } before do project.team << [user, :developer] @@ -22,7 +22,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from backlog' do it 'adds the label of the list it goes to' do issue = create(:labeled_issue, project: project, labels: [bug]) - params = { board_id: board.id, from_list_id: backlog.id, to_list_id: list1.id } + params = { board_id: board1.id, from_list_id: backlog.id, to_list_id: list1.id } described_class.new(project, user, params).execute(issue) @@ -33,7 +33,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving to backlog' do it 'removes all list-labels' do issue = create(:labeled_issue, project: project, labels: [bug, development, testing]) - params = { board_id: board.id, from_list_id: list1.id, to_list_id: backlog.id } + params = { board_id: board1.id, from_list_id: list1.id, to_list_id: backlog.id } described_class.new(project, user, params).execute(issue) @@ -44,7 +44,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from backlog to done' do it 'closes the issue' do issue = create(:labeled_issue, project: project, labels: [bug]) - params = { board_id: board.id, from_list_id: backlog.id, to_list_id: done.id } + params = { board_id: board1.id, from_list_id: backlog.id, to_list_id: done.id } described_class.new(project, user, params).execute(issue) issue.reload @@ -56,7 +56,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving an issue between lists' do let(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) } - let(:params) { { board_id: board.id, from_list_id: list1.id, to_list_id: list2.id } } + let(:params) { { board_id: board1.id, from_list_id: list1.id, to_list_id: list2.id } } it 'delegates the label changes to Issues::UpdateService' do expect_any_instance_of(Issues::UpdateService).to receive(:execute).with(issue).once @@ -72,8 +72,12 @@ describe Boards::Issues::MoveService, services: true do end context 'when moving to done' do - let(:issue) { create(:labeled_issue, project: project, labels: [bug, development, testing]) } - let(:params) { { board_id: board.id, from_list_id: list2.id, to_list_id: done.id } } + let(:board2) { create(:board, project: project) } + let(:regression) { create(:label, project: project, name: 'Regression') } + let!(:list3) { create(:list, board: board2, label: regression, position: 1) } + + let(:issue) { create(:labeled_issue, project: project, labels: [bug, development, testing, regression]) } + let(:params) { { board_id: board1.id, from_list_id: list2.id, to_list_id: done.id } } it 'delegates the close proceedings to Issues::CloseService' do expect_any_instance_of(Issues::CloseService).to receive(:execute).with(issue).once @@ -81,7 +85,7 @@ describe Boards::Issues::MoveService, services: true do described_class.new(project, user, params).execute(issue) end - it 'removes all list-labels and close the issue' do + it 'removes all list-labels from project boards and close the issue' do described_class.new(project, user, params).execute(issue) issue.reload @@ -92,7 +96,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from done' do let(:issue) { create(:labeled_issue, :closed, project: project, labels: [bug]) } - let(:params) { { board_id: board.id, from_list_id: done.id, to_list_id: list2.id } } + let(:params) { { board_id: board1.id, from_list_id: done.id, to_list_id: list2.id } } it 'delegates the re-open proceedings to Issues::ReopenService' do expect_any_instance_of(Issues::ReopenService).to receive(:execute).with(issue).once @@ -112,7 +116,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving from done to backlog' do it 'reopens the issue' do issue = create(:labeled_issue, :closed, project: project, labels: [bug]) - params = { board_id: board.id, from_list_id: done.id, to_list_id: backlog.id } + params = { board_id: board1.id, from_list_id: done.id, to_list_id: backlog.id } described_class.new(project, user, params).execute(issue) issue.reload @@ -124,7 +128,7 @@ describe Boards::Issues::MoveService, services: true do context 'when moving to same list' do let(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) } - let(:params) { { board_id: board.id, from_list_id: list1.id, to_list_id: list1.id } } + let(:params) { { board_id: board1.id, from_list_id: list1.id, to_list_id: list1.id } } it 'returns false' do expect(described_class.new(project, user, params).execute(issue)).to eq false -- cgit v1.2.1 From b4b8e0ec9405c4b5d17b53552612397e847e734d Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 16:01:06 -0300 Subject: Add Boards::ListService service to list project boards --- spec/services/boards/list_service_spec.rb | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 spec/services/boards/list_service_spec.rb (limited to 'spec') diff --git a/spec/services/boards/list_service_spec.rb b/spec/services/boards/list_service_spec.rb new file mode 100644 index 00000000000..dff33e4bcbb --- /dev/null +++ b/spec/services/boards/list_service_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe Boards::ListService, services: true do + describe '#execute' do + let(:project) { create(:empty_project) } + + subject(:service) { described_class.new(project, double) } + + context 'when project does not have a board' do + it 'creates a new project board' do + expect { service.execute }.to change(project.boards, :count).by(1) + end + + it 'delegates the project board creation to Boards::CreateService' do + expect_any_instance_of(Boards::CreateService).to receive(:execute).once + + service.execute + end + end + + context 'when project has a board' do + before do + create(:board, project: project) + end + + it 'does not create a new board' do + expect { service.execute }.not_to change(project.boards, :count) + end + end + + it 'returns project boards' do + board = create(:board, project: project) + + expect(service.execute).to match_array [board] + end + end +end -- cgit v1.2.1 From ecf4c10e9c395604583820ad01167db34d09d4aa Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 16:24:29 -0300 Subject: Add index action to Projects::BoardsController to return project boards --- .../controllers/projects/boards_controller_spec.rb | 47 ++++++++++++++++++++++ spec/fixtures/api/schemas/board.json | 12 ++++++ spec/fixtures/api/schemas/boards.json | 4 ++ 3 files changed, 63 insertions(+) create mode 100644 spec/fixtures/api/schemas/board.json create mode 100644 spec/fixtures/api/schemas/boards.json (limited to 'spec') diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb index 6f6e608e1f3..d7698afd141 100644 --- a/spec/controllers/projects/boards_controller_spec.rb +++ b/spec/controllers/projects/boards_controller_spec.rb @@ -9,6 +9,53 @@ describe Projects::BoardsController do sign_in(user) end + describe 'GET index' do + it 'creates a new project board when project does not have one' do + expect { list_boards }.to change(project.boards, :count).by(1) + end + + context 'when format is HTML' do + it 'renders template' do + list_boards + + expect(response).to render_template :index + expect(response.content_type).to eq 'text/html' + end + end + + context 'when format is JSON' do + it 'returns a list of project boards' do + create_list(:board, 2, project: project) + + list_boards format: :json + + parsed_response = JSON.parse(response.body) + + expect(response).to match_response_schema('boards') + expect(parsed_response.length).to eq 2 + end + end + + context 'with unauthorized user' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true) + allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) + end + + it 'returns a not found 404 response' do + list_boards + + expect(response).to have_http_status(404) + end + end + + def list_boards(format: :html) + get :index, namespace_id: project.namespace.to_param, + project_id: project.to_param, + format: format + end + end + describe 'GET show' do it 'creates a new board when project does not have one' do expect { read_board }.to change(Board, :count).by(1) diff --git a/spec/fixtures/api/schemas/board.json b/spec/fixtures/api/schemas/board.json new file mode 100644 index 00000000000..6c6e2bee8cb --- /dev/null +++ b/spec/fixtures/api/schemas/board.json @@ -0,0 +1,12 @@ +{ + "type": "object", + "required" : [ + "id", + "name" + ], + "properties" : { + "id": { "type": "integer" }, + "name": { "type": "string" } + }, + "additionalProperties": false +} diff --git a/spec/fixtures/api/schemas/boards.json b/spec/fixtures/api/schemas/boards.json new file mode 100644 index 00000000000..117564ef77a --- /dev/null +++ b/spec/fixtures/api/schemas/boards.json @@ -0,0 +1,4 @@ +{ + "type": "array", + "items": { "$ref": "board.json" } +} -- cgit v1.2.1 From 723ed9cc3a76f7ce0e2d1b358a33d05fb05865c9 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 17:08:55 -0300 Subject: Update Projects::BoardsController#show to look up for a specific board --- .../controllers/projects/boards_controller_spec.rb | 37 ++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb index d7698afd141..cc19035740e 100644 --- a/spec/controllers/projects/boards_controller_spec.rb +++ b/spec/controllers/projects/boards_controller_spec.rb @@ -57,15 +57,23 @@ describe Projects::BoardsController do end describe 'GET show' do - it 'creates a new board when project does not have one' do - expect { read_board }.to change(Board, :count).by(1) + let!(:board) { create(:board, project: project) } + + context 'when format is HTML' do + it 'renders template' do + read_board board: board + + expect(response).to render_template :show + expect(response.content_type).to eq 'text/html' + end end - it 'renders HTML template' do - read_board + context 'when format is JSON' do + it 'returns project board' do + read_board board: board, format: :json - expect(response).to render_template :show - expect(response.content_type).to eq 'text/html' + expect(response).to match_response_schema('board') + end end context 'with unauthorized user' do @@ -74,16 +82,27 @@ describe Projects::BoardsController do allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false) end - it 'returns a successful 404 response' do - read_board + it 'returns a not found 404 response' do + read_board board: board + + expect(response).to have_http_status(404) + end + end + + context 'when board does not belong to project' do + it 'returns a not found 404 response' do + another_board = create(:board) + + read_board board: another_board expect(response).to have_http_status(404) end end - def read_board(format: :html) + def read_board(board:, format: :html) get :show, namespace_id: project.namespace.to_param, project_id: project.to_param, + id: board.to_param, format: format end end -- cgit v1.2.1 From e1f889df6463203e5bd899fca8e98de6b705cd43 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 19:25:29 -0300 Subject: Update endpoints to handle with board list changes --- .../projects/boards/lists_controller_spec.rb | 57 ++++++++++++---------- 1 file changed, 31 insertions(+), 26 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/lists_controller_spec.rb b/spec/controllers/projects/boards/lists_controller_spec.rb index 709006a3601..a53a5feef44 100644 --- a/spec/controllers/projects/boards/lists_controller_spec.rb +++ b/spec/controllers/projects/boards/lists_controller_spec.rb @@ -13,7 +13,7 @@ describe Projects::Boards::ListsController do describe 'GET index' do it 'returns a successful 200 response' do - read_board_list user: user + read_board_list user: user, board: board expect(response).to have_http_status(200) expect(response.content_type).to eq 'application/json' @@ -22,7 +22,7 @@ describe Projects::Boards::ListsController do it 'returns a list of board lists' do create(:list, board: board) - read_board_list user: user + read_board_list user: user, board: board parsed_response = JSON.parse(response.body) @@ -37,17 +37,18 @@ describe Projects::Boards::ListsController do end it 'returns a forbidden 403 response' do - read_board_list user: user + read_board_list user: user, board: board expect(response).to have_http_status(403) end end - def read_board_list(user:) + def read_board_list(user:, board:) sign_in(user) get :index, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, format: :json end end @@ -57,13 +58,13 @@ describe Projects::Boards::ListsController do let(:label) { create(:label, project: project, name: 'Development') } it 'returns a successful 200 response' do - create_board_list user: user, label_id: label.id + create_board_list user: user, board: board, label_id: label.id expect(response).to have_http_status(200) end it 'returns the created list' do - create_board_list user: user, label_id: label.id + create_board_list user: user, board: board, label_id: label.id expect(response).to match_response_schema('list') end @@ -72,7 +73,7 @@ describe Projects::Boards::ListsController do context 'with invalid params' do context 'when label is nil' do it 'returns a not found 404 response' do - create_board_list user: user, label_id: nil + create_board_list user: user, board: board, label_id: nil expect(response).to have_http_status(404) end @@ -82,7 +83,7 @@ describe Projects::Boards::ListsController do it 'returns a not found 404 response' do label = create(:label, name: 'Development') - create_board_list user: user, label_id: label.id + create_board_list user: user, board: board, label_id: label.id expect(response).to have_http_status(404) end @@ -93,17 +94,18 @@ describe Projects::Boards::ListsController do it 'returns a forbidden 403 response' do label = create(:label, project: project, name: 'Development') - create_board_list user: guest, label_id: label.id + create_board_list user: guest, board: board, label_id: label.id expect(response).to have_http_status(403) end end - def create_board_list(user:, label_id:) + def create_board_list(user:, board:, label_id:) sign_in(user) post :create, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, list: { label_id: label_id }, format: :json end @@ -115,13 +117,13 @@ describe Projects::Boards::ListsController do context 'with valid position' do it 'returns a successful 200 response' do - move user: user, list: planning, position: 1 + move user: user, board: board, list: planning, position: 1 expect(response).to have_http_status(200) end it 'moves the list to the desired position' do - move user: user, list: planning, position: 1 + move user: user, board: board, list: planning, position: 1 expect(planning.reload.position).to eq 1 end @@ -129,7 +131,7 @@ describe Projects::Boards::ListsController do context 'with invalid position' do it 'returns an unprocessable entity 422 response' do - move user: user, list: planning, position: 6 + move user: user, board: board, list: planning, position: 6 expect(response).to have_http_status(422) end @@ -137,7 +139,7 @@ describe Projects::Boards::ListsController do context 'with invalid list id' do it 'returns a not found 404 response' do - move user: user, list: 999, position: 1 + move user: user, board: board, list: 999, position: 1 expect(response).to have_http_status(404) end @@ -145,17 +147,18 @@ describe Projects::Boards::ListsController do context 'with unauthorized user' do it 'returns a forbidden 403 response' do - move user: guest, list: planning, position: 6 + move user: guest, board: board, list: planning, position: 6 expect(response).to have_http_status(403) end end - def move(user:, list:, position:) + def move(user:, board:, list:, position:) sign_in(user) patch :update, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, id: list.to_param, list: { position: position }, format: :json @@ -167,19 +170,19 @@ describe Projects::Boards::ListsController do context 'with valid list id' do it 'returns a successful 200 response' do - remove_board_list user: user, list: planning + remove_board_list user: user, board: board, list: planning expect(response).to have_http_status(200) end it 'removes list from board' do - expect { remove_board_list user: user, list: planning }.to change(board.lists, :size).by(-1) + expect { remove_board_list user: user, board: board, list: planning }.to change(board.lists, :size).by(-1) end end context 'with invalid list id' do it 'returns a not found 404 response' do - remove_board_list user: user, list: 999 + remove_board_list user: user, board: board, list: 999 expect(response).to have_http_status(404) end @@ -187,17 +190,18 @@ describe Projects::Boards::ListsController do context 'with unauthorized user' do it 'returns a forbidden 403 response' do - remove_board_list user: guest, list: planning + remove_board_list user: guest, board: board, list: planning expect(response).to have_http_status(403) end end - def remove_board_list(user:, list:) + def remove_board_list(user:, board:, list:) sign_in(user) delete :destroy, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, id: list.to_param, format: :json end @@ -206,13 +210,13 @@ describe Projects::Boards::ListsController do describe 'POST generate' do context 'when board lists is empty' do it 'returns a successful 200 response' do - generate_default_board_lists user: user + generate_default_lists user: user, board: board expect(response).to have_http_status(200) end it 'returns the defaults lists' do - generate_default_board_lists user: user + generate_default_lists user: user, board: board expect(response).to match_response_schema('lists') end @@ -222,7 +226,7 @@ describe Projects::Boards::ListsController do it 'returns an unprocessable entity 422 response' do create(:list, board: board) - generate_default_board_lists user: user + generate_default_lists user: user, board: board expect(response).to have_http_status(422) end @@ -230,17 +234,18 @@ describe Projects::Boards::ListsController do context 'with unauthorized user' do it 'returns a forbidden 403 response' do - generate_default_board_lists user: guest + generate_default_lists user: guest, board: board expect(response).to have_http_status(403) end end - def generate_default_board_lists(user:) + def generate_default_lists(user:, board: board) sign_in(user) post :generate, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, format: :json end end -- cgit v1.2.1 From 67515098657704505935119503ef23e45f0fda04 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 23:44:44 -0300 Subject: Update endpoints to handle with board issues --- .../projects/boards/issues_controller_spec.rb | 53 ++++++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index 566658b508d..92e77291da9 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -1,15 +1,16 @@ require 'spec_helper' describe Projects::Boards::IssuesController do - let(:project) { create(:project_with_board) } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } let(:guest) { create(:user) } let(:planning) { create(:label, project: project, name: 'Planning') } let(:development) { create(:label, project: project, name: 'Development') } - let!(:list1) { create(:list, board: project.board, label: planning, position: 0) } - let!(:list2) { create(:list, board: project.board, label: development, position: 1) } + let!(:list1) { create(:list, board: board, label: planning, position: 0) } + let!(:list2) { create(:list, board: board, label: development, position: 1) } before do project.team << [user, :master] @@ -24,7 +25,7 @@ describe Projects::Boards::IssuesController do create(:labeled_issue, project: project, labels: [development]) create(:labeled_issue, project: project, labels: [development], assignee: johndoe) - list_issues user: user, list_id: list2 + list_issues user: user, board: board, list: list2 parsed_response = JSON.parse(response.body) @@ -33,9 +34,17 @@ describe Projects::Boards::IssuesController do end end + context 'with invalid board id' do + it 'returns a not found 404 response' do + list_issues user: user, board: 999, list: list2 + + expect(response).to have_http_status(404) + end + end + context 'with invalid list id' do it 'returns a not found 404 response' do - list_issues user: user, list_id: 999 + list_issues user: user, board: board, list: 999 expect(response).to have_http_status(404) end @@ -47,19 +56,20 @@ describe Projects::Boards::IssuesController do allow(Ability).to receive(:allowed?).with(user, :read_issue, project).and_return(false) end - it 'returns a successful 403 response' do - list_issues user: user, list_id: list2 + it 'returns a forbidden 403 response' do + list_issues user: user, board: board, list: list2 expect(response).to have_http_status(403) end end - def list_issues(user:, list_id:) + def list_issues(user:, board:, list:) sign_in(user) get :index, namespace_id: project.namespace.to_param, project_id: project.to_param, - list_id: list_id.to_param + board_id: board.to_param, + list_id: list.to_param end end @@ -122,13 +132,13 @@ describe Projects::Boards::IssuesController do context 'with valid params' do it 'returns a successful 200 response' do - move user: user, issue: issue, from_list_id: list1.id, to_list_id: list2.id + move user: user, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id expect(response).to have_http_status(200) end it 'moves issue to the desired list' do - move user: user, issue: issue, from_list_id: list1.id, to_list_id: list2.id + move user: user, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id expect(issue.reload.labels).to contain_exactly(development) end @@ -136,31 +146,44 @@ describe Projects::Boards::IssuesController do context 'with invalid params' do it 'returns a unprocessable entity 422 response for invalid lists' do - move user: user, issue: issue, from_list_id: nil, to_list_id: nil + move user: user, board: board, issue: issue, from_list_id: nil, to_list_id: nil expect(response).to have_http_status(422) end + it 'returns a not found 404 response for invalid board id' do + move user: user, board: 999, issue: issue, from_list_id: list1.id, to_list_id: list2.id + + expect(response).to have_http_status(404) + end + it 'returns a not found 404 response for invalid issue id' do - move user: user, issue: 999, from_list_id: list1.id, to_list_id: list2.id + move user: user, board: board, issue: 999, from_list_id: list1.id, to_list_id: list2.id expect(response).to have_http_status(404) end end context 'with unauthorized user' do + let(:guest) { create(:user) } + + before do + project.team << [guest, :guest] + end + it 'returns a forbidden 403 response' do - move user: guest, issue: issue, from_list_id: list1.id, to_list_id: list2.id + move user: guest, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id expect(response).to have_http_status(403) end end - def move(user:, issue:, from_list_id:, to_list_id:) + def move(user:, board:, issue:, from_list_id:, to_list_id:) sign_in(user) patch :update, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, id: issue.to_param, from_list_id: from_list_id, to_list_id: to_list_id, -- cgit v1.2.1 From 38cece495715df191fcb0c4ec0c5c2e44da2debf Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 5 Oct 2016 23:50:35 -0300 Subject: Fix rubocop offenses --- .../projects/boards/lists_controller_spec.rb | 2 +- spec/services/boards/issues/list_service_spec.rb | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/lists_controller_spec.rb b/spec/controllers/projects/boards/lists_controller_spec.rb index a53a5feef44..afede0191dc 100644 --- a/spec/controllers/projects/boards/lists_controller_spec.rb +++ b/spec/controllers/projects/boards/lists_controller_spec.rb @@ -240,7 +240,7 @@ describe Projects::Boards::ListsController do end end - def generate_default_lists(user:, board: board) + def generate_default_lists(user:, board:) sign_in(user) post :generate, namespace_id: project.namespace.to_param, diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index cc96fd05189..218a6d2bc2f 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -70,21 +70,21 @@ describe Boards::Issues::ListService, services: true do end end - context 'with list that does not belongs to the board' do - it 'raises an error' do - list = create(:list) - service = described_class.new(project, user, board_id: board.id, id: list.id) + context 'with list that does not belongs to the board' do + it 'raises an error' do + list = create(:list) + service = described_class.new(project, user, board_id: board.id, id: list.id) - expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) - end + expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) end + end - context 'with invalid list id' do - it 'raises an error' do - service = described_class.new(project, user, board_id: board.id, id: nil) + context 'with invalid list id' do + it 'raises an error' do + service = described_class.new(project, user, board_id: board.id, id: nil) - expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) - end + expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) end + end end end -- cgit v1.2.1 From 81c253ded12c96bfa3f5cf27f0e23c61619ad914 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 6 Oct 2016 14:37:41 -0300 Subject: Add Project#boards to import/export configuration file --- spec/lib/gitlab/import_export/all_models.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 006569254a6..5d5836e9bee 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -118,7 +118,7 @@ project: - creator - group - namespace -- board +- boards - last_event - services - campfire_service -- cgit v1.2.1 From 2c2a1dea67ef41a6e283c4816865645fba318a16 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 6 Oct 2016 17:13:33 -0300 Subject: Refactoring service to create a new issue in a board list --- spec/controllers/projects/boards/issues_controller_spec.rb | 13 +++++++------ spec/services/boards/issues/create_service_spec.rb | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index 92e77291da9..da59642f24d 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -76,13 +76,13 @@ describe Projects::Boards::IssuesController do describe 'POST create' do context 'with valid params' do it 'returns a successful 200 response' do - create_issue user: user, list: list1, title: 'New issue' + create_issue user: user, board: board, list: list1, title: 'New issue' expect(response).to have_http_status(200) end it 'returns the created issue' do - create_issue user: user, list: list1, title: 'New issue' + create_issue user: user, board: board, list: list1, title: 'New issue' expect(response).to match_response_schema('issue') end @@ -91,7 +91,7 @@ describe Projects::Boards::IssuesController do context 'with invalid params' do context 'when title is nil' do it 'returns an unprocessable entity 422 response' do - create_issue user: user, list: list1, title: nil + create_issue user: user, board: board, list: list1, title: nil expect(response).to have_http_status(422) end @@ -101,7 +101,7 @@ describe Projects::Boards::IssuesController do it 'returns a not found 404 response' do list = create(:list) - create_issue user: user, list: list, title: 'New issue' + create_issue user: user, board: board, list: list, title: 'New issue' expect(response).to have_http_status(404) end @@ -110,17 +110,18 @@ describe Projects::Boards::IssuesController do context 'with unauthorized user' do it 'returns a forbidden 403 response' do - create_issue user: guest, list: list1, title: 'New issue' + create_issue user: guest, board: board, list: list1, title: 'New issue' expect(response).to have_http_status(403) end end - def create_issue(user:, list:, title:) + def create_issue(user:, board:, list:, title:) sign_in(user) post :create, namespace_id: project.namespace.to_param, project_id: project.to_param, + board_id: board.to_param, list_id: list.to_param, issue: { title: title }, format: :json diff --git a/spec/services/boards/issues/create_service_spec.rb b/spec/services/boards/issues/create_service_spec.rb index 33e10e79f6d..360ee398f77 100644 --- a/spec/services/boards/issues/create_service_spec.rb +++ b/spec/services/boards/issues/create_service_spec.rb @@ -2,13 +2,13 @@ require 'spec_helper' describe Boards::Issues::CreateService, services: true do describe '#execute' do - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } let(:label) { create(:label, project: project, name: 'in-progress') } let!(:list) { create(:list, board: board, label: label, position: 0) } - subject(:service) { described_class.new(project, user, title: 'New issue') } + subject(:service) { described_class.new(project, user, board_id: board.id, list_id: list.id, title: 'New issue') } before do project.team << [user, :developer] @@ -17,15 +17,15 @@ describe Boards::Issues::CreateService, services: true do it 'delegates the create proceedings to Issues::CreateService' do expect_any_instance_of(Issues::CreateService).to receive(:execute).once - service.execute(list) + service.execute end it 'creates a new issue' do - expect { service.execute(list) }.to change(project.issues, :count).by(1) + expect { service.execute }.to change(project.issues, :count).by(1) end it 'adds the label of the list to the issue' do - issue = service.execute(list) + issue = service.execute expect(issue.labels).to eq [label] end -- cgit v1.2.1 From 1a2002d9084db71d5a0a2631985012b4544c4037 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 6 Oct 2016 17:14:39 -0300 Subject: Update board specs to use board factory instead of project_with_board --- spec/controllers/projects/boards/lists_controller_spec.rb | 4 ++-- spec/features/boards/boards_spec.rb | 5 +++-- spec/features/boards/new_issue_spec.rb | 3 ++- spec/services/boards/issues/list_service_spec.rb | 2 +- spec/services/boards/lists/destroy_service_spec.rb | 12 ++++++------ spec/services/boards/lists/list_service_spec.rb | 4 +--- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/lists_controller_spec.rb b/spec/controllers/projects/boards/lists_controller_spec.rb index afede0191dc..34d6119429d 100644 --- a/spec/controllers/projects/boards/lists_controller_spec.rb +++ b/spec/controllers/projects/boards/lists_controller_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe Projects::Boards::ListsController do - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } let(:guest) { create(:user) } diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 470e2bdbb9b..f79b6a77696 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -4,7 +4,8 @@ describe 'Issue Boards', feature: true, js: true do include WaitForAjax include WaitForVueResource - let(:project) { create(:project_with_board, :public) } + let(:project) { create(:empty_project, :public) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } let!(:user2) { create(:user) } @@ -468,7 +469,7 @@ describe 'Issue Boards', feature: true, js: true do it 'removes filtered labels' do wait_for_vue_resource - + page.within '.labels-filter' do click_button('Label') wait_for_ajax diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index c046e6b8d79..1ceb60d5297 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -4,7 +4,8 @@ describe 'Issue Boards new issue', feature: true, js: true do include WaitForAjax include WaitForVueResource - let(:project) { create(:project_with_board, :public) } + let(:project) { create(:empty_project, :public) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } context 'authorized user' do diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index 218a6d2bc2f..d9eb757f986 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Boards::Issues::ListService, services: true do describe '#execute' do let(:user) { create(:user) } - let(:project) { create(:project_with_board) } + let(:project) { create(:empty_project) } let(:board) { create(:board, project: project) } let(:bug) { create(:label, project: project, name: 'Bug') } diff --git a/spec/services/boards/lists/destroy_service_spec.rb b/spec/services/boards/lists/destroy_service_spec.rb index 474c4512471..628caf03476 100644 --- a/spec/services/boards/lists/destroy_service_spec.rb +++ b/spec/services/boards/lists/destroy_service_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe Boards::Lists::DestroyService, services: true do describe '#execute' do - let(:project) { create(:project_with_board) } - let(:board) { project.board } + let(:project) { create(:empty_project) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } context 'when list type is label' do @@ -15,11 +15,11 @@ describe Boards::Lists::DestroyService, services: true do end it 'decrements position of higher lists' do - backlog = project.board.backlog_list + backlog = board.backlog_list development = create(:list, board: board, position: 0) review = create(:list, board: board, position: 1) staging = create(:list, board: board, position: 2) - done = project.board.done_list + done = board.done_list described_class.new(project, user).execute(development) @@ -31,14 +31,14 @@ describe Boards::Lists::DestroyService, services: true do end it 'does not remove list from board when list type is backlog' do - list = project.board.backlog_list + list = board.backlog_list service = described_class.new(project, user) expect { service.execute(list) }.not_to change(board.lists, :count) end it 'does not remove list from board when list type is done' do - list = project.board.done_list + list = board.done_list service = described_class.new(project, user) expect { service.execute(list) }.not_to change(board.lists, :count) diff --git a/spec/services/boards/lists/list_service_spec.rb b/spec/services/boards/lists/list_service_spec.rb index 4464f80f796..334cee3f06d 100644 --- a/spec/services/boards/lists/list_service_spec.rb +++ b/spec/services/boards/lists/list_service_spec.rb @@ -6,13 +6,11 @@ describe Boards::Lists::ListService, services: true do project = create(:empty_project) board = create(:board, project: project) label = create(:label, project: project) - backlog_list = create(:backlog_list, board: board) list = create(:list, board: board, label: label) - done_list = create(:done_list, board: board) service = described_class.new(project, double) - expect(service.execute(board)).to eq [backlog_list, list, done_list] + expect(service.execute(board)).to eq [board.backlog_list, list, board.done_list] end end end -- cgit v1.2.1 From 7be133aa36c4160c31010dc74af002320e9070b8 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 7 Oct 2016 17:06:27 -0300 Subject: Fix typo on Boards::Issues::ListService spec --- spec/services/boards/issues/list_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index d9eb757f986..7c206cf3ce7 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -70,7 +70,7 @@ describe Boards::Issues::ListService, services: true do end end - context 'with list that does not belongs to the board' do + context 'with list that does not belong to the board' do it 'raises an error' do list = create(:list) service = described_class.new(project, user, board_id: board.id, id: list.id) -- cgit v1.2.1 From 2ad531f5e279bcd278600d1f95ff9d4e4988b034 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 10 Oct 2016 11:22:30 -0300 Subject: Add Project::BoardLimitExcedeed error class --- spec/models/project_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 1b13f1be477..308a00db9cd 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -99,7 +99,7 @@ describe Project, models: true do it 'raises an error when attempting to add more than one board to the project' do subject.boards.build - expect { subject.boards.build }.to raise_error(StandardError, 'Number of permitted boards exceeded') + expect { subject.boards.build }.to raise_error(Project::BoardLimitExceeded, 'Number of permitted boards exceeded') expect(subject.boards.size).to eq 1 end end -- cgit v1.2.1 From 53f50edf4dac5133ff4d67a67ba5071e3eb7e78a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 10 Oct 2016 23:29:20 -0300 Subject: Fix board relates specs --- spec/features/boards/boards_spec.rb | 16 ++++++++-------- spec/features/boards/keyboard_shortcut_spec.rb | 4 +--- spec/features/boards/new_issue_spec.rb | 4 ++-- spec/fixtures/api/schemas/board.json | 3 +-- 4 files changed, 12 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index f79b6a77696..0fb1608a0a3 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -18,7 +18,7 @@ describe 'Issue Boards', feature: true, js: true do context 'no lists' do before do - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource expect(page).to have_selector('.board', count: 3) end @@ -61,8 +61,8 @@ describe 'Issue Boards', feature: true, js: true do let!(:done) { create(:label, project: project, name: 'Done') } let!(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') } - let!(:list1) { create(:list, board: project.board, label: planning, position: 0) } - let!(:list2) { create(:list, board: project.board, label: development, position: 1) } + let!(:list1) { create(:list, board: board, label: planning, position: 0) } + let!(:list2) { create(:list, board: board, label: development, position: 1) } let!(:confidential_issue) { create(:issue, :confidential, project: project, author: user) } let!(:issue1) { create(:issue, project: project, assignee: user) } @@ -76,7 +76,7 @@ describe 'Issue Boards', feature: true, js: true do let!(:issue9) { create(:labeled_issue, project: project, labels: [testing, bug, accepting]) } before do - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource @@ -170,7 +170,7 @@ describe 'Issue Boards', feature: true, js: true do create(:issue, project: project) end - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource page.within(find('.board', match: :first)) do @@ -604,7 +604,7 @@ describe 'Issue Boards', feature: true, js: true do context 'keyboard shortcuts' do before do - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource end @@ -617,7 +617,7 @@ describe 'Issue Boards', feature: true, js: true do context 'signed out user' do before do logout - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource end @@ -633,7 +633,7 @@ describe 'Issue Boards', feature: true, js: true do project.team << [user_guest, :guest] logout login_as(user_guest) - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource end diff --git a/spec/features/boards/keyboard_shortcut_spec.rb b/spec/features/boards/keyboard_shortcut_spec.rb index 7ef68e9eb8d..a5fc766401f 100644 --- a/spec/features/boards/keyboard_shortcut_spec.rb +++ b/spec/features/boards/keyboard_shortcut_spec.rb @@ -6,9 +6,7 @@ describe 'Issue Boards shortcut', feature: true, js: true do let(:project) { create(:empty_project) } before do - project.create_board - project.board.lists.create(list_type: :backlog) - project.board.lists.create(list_type: :done) + create(:board, project: project) login_as :admin diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index 1ceb60d5297..67d6da5f39a 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -14,7 +14,7 @@ describe 'Issue Boards new issue', feature: true, js: true do login_as(user) - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource expect(page).to have_selector('.board', count: 3) @@ -70,7 +70,7 @@ describe 'Issue Boards new issue', feature: true, js: true do context 'unauthorized user' do before do - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource end diff --git a/spec/fixtures/api/schemas/board.json b/spec/fixtures/api/schemas/board.json index 6c6e2bee8cb..03aca4a3cc0 100644 --- a/spec/fixtures/api/schemas/board.json +++ b/spec/fixtures/api/schemas/board.json @@ -1,8 +1,7 @@ { "type": "object", "required" : [ - "id", - "name" + "id" ], "properties" : { "id": { "type": "integer" }, -- cgit v1.2.1 From 53b3c62e0f889d077ee5b19703c3e04384c85c03 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 11 Oct 2016 16:07:53 +0100 Subject: Fixed JS tests --- spec/javascripts/boards/boards_store_spec.js.es6 | 2 +- spec/javascripts/boards/issue_spec.js.es6 | 2 +- spec/javascripts/boards/list_spec.js.es6 | 2 +- spec/javascripts/boards/mock_data.js.es6 | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js.es6 index 078e4b00023..15c305ce321 100644 --- a/spec/javascripts/boards/boards_store_spec.js.es6 +++ b/spec/javascripts/boards/boards_store_spec.js.es6 @@ -14,7 +14,7 @@ (() => { beforeEach(() => { - gl.boardService = new BoardService('/test/issue-boards/board'); + gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); $.cookie('issue_board_welcome_hidden', 'false'); diff --git a/spec/javascripts/boards/issue_spec.js.es6 b/spec/javascripts/boards/issue_spec.js.es6 index 3569d1b98bd..328c6f82ab5 100644 --- a/spec/javascripts/boards/issue_spec.js.es6 +++ b/spec/javascripts/boards/issue_spec.js.es6 @@ -16,7 +16,7 @@ describe('Issue model', () => { let issue; beforeEach(() => { - gl.boardService = new BoardService('/test/issue-boards/board'); + gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); issue = new ListIssue({ diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6 index 1688b996162..ec78d82e919 100644 --- a/spec/javascripts/boards/list_spec.js.es6 +++ b/spec/javascripts/boards/list_spec.js.es6 @@ -16,7 +16,7 @@ describe('List model', () => { let list; beforeEach(() => { - gl.boardService = new BoardService('/test/issue-boards/board'); + gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); list = new List(listObj); diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6 index f3797ed44d4..052455f2ca6 100644 --- a/spec/javascripts/boards/mock_data.js.es6 +++ b/spec/javascripts/boards/mock_data.js.es6 @@ -26,7 +26,7 @@ const listObjDuplicate = { const BoardsMockData = { 'GET': { - '/test/issue-boards/board/lists{/id}/issues': { + '/test/issue-boards/board/1/lists{/id}/issues': { issues: [{ title: 'Testing', iid: 1, @@ -37,13 +37,13 @@ const BoardsMockData = { } }, 'POST': { - '/test/issue-boards/board/lists{/id}': listObj + '/test/issue-boards/board/1/lists{/id}': listObj }, 'PUT': { - '/test/issue-boards/board/lists{/id}': {} + '/test/issue-boards/board/1/lists{/id}': {} }, 'DELETE': { - '/test/issue-boards/board/lists{/id}': {} + '/test/issue-boards/board/1/lists{/id}': {} } }; -- cgit v1.2.1 From 8e70cf25641fc023e146ac1632f89203a55ce6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 11 Oct 2016 17:25:57 +0200 Subject: Addresses Robert's feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/users_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 56b2ec6271e..91e54af1209 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -898,7 +898,6 @@ describe API::API, api: true do describe 'GET /user/:id/events' do let(:user) { create(:user) } - let(:lambda_user) { create(:user) } let(:project) { create(:empty_project) } let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) } @@ -909,7 +908,9 @@ describe API::API, api: true do context "as a user than cannot see the event's project" do it 'returns no events' do - get api("/users/#{user.id}/events", lambda_user) + other_user = create(:user) + + get api("/users/#{user.id}/events", other_user) expect(response).to have_http_status(200) expect(json_response).to be_empty -- cgit v1.2.1 From c90483406ecc2717076391737ff57167b5a03393 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Mon, 3 Oct 2016 13:11:16 +0100 Subject: refactors tests because of gitlab-test repository changes --- spec/controllers/projects/commit_controller_spec.rb | 16 ++++++++++------ spec/helpers/search_helper_spec.rb | 2 +- spec/lib/gitlab/data_builder/push_spec.rb | 8 ++++---- spec/mailers/notify_spec.rb | 2 +- spec/models/commit_spec.rb | 8 ++++---- spec/models/merge_request_diff_spec.rb | 6 +++--- spec/models/merge_request_spec.rb | 4 ++-- spec/models/repository_spec.rb | 15 ++++++++++++++- spec/requests/api/commits_spec.rb | 12 +++++++++--- spec/requests/api/repositories_spec.rb | 8 ++++---- spec/requests/git_http_spec.rb | 4 ++-- spec/services/merge_requests/refresh_service_spec.rb | 4 ++-- spec/services/system_note_service_spec.rb | 8 ++++---- spec/workers/emails_on_push_worker_spec.rb | 4 ++-- 14 files changed, 62 insertions(+), 39 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb index 7e440193d7b..646b097d74e 100644 --- a/spec/controllers/projects/commit_controller_spec.rb +++ b/spec/controllers/projects/commit_controller_spec.rb @@ -102,15 +102,16 @@ describe Projects::CommitController do describe "as patch" do include_examples "export as", :patch let(:format) { :patch } + let(:commit2) { project.commit('498214de67004b1da3d820901307bed2a68a8ef6') } it "is a git email patch" do - go(id: commit.id, format: format) + go(id: commit2.id, format: format) - expect(response.body).to start_with("From #{commit.id}") + expect(response.body).to start_with("From #{commit2.id}") end it "contains a git diff" do - go(id: commit.id, format: format) + go(id: commit2.id, format: format) expect(response.body).to match(/^diff --git/) end @@ -135,6 +136,8 @@ describe Projects::CommitController do describe "GET branches" do it "contains branch and tags information" do + commit = project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e') + get(:branches, namespace_id: project.namespace.to_param, project_id: project.to_param, @@ -254,16 +257,17 @@ describe Projects::CommitController do end let(:existing_path) { '.gitmodules' } + let(:commit2) { project.commit('5937ac0a7beb003549fc5fd26fc247adbce4a52e') } context 'when the commit exists' do context 'when the user has access to the project' do context 'when the path exists in the diff' do it 'enables diff notes' do - diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path) + diff_for_path(id: commit2.id, old_path: existing_path, new_path: existing_path) expect(assigns(:diff_notes_disabled)).to be_falsey expect(assigns(:comments_target)).to eq(noteable_type: 'Commit', - commit_id: commit.id) + commit_id: commit2.id) end it 'only renders the diffs for the path given' do @@ -272,7 +276,7 @@ describe Projects::CommitController do meth.call(diffs) end - diff_for_path(id: commit.id, old_path: existing_path, new_path: existing_path) + diff_for_path(id: commit2.id, old_path: existing_path, new_path: existing_path) end end diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index c5b5aa8c445..64aa41020c9 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -19,7 +19,7 @@ describe SearchHelper do expect(subject.filename).to eq('CHANGELOG') expect(subject.basename).to eq('CHANGELOG') expect(subject.ref).to eq('master') - expect(subject.startline).to eq(186) + expect(subject.startline).to eq(188) expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") end diff --git a/spec/lib/gitlab/data_builder/push_spec.rb b/spec/lib/gitlab/data_builder/push_spec.rb index b73434e8dd7..a379f798a16 100644 --- a/spec/lib/gitlab/data_builder/push_spec.rb +++ b/spec/lib/gitlab/data_builder/push_spec.rb @@ -8,13 +8,13 @@ describe Gitlab::DataBuilder::Push, lib: true do let(:data) { described_class.build_sample(project, user) } it { expect(data).to be_a(Hash) } - it { expect(data[:before]).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } - it { expect(data[:after]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') } + it { expect(data[:before]).to eq('1b12f15a11fc6e62177bef08f47bc7b5ce50b141') } + it { expect(data[:after]).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') } it { expect(data[:ref]).to eq('refs/heads/master') } it { expect(data[:commits].size).to eq(3) } it { expect(data[:total_commits_count]).to eq(3) } - it { expect(data[:commits].first[:added]).to eq(['gitlab-grack']) } - it { expect(data[:commits].first[:modified]).to eq(['.gitmodules']) } + it { expect(data[:commits].first[:added]).to eq(['bar/branch-test.txt']) } + it { expect(data[:commits].first[:modified]).to eq([]) } it { expect(data[:commits].first[:removed]).to eq([]) } include_examples 'project hook data with deprecateds' diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 0e4130e8a3a..c8207e58e90 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -628,7 +628,7 @@ describe Notify do it_behaves_like 'a user cannot unsubscribe through footer link' it 'has the correct subject' do - is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/ + is_expected.to have_subject /Re: #{project.name} | #{commit.title} \(#{commit.short_id}\)/ end it 'contains a link to the commit' do diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index d3e6a6648cc..51be3f36135 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -164,10 +164,10 @@ eos let(:data) { commit.hook_attrs(with_changed_files: true) } it { expect(data).to be_a(Hash) } - it { expect(data[:message]).to include('Add submodule from gitlab.com') } - it { expect(data[:timestamp]).to eq('2014-02-27T11:01:38+02:00') } - it { expect(data[:added]).to eq(["gitlab-grack"]) } - it { expect(data[:modified]).to eq([".gitmodules"]) } + it { expect(data[:message]).to include('adds bar folder and branch-test text file to check Repository merged_to_root_ref method') } + it { expect(data[:timestamp]).to eq('2016-09-27T14:37:46+00:00') } + it { expect(data[:added]).to eq(["bar/branch-test.txt"]) } + it { expect(data[:modified]).to eq([]) } it { expect(data[:removed]).to eq([]) } end diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 530a7def553..a27c2b28326 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -6,9 +6,9 @@ describe MergeRequestDiff, models: true do it { expect(subject).to be_valid } it { expect(subject).to be_persisted } - it { expect(subject.commits.count).to eq(5) } - it { expect(subject.diffs.count).to eq(8) } - it { expect(subject.head_commit_sha).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') } + it { expect(subject.commits.count).to eq(29) } + it { expect(subject.diffs.count).to eq(20) } + it { expect(subject.head_commit_sha).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0') } it { expect(subject.base_commit_sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') } it { expect(subject.start_commit_sha).to eq('0b4bc9a49b562e85de7cc9e834518ea6828729b9') } end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 38b6da50168..5884b4cff8c 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -489,7 +489,7 @@ describe MergeRequest, models: true do subject(:merge_request_with_divergence) { create(:merge_request, :diverged, source_project: project, target_project: project) } it 'counts commits that are on target branch but not on source branch' do - expect(subject.diverged_commits_count).to eq(5) + expect(subject.diverged_commits_count).to eq(29) end end @@ -497,7 +497,7 @@ describe MergeRequest, models: true do subject(:merge_request_fork_with_divergence) { create(:merge_request, :diverged, source_project: fork_project, target_project: project) } it 'counts commits that are on target branch but not on source branch' do - expect(subject.diverged_commits_count).to eq(5) + expect(subject.diverged_commits_count).to eq(29) end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 6dd3f91be17..4df78713a82 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -114,17 +114,30 @@ describe Repository, models: true do end describe '#merged_to_root_ref?' do - context 'merged branch' do + context 'merged branch without ff' do subject { repository.merged_to_root_ref?('branch-merged') } it { is_expected.to be_truthy } end + # If the HEAD was ff then it will be false + context 'merged with ff' do + subject { repository.merged_to_root_ref?('improve/awesome') } + + it { is_expected.to be_truthy } + end + context 'not merged branch' do subject { repository.merged_to_root_ref?('not-merged-branch') } it { is_expected.to be_falsey } end + + context 'default branch' do + subject { repository.merged_to_root_ref?('master') } + + it { is_expected.to be_falsey } + end end describe '#can_be_merged?' do diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index aa610557056..66fa0c0c01f 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -53,7 +53,12 @@ describe API::API, api: true do get api("/projects/#{project.id}/repository/commits?until=#{before.utc.iso8601}", user) - expect(json_response.size).to eq(commits.size - 1) + if commits.size >= 20 + expect(json_response.size).to eq(20) + else + expect(json_response.size).to eq(commits.size - 1) + end + expect(json_response.first["id"]).to eq(commits.second.id) expect(json_response.second["id"]).to eq(commits.third.id) end @@ -447,11 +452,12 @@ describe API::API, api: true do end it 'returns the inline comment' do - post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.raw_diffs.first.new_path, line: 7, line_type: 'new' + post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.raw_diffs.first.new_path, line: 1, line_type: 'new' + expect(response).to have_http_status(201) expect(json_response['note']).to eq('My comment') expect(json_response['path']).to eq(project.repository.commit.raw_diffs.first.new_path) - expect(json_response['line']).to eq(7) + expect(json_response['line']).to eq(1) expect(json_response['line_type']).to eq('new') end diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 80a856a6e90..c4dc2d9006a 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -21,7 +21,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.first['name']).to eq('encoding') + expect(json_response.first['name']).to eq('bar') expect(json_response.first['type']).to eq('tree') expect(json_response.first['mode']).to eq('040000') end @@ -166,9 +166,9 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response).to be_an Array contributor = json_response.first - expect(contributor['email']).to eq('dmitriy.zaporozhets@gmail.com') - expect(contributor['name']).to eq('Dmitriy Zaporozhets') - expect(contributor['commits']).to eq(13) + expect(contributor['email']).to eq('tiagonbotelho@hotmail.com') + expect(contributor['name']).to eq('tiagonbotelho') + expect(contributor['commits']).to eq(1) expect(contributor['additions']).to eq(0) expect(contributor['deletions']).to eq(0) end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index c0c1e62e910..27f0fd22ae6 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -440,8 +440,8 @@ describe 'Git HTTP requests', lib: true do before do # Provide a dummy file in its place allow_any_instance_of(Repository).to receive(:blob_at).and_call_original - allow_any_instance_of(Repository).to receive(:blob_at).with('5937ac0a7beb003549fc5fd26fc247adbce4a52e', 'info/refs') do - Gitlab::Git::Blob.find(project.repository, 'master', '.gitignore') + allow_any_instance_of(Repository).to receive(:blob_at).with('b83d6e391c22777fca1ed3012fce84f633d7fed0', 'info/refs') do + Gitlab::Git::Blob.find(project.repository, 'master', 'bar/branch-test.txt') end get "/#{project.path_with_namespace}/blob/master/info/refs" diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 59d3912018a..5b4e4908add 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -118,7 +118,7 @@ describe MergeRequests::RefreshService, services: true do it { expect(@merge_request.notes).to be_empty } it { expect(@merge_request).to be_open } - it { expect(@fork_merge_request.notes.last.note).to include('Added 4 commits') } + it { expect(@fork_merge_request.notes.last.note).to include('Added 28 commits') } it { expect(@fork_merge_request).to be_open } it { expect(@build_failed_todo).to be_pending } it { expect(@fork_build_failed_todo).to be_pending } @@ -169,7 +169,7 @@ describe MergeRequests::RefreshService, services: true do notes = @fork_merge_request.notes.reorder(:created_at).map(&:note) expect(notes[0]).to include('Restored source branch `master`') - expect(notes[1]).to include('Added 4 commits') + expect(notes[1]).to include('Added 28 commits') expect(@fork_merge_request).to be_open end end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 304d4e62396..b4ba28dfe8e 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -54,7 +54,7 @@ describe SystemNoteService, services: true do it 'adds a message line for each commit' do new_commits.each_with_index do |commit, i| # Skip the header - expect(note_lines[i + 1]).to eq "* #{commit.short_id} - #{commit.title}" + expect(HTMLEntities.new.decode(note_lines[i + 1])).to eq "* #{commit.short_id} - #{commit.title}" end end end @@ -81,7 +81,7 @@ describe SystemNoteService, services: true do end it 'includes a commit count' do - expect(summary_line).to end_with " - 2 commits from branch `feature`" + expect(summary_line).to end_with " - 26 commits from branch `feature`" end end @@ -91,7 +91,7 @@ describe SystemNoteService, services: true do end it 'includes a commit count' do - expect(summary_line).to end_with " - 2 commits from branch `feature`" + expect(summary_line).to end_with " - 26 commits from branch `feature`" end end @@ -537,7 +537,7 @@ describe SystemNoteService, services: true do let(:mergereq) { create(:merge_request, :simple, target_project: project, source_project: project) } let(:jira_issue) { ExternalIssue.new("JIRA-1", project)} let(:jira_tracker) { project.jira_service } - let(:commit) { project.commit } + let(:commit) { project.repository.commits('master').find { |commit| commit.id == '5937ac0a7beb003549fc5fd26fc247adbce4a52e' } } context 'in JIRA issue tracker' do before do diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index 7ca2c29da1c..036d037f3f9 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -57,7 +57,7 @@ describe EmailsOnPushWorker do end it "sends a mail with the correct subject" do - expect(email.subject).to include('Change some files') + expect(email.subject).to include('adds bar folder and branch-test text file') end it "mentions force pushing in the body" do @@ -73,7 +73,7 @@ describe EmailsOnPushWorker do before { perform } it "sends a mail with the correct subject" do - expect(email.subject).to include('Change some files') + expect(email.subject).to include('adds bar folder and branch-test text file') end it "does not mention force pushing in the body" do -- cgit v1.2.1 From 8213fc6a744cb5c9fa4c7461dbf1a96f48898662 Mon Sep 17 00:00:00 2001 From: barthc Date: Mon, 10 Oct 2016 16:04:52 +0100 Subject: allow multiple labels commands --- .../slash_commands/interpret_service_spec.rb | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'spec') diff --git a/spec/services/slash_commands/interpret_service_spec.rb b/spec/services/slash_commands/interpret_service_spec.rb index ae4d286d250..b57e338b782 100644 --- a/spec/services/slash_commands/interpret_service_spec.rb +++ b/spec/services/slash_commands/interpret_service_spec.rb @@ -86,6 +86,25 @@ describe SlashCommands::InterpretService, services: true do end end + shared_examples 'multiple label command' do + it 'fetches label ids and populates add_label_ids if content contains multiple /label' do + bug # populate the label + inprogress # populate the label + _, updates = service.execute(content, issuable) + + expect(updates).to eq(add_label_ids: [inprogress.id, bug.id]) + end + end + + shared_examples 'multiple label with same argument' do + it 'prevents duplicate label ids and populates add_label_ids if content contains multiple /label' do + inprogress # populate the label + _, updates = service.execute(content, issuable) + + expect(updates).to eq(add_label_ids: [inprogress.id]) + end + end + shared_examples 'unlabel command' do it 'fetches label ids and populates remove_label_ids if content contains /unlabel' do issuable.update(label_ids: [inprogress.id]) # populate the label @@ -95,6 +114,15 @@ describe SlashCommands::InterpretService, services: true do end end + shared_examples 'multiple unlabel command' do + it 'fetches label ids and populates remove_label_ids if content contains mutiple /unlabel' do + issuable.update(label_ids: [inprogress.id, bug.id]) # populate the label + _, updates = service.execute(content, issuable) + + expect(updates).to eq(remove_label_ids: [inprogress.id, bug.id]) + end + end + shared_examples 'unlabel command with no argument' do it 'populates label_ids: [] if content contains /unlabel with no arguments' do issuable.update(label_ids: [inprogress.id]) # populate the label @@ -285,6 +313,16 @@ describe SlashCommands::InterpretService, services: true do let(:issuable) { merge_request } end + it_behaves_like 'multiple label command' do + let(:content) { %(/label ~"#{inprogress.title}" \n/label ~#{bug.title}) } + let(:issuable) { issue } + end + + it_behaves_like 'multiple label with same argument' do + let(:content) { %(/label ~"#{inprogress.title}" \n/label ~#{inprogress.title}) } + let(:issuable) { issue } + end + it_behaves_like 'unlabel command' do let(:content) { %(/unlabel ~"#{inprogress.title}") } let(:issuable) { issue } @@ -295,6 +333,11 @@ describe SlashCommands::InterpretService, services: true do let(:issuable) { merge_request } end + it_behaves_like 'multiple unlabel command' do + let(:content) { %(/unlabel ~"#{inprogress.title}" \n/unlabel ~#{bug.title}) } + let(:issuable) { issue } + end + it_behaves_like 'unlabel command with no argument' do let(:content) { %(/unlabel) } let(:issuable) { issue } -- cgit v1.2.1 From 670b2eb5c05a721f810a5b248612cadde0eaf2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 11 Oct 2016 10:20:35 +0000 Subject: Merge branch 'api-fix-project-group-sharing' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API: Share projects only with groups current_user can access Aims to address the issues here: https://gitlab.com/gitlab-org/gitlab-ce/issues/23004 * Projects can be shared with non-existent groups * Projects can be shared with groups that the current user does not have access to read Concerns: The new implementation of the API endpoint allows projects to be shared with a larger range of groups than can be done via the web UI. The form for sharing a project with a group uses the following API endpoint to index the available groups: https://gitlab.com/gitlab-org/gitlab-ce/blob/494269fc92f61098ee6bd635a0426129ce2c5456/lib/api/groups.rb#L17. The groups indexed in the web form will only be those groups that the user is currently a member of. The new implementation allows projects to be shared with any group that the authenticated user has access to view. This widens the range of groups to those that are public and internal. See merge request !2005 Signed-off-by: Rémy Coutable --- spec/models/project_group_link_spec.rb | 2 +- spec/requests/api/projects_spec.rb | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb index 2fa6715fcaf..c5ff1941378 100644 --- a/spec/models/project_group_link_spec.rb +++ b/spec/models/project_group_link_spec.rb @@ -11,7 +11,7 @@ describe ProjectGroupLink do it { should validate_presence_of(:project_id) } it { should validate_uniqueness_of(:group_id).scoped_to(:project_id).with_message(/already shared/) } - it { should validate_presence_of(:group_id) } + it { should validate_presence_of(:group) } it { should validate_presence_of(:group_access) } end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5f19638b460..19a2c7a2700 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -819,6 +819,20 @@ describe API::API, api: true do expect(response.status).to eq 400 end + it 'returns a 404 error when user cannot read group' do + private_group = create(:group, :private) + + post api("/projects/#{project.id}/share", user), group_id: private_group.id, group_access: Gitlab::Access::DEVELOPER + + expect(response.status).to eq 404 + end + + it 'returns a 404 error when group does not exist' do + post api("/projects/#{project.id}/share", user), group_id: 1234, group_access: Gitlab::Access::DEVELOPER + + expect(response.status).to eq 404 + end + it "returns a 409 error when wrong params passed" do post api("/projects/#{project.id}/share", user), group_id: group.id, group_access: 1234 expect(response.status).to eq 409 -- cgit v1.2.1 From c7865786572a3a2e12ed67a3f8121c0be8c4ba38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 11 Oct 2016 21:26:49 +0200 Subject: Make spec deterministic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/requests/api/users_spec.rb | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 91e54af1209..684c27f4353 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -926,20 +926,18 @@ describe API::API, api: true do it 'returns the "joined" event' do get api("/users/#{user.id}/events", user) - first_event = json_response.first + comment_event = json_response.find { |e| e['action_name'] == 'commented on' } - expect(first_event['action_name']).to eq('commented on') - expect(first_event['project_id'].to_i).to eq(project.id) - expect(first_event['author_username']).to eq(user.username) - expect(first_event['note']['id']).to eq(note.id) - expect(first_event['note']['body']).to eq('What an awesome day!') + expect(comment_event['project_id'].to_i).to eq(project.id) + expect(comment_event['author_username']).to eq(user.username) + expect(comment_event['note']['id']).to eq(note.id) + expect(comment_event['note']['body']).to eq('What an awesome day!') - last_event = json_response.last + joined_event = json_response.find { |e| e['action_name'] == 'joined' } - expect(last_event['action_name']).to eq('joined') - expect(last_event['project_id'].to_i).to eq(project.id) - expect(last_event['author_username']).to eq(user.username) - expect(last_event['author']['name']).to eq(user.name) + expect(joined_event['project_id'].to_i).to eq(project.id) + expect(joined_event['author_username']).to eq(user.username) + expect(joined_event['author']['name']).to eq(user.name) end end end -- cgit v1.2.1 From 9c92443ffe90ec58490fb66ebce98e8e19a07c9b Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Wed, 12 Oct 2016 10:46:30 +0500 Subject: Remove unused lets from deploy_key spec --- spec/models/deploy_key_spec.rb | 3 --- 1 file changed, 3 deletions(-) (limited to 'spec') diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index 6a90598a629..93623e8e99b 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -1,9 +1,6 @@ require 'spec_helper' describe DeployKey, models: true do - let(:project) { create(:project) } - let(:deploy_key) { create(:deploy_key, projects: [project]) } - describe "Associations" do it { is_expected.to have_many(:deploy_keys_projects) } it { is_expected.to have_many(:projects) } -- cgit v1.2.1 From 31c41a8fe1ef67347e5bcfdb97ff15a079976945 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Wed, 12 Oct 2016 10:50:01 +0500 Subject: Use build instead create record in appearance_spec --- spec/models/appearance_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index c5658bd26e1..0b72a2f979b 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' RSpec.describe Appearance, type: :model do - subject { create(:appearance) } + subject { build(:appearance) } it { is_expected.to be_valid } -- cgit v1.2.1 From b9b13ea8016077e186374e4ee45dfc8a59ea5a78 Mon Sep 17 00:00:00 2001 From: Thomas Balthazar Date: Mon, 8 Aug 2016 13:42:24 +0200 Subject: Create a new /templates API namespace The /licenses, /gitignores and /gitlab_ci_ymls endpoints are now also available under a new /templates namespace. Old endpoints will be deprecated when GitLab 9.0.0 is released. --- spec/requests/api/license_templates_spec.rb | 136 ------------------- spec/requests/api/templates_spec.rb | 204 ++++++++++++++++++++++++---- 2 files changed, 176 insertions(+), 164 deletions(-) delete mode 100644 spec/requests/api/license_templates_spec.rb (limited to 'spec') diff --git a/spec/requests/api/license_templates_spec.rb b/spec/requests/api/license_templates_spec.rb deleted file mode 100644 index 9a1894d63a2..00000000000 --- a/spec/requests/api/license_templates_spec.rb +++ /dev/null @@ -1,136 +0,0 @@ -require 'spec_helper' - -describe API::API, api: true do - include ApiHelpers - - describe 'Entity' do - before { get api('/licenses/mit') } - - it { expect(json_response['key']).to eq('mit') } - it { expect(json_response['name']).to eq('MIT License') } - it { expect(json_response['nickname']).to be_nil } - it { expect(json_response['popular']).to be true } - it { expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/') } - it { expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT') } - it { expect(json_response['description']).to include('A permissive license that is short and to the point.') } - it { expect(json_response['conditions']).to eq(%w[include-copyright]) } - it { expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use]) } - it { expect(json_response['limitations']).to eq(%w[no-liability]) } - it { expect(json_response['content']).to include('The MIT License (MIT)') } - end - - describe 'GET /licenses' do - it 'returns a list of available license templates' do - get api('/licenses') - - expect(response).to have_http_status(200) - expect(json_response).to be_an Array - expect(json_response.size).to eq(15) - expect(json_response.map { |l| l['key'] }).to include('agpl-3.0') - end - - describe 'the popular parameter' do - context 'with popular=1' do - it 'returns a list of available popular license templates' do - get api('/licenses?popular=1') - - expect(response).to have_http_status(200) - expect(json_response).to be_an Array - expect(json_response.size).to eq(3) - expect(json_response.map { |l| l['key'] }).to include('apache-2.0') - end - end - end - end - - describe 'GET /licenses/:key' do - context 'with :project and :fullname given' do - before do - get api("/licenses/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}") - end - - context 'for the mit license' do - let(:license_type) { 'mit' } - - it 'returns the license text' do - expect(json_response['content']).to include('The MIT License (MIT)') - end - - it 'replaces placeholder values' do - expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton") - end - end - - context 'for the agpl-3.0 license' do - let(:license_type) { 'agpl-3.0' } - - it 'returns the license text' do - expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE') - end - - it 'replaces placeholder values' do - expect(json_response['content']).to include('My Awesome Project') - expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton") - end - end - - context 'for the gpl-3.0 license' do - let(:license_type) { 'gpl-3.0' } - - it 'returns the license text' do - expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE') - end - - it 'replaces placeholder values' do - expect(json_response['content']).to include('My Awesome Project') - expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton") - end - end - - context 'for the gpl-2.0 license' do - let(:license_type) { 'gpl-2.0' } - - it 'returns the license text' do - expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE') - end - - it 'replaces placeholder values' do - expect(json_response['content']).to include('My Awesome Project') - expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton") - end - end - - context 'for the apache-2.0 license' do - let(:license_type) { 'apache-2.0' } - - it 'returns the license text' do - expect(json_response['content']).to include('Apache License') - end - - it 'replaces placeholder values' do - expect(json_response['content']).to include("Copyright #{Time.now.year} Anton") - end - end - - context 'for an uknown license' do - let(:license_type) { 'muth-over9000' } - - it 'returns a 404' do - expect(response).to have_http_status(404) - end - end - end - - context 'with no :fullname given' do - context 'with an authenticated user' do - let(:user) { create(:user) } - - it 'replaces the copyright owner placeholder with the name of the current user' do - get api('/licenses/mit', user) - - expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}") - end - end - end - end -end diff --git a/spec/requests/api/templates_spec.rb b/spec/requests/api/templates_spec.rb index 5bd5b861792..d32ba60fc4c 100644 --- a/spec/requests/api/templates_spec.rb +++ b/spec/requests/api/templates_spec.rb @@ -3,53 +3,201 @@ require 'spec_helper' describe API::Templates, api: true do include ApiHelpers - context 'global templates' do - describe 'the Template Entity' do - before { get api('/gitignores/Ruby') } + shared_examples_for 'the Template Entity' do |path| + before { get api(path) } - it { expect(json_response['name']).to eq('Ruby') } - it { expect(json_response['content']).to include('*.gem') } + it { expect(json_response['name']).to eq('Ruby') } + it { expect(json_response['content']).to include('*.gem') } + end + + shared_examples_for 'the TemplateList Entity' do |path| + before { get api(path) } + + it { expect(json_response.first['name']).not_to be_nil } + it { expect(json_response.first['content']).to be_nil } + end + + shared_examples_for 'requesting gitignores' do |path| + it 'returns a list of available gitignore templates' do + get api(path) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.size).to be > 15 end + end - describe 'the TemplateList Entity' do - before { get api('/gitignores') } + shared_examples_for 'requesting gitlab-ci-ymls' do |path| + it 'returns a list of available gitlab_ci_ymls' do + get api(path) - it { expect(json_response.first['name']).not_to be_nil } - it { expect(json_response.first['content']).to be_nil } + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).not_to be_nil end + end + + shared_examples_for 'requesting gitlab-ci-yml for Ruby' do |path| + it 'adds a disclaimer on the top' do + get api(path) + + expect(response).to have_http_status(200) + expect(json_response['content']).to start_with("# This file is a template,") + end + end + + shared_examples_for 'the License Template Entity' do |path| + before { get api(path) } + + it 'returns a license template' do + expect(json_response['key']).to eq('mit') + expect(json_response['name']).to eq('MIT License') + expect(json_response['nickname']).to be_nil + expect(json_response['popular']).to be true + expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/') + expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT') + expect(json_response['description']).to include('A permissive license that is short and to the point.') + expect(json_response['conditions']).to eq(%w[include-copyright]) + expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use]) + expect(json_response['limitations']).to eq(%w[no-liability]) + expect(json_response['content']).to include('The MIT License (MIT)') + end + end - context 'requesting gitignores' do - describe 'GET /gitignores' do - it 'returns a list of available gitignore templates' do - get api('/gitignores') + shared_examples_for 'GET licenses' do |path| + it 'returns a list of available license templates' do + get api(path) - expect(response.status).to eq(200) + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(15) + expect(json_response.map { |l| l['key'] }).to include('agpl-3.0') + end + + describe 'the popular parameter' do + context 'with popular=1' do + it 'returns a list of available popular license templates' do + get api("#{path}?popular=1") + + expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.size).to be > 15 + expect(json_response.size).to eq(3) + expect(json_response.map { |l| l['key'] }).to include('apache-2.0') end end end + end - context 'requesting gitlab-ci-ymls' do - describe 'GET /gitlab_ci_ymls' do - it 'returns a list of available gitlab_ci_ymls' do - get api('/gitlab_ci_ymls') + shared_examples_for 'GET licenses/:name' do |path| + context 'with :project and :fullname given' do + before do + get api("#{path}/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}") + end - expect(response.status).to eq(200) - expect(json_response).to be_an Array - expect(json_response.first['name']).not_to be_nil + context 'for the mit license' do + let(:license_type) { 'mit' } + + it 'returns the license text' do + expect(json_response['content']).to include('The MIT License (MIT)') + end + + it 'replaces placeholder values' do + expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton") + end + end + + context 'for the agpl-3.0 license' do + let(:license_type) { 'agpl-3.0' } + + it 'returns the license text' do + expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE') + end + + it 'replaces placeholder values' do + expect(json_response['content']).to include('My Awesome Project') + expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton") + end + end + + context 'for the gpl-3.0 license' do + let(:license_type) { 'gpl-3.0' } + + it 'returns the license text' do + expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE') + end + + it 'replaces placeholder values' do + expect(json_response['content']).to include('My Awesome Project') + expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton") + end + end + + context 'for the gpl-2.0 license' do + let(:license_type) { 'gpl-2.0' } + + it 'returns the license text' do + expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE') + end + + it 'replaces placeholder values' do + expect(json_response['content']).to include('My Awesome Project') + expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton") + end + end + + context 'for the apache-2.0 license' do + let(:license_type) { 'apache-2.0' } + + it 'returns the license text' do + expect(json_response['content']).to include('Apache License') + end + + it 'replaces placeholder values' do + expect(json_response['content']).to include("Copyright #{Time.now.year} Anton") + end + end + + context 'for an uknown license' do + let(:license_type) { 'muth-over9000' } + + it 'returns a 404' do + expect(response).to have_http_status(404) end end end - describe 'GET /gitlab_ci_ymls/Ruby' do - it 'adds a disclaimer on the top' do - get api('/gitlab_ci_ymls/Ruby') + context 'with no :fullname given' do + context 'with an authenticated user' do + let(:user) { create(:user) } + + it 'replaces the copyright owner placeholder with the name of the current user' do + get api('/templates/licenses/mit', user) - expect(response).to have_http_status(200) - expect(json_response['name']).not_to be_nil - expect(json_response['content']).to start_with("# This file is a template,") + expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}") + end end end end + + describe 'with /templates namespace' do + it_behaves_like 'the Template Entity', '/templates/gitignores/Ruby' + it_behaves_like 'the TemplateList Entity', '/templates/gitignores' + it_behaves_like 'requesting gitignores', '/templates/gitignores' + it_behaves_like 'requesting gitlab-ci-ymls', '/templates/gitlab_ci_ymls' + it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/templates/gitlab_ci_ymls/Ruby' + it_behaves_like 'the License Template Entity', '/templates/licenses/mit' + it_behaves_like 'GET licenses', '/templates/licenses' + it_behaves_like 'GET licenses/:name', '/templates/licenses' + end + + describe 'without /templates namespace' do + it_behaves_like 'the Template Entity', '/gitignores/Ruby' + it_behaves_like 'the TemplateList Entity', '/gitignores' + it_behaves_like 'requesting gitignores', '/gitignores' + it_behaves_like 'requesting gitlab-ci-ymls', '/gitlab_ci_ymls' + it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/gitlab_ci_ymls/Ruby' + it_behaves_like 'the License Template Entity', '/licenses/mit' + it_behaves_like 'GET licenses', '/licenses' + it_behaves_like 'GET licenses/:name', '/licenses' + end end -- cgit v1.2.1 From 9eedd6f9c7baa5693a24c33c29909bfc7dac1b21 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 12 Oct 2016 12:23:52 +0200 Subject: Improve desc for pipeline integration spec in MWBS --- .../merge_when_build_succeeds_service_spec.rb | 36 ++++++++++++---------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb index 01cdc172136..b80cfd8f450 100644 --- a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb @@ -98,7 +98,26 @@ describe MergeRequests::MergeWhenBuildSucceedsService do service.trigger(unrelated_pipeline) end end + end + + describe "#cancel" do + before do + service.cancel(mr_merge_if_green_enabled) + end + + it "resets all the merge_when_build_succeeds params" do + expect(mr_merge_if_green_enabled.merge_when_build_succeeds).to be_falsey + expect(mr_merge_if_green_enabled.merge_params).to eq({}) + expect(mr_merge_if_green_enabled.merge_user).to be nil + end + + it 'Posts a system note' do + note = mr_merge_if_green_enabled.notes.last + expect(note.note).to include 'Canceled the automatic merge' + end + end + describe 'pipeline integration' do context 'when there are multiple stages in the pipeline' do let(:ref) { mr_merge_if_green_enabled.source_branch } let(:sha) { project.commit(ref).id } @@ -139,21 +158,4 @@ describe MergeRequests::MergeWhenBuildSucceedsService do end end end - - describe "#cancel" do - before do - service.cancel(mr_merge_if_green_enabled) - end - - it "resets all the merge_when_build_succeeds params" do - expect(mr_merge_if_green_enabled.merge_when_build_succeeds).to be_falsey - expect(mr_merge_if_green_enabled.merge_params).to eq({}) - expect(mr_merge_if_green_enabled.merge_user).to be nil - end - - it 'Posts a system note' do - note = mr_merge_if_green_enabled.notes.last - expect(note.note).to include 'Canceled the automatic merge' - end - end end -- cgit v1.2.1 From 2b37f040b612303b714ec8cee0b482427e7c2b3c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 11 Oct 2016 12:58:56 +0200 Subject: Ignore deployment for statistics in Cycle Analytics, except in staging and production stages Also, updated specs and docs. --- spec/models/cycle_analytics/code_spec.rb | 88 +++++++++++++++++++++--------- spec/models/cycle_analytics/issue_spec.rb | 2 - spec/models/cycle_analytics/plan_spec.rb | 2 - spec/models/cycle_analytics/review_spec.rb | 4 +- spec/models/cycle_analytics/test_spec.rb | 5 -- 5 files changed, 62 insertions(+), 39 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index b9381e33914..7691d690db0 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -8,35 +8,69 @@ describe 'CycleAnalytics#code', feature: true do let(:user) { create(:user, :admin) } subject { CycleAnalytics.new(project, from: from_date) } - generate_cycle_analytics_spec( - phase: :code, - data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, - start_time_conditions: [["issue mentioned in a commit", - -> (context, data) do - context.create_commit_referencing_issue(data[:issue]) - end]], - end_time_conditions: [["merge request that closes issue is created", - -> (context, data) do - context.create_merge_request_closing_issue(data[:issue]) - end]], - post_fn: -> (context, data) do - context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master - end) - - 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) - - create_commit_referencing_issue(issue) - create_merge_request_closing_issue(issue, message: "Closes nothing") - - merge_merge_requests_closing_issue(issue) - deploy_master + context 'with deployment' do + generate_cycle_analytics_spec( + phase: :code, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["issue mentioned in a commit", + -> (context, data) do + context.create_commit_referencing_issue(data[:issue]) + end]], + end_time_conditions: [["merge request that closes issue is created", + -> (context, data) do + context.create_merge_request_closing_issue(data[:issue]) + end]], + post_fn: -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + context.deploy_master + end) + + 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) + + create_commit_referencing_issue(issue) + create_merge_request_closing_issue(issue, message: "Closes nothing") + + merge_merge_requests_closing_issue(issue) + deploy_master + end + + expect(subject.code).to be_nil end + end + end - expect(subject.code).to be_nil + context 'without deployment' do + generate_cycle_analytics_spec( + phase: :code, + data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } }, + start_time_conditions: [["issue mentioned in a commit", + -> (context, data) do + context.create_commit_referencing_issue(data[:issue]) + end]], + end_time_conditions: [["merge request that closes issue is created", + -> (context, data) do + context.create_merge_request_closing_issue(data[:issue]) + end]], + post_fn: -> (context, data) do + context.merge_merge_requests_closing_issue(data[:issue]) + end) + + 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) + + create_commit_referencing_issue(issue) + create_merge_request_closing_issue(issue, message: "Closes nothing") + + merge_merge_requests_closing_issue(issue) + end + + expect(subject.code).to be_nil + end end end end diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index e9cc71254ab..f649b44d367 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -28,7 +28,6 @@ describe 'CycleAnalytics#issue', models: true do if data[:issue].persisted? context.create_merge_request_closing_issue(data[:issue].reload) context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master end end) @@ -41,7 +40,6 @@ describe 'CycleAnalytics#issue', models: true do create_merge_request_closing_issue(issue) merge_merge_requests_closing_issue(issue) - deploy_master end expect(subject.issue).to be_nil diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 5b8c96dc992..2cdefbeef21 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -31,7 +31,6 @@ describe 'CycleAnalytics#plan', feature: true do post_fn: -> (context, data) do context.create_merge_request_closing_issue(data[:issue], source_branch: data[:branch_name]) context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master end) context "when a regular label (instead of a list label) is added to the issue" do @@ -44,7 +43,6 @@ describe 'CycleAnalytics#plan', feature: true do create_merge_request_closing_issue(issue, source_branch: branch_name) merge_merge_requests_closing_issue(issue) - deploy_master expect(subject.issue).to be_nil end diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index b6e26d8f261..0ed080a42b1 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -19,14 +19,12 @@ describe 'CycleAnalytics#review', feature: true do -> (context, data) do context.merge_merge_requests_closing_issue(data[:issue]) end]], - post_fn: -> (context, data) { context.deploy_master }) + post_fn: nil) 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)) - - deploy_master end expect(subject.review).to be_nil diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index 89ace0b2742..c454e3e0701 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -20,7 +20,6 @@ describe 'CycleAnalytics#test', feature: true do end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]], post_fn: -> (context, data) do context.merge_merge_requests_closing_issue(data[:issue]) - context.deploy_master end) context "when the pipeline is for a regular merge request (that doesn't close an issue)" do @@ -34,7 +33,6 @@ describe 'CycleAnalytics#test', feature: true do pipeline.succeed! merge_merge_requests_closing_issue(issue) - deploy_master end expect(subject.test).to be_nil @@ -49,7 +47,6 @@ describe 'CycleAnalytics#test', feature: true do pipeline.run! pipeline.succeed! - deploy_master end expect(subject.test).to be_nil @@ -67,7 +64,6 @@ describe 'CycleAnalytics#test', feature: true do pipeline.drop! merge_merge_requests_closing_issue(issue) - deploy_master end expect(subject.test).to be_nil @@ -85,7 +81,6 @@ describe 'CycleAnalytics#test', feature: true do pipeline.cancel! merge_merge_requests_closing_issue(issue) - deploy_master end expect(subject.test).to be_nil -- cgit v1.2.1 From 42ba19f339a63a1e49a40fd4df9c75470ec71f25 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 12 Oct 2016 14:30:49 +0200 Subject: fixed newline --- spec/models/cycle_analytics/test_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index c454e3e0701..02ddfeed9c1 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -46,7 +46,6 @@ describe 'CycleAnalytics#test', feature: true do pipeline.run! pipeline.succeed! - end expect(subject.test).to be_nil -- cgit v1.2.1 From 1bb64ec99476451d67463e3508b449aeea7e694f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Sep 2016 17:21:19 +0300 Subject: Add spec for compare service Signed-off-by: Dmitriy Zaporozhets --- spec/services/compare_service_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 spec/services/compare_service_spec.rb (limited to 'spec') diff --git a/spec/services/compare_service_spec.rb b/spec/services/compare_service_spec.rb new file mode 100644 index 00000000000..d809f291b44 --- /dev/null +++ b/spec/services/compare_service_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe CompareService, services: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:service) { described_class.new } + + describe '#execute' do + context 'compare with base, like feature...fix' do + subject { service.execute(project, 'feature', project, 'fix', false) } + + it { expect(subject.diffs.size).to eq(1) } + end + + context 'straight compare, like feature..fix' do + subject { service.execute(project, 'feature', project, 'fix', true) } + + it { expect(subject.diffs.size).to eq(3) } + end + end +end -- cgit v1.2.1 From cdcc11d48fe6d04f6a1cfebc39bcea71d35b3e4a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Sep 2016 17:46:47 +0300 Subject: Improve tests for merge request diff model Signed-off-by: Dmitriy Zaporozhets --- spec/models/merge_request_diff_spec.rb | 40 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index f27de0948ee..69b8afd22a3 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -74,27 +74,37 @@ describe MergeRequestDiff, models: true do end end end + end - describe '#commits_sha' do - shared_examples 'returning all commits SHA' do - it 'returns all commits SHA' do - commits_sha = subject.commits_sha + describe '#commits_sha' do + shared_examples 'returning all commits SHA' do + it 'returns all commits SHA' do + commits_sha = subject.commits_sha - expect(commits_sha).to eq(subject.commits.map(&:sha)) - end + expect(commits_sha).to eq(subject.commits.map(&:sha)) end + end - context 'when commits were loaded' do - before do - subject.commits - end - - it_behaves_like 'returning all commits SHA' + context 'when commits were loaded' do + before do + subject.commits end - context 'when commits were not loaded' do - it_behaves_like 'returning all commits SHA' - end + it_behaves_like 'returning all commits SHA' + end + + context 'when commits were not loaded' do + it_behaves_like 'returning all commits SHA' + end + end + + describe '#compare_with' do + subject { create(:merge_request).merge_request_diff } + + it 'delegates compare to the service' do + expect(CompareService).to receive(:new).and_call_original + + subject.compare_with('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') end end end -- cgit v1.2.1 From 7421c08ace8a129b37c4942eb21a0b5cf1a73a53 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Sep 2016 18:02:06 +0300 Subject: Better tests for MergeRequestDiff#compare_with method Signed-off-by: Dmitriy Zaporozhets --- spec/models/merge_request_diff_spec.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 69b8afd22a3..e5007424041 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -99,12 +99,18 @@ describe MergeRequestDiff, models: true do end describe '#compare_with' do - subject { create(:merge_request).merge_request_diff } + subject { create(:merge_request, source_branch: 'fix').merge_request_diff } it 'delegates compare to the service' do expect(CompareService).to receive(:new).and_call_original - subject.compare_with('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') + subject.compare_with(nil) + end + + it 'uses git diff A..B approach by default' do + diffs = subject.compare_with('0b4bc9a49b562e85de7cc9e834518ea6828729b9').diffs + + expect(diffs.size).to eq(3) end end end -- cgit v1.2.1 From b48c4b2662e7db9d68052392fb34dd2b27d12cf5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 12 Oct 2016 13:27:59 +0300 Subject: Refactor straight compare diff code Signed-off-by: Dmitriy Zaporozhets --- spec/services/compare_service_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/services/compare_service_spec.rb b/spec/services/compare_service_spec.rb index d809f291b44..3760f19aaa2 100644 --- a/spec/services/compare_service_spec.rb +++ b/spec/services/compare_service_spec.rb @@ -7,13 +7,13 @@ describe CompareService, services: true do describe '#execute' do context 'compare with base, like feature...fix' do - subject { service.execute(project, 'feature', project, 'fix', false) } + subject { service.execute(project, 'feature', 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', true) } + subject { service.execute(project, 'feature', project, 'fix', straight: true) } it { expect(subject.diffs.size).to eq(3) } end -- cgit v1.2.1 From 8aa381c9c408baef295e721f4f11964de8db1aa0 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 12 Oct 2016 14:45:26 +0000 Subject: Revert "Merge branch 'tests-use-tmpfs' into 'master'" This reverts merge request !6730 --- spec/spec_helper.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'spec') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f313bd4f249..b19f5824236 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -50,11 +50,6 @@ RSpec.configure do |config| example.run Rails.cache = caching_store end - - config.after(:each) do - FileUtils.rm_rf("tmp/tests/repositories") - FileUtils.mkdir_p("tmp/tests/repositories") - end end FactoryGirl::SyntaxRunner.class_eval do -- cgit v1.2.1 From b998479c81512b7c9a2cff28e7aabff3c4be0424 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 12 Oct 2016 13:32:48 +0200 Subject: API: Version information --- spec/requests/api/version_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 spec/requests/api/version_spec.rb (limited to 'spec') diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb new file mode 100644 index 00000000000..54b69a0cae7 --- /dev/null +++ b/spec/requests/api/version_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + describe 'GET /version' do + context 'when unauthenticated' do + it 'returns authentication error' do + get api('/version') + + expect(response).to have_http_status(401) + end + end + + context 'when authenticated' do + let(:user) { create(:user) } + + it 'returns the version information' do + get api('/version', user) + + expect(response).to have_http_status(200) + expect(json_response['version']).to eq(Gitlab::VERSION) + expect(json_response['revision']).to eq(Gitlab::REVISION) + end + end + end +end -- cgit v1.2.1 From f32bc1f52662664048876b27e181a1cacda02580 Mon Sep 17 00:00:00 2001 From: Georg G Date: Wed, 12 Oct 2016 18:48:53 +0200 Subject: Add spec for Projects::GraphsController#languages --- .../controllers/projects/graphs_controller_spec.rb | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 spec/controllers/projects/graphs_controller_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb new file mode 100644 index 00000000000..3f4535b7a24 --- /dev/null +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' +require 'ostruct' + +describe Projects::GraphsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + sign_in(user) + project.team << [user, :master] + end + + describe 'GET #languages' do + let(:linguist_repository) do + OpenStruct.new(languages: { + 'Ruby' => 1000, + 'CoffeeScript' => 350, + 'PowerShell' => 15 + }) + end + + let(:expected_values) do + ps_color = "##{Digest::SHA256.hexdigest('PowerShell')[0...6]}" + [ + # colors from Linguist: + { value: 73.26, label: "Ruby", color: "#701516", highlight: "#701516" }, + { value: 25.64, label: "CoffeeScript", color: "#244776", highlight: "#244776" }, + # colors from SHA256 fallback: + { value: 1.1, label: "PowerShell", color: ps_color, highlight: ps_color } + ] + end + + before do + allow(Linguist::Repository).to receive(:new).and_return(linguist_repository) + end + + it 'sets the correct colour according to language' do + get(:languages, namespace_id: project.namespace.path, project_id: project.path, id: 'master') + + expect(assigns(:languages)).to eq(expected_values) + end + end +end -- cgit v1.2.1 From 2461e10912b484c6942cd26f8fffd5c5557befa7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 12 Oct 2016 13:44:33 +0200 Subject: Execute pipeline hooks asynchronously --- spec/workers/pipeline_hooks_worker_spec.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spec/workers/pipeline_hooks_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb new file mode 100644 index 00000000000..035e329839f --- /dev/null +++ b/spec/workers/pipeline_hooks_worker_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe PipelineHooksWorker do + describe '#perform' do + context 'when pipeline exists' do + let(:pipeline) { create(:ci_pipeline) } + + it 'executes hooks for the pipeline' do + expect_any_instance_of(Ci::Pipeline) + .to receive(:execute_hooks) + + described_class.new.perform(pipeline.id) + end + end + + context 'when pipeline does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From ce4dad45557888066733bb20470bf56b87d4c8b7 Mon Sep 17 00:00:00 2001 From: Georg G Date: Thu, 13 Oct 2016 07:01:34 +0200 Subject: Use test double and matchers --- spec/controllers/projects/graphs_controller_spec.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index 3f4535b7a24..dd743356145 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require 'ostruct' describe Projects::GraphsController do let(:project) { create(:project) } @@ -12,7 +11,7 @@ describe Projects::GraphsController do describe 'GET #languages' do let(:linguist_repository) do - OpenStruct.new(languages: { + double(languages: { 'Ruby' => 1000, 'CoffeeScript' => 350, 'PowerShell' => 15 @@ -23,10 +22,10 @@ describe Projects::GraphsController do ps_color = "##{Digest::SHA256.hexdigest('PowerShell')[0...6]}" [ # colors from Linguist: - { value: 73.26, label: "Ruby", color: "#701516", highlight: "#701516" }, - { value: 25.64, label: "CoffeeScript", color: "#244776", highlight: "#244776" }, + { label: "Ruby", color: "#701516", highlight: "#701516" }, + { label: "CoffeeScript", color: "#244776", highlight: "#244776" }, # colors from SHA256 fallback: - { value: 1.1, label: "PowerShell", color: ps_color, highlight: ps_color } + { label: "PowerShell", color: ps_color, highlight: ps_color } ] end @@ -37,7 +36,9 @@ describe Projects::GraphsController do it 'sets the correct colour according to language' do get(:languages, namespace_id: project.namespace.path, project_id: project.path, id: 'master') - expect(assigns(:languages)).to eq(expected_values) + expected_values.each do |val| + expect(assigns(:languages)).to include(include(val)) + end end end end -- cgit v1.2.1 From 48015deda12cdff6b814785c97316e5b77c4a03e Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Wed, 12 Oct 2016 11:16:29 +0500 Subject: Union examples in event spec fo speed up --- spec/models/event_spec.rb | 110 +++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 49 deletions(-) (limited to 'spec') diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 06cac929bbf..733b79079ed 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -27,17 +27,17 @@ describe Event, models: true do end describe "Push event" do - before do - project = create(:project) - @user = project.owner - @event = create_event(project, @user) + let(:project) { create(:project) } + let(:user) { project.owner } + let(:event) { create_event(project, user) } + + it do + expect(event.push?).to be_truthy + expect(event.visible_to_user?).to be_truthy + expect(event.tag?).to be_falsey + expect(event.branch_name).to eq("master") + expect(event.author).to eq(user) end - - it { expect(@event.push?).to be_truthy } - it { expect(@event.visible_to_user?).to be_truthy } - it { expect(@event.tag?).to be_falsey } - it { expect(@event.branch_name).to eq("master") } - it { expect(@event.author).to eq(@user) } end describe '#note?' do @@ -59,8 +59,8 @@ describe Event, models: true do describe '#visible_to_user?' do let(:project) { create(:empty_project, :public) } let(:non_member) { create(:user) } - let(:member) { create(:user) } - let(:guest) { create(:user) } + let(:member) { create(:user) } + let(:guest) { create(:user) } let(:author) { create(:author) } let(:assignee) { create(:user) } let(:admin) { create(:admin) } @@ -79,23 +79,27 @@ describe Event, models: true do context 'for non confidential issues' do let(:target) { issue } - it { expect(event.visible_to_user?(non_member)).to eq true } - it { expect(event.visible_to_user?(author)).to eq true } - it { expect(event.visible_to_user?(assignee)).to eq true } - it { expect(event.visible_to_user?(member)).to eq true } - it { expect(event.visible_to_user?(guest)).to eq true } - it { expect(event.visible_to_user?(admin)).to eq true } + it do + expect(event.visible_to_user?(non_member)).to eq true + expect(event.visible_to_user?(author)).to eq true + expect(event.visible_to_user?(assignee)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq true + expect(event.visible_to_user?(admin)).to eq true + end end context 'for confidential issues' do let(:target) { confidential_issue } - it { expect(event.visible_to_user?(non_member)).to eq false } - it { expect(event.visible_to_user?(author)).to eq true } - it { expect(event.visible_to_user?(assignee)).to eq true } - it { expect(event.visible_to_user?(member)).to eq true } - it { expect(event.visible_to_user?(guest)).to eq false } - it { expect(event.visible_to_user?(admin)).to eq true } + it do + expect(event.visible_to_user?(non_member)).to eq false + expect(event.visible_to_user?(author)).to eq true + expect(event.visible_to_user?(assignee)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq false + expect(event.visible_to_user?(admin)).to eq true + end end end @@ -103,23 +107,27 @@ describe Event, models: true do context 'on non confidential issues' do let(:target) { note_on_issue } - it { expect(event.visible_to_user?(non_member)).to eq true } - it { expect(event.visible_to_user?(author)).to eq true } - it { expect(event.visible_to_user?(assignee)).to eq true } - it { expect(event.visible_to_user?(member)).to eq true } - it { expect(event.visible_to_user?(guest)).to eq true } - it { expect(event.visible_to_user?(admin)).to eq true } + it do + expect(event.visible_to_user?(non_member)).to eq true + expect(event.visible_to_user?(author)).to eq true + expect(event.visible_to_user?(assignee)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq true + expect(event.visible_to_user?(admin)).to eq true + end end context 'on confidential issues' do let(:target) { note_on_confidential_issue } - it { expect(event.visible_to_user?(non_member)).to eq false } - it { expect(event.visible_to_user?(author)).to eq true } - it { expect(event.visible_to_user?(assignee)).to eq true } - it { expect(event.visible_to_user?(member)).to eq true } - it { expect(event.visible_to_user?(guest)).to eq false } - it { expect(event.visible_to_user?(admin)).to eq true } + it do + expect(event.visible_to_user?(non_member)).to eq false + expect(event.visible_to_user?(author)).to eq true + expect(event.visible_to_user?(assignee)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq false + expect(event.visible_to_user?(admin)).to eq true + end end end @@ -129,22 +137,26 @@ describe Event, models: true do let(:note_on_merge_request) { create(:legacy_diff_note_on_merge_request, noteable: merge_request, project: project) } let(:target) { note_on_merge_request } - it { expect(event.visible_to_user?(non_member)).to eq true } - it { expect(event.visible_to_user?(author)).to eq true } - it { expect(event.visible_to_user?(assignee)).to eq true } - it { expect(event.visible_to_user?(member)).to eq true } - it { expect(event.visible_to_user?(guest)).to eq true } - it { expect(event.visible_to_user?(admin)).to eq true } + it do + expect(event.visible_to_user?(non_member)).to eq true + expect(event.visible_to_user?(author)).to eq true + expect(event.visible_to_user?(assignee)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq true + expect(event.visible_to_user?(admin)).to eq true + end context 'private project' do let(:project) { create(:project, :private) } - it { expect(event.visible_to_user?(non_member)).to eq false } - it { expect(event.visible_to_user?(author)).to eq true } - it { expect(event.visible_to_user?(assignee)).to eq true } - it { expect(event.visible_to_user?(member)).to eq true } - it { expect(event.visible_to_user?(guest)).to eq false } - it { expect(event.visible_to_user?(admin)).to eq true } + it do + expect(event.visible_to_user?(non_member)).to eq false + expect(event.visible_to_user?(author)).to eq true + expect(event.visible_to_user?(assignee)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq false + expect(event.visible_to_user?(admin)).to eq true + end end end end @@ -214,6 +226,6 @@ describe Event, models: true do action: Event::PUSHED, data: data, author_id: user.id - }.merge(attrs)) + }.merge!(attrs)) end end -- cgit v1.2.1 From 3c476ee62512a0642ca3e5e6b228f9abdd867a34 Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Tue, 11 Oct 2016 16:52:49 +0100 Subject: Maintain "force_remove_source_branch" options on Merge Request unless specified --- spec/services/merge_requests/update_service_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index fd5f94047c2..2433a7dad06 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -105,6 +105,18 @@ describe MergeRequests::UpdateService, services: true do expect(note).not_to be_nil expect(note.note).to eq 'Target branch changed from `master` to `target`' end + + context 'when not including source branch removal options' do + before do + opts.delete(:force_remove_source_branch) + end + + it 'maintains the original options' do + update_merge_request(opts) + + expect(@merge_request.merge_params["force_remove_source_branch"]).to eq("1") + end + end end context 'todos' do -- cgit v1.2.1 From fafc5a1777484ba6b1b12c5e88f3fc783fb4d839 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 12:45:16 +0200 Subject: Perform CI build hooks asynchronously using worker --- spec/workers/build_hooks_worker_spec.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spec/workers/build_hooks_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb new file mode 100644 index 00000000000..97654a93f5c --- /dev/null +++ b/spec/workers/build_hooks_worker_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe BuildHooksWorker do + describe '#perform' do + context 'when build exists' do + let!(:build) { create(:ci_build) } + + it 'calls build hooks' do + expect_any_instance_of(Ci::Build) + .to receive(:execute_hooks) + + described_class.new.perform(build.id) + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 204fdcb1abb9c76b2d4bd6260c6e5ce91529aeb8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 12:58:25 +0200 Subject: Add build success worker that runs asynchronously --- spec/workers/build_success_worker_spec.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 spec/workers/build_success_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb new file mode 100644 index 00000000000..c42bcd45d50 --- /dev/null +++ b/spec/workers/build_success_worker_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe BuildSuccessWorker do + describe '#perform' do + context 'when build exists' do + context 'when build belogs to the environment' do + let!(:build) { create(:ci_build, environment: 'production') } + + it 'executes deployment service' do + expect_any_instance_of(CreateDeploymentService) + .to receive(:execute) + + described_class.new.perform(build.id) + end + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From 85324ff8d36165709d5c98569ca0745b32ba9095 Mon Sep 17 00:00:00 2001 From: Georg G Date: Thu, 13 Oct 2016 13:08:19 +0200 Subject: Fix indentation and change inner matcher --- spec/controllers/projects/graphs_controller_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index dd743356145..74e6603b0cb 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -12,10 +12,10 @@ describe Projects::GraphsController do describe 'GET #languages' do let(:linguist_repository) do double(languages: { - 'Ruby' => 1000, - 'CoffeeScript' => 350, - 'PowerShell' => 15 - }) + 'Ruby' => 1000, + 'CoffeeScript' => 350, + 'PowerShell' => 15 + }) end let(:expected_values) do @@ -37,7 +37,7 @@ describe Projects::GraphsController do get(:languages, namespace_id: project.namespace.path, project_id: project.path, id: 'master') expected_values.each do |val| - expect(assigns(:languages)).to include(include(val)) + expect(assigns(:languages)).to include(a_hash_including(val)) end end end -- cgit v1.2.1 From bc4d732af126277b3e85aedce795158bd389fbea Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 13 Oct 2016 14:11:26 +0300 Subject: Update users routing spec Signed-off-by: Dmitriy Zaporozhets --- spec/features/users_spec.rb | 12 ++++++++++++ spec/routing/routing_spec.rb | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 6498b7317b4..c78c84dc5d0 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -49,6 +49,18 @@ feature 'Users', feature: true do expect(current_path).to eq user_path(user) expect(page).to have_text(user.name) end + + scenario '/u/user1/groups redirects to user groups page' do + visit '/u/user1/groups' + + expect(current_path).to eq user_groups_path(user) + end + + scenario '/u/user1/projects redirects to user projects page' do + visit '/u/user1/projects' + + expect(current_path).to eq user_projects_path(user) + end end def errors_on_page(page) diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 0ee1c811dfb..f848d96c729 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -15,27 +15,27 @@ describe UsersController, "routing" do end it "to #groups" do - expect(get("/u/User/groups")).to route_to('users#groups', username: 'User') + expect(get("/users/User/groups")).to route_to('users#groups', username: 'User') end it "to #projects" do - expect(get("/u/User/projects")).to route_to('users#projects', username: 'User') + expect(get("/users/User/projects")).to route_to('users#projects', username: 'User') end it "to #contributed" do - expect(get("/u/User/contributed")).to route_to('users#contributed', username: 'User') + expect(get("/users/User/contributed")).to route_to('users#contributed', username: 'User') end it "to #snippets" do - expect(get("/u/User/snippets")).to route_to('users#snippets', username: 'User') + expect(get("/users/User/snippets")).to route_to('users#snippets', username: 'User') end it "to #calendar" do - expect(get("/u/User/calendar")).to route_to('users#calendar', username: 'User') + expect(get("/users/User/calendar")).to route_to('users#calendar', username: 'User') end it "to #calendar_activities" do - expect(get("/u/User/calendar_activities")).to route_to('users#calendar_activities', username: 'User') + expect(get("/users/User/calendar_activities")).to route_to('users#calendar_activities', username: 'User') end end -- cgit v1.2.1 From ae95118a4ff3242a210d93e57370f6ef400db886 Mon Sep 17 00:00:00 2001 From: Johan H Date: Tue, 11 Oct 2016 16:27:09 +0200 Subject: Convert UTF-8 Emoji to Gitlab emoji --- spec/lib/banzai/filter/emoji_filter_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'spec') diff --git a/spec/lib/banzai/filter/emoji_filter_spec.rb b/spec/lib/banzai/filter/emoji_filter_spec.rb index 475160bb5ec..c8e62f528df 100644 --- a/spec/lib/banzai/filter/emoji_filter_spec.rb +++ b/spec/lib/banzai/filter/emoji_filter_spec.rb @@ -16,10 +16,12 @@ describe Banzai::Filter::EmojiFilter, lib: true do doc = filter('

    :heart:

    ') expect(doc.css('img').first.attr('src')).to eq 'https://foo.com/assets/2764.png' end + it 'replaces supported unicode emoji' do doc = filter('

    ❤️

    ') expect(doc.css('img').first.attr('src')).to eq 'https://foo.com/assets/2764.png' end + it 'ignores unsupported emoji' do exp = act = '

    :foo:

    ' doc = filter(act) @@ -162,4 +164,18 @@ describe Banzai::Filter::EmojiFilter, lib: true do doc = filter(':frowning:', asset_host: 'https://this-is-ignored-i-guess?') expect(doc.css('img').first.attr('src')).to start_with('https://cdn.example.com') end + + it 'uses a custom asset_root context' do + root = Gitlab.config.gitlab.url + 'gitlab/root' + + doc = filter("'🎱'", asset_root: root) + expect(doc.css('img').first.attr('src')).to start_with(root) + end + + it 'uses a custom asset_host context' do + ActionController::Base.asset_host = 'https://cdn.example.com' + + doc = filter("'🎱'", asset_host: 'https://this-is-ignored-i-guess?') + expect(doc.css('img').first.attr('src')).to start_with('https://cdn.example.com') + end end -- cgit v1.2.1 From 8efa041a730515e57f127850414b3557c7af60b4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 14:55:44 +0200 Subject: Do not process build success if project was removed --- spec/workers/build_success_worker_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'spec') diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb index c42bcd45d50..dba70883130 100644 --- a/spec/workers/build_success_worker_spec.rb +++ b/spec/workers/build_success_worker_spec.rb @@ -13,6 +13,17 @@ describe BuildSuccessWorker do described_class.new.perform(build.id) end end + + context 'when build is not associated with project' do + let!(:build) { create(:ci_build, project: nil) } + + it 'does not create deployment' do + expect_any_instance_of(CreateDeploymentService) + .not_to receive(:execute) + + described_class.new.perform(build.id) + end + end end context 'when build does not exist' do -- cgit v1.2.1 From 3ca064eeef874cbb258903abb8009e3ce257a4b4 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Thu, 13 Oct 2016 18:08:15 +0500 Subject: Add missing tests for download snippet ref: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6720 --- spec/controllers/snippets_controller_spec.rb | 156 ++++++++++++++------------- 1 file changed, 83 insertions(+), 73 deletions(-) (limited to 'spec') diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index 41d263a46a4..2d762fdaa04 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -116,116 +116,126 @@ describe SnippetsController do end end - describe 'GET #raw' do - let(:user) { create(:user) } + %w(raw download).each do |action| + describe "GET #{action}" do + context 'when the personal snippet is private' do + let(:personal_snippet) { create(:personal_snippet, :private, author: user) } + + context 'when signed in' do + before do + sign_in(user) + end - context 'when the personal snippet is private' do - let(:personal_snippet) { create(:personal_snippet, :private, author: user) } + context 'when signed in user is not the author' do + let(:other_author) { create(:author) } + let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) } - context 'when signed in' do - before do - sign_in(user) - end + it 'responds with status 404' do + get action, id: other_personal_snippet.to_param - context 'when signed in user is not the author' do - let(:other_author) { create(:author) } - let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) } + expect(response).to have_http_status(404) + end + end - it 'responds with status 404' do - get :raw, id: other_personal_snippet.to_param + context 'when signed in user is the author' do + before { get action, id: personal_snippet.to_param } - expect(response).to have_http_status(404) - end - end + it 'responds with status 200' do + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response).to have_http_status(200) + end - context 'when signed in user is the author' do - it 'renders the raw snippet' do - get :raw, id: personal_snippet.to_param + it 'has expected headers' do + expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8') - expect(assigns(:snippet)).to eq(personal_snippet) - expect(response).to have_http_status(200) + if action == :download + expect(response.header['Content-Disposition']).to match(/attachment/) + elsif action == :raw + expect(response.header['Content-Disposition']).to match(/inline/) + end + end end end - end - context 'when not signed in' do - it 'redirects to the sign in page' do - get :raw, id: personal_snippet.to_param + context 'when not signed in' do + it 'redirects to the sign in page' do + get action, id: personal_snippet.to_param - expect(response).to redirect_to(new_user_session_path) + expect(response).to redirect_to(new_user_session_path) + end end end - end - context 'when the personal snippet is internal' do - let(:personal_snippet) { create(:personal_snippet, :internal, author: user) } + context 'when the personal snippet is internal' do + let(:personal_snippet) { create(:personal_snippet, :internal, author: user) } - context 'when signed in' do - before do - sign_in(user) - end + context 'when signed in' do + before do + sign_in(user) + end - it 'renders the raw snippet' do - get :raw, id: personal_snippet.to_param + it 'responds with status 200' do + get action, id: personal_snippet.to_param - expect(assigns(:snippet)).to eq(personal_snippet) - expect(response).to have_http_status(200) + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response).to have_http_status(200) + end end - end - context 'when not signed in' do - it 'redirects to the sign in page' do - get :raw, id: personal_snippet.to_param + context 'when not signed in' do + it 'redirects to the sign in page' do + get action, id: personal_snippet.to_param - expect(response).to redirect_to(new_user_session_path) + expect(response).to redirect_to(new_user_session_path) + end end end - end - context 'when the personal snippet is public' do - let(:personal_snippet) { create(:personal_snippet, :public, author: user) } + context 'when the personal snippet is public' do + let(:personal_snippet) { create(:personal_snippet, :public, author: user) } - context 'when signed in' do - before do - sign_in(user) - end + context 'when signed in' do + before do + sign_in(user) + end - it 'renders the raw snippet' do - get :raw, id: personal_snippet.to_param + it 'responds with status 200' do + get action, id: personal_snippet.to_param - expect(assigns(:snippet)).to eq(personal_snippet) - expect(response).to have_http_status(200) + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response).to have_http_status(200) + end end - end - context 'when not signed in' do - it 'renders the raw snippet' do - get :raw, id: personal_snippet.to_param + context 'when not signed in' do + it 'responds with status 200' do + get action, id: personal_snippet.to_param - expect(assigns(:snippet)).to eq(personal_snippet) - expect(response).to have_http_status(200) + expect(assigns(:snippet)).to eq(personal_snippet) + expect(response).to have_http_status(200) + end end end - end - context 'when the personal snippet does not exist' do - context 'when signed in' do - before do - sign_in(user) - end + context 'when the personal snippet does not exist' do + context 'when signed in' do + before do + sign_in(user) + end - it 'responds with status 404' do - get :raw, id: 'doesntexist' + it 'responds with status 404' do + get action, id: 'doesntexist' - expect(response).to have_http_status(404) + expect(response).to have_http_status(404) + end end - end - context 'when not signed in' do - it 'responds with status 404' do - get :raw, id: 'doesntexist' + context 'when not signed in' do + it 'responds with status 404' do + get action, id: 'doesntexist' - expect(response).to have_http_status(404) + expect(response).to have_http_status(404) + end end end end -- cgit v1.2.1 From 5fd635d18b77f56f6acd264ccaa1a357e2fa1cdd Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 13 Oct 2016 15:22:55 +0200 Subject: Update code coverage for CI build asynchronously --- spec/workers/build_coverage_worker_spec.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 spec/workers/build_coverage_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/build_coverage_worker_spec.rb b/spec/workers/build_coverage_worker_spec.rb new file mode 100644 index 00000000000..ba20488f663 --- /dev/null +++ b/spec/workers/build_coverage_worker_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe BuildCoverageWorker do + describe '#perform' do + context 'when build exists' do + let!(:build) { create(:ci_build) } + + it 'updates code coverage' do + expect_any_instance_of(Ci::Build) + .to receive(:update_coverage) + + described_class.new.perform(build.id) + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From ae851edc3c76fd7b81de2e3d48ec8a531f3609b3 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Mon, 10 Oct 2016 03:19:55 +0100 Subject: Added no-template functionality Added tests --- spec/features/projects/issuable_templates_spec.rb | 40 +++++++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index cd79c4f512d..d886909ce85 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -15,6 +15,7 @@ feature 'issuable templates', feature: true, js: true do let(:template_content) { 'this is a test "bug" template' } let(:longtemplate_content) { %Q(this\n\n\n\n\nis\n\n\n\n\na\n\n\n\n\nbug\n\n\n\n\ntemplate) } let(:issue) { create(:issue, author: user, assignee: user, project: project) } + 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) @@ -26,7 +27,26 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "bug" template' do select_template 'bug' wait_for_ajax - preview_template(template_content) + preview_template + save_changes + end + + scenario 'user selects "bug" template and then "no template"' do + select_template 'bug' + wait_for_ajax + select_option 'No template' + wait_for_ajax + preview_template('') + save_changes('') + end + + scenario 'user selects "bug" template, edits description and then selects "reset template"' do + select_template 'bug' + wait_for_ajax + find_field('issue_description').send_keys(description_addition) + preview_template(template_content + description_addition) + select_option 'Reset template' + preview_template save_changes end @@ -37,7 +57,7 @@ feature 'issuable templates', feature: true, js: true do wait_for_ajax end_height = page.evaluate_script('$(".markdown-area").outerHeight()') - + expect(end_height).not_to eq(start_height) end end @@ -75,7 +95,7 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "feature-proposal" template' do select_template 'feature-proposal' wait_for_ajax - preview_template(template_content) + preview_template save_changes end end @@ -102,25 +122,31 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects template' do select_template 'feature-proposal' wait_for_ajax - preview_template(template_content) + preview_template save_changes end end end end - def preview_template(expected_content) + def preview_template(expected_content = template_content) click_link 'Preview' expect(page).to have_content expected_content + click_link 'Write' end - def save_changes + def save_changes(expected_content = template_content) click_button "Save changes" - expect(page).to have_content template_content + expect(page).to have_content expected_content end def select_template(name) first('.js-issuable-selector').click first('.js-issuable-selector-wrap .dropdown-content a', text: name).click end + + def select_option(name) + first('.js-issuable-selector').click + first('.js-issuable-selector-wrap .dropdown-footer-list a', text: name).click + end end -- cgit v1.2.1 From 776cea4c00d883cafc2bc5381f3b61b146a93976 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 13 Oct 2016 14:19:52 +0100 Subject: Handle case where deployment ref no longer exists Keep-around refs for deployments were only introduced in 8.10, so any deployment created in 8.9 could have a SHA pointing to a commit that no longer exists in the repository. We can't do anything useful with those deployments, so make `#includes_commit?` always return false for those. --- spec/models/deployment_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index bfff639ad78..01a4a53a264 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -38,5 +38,14 @@ describe Deployment, models: true do expect(deployment.includes_commit?(commit)).to be true end end + + context 'when the SHA for the deployment does not exist in the repo' do + it 'returns false' do + deployment.update(sha: Gitlab::Git::BLANK_SHA) + commit = project.commit + + expect(deployment.includes_commit?(commit)).to be false + end + end end end -- cgit v1.2.1 From bba47886264d0ca7650d2b4b202d69984650b0ae Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Mon, 10 Oct 2016 09:40:14 +0200 Subject: Extract project#update_merge_requests and SystemHooks to its own worker from GitPushService --- spec/models/project_spec.rb | 21 ------------ spec/services/git_push_service_spec.rb | 4 +-- .../merge_requests/refresh_service_spec.rb | 3 +- spec/workers/post_receive_spec.rb | 8 ++++- spec/workers/update_merge_requests_worker_spec.rb | 38 ++++++++++++++++++++++ 5 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 spec/workers/update_merge_requests_worker_spec.rb (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index dae546a0cdc..7435713d4c0 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -219,7 +219,6 @@ describe Project, models: true do describe 'Respond to' do it { is_expected.to respond_to(:url_to_repo) } it { is_expected.to respond_to(:repo_exists?) } - it { is_expected.to respond_to(:update_merge_requests) } it { is_expected.to respond_to(:execute_hooks) } it { is_expected.to respond_to(:owner) } it { is_expected.to respond_to(:path_with_namespace) } @@ -380,26 +379,6 @@ describe Project, models: true do end end - describe '#update_merge_requests' do - let(:project) { create(:project) } - let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } - let(:key) { create(:key, user_id: project.owner.id) } - let(:prev_commit_id) { merge_request.commits.last.id } - let(:commit_id) { merge_request.commits.first.id } - - it 'closes merge request if last commit from source branch was pushed to target branch' do - project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.target_branch}", key.user) - merge_request.reload - expect(merge_request.merged?).to be_truthy - end - - it 'updates merge request commits with new one if pushed to source branch' do - project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user) - merge_request.reload - expect(merge_request.diff_head_sha).to eq(commit_id) - end - end - describe '.find_with_namespace' do context 'with namespace' do before do diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 8e3e12114f2..dd2a9e9903a 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -184,8 +184,8 @@ describe GitPushService, services: true do context "Updates merge requests" do it "when pushing a new branch for the first time" do - expect(project).to receive(:update_merge_requests). - with(@blankrev, 'newrev', 'refs/heads/master', user) + expect(UpdateMergeRequestsWorker).to receive(:perform_async). + with(project.id, user.id, @blankrev, 'newrev', 'refs/heads/master') execute_service(project, user, @blankrev, 'newrev', 'refs/heads/master' ) end end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 5b4e4908add..e515bc9f89c 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -62,7 +62,8 @@ describe MergeRequests::RefreshService, services: true do it { expect(@merge_request.notes).not_to be_empty } it { expect(@merge_request).to be_open } - it { expect(@merge_request.merge_when_build_succeeds).to be_falsey} + it { expect(@merge_request.merge_when_build_succeeds).to be_falsey } + it { expect(@merge_request.diff_head_sha).to eq(@newrev) } it { expect(@fork_merge_request).to be_open } it { expect(@fork_merge_request.notes).to be_empty } it { expect(@build_failed_todo).to be_done } diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index ffeaafe654a..984acdade36 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -92,7 +92,13 @@ describe PostReceive do allow(Project).to receive(:find_with_namespace).and_return(project) expect(project).to receive(:execute_hooks).twice expect(project).to receive(:execute_services).twice - expect(project).to receive(:update_merge_requests) + + PostReceive.new.perform(pwd(project), key_id, base64_changes) + end + + it "enqueues a UpdateMergeRequestsWorker job" do + allow(Project).to receive(:find_with_namespace).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) end diff --git a/spec/workers/update_merge_requests_worker_spec.rb b/spec/workers/update_merge_requests_worker_spec.rb new file mode 100644 index 00000000000..c78a69eda67 --- /dev/null +++ b/spec/workers/update_merge_requests_worker_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe UpdateMergeRequestsWorker do + include RepoHelpers + + let(:project) { create(:project) } + let(:user) { create(:user) } + + subject { described_class.new } + + describe '#perform' do + let(:oldrev) { "123456" } + let(:newrev) { "789012" } + let(:ref) { "refs/heads/test" } + + def perform + subject.perform(project.id, user.id, oldrev, newrev, ref) + end + + it 'executes MergeRequests::RefreshService with expected values' do + expect(MergeRequests::RefreshService).to receive(:new).with(project, user).and_call_original + expect_any_instance_of(MergeRequests::RefreshService).to receive(:execute).with(oldrev, newrev, ref) + + perform + end + + it 'executes SystemHooksService with expected values' do + push_data = double('push_data') + expect(Gitlab::DataBuilder::Push).to receive(:build).with(project, user, oldrev, newrev, ref, []).and_return(push_data) + + system_hook_service = double('system_hook_service') + expect(SystemHooksService).to receive(:new).and_return(system_hook_service) + expect(system_hook_service).to receive(:execute_hooks).with(push_data, :push_hooks) + + perform + end + end +end -- cgit v1.2.1 From 3f71c43e88c56bb5310c8814cd9f95cafb4f53ef Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 1 Sep 2016 13:59:10 +0100 Subject: Allow setting content for resolutions When reading conflicts: 1. Add a `type` field. `text` works as before, and has `sections`; `text-editor` is a file with ambiguous conflict markers that can only be resolved in an editor. 2. Add a `content_path` field pointing to a JSON representation of the file's content for a single file. 3. Hitting `content_path` returns a similar datastructure to the `file`, but without the `content_path` and `sections` fields, and with a `content` field containing the full contents of the file (with conflict markers). When writing conflicts: 1. Instead of `sections` being at the top level, they are now in a `files` array. This matches the read format better. 2. The `files` array contains file hashes, each of which must contain: a. `new_path` b. `old_path` c. EITHER `sections` (which works as before) or `content` (with the full content of the resolved file). --- .../projects/merge_requests_controller_spec.rb | 168 +++++++++++++++++++-- .../merge_requests/resolve_service_spec.rb | 139 +++++++++++++++-- 2 files changed, 289 insertions(+), 18 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 84298f8bef4..1311b4aa264 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -570,7 +570,7 @@ describe Projects::MergeRequestsController do context 'when the conflicts cannot be resolved in the UI' do before do allow_any_instance_of(Gitlab::Conflict::Parser). - to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnexpectedDelimiter) + to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnmergeableFile) get :conflicts, namespace_id: merge_request_with_conflicts.project.namespace.to_param, @@ -655,6 +655,61 @@ describe Projects::MergeRequestsController do id: merge_request.iid expect(merge_request.reload.title).to eq(merge_request.wipless_title) + end + + describe 'GET conflict_for_path' do + let(:json_response) { JSON.parse(response.body) } + + def conflict_for_path(path) + get :conflict_for_path, + namespace_id: merge_request_with_conflicts.project.namespace.to_param, + project_id: merge_request_with_conflicts.project.to_param, + id: merge_request_with_conflicts.iid, + old_path: path, + new_path: path, + format: 'json' + end + + context 'when the conflicts cannot be resolved in the UI' do + before do + allow_any_instance_of(Gitlab::Conflict::Parser). + to receive(:parse).and_raise(Gitlab::Conflict::Parser::UnmergeableFile) + + conflict_for_path('files/ruby/regex.rb') + end + + + it 'returns a 404 status code' do + expect(response).to have_http_status(:not_found) + end + end + + context 'when the file does not exist cannot be resolved in the UI' do + before { conflict_for_path('files/ruby/regexp.rb') } + + it 'returns a 404 status code' do + expect(response).to have_http_status(:not_found) + end + end + + context 'with an existing file' do + let(:path) { 'files/ruby/regex.rb' } + + before { conflict_for_path(path) } + + it 'returns a 200 status code' do + expect(response).to have_http_status(:ok) + end + + it 'returns the file in JSON format' do + content = merge_request_with_conflicts.conflicts.file_for_path(path, path).content + + expect(json_response).to include('old_path' => path, + 'new_path' => path, + 'blob_icon' => 'file-text-o', + 'blob_path' => a_string_ending_with(path), + 'content' => content) + end end end @@ -662,22 +717,37 @@ describe Projects::MergeRequestsController do let(:json_response) { JSON.parse(response.body) } let!(:original_head_sha) { merge_request_with_conflicts.diff_head_sha } - def resolve_conflicts(sections) + def resolve_conflicts(files) post :resolve_conflicts, namespace_id: merge_request_with_conflicts.project.namespace.to_param, project_id: merge_request_with_conflicts.project.to_param, id: merge_request_with_conflicts.iid, format: 'json', - sections: sections, + files: files, commit_message: 'Commit message' end context 'with valid params' do before do - resolve_conflicts('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head', - '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', - '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', - '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin') + resolved_files = [ + { + 'new_path' => 'files/ruby/popen.rb', + 'old_path' => 'files/ruby/popen.rb', + 'sections' => { + '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head' + } + }, { + 'new_path' => 'files/ruby/regex.rb', + 'old_path' => 'files/ruby/regex.rb', + 'sections' => { + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin' + } + } + ] + + resolve_conflicts(resolved_files) end it 'creates a new commit on the branch' do @@ -692,7 +762,23 @@ describe Projects::MergeRequestsController do context 'when sections are missing' do before do - resolve_conflicts('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head') + resolved_files = [ + { + 'new_path' => 'files/ruby/popen.rb', + 'old_path' => 'files/ruby/popen.rb', + 'sections' => { + '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head' + } + }, { + 'new_path' => 'files/ruby/regex.rb', + 'old_path' => 'files/ruby/regex.rb', + 'sections' => { + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head' + } + } + ] + + resolve_conflicts(resolved_files) end it 'returns a 400 error' do @@ -700,7 +786,71 @@ describe Projects::MergeRequestsController do end it 'has a message with the name of the first missing section' do - expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9') + expect(json_response['message']).to include('6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21') + end + + it 'does not create a new commit' do + expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha) + end + end + + context 'when files are missing' do + before do + resolved_files = [ + { + 'new_path' => 'files/ruby/regex.rb', + 'old_path' => 'files/ruby/regex.rb', + 'sections' => { + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin' + } + } + ] + + resolve_conflicts(resolved_files) + end + + it 'returns a 400 error' do + expect(response).to have_http_status(:bad_request) + end + + it 'has a message with the name of the missing file' do + expect(json_response['message']).to include('files/ruby/popen.rb') + end + + it 'does not create a new commit' do + expect(original_head_sha).to eq(merge_request_with_conflicts.source_branch_head.sha) + end + end + + context 'when a file has identical content to the conflict' do + before do + resolved_files = [ + { + 'new_path' => 'files/ruby/popen.rb', + 'old_path' => 'files/ruby/popen.rb', + 'content' => merge_request_with_conflicts.conflicts.file_for_path('files/ruby/popen.rb', 'files/ruby/popen.rb').content + }, { + 'new_path' => 'files/ruby/regex.rb', + 'old_path' => 'files/ruby/regex.rb', + 'sections' => { + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin' + } + } + ] + + resolve_conflicts(resolved_files) + end + + it 'returns a 400 error' do + expect(response).to have_http_status(:bad_request) + end + + it 'has a message with the path of the problem file' do + expect(json_response['message']).to include('files/ruby/popen.rb') end it 'does not create a new commit' do diff --git a/spec/services/merge_requests/resolve_service_spec.rb b/spec/services/merge_requests/resolve_service_spec.rb index d71932458fa..e667e93bea4 100644 --- a/spec/services/merge_requests/resolve_service_spec.rb +++ b/spec/services/merge_requests/resolve_service_spec.rb @@ -24,15 +24,26 @@ describe MergeRequests::ResolveService do end describe '#execute' do - context 'with valid params' do + context 'with section params' do let(:params) do { - sections: { - '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head', - '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', - '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', - '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin' - }, + files: [ + { + old_path: 'files/ruby/popen.rb', + new_path: 'files/ruby/popen.rb', + sections: { + '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head' + } + }, { + old_path: 'files/ruby/regex.rb', + new_path: 'files/ruby/regex.rb', + sections: { + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin' + } + } + ], commit_message: 'This is a commit message!' } end @@ -74,8 +85,96 @@ describe MergeRequests::ResolveService do end end - context 'when a resolution is missing' do - let(:invalid_params) { { sections: { '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_14' => 'head' } } } + context 'with content and sections params' do + let(:popen_content) { "class Popen\nend" } + + let(:params) do + { + files: [ + { + old_path: 'files/ruby/popen.rb', + new_path: 'files/ruby/popen.rb', + content: popen_content + }, { + old_path: 'files/ruby/regex.rb', + new_path: 'files/ruby/regex.rb', + sections: { + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_21_21' => 'origin', + '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_49_49' => 'origin' + } + } + ], + commit_message: 'This is a commit message!' + } + end + + before do + MergeRequests::ResolveService.new(project, user, params).execute(merge_request) + end + + it 'creates a commit with the message' do + expect(merge_request.source_branch_head.message).to eq(params[:commit_message]) + end + + it 'creates a commit with the correct parents' do + expect(merge_request.source_branch_head.parents.map(&:id)). + to eq(['1450cd639e0bc6721eb02800169e464f212cde06', + '75284c70dd26c87f2a3fb65fd5a1f0b0138d3a6b']) + end + + it 'sets the content to the content given' do + blob = merge_request.source_project.repository.blob_at(merge_request.source_branch_head.sha, + 'files/ruby/popen.rb') + + expect(blob.data).to eq(popen_content) + end + end + + context 'when a resolution section is missing' do + let(:invalid_params) do + { + files: [ + { + old_path: 'files/ruby/popen.rb', + new_path: 'files/ruby/popen.rb', + content: '' + }, { + old_path: 'files/ruby/regex.rb', + new_path: 'files/ruby/regex.rb', + sections: { '6eb14e00385d2fb284765eb1cd8d420d33d63fc9_9_9' => 'head' } + } + ], + commit_message: 'This is a commit message!' + } + end + + let(:service) { MergeRequests::ResolveService.new(project, user, invalid_params) } + + it 'raises a MissingResolution error' do + expect { service.execute(merge_request) }. + to raise_error(Gitlab::Conflict::File::MissingResolution) + end + end + + context 'when the content of a file is unchanged' do + let(:invalid_params) do + { + files: [ + { + old_path: 'files/ruby/popen.rb', + new_path: 'files/ruby/popen.rb', + content: '' + }, { + old_path: 'files/ruby/regex.rb', + new_path: 'files/ruby/regex.rb', + content: merge_request.conflicts.file_for_path('files/ruby/regex.rb', 'files/ruby/regex.rb').content + } + ], + commit_message: 'This is a commit message!' + } + end + let(:service) { MergeRequests::ResolveService.new(project, user, invalid_params) } it 'raises a MissingResolution error' do @@ -83,5 +182,27 @@ describe MergeRequests::ResolveService do to raise_error(Gitlab::Conflict::File::MissingResolution) end end + + context 'when a file is missing' do + let(:invalid_params) do + { + files: [ + { + old_path: 'files/ruby/popen.rb', + new_path: 'files/ruby/popen.rb', + content: '' + } + ], + commit_message: 'This is a commit message!' + } + end + + let(:service) { MergeRequests::ResolveService.new(project, user, invalid_params) } + + it 'raises a MissingFiles error' do + expect { service.execute(merge_request) }. + to raise_error(MergeRequests::ResolveService::MissingFiles) + end + end end end -- cgit v1.2.1 From 9727366b5a0a39a125925e2a7a78ed47e29b02f7 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 1 Sep 2016 16:19:16 +0100 Subject: Make RuboCop happy --- spec/controllers/projects/merge_requests_controller_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 1311b4aa264..b4f637c93e2 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -678,7 +678,6 @@ describe Projects::MergeRequestsController do conflict_for_path('files/ruby/regex.rb') end - it 'returns a 404 status code' do expect(response).to have_http_status(:not_found) end -- cgit v1.2.1 From 241cca011f9a35c03e8f5fae1381a4af8a8f26bb Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 1 Sep 2016 16:20:29 +0100 Subject: Fix specs --- spec/support/test_env.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index d56274d0979..243d671c521 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -26,10 +26,10 @@ module TestEnv 'expand-collapse-lines' => '238e82d', 'video' => '8879059', 'crlf-diff' => '5938907', - 'conflict-start' => '75284c7', + 'conflict-start' => '824be60', 'conflict-resolvable' => '1450cd6', 'conflict-binary-file' => '259a6fb', - 'conflict-contains-conflict-markers' => '5e0964c', + 'conflict-contains-conflict-markers' => '78a3086', 'conflict-missing-side' => 'eb227b3', 'conflict-non-utf8' => 'd0a293c', 'conflict-too-large' => '39fa04f', -- cgit v1.2.1 From 082be0917cf15d410b1db3ca49b32049a56c117e Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 1 Sep 2016 16:50:53 +0100 Subject: Fix MR model spec --- spec/models/merge_request_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 5884b4cff8c..91a423b670c 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1155,12 +1155,6 @@ describe MergeRequest, models: true do expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey end - it 'returns a falsey value when the conflicts contain a file with ambiguous conflict markers' do - merge_request = create_merge_request('conflict-contains-conflict-markers') - - expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_falsey - end - it 'returns a falsey value when the conflicts contain a file edited in one branch and deleted in another' do merge_request = create_merge_request('conflict-missing-side') @@ -1172,6 +1166,12 @@ describe MergeRequest, models: true do expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_truthy end + + it 'returns a truthy value when the conflicts have to be resolved in an editor' do + merge_request = create_merge_request('conflict-contains-conflict-markers') + + expect(merge_request.conflicts_can_be_resolved_in_ui?).to be_truthy + end end describe "#forked_source_project_missing?" do -- cgit v1.2.1 From 98dd958df3b4dd1b58b3a3387ea9d52dc78af46b Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 1 Sep 2016 17:44:35 +0100 Subject: Fix resolve service specs --- spec/services/merge_requests/resolve_service_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/resolve_service_spec.rb b/spec/services/merge_requests/resolve_service_spec.rb index e667e93bea4..388abb6a0df 100644 --- a/spec/services/merge_requests/resolve_service_spec.rb +++ b/spec/services/merge_requests/resolve_service_spec.rb @@ -60,7 +60,7 @@ describe MergeRequests::ResolveService do it 'creates a commit with the correct parents' do expect(merge_request.source_branch_head.parents.map(&:id)). to eq(['1450cd639e0bc6721eb02800169e464f212cde06', - '75284c70dd26c87f2a3fb65fd5a1f0b0138d3a6b']) + '824be604a34828eb682305f0d963056cfac87b2d']) end end @@ -120,7 +120,7 @@ describe MergeRequests::ResolveService do it 'creates a commit with the correct parents' do expect(merge_request.source_branch_head.parents.map(&:id)). to eq(['1450cd639e0bc6721eb02800169e464f212cde06', - '75284c70dd26c87f2a3fb65fd5a1f0b0138d3a6b']) + '824be604a34828eb682305f0d963056cfac87b2d']) end it 'sets the content to the content given' do -- cgit v1.2.1 From 7529bbae944823041e8690c011c4cfb39534074b Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 2 Sep 2016 16:16:54 +0100 Subject: Add JSON Schema --- .../projects/merge_requests_controller_spec.rb | 4 + spec/fixtures/api/schemas/conflicts.json | 137 +++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 spec/fixtures/api/schemas/conflicts.json (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index b4f637c93e2..06b37aa4997 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -597,6 +597,10 @@ describe Projects::MergeRequestsController do format: 'json' end + it 'matches the schema' do + expect(response).to match_response_schema('conflicts') + end + it 'includes meta info about the MR' do expect(json_response['commit_message']).to include('Merge branch') expect(json_response['commit_sha']).to match(/\h{40}/) diff --git a/spec/fixtures/api/schemas/conflicts.json b/spec/fixtures/api/schemas/conflicts.json new file mode 100644 index 00000000000..a947783d505 --- /dev/null +++ b/spec/fixtures/api/schemas/conflicts.json @@ -0,0 +1,137 @@ +{ + "type": "object", + "required": [ + "commit_message", + "commit_sha", + "source_branch", + "target_branch", + "files" + ], + "properties": { + "commit_message": {"type": "string"}, + "commit_sha": {"type": "string", "pattern": "^[0-9a-f]{40}$"}, + "source_branch": {"type": "string"}, + "target_branch": {"type": "string"}, + "files": { + "type": "array", + "items": { + "oneOf": [ + { "$ref": "#/definitions/conflict-text-with-sections" }, + { "$ref": "#/definitions/conflict-text-for-editor" } + ] + } + } + }, + "definitions": { + "conflict-base": { + "type": "object", + "required": [ + "old_path", + "new_path", + "blob_icon", + "blob_path" + ], + "properties": { + "old_path": {"type": "string"}, + "new_path": {"type": "string"}, + "blob_icon": {"type": "string"}, + "blob_path": {"type": "string"} + } + }, + "conflict-text-for-editor": { + "allOf": [ + {"$ref": "#/definitions/conflict-base"}, + { + "type": "object", + "required": [ + "type", + "content_path" + ], + "properties": { + "type": {"type": {"enum": ["text-editor"]}}, + "content_path": {"type": "string"} + } + } + ] + }, + "conflict-text-with-sections": { + "allOf": [ + {"$ref": "#/definitions/conflict-base"}, + { + "type": "object", + "required": [ + "type", + "content_path", + "sections" + ], + "properties": { + "type": {"type": {"enum": ["text"]}}, + "content_path": {"type": "string"}, + "sections": { + "type": "array", + "items": { + "oneOf": [ + { "$ref": "#/definitions/section-context" }, + { "$ref": "#/definitions/section-conflict" } + ] + } + } + } + } + ] + }, + "section-base": { + "type": "object", + "required": [ + "conflict", + "lines" + ], + "properties": { + "conflict": {"type": "boolean"}, + "lines": { + "type": "array", + "items": { + "type": "object", + "required": [ + "old_line", + "new_line", + "text", + "rich_text" + ], + "properties": { + "type": {"type": "string"}, + "old_line": {"type": "string"}, + "new_line": {"type": "string"}, + "text": {"type": "string"}, + "rich_text": {"type": "string"} + } + } + } + } + }, + "section-context": { + "allOf": [ + {"$ref": "#/definitions/section-base"}, + { + "type": "object", + "properties": { + "conflict": {"enum": [false]} + } + } + ] + }, + "section-conflict": { + "allOf": [ + {"$ref": "#/definitions/section-base"}, + { + "type": "object", + "required": ["id"], + "properties": { + "conflict": {"enum": [true]}, + "id": {"type": "string"} + } + } + ] + } + } +} -- cgit v1.2.1 From 6af52d7d23cf9dbfcd58a2d3031ed19887f7a558 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 20 Sep 2016 09:16:35 +0300 Subject: We now support resolving conflicts with ambiguous markers --- spec/features/merge_requests/conflicts_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 759edf8ec80..1e8aeacea05 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -42,7 +42,6 @@ feature 'Merge request conflict resolution', js: true, feature: true do UNRESOLVABLE_CONFLICTS = { 'conflict-too-large' => 'when the conflicts contain a large file', 'conflict-binary-file' => 'when the conflicts contain a binary file', - 'conflict-contains-conflict-markers' => 'when the conflicts contain a file with ambiguous conflict markers', 'conflict-missing-side' => 'when the conflicts contain a file edited in one branch and deleted in another', 'conflict-non-utf8' => 'when the conflicts contain a non-UTF-8 file', } -- cgit v1.2.1 From 4178ddee18918c5186ba75aaf9b303138fb97b30 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Sun, 25 Sep 2016 15:45:58 -0500 Subject: Add tests to check if files are resolved with Edit Inline mode --- spec/features/merge_requests/conflicts_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'spec') diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 1e8aeacea05..d2057aa2fe7 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -36,6 +36,32 @@ feature 'Merge request conflict resolution', js: true, feature: true do retry end end + + context 'when in inline mode' do + it 'resolves files manually' do + within find('.files-wrapper .diff-file.inline-view', text: 'files/ruby/popen.rb') do + click_button 'Edit inline' + wait_for_ajax + execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[0]).setValue("One morning");'); + end + + within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do + click_button 'Edit inline' + wait_for_ajax + execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[1]).setValue("Gregor Samsa woke from troubled dreams");'); + end + + click_button 'Commit conflict resolution' + wait_for_ajax + expect(page).to have_content('All merge conflicts were resolved') + + click_on 'Changes' + wait_for_ajax + + expect(page).to have_content('One morning') + expect(page).to have_content('Gregor Samsa woke from troubled dreams') + end + end end end -- cgit v1.2.1 From e84f959ae47e35eaebdc6c0adaf1e089326601ce Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 26 Sep 2016 15:49:04 +0100 Subject: Fix editor spec --- spec/features/merge_requests/conflicts_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index d2057aa2fe7..721360b207e 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -54,6 +54,7 @@ feature 'Merge request conflict resolution', js: true, feature: true do click_button 'Commit conflict resolution' wait_for_ajax expect(page).to have_content('All merge conflicts were resolved') + merge_request.reload_diff click_on 'Changes' wait_for_ajax -- cgit v1.2.1 From a8ac9089afb664e569b34c61dc6782d20d1019d1 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 28 Sep 2016 05:12:13 -0500 Subject: Refactor JS code - Use a store base object to manage application state. - Add a service to handle ajax requests. - Load code only when needed --- spec/features/merge_requests/conflicts_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 721360b207e..f2ff000486b 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -42,13 +42,13 @@ feature 'Merge request conflict resolution', js: true, feature: true do within find('.files-wrapper .diff-file.inline-view', text: 'files/ruby/popen.rb') do click_button 'Edit inline' wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[0]).setValue("One morning");'); + execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[0]).setValue("One morning");') end within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do click_button 'Edit inline' wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[1]).setValue("Gregor Samsa woke from troubled dreams");'); + execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[1]).setValue("Gregor Samsa woke from troubled dreams");') end click_button 'Commit conflict resolution' -- cgit v1.2.1 From 197ac5ebbfd8ca7fbcb79776fd25ca0e213376c4 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Thu, 29 Sep 2016 20:26:01 -0500 Subject: Ability to resolve conflicts for files with `text-editor` as conflict type --- spec/features/merge_requests/conflicts_spec.rb | 38 +++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index f2ff000486b..0e5507a0210 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -37,7 +37,7 @@ feature 'Merge request conflict resolution', js: true, feature: true do end end - context 'when in inline mode' do + context 'when in inline mode' do it 'resolves files manually' do within find('.files-wrapper .diff-file.inline-view', text: 'files/ruby/popen.rb') do click_button 'Edit inline' @@ -66,6 +66,42 @@ feature 'Merge request conflict resolution', js: true, feature: true do end end + context 'when a merge request can be resolved in the UI' do + let(:merge_request) { create_merge_request('conflict-contains-conflict-markers') } + + before do + project.team << [user, :developer] + login_as(user) + + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + context 'a conflict contain markers' do + before { click_link('conflicts', href: /\/conflicts\Z/) } + + it 'resolves files manually' do + within find('.files-wrapper .diff-file.inline-view', text: 'files/markdown/ruby-style-guide.md') do + wait_for_ajax + execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[0]).setValue("Gregor Samsa woke from troubled dreams");') + end + + click_button 'Commit conflict resolution' + wait_for_ajax + + expect(page).to have_content('All merge conflicts were resolved') + + merge_request.reload_diff + + click_on 'Changes' + wait_for_ajax + find('.nothing-here-block', visible: true).click + wait_for_ajax + + expect(page).to have_content('Gregor Samsa woke from troubled dreams') + end + end + end + UNRESOLVABLE_CONFLICTS = { 'conflict-too-large' => 'when the conflicts contain a large file', 'conflict-binary-file' => 'when the conflicts contain a binary file', -- cgit v1.2.1 From f947972dede2f8d68215555e4b4fd6e90a6bc437 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Fri, 30 Sep 2016 17:42:36 -0500 Subject: Improve diff view switching and components --- spec/features/merge_requests/conflicts_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 0e5507a0210..4cecc22aa6c 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -39,16 +39,16 @@ feature 'Merge request conflict resolution', js: true, feature: true do context 'when in inline mode' do it 'resolves files manually' do - within find('.files-wrapper .diff-file.inline-view', text: 'files/ruby/popen.rb') do + within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do click_button 'Edit inline' wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[0]).setValue("One morning");') + execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("One morning");') end within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do click_button 'Edit inline' wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[1]).setValue("Gregor Samsa woke from troubled dreams");') + execute_script('ace.edit($(".files-wrapper .diff-file pre")[1]).setValue("Gregor Samsa woke from troubled dreams");') end click_button 'Commit conflict resolution' @@ -80,9 +80,9 @@ feature 'Merge request conflict resolution', js: true, feature: true do before { click_link('conflicts', href: /\/conflicts\Z/) } it 'resolves files manually' do - within find('.files-wrapper .diff-file.inline-view', text: 'files/markdown/ruby-style-guide.md') do + within find('.files-wrapper .diff-file', text: 'files/markdown/ruby-style-guide.md') do wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file.inline-view pre")[0]).setValue("Gregor Samsa woke from troubled dreams");') + execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("Gregor Samsa woke from troubled dreams");') end click_button 'Commit conflict resolution' -- cgit v1.2.1 From 54bfe70795e289b86485b2a57d72b6711e4994bd Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 5 Oct 2016 07:57:57 -0500 Subject: Add more tests to check conflicts resolution --- .../projects/merge_requests_controller_spec.rb | 1 + spec/features/merge_requests/conflicts_spec.rb | 145 ++++++++++++++------- 2 files changed, 97 insertions(+), 49 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 06b37aa4997..31f43bdc89a 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -659,6 +659,7 @@ describe Projects::MergeRequestsController do id: merge_request.iid expect(merge_request.reload.title).to eq(merge_request.wipless_title) + end end describe 'GET conflict_for_path' do diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 4cecc22aa6c..d258ff52bbb 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -12,74 +12,121 @@ feature 'Merge request conflict resolution', js: true, feature: true do end end - context 'when a merge request can be resolved in the UI' do - let(:merge_request) { create_merge_request('conflict-resolvable') } + shared_examples "conflicts are resolved in Interactive mode" do + it 'conflicts are resolved in Interactive mode' do + within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do + click_button 'Use ours' + end - before do - project.team << [user, :developer] - login_as(user) + within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do + all('button', text: 'Use ours').each do |button| + button.click + end + end - visit namespace_project_merge_request_path(project.namespace, project, merge_request) - end + click_button 'Commit conflict resolution' + wait_for_ajax - it 'shows a link to the conflict resolution page' do - expect(page).to have_link('conflicts', href: /\/conflicts\Z/) - end + expect(page).to have_content('All merge conflicts were resolved') + merge_request.reload_diff - context 'visiting the conflicts resolution page' do - before { click_link('conflicts', href: /\/conflicts\Z/) } + click_on 'Changes' + wait_for_ajax - it 'shows the conflicts' do - begin - expect(find('#conflicts')).to have_content('popen.rb') - rescue Capybara::Poltergeist::JavascriptError - retry - end + within find('.diff-file', text: 'files/ruby/popen.rb') do + expect(page).to have_selector('.line_content.new', text: "vars = { 'PWD' => path }") + expect(page).to have_selector('.line_content.new', text: "options = { chdir: path }") end - context 'when in inline mode' do - it 'resolves files manually' do - within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do - click_button 'Edit inline' - wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("One morning");') - end - - within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do - click_button 'Edit inline' - wait_for_ajax - execute_script('ace.edit($(".files-wrapper .diff-file pre")[1]).setValue("Gregor Samsa woke from troubled dreams");') - end - - click_button 'Commit conflict resolution' - wait_for_ajax - expect(page).to have_content('All merge conflicts were resolved') - merge_request.reload_diff + within find('.diff-file', text: 'files/ruby/regex.rb') do + expect(page).to have_selector('.line_content.new', text: "def username_regexp") + expect(page).to have_selector('.line_content.new', text: "def project_name_regexp") + expect(page).to have_selector('.line_content.new', text: "def path_regexp") + expect(page).to have_selector('.line_content.new', text: "def archive_formats_regexp") + expect(page).to have_selector('.line_content.new', text: "def git_reference_regexp") + expect(page).to have_selector('.line_content.new', text: "def default_regexp") + end + end + end - click_on 'Changes' - wait_for_ajax + shared_examples "conflicts are resolved in Edit inline mode" do + it 'conflicts are resolved in Edit inline mode' do + expect(find('#conflicts')).to have_content('popen.rb') - expect(page).to have_content('One morning') - expect(page).to have_content('Gregor Samsa woke from troubled dreams') - end + within find('.files-wrapper .diff-file', text: 'files/ruby/popen.rb') do + click_button 'Edit inline' + wait_for_ajax + execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("One morning");') end + + within find('.files-wrapper .diff-file', text: 'files/ruby/regex.rb') do + click_button 'Edit inline' + wait_for_ajax + execute_script('ace.edit($(".files-wrapper .diff-file pre")[1]).setValue("Gregor Samsa woke from troubled dreams");') + end + + click_button 'Commit conflict resolution' + wait_for_ajax + expect(page).to have_content('All merge conflicts were resolved') + merge_request.reload_diff + + click_on 'Changes' + wait_for_ajax + + expect(page).to have_content('One morning') + expect(page).to have_content('Gregor Samsa woke from troubled dreams') end end - context 'when a merge request can be resolved in the UI' do - let(:merge_request) { create_merge_request('conflict-contains-conflict-markers') } - + context 'can be resolved in the UI' do before do project.team << [user, :developer] login_as(user) + end - visit namespace_project_merge_request_path(project.namespace, project, merge_request) + context 'the conflicts are resolvable' do + let(:merge_request) { create_merge_request('conflict-resolvable') } + + before { visit namespace_project_merge_request_path(project.namespace, project, merge_request) } + + it 'shows a link to the conflict resolution page' do + expect(page).to have_link('conflicts', href: /\/conflicts\Z/) + end + + context 'in Inline view mode' do + before { click_link('conflicts', href: /\/conflicts\Z/) } + + include_examples "conflicts are resolved in Interactive mode" + include_examples "conflicts are resolved in Edit inline mode" + end + + context 'in Parallel view mode' do + before do + click_link('conflicts', href: /\/conflicts\Z/) + click_button 'Side-by-side' + end + + include_examples "conflicts are resolved in Interactive mode" + include_examples "conflicts are resolved in Edit inline mode" + end end - context 'a conflict contain markers' do - before { click_link('conflicts', href: /\/conflicts\Z/) } + context 'the conflict contain markers' do + let(:merge_request) { create_merge_request('conflict-contains-conflict-markers') } + + before do + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + click_link('conflicts', href: /\/conflicts\Z/) + end + + it 'conflicts can not be resolved in Interactive mode' do + within find('.files-wrapper .diff-file', text: 'files/markdown/ruby-style-guide.md') do + expect(page).not_to have_content 'Interactive mode' + expect(page).not_to have_content 'Edit inline' + end + end - it 'resolves files manually' do + it 'conflicts are resolved in Edit inline mode' do within find('.files-wrapper .diff-file', text: 'files/markdown/ruby-style-guide.md') do wait_for_ajax execute_script('ace.edit($(".files-wrapper .diff-file pre")[0]).setValue("Gregor Samsa woke from troubled dreams");') @@ -94,7 +141,7 @@ feature 'Merge request conflict resolution', js: true, feature: true do click_on 'Changes' wait_for_ajax - find('.nothing-here-block', visible: true).click + find('.click-to-expand').click wait_for_ajax expect(page).to have_content('Gregor Samsa woke from troubled dreams') -- cgit v1.2.1 From 3764fd4b4166bdf869cc04e4e82558d6b80b4ca5 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 13 Oct 2016 10:34:15 +0100 Subject: Add blob_ace_mode to conflict content response --- spec/controllers/projects/merge_requests_controller_spec.rb | 1 + spec/lib/gitlab/conflict/file_spec.rb | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 31f43bdc89a..3fe90375b92 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -712,6 +712,7 @@ describe Projects::MergeRequestsController do 'new_path' => path, 'blob_icon' => 'file-text-o', 'blob_path' => a_string_ending_with(path), + 'blob_ace_mode' => 'ruby', 'content' => content) end end diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb index 60020487061..648d342ecf8 100644 --- a/spec/lib/gitlab/conflict/file_spec.rb +++ b/spec/lib/gitlab/conflict/file_spec.rb @@ -257,5 +257,16 @@ FILE it 'includes the blob icon for the file' do expect(conflict_file.as_json[:blob_icon]).to eq('file-text-o') end + + context 'with the full_content option passed' do + it 'includes the full content of the conflict' do + expect(conflict_file.as_json(full_content: true)).to have_key(:content) + end + + it 'includes the detected language of the conflict file' do + expect(conflict_file.as_json(full_content: true)[:blob_ace_mode]). + to eq('ruby') + end + end end end -- cgit v1.2.1 From 17e23b4c9c141bdbdcde4efec0bbcfdd544da8bd Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 14 Oct 2016 00:06:44 -0700 Subject: Add specs for group edit and deletion --- spec/features/groups_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'spec') diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index c54ec2563ad..3f908294cbb 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -47,6 +47,32 @@ feature 'Group', feature: true do end end + describe 'Group Edit' do + let(:group) { create(:group) } + let(:path) { edit_group_path(group) } + + it 'saves new settings' do + expect(group.request_access_enabled).to be_truthy + visit path + + find('#group_request_access_enabled').set(false) + + click_button 'Save group' + + expect(page).to have_content 'successfully updated' + group.reload + expect(group.request_access_enabled).to be_falsey + end + + it 'removes group' do + visit path + + click_link 'Remove Group' + + expect(page).to have_content "scheduled for deletion" + end + end + describe 'description' do let(:group) { create(:group) } let(:path) { group_path(group) } -- cgit v1.2.1 From 3726dc4bb73647123ebef5c97f401f5537d3ae16 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 14 Oct 2016 10:19:16 +0200 Subject: Check if project exists before creating deployment --- spec/services/create_deployment_service_spec.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 343b4385bf2..5fe56e7725f 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -84,11 +84,22 @@ describe CreateDeploymentService, services: true do expect(subject).to be_persisted end end + + context 'when project was removed' do + let(:project) { nil } + + it 'does not create deployment or environment' do + expect { subject }.not_to raise_error + + expect(Environment.count).to be_zero + expect(Deployment.count).to be_zero + end + end end describe 'processing of builds' do let(:environment) { nil } - + shared_examples 'does not create environment and deployment' do it 'does not create a new environment' do expect { subject }.not_to change { Environment.count } @@ -133,12 +144,12 @@ describe CreateDeploymentService, services: true do context 'without environment specified' do let(:build) { create(:ci_build, project: project) } - + it_behaves_like 'does not create environment and deployment' do subject { build.success } end end - + context 'when environment is specified' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline, environment: 'production', options: options) } -- cgit v1.2.1 From 6a4f71008390752e6b5574a9e9bdf277732d852d Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 4 Oct 2016 16:03:13 +0200 Subject: Show what time ago a MR was deployed --- .../merge_requests/widget_deployments_spec.rb | 26 ++++++++++++++++++++ spec/javascripts/merge_request_widget_spec.js | 27 +++++++++++++++++---- spec/models/environment_spec.rb | 17 +++++++++++++ spec/models/repository_spec.rb | 23 ++++++++++++++++++ .../merge_requests/_heading.html.haml_spec.rb | 28 ---------------------- 5 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 spec/features/merge_requests/widget_deployments_spec.rb delete mode 100644 spec/views/projects/merge_requests/_heading.html.haml_spec.rb (limited to 'spec') diff --git a/spec/features/merge_requests/widget_deployments_spec.rb b/spec/features/merge_requests/widget_deployments_spec.rb new file mode 100644 index 00000000000..8e23ec50d4a --- /dev/null +++ b/spec/features/merge_requests/widget_deployments_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +feature 'Widget Deployments Header', feature: true, js: true do + include WaitForAjax + + describe 'when deployed to an environment' do + let(:project) { merge_request.target_project } + let(:merge_request) { create(:merge_request, :merged) } + let(:environment) { create(:environment, project: project) } + let!(:deployment) do + create(:deployment, environment: environment, sha: project.commit('master').id) + end + + before do + login_as :admin + visit namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'displays that the environment is deployed' do + wait_for_ajax + + expect(page).to have_content("Deployed to #{environment.name}") + expect(find('.ci_widget > span > span')['data-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium)) + end + end +end diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 17b32914ec3..75ef10939de 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,5 +1,5 @@ - /*= require merge_request_widget */ +/*= require lib/utils/jquery.timeago.js */ (function() { describe('MergeRequestWidget', function() { @@ -20,7 +20,7 @@ gitlab_icon: "gitlab_logo.png", builds_path: "http://sampledomain.local/sampleBuildsPath" }; - this["class"] = new MergeRequestWidget(this.opts); + this["class"] = new window.gl.MergeRequestWidget(this.opts); return this.ciStatusData = { "title": "Sample MR title", "sha": "12a34bc5", @@ -30,7 +30,7 @@ }); return describe('getCIStatus', function() { beforeEach(function() { - return spyOn(jQuery, 'getJSON').and.callFake((function(_this) { + spyOn(jQuery, 'getJSON').and.callFake((function(_this) { return function(req, cb) { return cb(_this.ciStatusData); }; @@ -61,13 +61,30 @@ this["class"].getCIStatus(false); return expect(spy).not.toHaveBeenCalled(); }); - return it('should not display a notification on the first check after the widget has been created', function() { + it('should not display a notification on the first check after the widget has been created', function() { var spy; spy = spyOn(window, 'notify'); - this["class"] = new MergeRequestWidget(this.opts); + this["class"] = new window.gl.MergeRequestWidget(this.opts); this["class"].getCIStatus(true); return expect(spy).not.toHaveBeenCalled(); }); + it('should call renderEnvironments when the environments property is set', function() { + this.ciStatusData.environments = [{ + created_at: '2016-09-12T13:38:30.636Z', + environment_id: 1, + environment_name: 'env1', + external_url: 'https://test-url.com', + external_url_formatted: 'test-url.com' + }]; + var spy = spyOn(this['class'], 'renderEnvironments').and.stub(); + this['class'].getCIStatus(false); + expect(spy).toHaveBeenCalledWith(this.ciStatusData.environments); + }); + it('should not call renderEnvironments when the environments property is not set', function() { + var spy = spyOn(this['class'], 'renderEnvironments').and.stub(); + this['class'].getCIStatus(false); + expect(spy).not.toHaveBeenCalled(); + }); }); }); diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 6b1867a44e1..fb9629ac47a 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -64,6 +64,23 @@ describe Environment, models: true do end end + describe '#deployment_id_for' do + let(:project) { create(:project) } + let!(:environment) { create(:environment, project: project) } + let!(:deployment) { create(:deployment, environment: environment, ref: commit.parent.id) } + let!(:deployment1) { create(:deployment, environment: environment, ref: commit.id) } + let(:head_commit) { project.commit } + let(:commit) { project.commit.parent } + + it 'returns deployment id for the environment' do + expect(environment.deployment_id_for(commit)).to eq deployment1.id + end + + it 'return nil when no deployment is found' do + expect(environment.deployment_id_for(head_commit)).to eq nil + end + end + describe '#environment_type' do subject { environment.environment_type } diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 4b80efbe12b..f977cf73673 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -7,15 +7,18 @@ describe Repository, models: true do let(:project) { create(:project) } let(:repository) { project.repository } let(:user) { create(:user) } + let(:commit_options) do author = repository.user_to_committer(user) { message: 'Test message', committer: author, author: author } end + 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) repository.commit(merge_commit_id) end + let(:author_email) { FFaker::Internet.email } # I have to remove periods from the end of the name @@ -90,6 +93,26 @@ describe Repository, models: true do end end + describe '#ref_name_for_sha' do + context 'ref found' do + it 'returns the ref' do + allow_any_instance_of(Gitlab::Popen).to receive(:popen). + and_return(["b8d95eb4969eefacb0a58f6a28f6803f8070e7b9 commit\trefs/environments/production/77\n", 0]) + + expect(repository.ref_name_for_sha('bla', '0' * 40)).to eq 'refs/environments/production/77' + end + end + + context 'ref not found' do + it 'returns nil' do + allow_any_instance_of(Gitlab::Popen).to receive(:popen). + and_return(["", 0]) + + expect(repository.ref_name_for_sha('bla', '0' * 40)).to eq nil + end + end + end + describe '#last_commit_for_path' do subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id } diff --git a/spec/views/projects/merge_requests/_heading.html.haml_spec.rb b/spec/views/projects/merge_requests/_heading.html.haml_spec.rb deleted file mode 100644 index 86980f59cd8..00000000000 --- a/spec/views/projects/merge_requests/_heading.html.haml_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'spec_helper' - -describe 'projects/merge_requests/widget/_heading' do - include Devise::Test::ControllerHelpers - - context 'when released to an environment' do - let(:project) { merge_request.target_project } - let(:merge_request) { create(:merge_request, :merged) } - let(:environment) { create(:environment, project: project) } - let!(:deployment) do - create(:deployment, environment: environment, sha: project.commit('master').id) - end - - before do - assign(:merge_request, merge_request) - assign(:project, project) - - allow(view).to receive(:can?).and_return(true) - - render - end - - it 'displays that the environment is deployed' do - expect(rendered).to match("Deployed to") - expect(rendered).to match("#{environment.name}") - end - end -end -- cgit v1.2.1 From 58368fbc53bfe7c2a9b425626819eae576afff09 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 7 Oct 2016 23:10:06 +0100 Subject: Moved ci_status environments logic to new action ci_envrionments_status and set up frontend polling --- spec/javascripts/merge_request_widget_spec.js | 60 +++++++++++++++++---------- 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 75ef10939de..7b20572742c 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -8,6 +8,7 @@ window.notify = function() {}; this.opts = { ci_status_url: "http://sampledomain.local/ci/getstatus", + ci_environments_status_url: "http://sampledomain.local/ci/getenvironmentsstatus", ci_status: "", ci_message: { normal: "Build {{status}} for \"{{title}}\"", @@ -21,15 +22,45 @@ builds_path: "http://sampledomain.local/sampleBuildsPath" }; this["class"] = new window.gl.MergeRequestWidget(this.opts); - return this.ciStatusData = { - "title": "Sample MR title", - "sha": "12a34bc5", - "status": "success", - "coverage": 98 - }; }); + + describe('getCIEnvironmentsStatus', function() { + beforeEach(function() { + this.ciEnvironmentsStatusData = { + created_at: '2016-09-12T13:38:30.636Z', + environment_id: 1, + environment_name: 'env1', + external_url: 'https://test-url.com', + external_url_formatted: 'test-url.com' + }; + + spyOn(jQuery, 'getJSON').and.callFake((req, cb) => { + cb(this.ciEnvironmentsStatusData); + }); + }); + + it('should call renderEnvironments when the environments property is set', function() { + const spy = spyOn(this.class, 'renderEnvironments').and.stub(); + this.class.getCIEnvironmentsStatus(); + expect(spy).toHaveBeenCalledWith(this.ciEnvironmentsStatusData); + }); + + it('should not call renderEnvironments when the environments property is not set', function() { + const spy = spyOn(this.class, 'renderEnvironments').and.stub(); + this.class.getCIEnvironmentsStatus(); + expect(spy).not.toHaveBeenCalled(); + }); + }); + return describe('getCIStatus', function() { beforeEach(function() { + this.ciStatusData = { + "title": "Sample MR title", + "sha": "12a34bc5", + "status": "success", + "coverage": 98 + }; + spyOn(jQuery, 'getJSON').and.callFake((function(_this) { return function(req, cb) { return cb(_this.ciStatusData); @@ -68,23 +99,6 @@ this["class"].getCIStatus(true); return expect(spy).not.toHaveBeenCalled(); }); - it('should call renderEnvironments when the environments property is set', function() { - this.ciStatusData.environments = [{ - created_at: '2016-09-12T13:38:30.636Z', - environment_id: 1, - environment_name: 'env1', - external_url: 'https://test-url.com', - external_url_formatted: 'test-url.com' - }]; - var spy = spyOn(this['class'], 'renderEnvironments').and.stub(); - this['class'].getCIStatus(false); - expect(spy).toHaveBeenCalledWith(this.ciStatusData.environments); - }); - it('should not call renderEnvironments when the environments property is not set', function() { - var spy = spyOn(this['class'], 'renderEnvironments').and.stub(); - this['class'].getCIStatus(false); - expect(spy).not.toHaveBeenCalled(); - }); }); }); -- cgit v1.2.1 From 88b03bb542a8480d61c260a9dc3769ab791995e5 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 10 Oct 2016 20:38:48 +0200 Subject: Rename method in test --- spec/models/environment_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index fb9629ac47a..e172ee8e590 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -64,7 +64,7 @@ describe Environment, models: true do end end - describe '#deployment_id_for' do + describe '#first_deployment_for' do let(:project) { create(:project) } let!(:environment) { create(:environment, project: project) } let!(:deployment) { create(:deployment, environment: environment, ref: commit.parent.id) } @@ -73,11 +73,11 @@ describe Environment, models: true do let(:commit) { project.commit.parent } it 'returns deployment id for the environment' do - expect(environment.deployment_id_for(commit)).to eq deployment1.id + expect(environment.first_deployment_for(commit)).to eq deployment1 end it 'return nil when no deployment is found' do - expect(environment.deployment_id_for(head_commit)).to eq nil + expect(environment.first_deployment_for(head_commit)).to eq nil end end -- cgit v1.2.1 From 4b40027b50a2be4bad76b0a4a6a5e92c0de14255 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 11 Oct 2016 18:48:43 +0100 Subject: Fixed conflict and corrected teaspoon test --- spec/javascripts/merge_request_widget_spec.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 7b20572742c..c9175e2b704 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -26,13 +26,13 @@ describe('getCIEnvironmentsStatus', function() { beforeEach(function() { - this.ciEnvironmentsStatusData = { + this.ciEnvironmentsStatusData = [{ created_at: '2016-09-12T13:38:30.636Z', environment_id: 1, environment_name: 'env1', external_url: 'https://test-url.com', external_url_formatted: 'test-url.com' - }; + }]; spyOn(jQuery, 'getJSON').and.callFake((req, cb) => { cb(this.ciEnvironmentsStatusData); @@ -46,6 +46,7 @@ }); it('should not call renderEnvironments when the environments property is not set', function() { + this.ciEnvironmentsStatusData = null; const spy = spyOn(this.class, 'renderEnvironments').and.stub(); this.class.getCIEnvironmentsStatus(); expect(spy).not.toHaveBeenCalled(); -- cgit v1.2.1 From 78c69d8d66ae254bae5736e927772e280f2c6b93 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 14 Oct 2016 17:08:48 +0800 Subject: Space between subject and {, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6019#note_16956860 --- spec/services/ci/send_pipeline_notification_service_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index 6a32357b72c..288302cc94f 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -11,6 +11,7 @@ describe Ci::SendPipelineNotificationService, services: true do let(:project) { create(:project) } let(:user) { create(:user) } + subject{ described_class.new(pipeline) } describe '#execute' do -- cgit v1.2.1 From cf15af31353b141028717456aa6967c9c11697af Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 13 Oct 2016 14:23:18 +0200 Subject: Add test, fix merge error --- .../projects/merge_requests_controller_spec.rb | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 84298f8bef4..d509f0f2b96 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -756,4 +756,34 @@ describe Projects::MergeRequestsController do post_assign_issues end end + + describe 'GET ci_environments_status' do + context 'when the environment is from a forked project' do + let!(:forked) { create(:project) } + let!(:environment) { create(:environment, project: forked) } + let!(:deployment) { create(:deployment, environment: environment, sha: forked.commit.id, ref: 'master') } + let(:json_response) { JSON.parse(response.body) } + let(:admin) { create(:admin) } + + let(:merge_request) do + create(:forked_project_link, forked_to_project: forked, + forked_from_project: project) + + create(:merge_request, source_project: forked, target_project: project) + end + + before do + forked.team << [user, :master] + + get :ci_environments_status, + namespace_id: merge_request.project.namespace.to_param, + project_id: merge_request.project.to_param, + id: merge_request.iid, format: 'json' + end + + it 'links to the environment on that project' do + expect(json_response.first['url']).to match /#{forked.path_with_namespace}/ + end + end + end end -- cgit v1.2.1 From b5f9d4c4bc48b252d3175432a3bb6fb1ca394af9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 14 Oct 2016 19:13:11 +0800 Subject: Introduce Pipeline#merge_requests_with_active_first, Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6019#note_16956802 --- spec/models/ci/pipeline_spec.rb | 31 +++++++++++++++++++++++++++++++ spec/models/merge_request_spec.rb | 10 +++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 550a890797e..2a0b00dc545 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -523,4 +523,35 @@ describe Ci::Pipeline, models: true do expect(pipeline.merge_requests).to be_empty end end + + describe '#merge_requests_with_active_first' do + let(:project) { create(:project) } + + let(:pipeline) do + create(:ci_empty_pipeline, + status: 'created', + project: project, + ref: 'master', + sha: project.repository.commit('master').sha) + end + + let!(:merge_requests) do + [create_merge_request(:merged, Time.at(0)), + create_merge_request(:merged, Time.at(9)), + create_merge_request(:opened, Time.at(0))] + end + + it 'returns opened/recent merge requests first, then closed ones' do + expect(pipeline.merge_requests_with_active_first). + to eq(merge_requests.reverse) + end + + def create_merge_request(state, updated_at) + create(:merge_request, + source_project: project, + source_branch: pipeline.ref, + state: state, + updated_at: updated_at) + end + end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 38b6da50168..8cf53fd1dee 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -58,6 +58,14 @@ describe MergeRequest, models: true do it { is_expected.to respond_to(:merge_when_build_succeeds) } end + describe '#state_priority' do + it 'returns the priority of state' do + %w[opened reopened closed merged locked].each.with_index do |state, idx| + expect(MergeRequest.new(state: state).state_priority).to eq(idx) + end + end + end + describe '.in_projects' do it 'returns the merge requests for a set of projects' do expect(described_class.in_projects(Project.all)).to eq([subject]) @@ -334,7 +342,7 @@ describe MergeRequest, models: true do wip_title = "WIP: #{subject.title}" expect(subject.wip_title).to eq wip_title - end + end it "does not add the WIP: prefix multiple times" do wip_title = "WIP: #{subject.title}" -- cgit v1.2.1 From d7324f0ed5181f0eb765871a35eaee587bf25fa9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 14 Oct 2016 14:51:59 +0300 Subject: Move edit group scenario to rspec and refactor groups_spec Signed-off-by: Dmitriy Zaporozhets --- spec/features/groups_spec.rb | 78 ++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 36 deletions(-) (limited to 'spec') diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 3f908294cbb..13bfe90302c 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -11,93 +11,99 @@ feature 'Group', feature: true do end end - describe 'creating a group with space in group path' do - it 'renders new group form with validation errors' do - visit new_group_path - fill_in 'Group path', with: 'space group' + describe 'create a group' do + before { visit new_group_path } - click_button 'Create group' + describe 'with space in group path' do + it 'renders new group form with validation errors' do + fill_in 'Group path', with: 'space group' + click_button 'Create group' - expect(current_path).to eq(groups_path) - expect(page).to have_namespace_error_message + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end end - end - - describe 'creating a group with .atom at end of group path' do - it 'renders new group form with validation errors' do - visit new_group_path - fill_in 'Group path', with: 'atom_group.atom' - click_button 'Create group' + describe 'with .atom at end of group path' do + it 'renders new group form with validation errors' do + fill_in 'Group path', with: 'atom_group.atom' + click_button 'Create group' - expect(current_path).to eq(groups_path) - expect(page).to have_namespace_error_message + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end end - end - - describe 'creating a group with .git at end of group path' do - it 'renders new group form with validation errors' do - visit new_group_path - fill_in 'Group path', with: 'git_group.git' - click_button 'Create group' + describe 'with .git at end of group path' do + it 'renders new group form with validation errors' do + fill_in 'Group path', with: 'git_group.git' + click_button 'Create group' - expect(current_path).to eq(groups_path) - expect(page).to have_namespace_error_message + expect(current_path).to eq(groups_path) + expect(page).to have_namespace_error_message + end end end - describe 'Group Edit' do + describe 'group edit' do let(:group) { create(:group) } let(:path) { edit_group_path(group) } + let(:new_name) { 'new-name' } - it 'saves new settings' do - expect(group.request_access_enabled).to be_truthy - visit path - - find('#group_request_access_enabled').set(false) + before { visit path } + it 'saves new settings' do + fill_in 'group_name', with: new_name click_button 'Save group' expect(page).to have_content 'successfully updated' - group.reload - expect(group.request_access_enabled).to be_falsey + expect(find('#group_name').value).to eq(new_name) + + page.within ".navbar-gitlab" do + expect(page).to have_content new_name + end end it 'removes group' do - visit path - click_link 'Remove Group' expect(page).to have_content "scheduled for deletion" end end - describe 'description' do + describe 'group page with markdown description' do let(:group) { create(:group) } let(:path) { group_path(group) } it 'parses Markdown' do group.update_attribute(:description, 'This is **my** group') + visit path + expect(page).to have_css('.description > p > strong') end it 'passes through html-pipeline' do group.update_attribute(:description, 'This group is the :poop:') + visit path + expect(page).to have_css('.description > p > img') end it 'sanitizes unwanted tags' do group.update_attribute(:description, '# Group Description') + visit path + expect(page).not_to have_css('.description h1') end it 'permits `rel` attribute on links' do group.update_attribute(:description, 'https://google.com/') + visit path + expect(page).to have_css('.description a[rel]') end end -- cgit v1.2.1 From 7d97a22e860b92a58f862214a6d13f9e5e29c64a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 14 Oct 2016 19:54:51 +0800 Subject: Just show the first merge request we found, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6019#note_16963209 --- spec/models/ci/pipeline_spec.rb | 31 ------------------------------- spec/models/merge_request_spec.rb | 8 -------- 2 files changed, 39 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 2a0b00dc545..550a890797e 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -523,35 +523,4 @@ describe Ci::Pipeline, models: true do expect(pipeline.merge_requests).to be_empty end end - - describe '#merge_requests_with_active_first' do - let(:project) { create(:project) } - - let(:pipeline) do - create(:ci_empty_pipeline, - status: 'created', - project: project, - ref: 'master', - sha: project.repository.commit('master').sha) - end - - let!(:merge_requests) do - [create_merge_request(:merged, Time.at(0)), - create_merge_request(:merged, Time.at(9)), - create_merge_request(:opened, Time.at(0))] - end - - it 'returns opened/recent merge requests first, then closed ones' do - expect(pipeline.merge_requests_with_active_first). - to eq(merge_requests.reverse) - end - - def create_merge_request(state, updated_at) - create(:merge_request, - source_project: project, - source_branch: pipeline.ref, - state: state, - updated_at: updated_at) - end - end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index a570e42c6ac..2167a988f99 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -58,14 +58,6 @@ describe MergeRequest, models: true do it { is_expected.to respond_to(:merge_when_build_succeeds) } end - describe '#state_priority' do - it 'returns the priority of state' do - %w[opened reopened closed merged locked].each.with_index do |state, idx| - expect(MergeRequest.new(state: state).state_priority).to eq(idx) - end - end - end - describe '.in_projects' do it 'returns the merge requests for a set of projects' do expect(described_class.in_projects(Project.all)).to eq([subject]) -- cgit v1.2.1 From 04593581037bca7a7c3b00c719404e610c158cc1 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 13 Oct 2016 19:32:10 +0200 Subject: API: Fix Sytem hooks delete behavior --- spec/requests/api/system_hooks_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index 1ce2658569e..f8a1aed5441 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -73,9 +73,10 @@ describe API::API, api: true do end.to change { SystemHook.count }.by(-1) end - it "returns success if hook id not found" do - delete api("/hooks/12345", admin) - expect(response).to have_http_status(200) + it 'returns 404 if the system hook does not exist' do + delete api('/hooks/12345', admin) + + expect(response).to have_http_status(404) end end end -- cgit v1.2.1 From 5904793ad8ba88d3dfc9c973bcffd1d426db5a33 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 14 Oct 2016 12:53:51 +0200 Subject: Add build finished worker that creates a workflow --- spec/workers/build_finished_worker_spec.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 spec/workers/build_finished_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb new file mode 100644 index 00000000000..2868167c7d4 --- /dev/null +++ b/spec/workers/build_finished_worker_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe BuildFinishedWorker do + describe '#perform' do + context 'when build exists' do + let(:build) { create(:ci_build) } + + it 'calculates coverage and calls hooks' do + expect(BuildCoverageWorker) + .to receive(:new).ordered.and_call_original + expect(BuildHooksWorker) + .to receive(:new).ordered.and_call_original + + expect_any_instance_of(BuildCoverageWorker) + .to receive(:perform) + expect_any_instance_of(BuildHooksWorker) + .to receive(:perform) + + described_class.new.perform(build.id) + end + end + + context 'when build does not exist' do + it 'does not raise exception' do + expect { described_class.new.perform(123) } + .not_to raise_error + end + end + end +end -- cgit v1.2.1 From b0622d657893b156ac0c265f397efeb28d5b0b4c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 15 Oct 2016 01:48:14 +0300 Subject: Revert "Update git over http test to match new routing" This reverts commit 68ab7047dae98172a0bd8b92956f2ee51b9167a0. --- spec/requests/git_http_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 5a1ed7d4a25..27f0fd22ae6 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -412,9 +412,10 @@ describe 'Git HTTP requests', lib: true do context "when the params are anything else" do let(:params) { { service: 'git-implode-pack' } } + before { get path, params } - it "fails to find a route" do - expect { get(path, params) }.to raise_error(ActionController::RoutingError) + it "redirects to the sign-in page" do + expect(response).to redirect_to(new_user_session_path) end end end -- cgit v1.2.1 From 1dd826d4aad2ce6c195bad24b458b1967b74db1d Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 9 Sep 2016 14:21:00 +0200 Subject: Make UX upgrades to SignIn/Register views. - Tab between register and sign in forms - Add individual input validation error messages - Validate username - Update many styles for all login-box forms --- spec/features/signup_spec.rb | 8 ++++---- spec/features/u2f_spec.rb | 14 +++++++------- spec/features/users_spec.rb | 32 ++++++++++++++++++++++++++++--- spec/javascripts/u2f/authenticate_spec.js | 2 +- 4 files changed, 41 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb index a752c1d7235..65544f79eba 100644 --- a/spec/features/signup_spec.rb +++ b/spec/features/signup_spec.rb @@ -14,7 +14,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq users_almost_there_path expect(page).to have_content("Please check your email to confirm your account") @@ -33,7 +33,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq dashboard_projects_path expect(page).to have_content("Welcome! You have signed up successfully.") @@ -52,7 +52,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: existing_user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq user_registration_path expect(page).to have_content("error prohibited this user from being saved") @@ -69,7 +69,7 @@ feature 'Signup', feature: true do fill_in 'new_user_username', with: user.username fill_in 'new_user_email', with: existing_user.email fill_in 'new_user_password', with: user.password - click_button "Sign up" + click_button "Register" expect(current_path).to eq user_registration_path expect(page.body).not_to match(/#{user.password}/) diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb index ff6933dc8d9..b750f27ea72 100644 --- a/spec/features/u2f_spec.rb +++ b/spec/features/u2f_spec.rb @@ -160,7 +160,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: login_with(user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -174,7 +174,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: login_with(user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -186,7 +186,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: login_with(user, remember: true) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') within 'div#js-authenticate-u2f' do @@ -209,7 +209,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: # Try authenticating user with the old U2F device login_as(current_user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -230,7 +230,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: # Try authenticating user with the same U2F device login_as(current_user) @u2f_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -244,7 +244,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: unregistered_device = FakeU2fDevice.new(page, FFaker::Name.first_name) login_as(user) unregistered_device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" @@ -271,7 +271,7 @@ feature 'Using U2F (Universal 2nd Factor) Devices for Authentication', feature: [first_device, second_device].each do |device| login_as(user) device.respond_to_u2f_authentication - click_on "Login Via U2F Device" + click_on "Sign in via U2F device" expect(page.body).to match('We heard back from your U2F device') click_on "Authenticate via U2F Device" diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 6498b7317b4..63743169302 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,15 +1,16 @@ require 'spec_helper' -feature 'Users', feature: true do +feature 'Users', feature: true, js: true do let(:user) { create(:user, username: 'user1', name: 'User 1', email: 'user1@gitlab.com') } scenario 'GET /users/sign_in creates a new user account' do visit new_user_session_path + click_link 'Register' fill_in 'new_user_name', with: 'Name Surname' fill_in 'new_user_username', with: 'Great' fill_in 'new_user_email', with: 'name@mail.com' fill_in 'new_user_password', with: 'password1234' - expect { click_button 'Sign up' }.to change { User.count }.by(1) + expect { click_button 'Register' }.to change { User.count }.by(1) end scenario 'Successful user signin invalidates password reset token' do @@ -31,11 +32,12 @@ feature 'Users', feature: true do scenario 'Should show one error if email is already taken' do visit new_user_session_path + click_link 'Register' fill_in 'new_user_name', with: 'Another user name' fill_in 'new_user_username', with: 'anotheruser' fill_in 'new_user_email', with: user.email fill_in 'new_user_password', with: '12341234' - expect { click_button 'Sign up' }.to change { User.count }.by(0) + expect { click_button 'Register' }.to change { User.count }.by(0) expect(page).to have_text('Email has already been taken') expect(number_of_errors_on_page(page)).to be(1), 'errors on page:\n #{errors_on_page page}' end @@ -51,6 +53,30 @@ feature 'Users', feature: true do end end + feature 'username validation' do + include WaitForAjax + let(:loading_icon) { '.fa.fa-spinner' } + let(:username_input) { 'new_user_username' } + + before(:each) do + visit new_user_session_path + click_link 'Register' + @username_field = find '.username' + end + + scenario 'shows an error border if the username already exists' do + fill_in username_input, with: user.username + wait_for_ajax + expect(@username_field).to have_css '.gl-field-error-outline' + end + + scenario 'doesn\'t show an error border if the username is available' do + fill_in username_input, with: 'new-user' + wait_for_ajax + expect(@username_field).not_to have_css '.gl-field-error-outline' + end + end + def errors_on_page(page) page.find('#error_explanation').find('ul').all('li').map{ |item| item.text }.join("\n") end diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js index 7ce3884f844..784b43d4846 100644 --- a/spec/javascripts/u2f/authenticate_spec.js +++ b/spec/javascripts/u2f/authenticate_spec.js @@ -21,7 +21,7 @@ setupButton = this.container.find("#js-login-u2f-device"); setupMessage = this.container.find("p"); expect(setupMessage.text()).toContain('Insert your security key'); - expect(setupButton.text()).toBe('Login Via U2F Device'); + expect(setupButton.text()).toBe('Sign in via U2F device'); setupButton.trigger('click'); inProgressMessage = this.container.find("p"); expect(inProgressMessage.text()).toContain("Trying to communicate with your device"); -- cgit v1.2.1 From 83fb1190205c3d1fbe16a684794ed1af10ed1bff Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 23 Sep 2016 11:15:07 +0200 Subject: Get tests passing. --- spec/features/users_spec.rb | 9 +++++---- spec/support/login_helpers.rb | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 63743169302..73d6fb6b651 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -61,16 +61,17 @@ feature 'Users', feature: true, js: true do before(:each) do visit new_user_session_path click_link 'Register' - @username_field = find '.username' + @username_form_group = find '.username' + @username_field = find '#new_user_username' end - scenario 'shows an error border if the username already exists' do + scenario 'shows an error border if the username already exists', focus: true do fill_in username_input, with: user.username wait_for_ajax - expect(@username_field).to have_css '.gl-field-error-outline' + expect(@username_form_group).to have_css '.gl-field-error-outline' end - scenario 'doesn\'t show an error border if the username is available' do + scenario 'doesn\'t show an error border if the username is available', focus: true do fill_in username_input, with: 'new-user' wait_for_ajax expect(@username_field).not_to have_css '.gl-field-error-outline' diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index c0b3e83244d..3e90c95918c 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -33,7 +33,9 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "12345678" check 'user_remember_me' if remember - click_button "Sign in" + page.within '.login-box' do + click_button "Sign in" + end Thread.current[:current_user] = user end -- cgit v1.2.1 From 076749645a51c4fe948cdf5ed16dc8455a9aae05 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Tue, 27 Sep 2016 14:54:15 +0200 Subject: Shush rubocop. --- spec/features/users_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 73d6fb6b651..17a555e4673 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -65,13 +65,13 @@ feature 'Users', feature: true, js: true do @username_field = find '#new_user_username' end - scenario 'shows an error border if the username already exists', focus: true do + scenario 'shows an error border if the username already exists' do fill_in username_input, with: user.username wait_for_ajax expect(@username_form_group).to have_css '.gl-field-error-outline' end - scenario 'doesn\'t show an error border if the username is available', focus: true do + scenario 'doesn\'t show an error border if the username is available' do fill_in username_input, with: 'new-user' wait_for_ajax expect(@username_field).not_to have_css '.gl-field-error-outline' -- cgit v1.2.1 From 69f9c00cfb7d80959a523a10ef7d5f53a37b21e5 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 13:01:03 +0200 Subject: Add tests for gl_field_errors. --- .../javascripts/fixtures/gl_field_errors.html.haml | 15 +++ spec/javascripts/gl_field_errors_spec.js.es6 | 111 +++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 spec/javascripts/fixtures/gl_field_errors.html.haml create mode 100644 spec/javascripts/gl_field_errors_spec.js.es6 (limited to 'spec') diff --git a/spec/javascripts/fixtures/gl_field_errors.html.haml b/spec/javascripts/fixtures/gl_field_errors.html.haml new file mode 100644 index 00000000000..2526e5e33a5 --- /dev/null +++ b/spec/javascripts/fixtures/gl_field_errors.html.haml @@ -0,0 +1,15 @@ +%form.show-gl-field-errors{action: 'submit', method: 'post'} + .form-group + %input.required-text{required: true, type: 'text'} Text + .form-group + %input.email{type: 'email', title: 'Please provide a valid email address.', required: true } Email + .form-group + %input.password{type: 'password', required: true} Password + .form-group + %input.alphanumeric{type: 'text', pattern: '[a-zA-Z0-9]', required: true} Alphanumeric + .form-group + %input.hidden{ type:'hidden' } + .form-group + %input.custom.no-gl-field-errors{ type:'text' } Custom, do not validate + .form-group + %input.submit{type: 'submit'} Submit diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6 new file mode 100644 index 00000000000..36feb2b2aa5 --- /dev/null +++ b/spec/javascripts/gl_field_errors_spec.js.es6 @@ -0,0 +1,111 @@ +//= require jquery +//= require gl_field_errors + +((global) => { + fixture.preload('gl_field_errors.html'); + + describe('GL Style Field Errors', function() { + beforeEach(function() { + fixture.load('gl_field_errors.html'); + const $form = this.$form = $('form.show-gl-field-errors'); + this.fieldErrors = new global.GlFieldErrors($form); + }); + + it('should properly initialize the form', function() { + expect(this.$form).toBeDefined(); + expect(this.$form.length).toBe(1); + expect(this.fieldErrors).toBeDefined(); + const inputs = this.fieldErrors.state.inputs; + expect(inputs.length).toBe(5); + }); + + it('should ignore elements with custom error handling', function() { + const customErrorFlag = 'no-gl-field-errors'; + const customErrorElem = $(`.${customErrorFlag}`); + + expect(customErrorElem.length).toBe(1); + + const customErrors = this.fieldErrors.state.inputs.filter((input) => { + return input.inputElement.hasClass(customErrorFlag); + }); + expect(customErrors.length).toBe(0); + }); + + it('should not show any errors before submit attempt', function() { + this.$form.find('.email').val('not-a-valid-email').keyup(); + this.$form.find('.text-required').val('').keyup(); + this.$form.find('.alphanumberic').val('?---*').keyup(); + + const errorsShown = this.$form.find('.gl-field-error-outline'); + expect(errorsShown.length).toBe(0); + }); + + it('should show errors when input valid is submitted', function() { + this.$form.find('.email').val('not-a-valid-email').keyup(); + this.$form.find('.text-required').val('').keyup(); + this.$form.find('.alphanumberic').val('?---*').keyup(); + + this.$form.submit(); + + const errorsShown = this.$form.find('.gl-field-error-outline'); + expect(errorsShown.length).toBe(4); + }); + + it('should properly track validity state on input after invalid submission attempt', function() { + this.$form.submit(); + + const emailInputModel = this.fieldErrors.state.inputs[1]; + const fieldState = emailInputModel.state; + const emailInputElement = emailInputModel.inputElement; + + // No input + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(true); + expect(fieldState.valid).toBe(false); + + // Then invalid input + emailInputElement.val('not-a-valid-email').keyup(); + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(false); + + // Then valid input + emailInputElement.val('email@gitlab.com').keyup(); + expect(emailInputElement).not.toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(true); + + // Then invalid input + emailInputElement.val('not-a-valid-email').keyup(); + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(false); + + // Then empty input + emailInputElement.val('').keyup(); + expect(emailInputElement).toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(true); + expect(fieldState.valid).toBe(false); + + // Then valid input + emailInputElement.val('email@gitlab.com').keyup(); + expect(emailInputElement).not.toHaveClass('gl-field-error-outline'); + expect(fieldState.empty).toBe(false); + expect(fieldState.valid).toBe(true); + }); + + it('should properly infer error messages', function() { + this.$form.submit(); + const trackedInputs = this.fieldErrors.state.inputs; + const inputHasTitle = trackedInputs[1]; + const hasTitleErrorElem = inputHasTitle.inputElement.siblings('.gl-field-error'); + const inputNoTitle = trackedInputs[2]; + const noTitleErrorElem = inputNoTitle.inputElement.siblings('.gl-field-error'); + + expect(noTitleErrorElem.text()).toBe('This field is required.'); + expect(hasTitleErrorElem.text()).toBe('Please provide a valid email address.'); + }); + + }); + +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 1fd09260826413da928363c3199d4dfbb770d2c3 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 15:47:21 +0200 Subject: Click first Sign In in login_helper. --- spec/support/login_helpers.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index 3e90c95918c..ea9edc85248 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -33,9 +33,7 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "12345678" check 'user_remember_me' if remember - page.within '.login-box' do - click_button "Sign in" - end + first('.login-box').click_button('Sign in') Thread.current[:current_user] = user end -- cgit v1.2.1 From 445711675ca198660dcaee014cd4229b8eb266ab Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 28 Sep 2016 17:13:42 +0200 Subject: Fix nesting on sessions/new. --- spec/support/login_helpers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index ea9edc85248..c0b3e83244d 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -33,7 +33,7 @@ module LoginHelpers fill_in "user_login", with: user.email fill_in "user_password", with: "12345678" check 'user_remember_me' if remember - first('.login-box').click_button('Sign in') + click_button "Sign in" Thread.current[:current_user] = user end -- cgit v1.2.1 From 091f4cb26a79bf20542f5e260d461a235ec85011 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 29 Sep 2016 12:00:12 +0200 Subject: Update filled in field for two_factor auth to use id. --- spec/features/login_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb index 2523b4b7898..996f39ea06d 100644 --- a/spec/features/login_spec.rb +++ b/spec/features/login_spec.rb @@ -29,7 +29,7 @@ feature 'Login', feature: true do describe 'with two-factor authentication' do def enter_code(code) - fill_in 'Two-Factor Authentication code', with: code + fill_in 'user_otp_attempt', with: code click_button 'Verify code' end -- cgit v1.2.1 From 716406bc71fc3866588ccca8c132060d4f33e53e Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 12 Oct 2016 18:47:31 +0200 Subject: Back off the array spreading, bc poltergeist freaks out. --- spec/features/merge_requests/user_uses_slash_commands_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/user_uses_slash_commands_spec.rb b/spec/features/merge_requests/user_uses_slash_commands_spec.rb index cb3cea3fd51..7b8af555f0e 100644 --- a/spec/features/merge_requests/user_uses_slash_commands_spec.rb +++ b/spec/features/merge_requests/user_uses_slash_commands_spec.rb @@ -20,7 +20,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do login_with(user) visit namespace_project_merge_request_path(project.namespace, project, merge_request) end - + after do wait_for_ajax end @@ -34,7 +34,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do expect(page).to have_content 'Your commands have been executed!' expect(merge_request.reload.work_in_progress?).to eq true - end + end it 'removes the WIP: prefix from the title' do merge_request.title = merge_request.wip_title @@ -45,7 +45,7 @@ feature 'Merge Requests > User uses slash commands', feature: true, js: true do expect(page).to have_content 'Your commands have been executed!' expect(merge_request.reload.work_in_progress?).to eq false - end + end end context 'when the current user cannot toggle the WIP prefix' do -- cgit v1.2.1 From b46307d3c59e3cf24eef3a2411ea8af2f25e78ba Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 13 Oct 2016 17:59:55 +0200 Subject: Don't use member properties in users_spec, and remove loading ref. --- spec/features/users_spec.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 17a555e4673..ec4c4d62f53 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -61,20 +61,17 @@ feature 'Users', feature: true, js: true do before(:each) do visit new_user_session_path click_link 'Register' - @username_form_group = find '.username' - @username_field = find '#new_user_username' end - scenario 'shows an error border if the username already exists' do fill_in username_input, with: user.username wait_for_ajax - expect(@username_form_group).to have_css '.gl-field-error-outline' + expect(find('.username')).to have_css '.gl-field-error-outline' end scenario 'doesn\'t show an error border if the username is available' do fill_in username_input, with: 'new-user' wait_for_ajax - expect(@username_field).not_to have_css '.gl-field-error-outline' + expect(find('#new_user_username')).not_to have_css '.gl-field-error-outline' end end -- cgit v1.2.1 From 5a8738a7b43ae567829bca36db6f13f430b56c83 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 15 Oct 2016 14:49:20 -0700 Subject: Fix Spinach merge request diff failures gitlab-git-test `master` was updated in ff076d88, and this caused the merge request diffs to change in a way that broke assumptions in the Spinach tests. Partial fix to #23378 --- spec/support/test_env.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index d56274d0979..ad8ae763f6d 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -17,6 +17,7 @@ module TestEnv 'markdown' => '0ed8c6c', 'lfs' => 'be93687', 'master' => 'b83d6e3', + 'merge-test' => '5937ac0', "'test'" => 'e56497b', 'orphaned-branch' => '45127a9', 'binary-encoding' => '7b1cf43', -- cgit v1.2.1 From c48f7153181eab0d872d84b1c00e83cec5f2f046 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 16 Oct 2016 12:49:23 +0300 Subject: Fix 404 when group path has dot in the name Signed-off-by: Dmitriy Zaporozhets --- spec/routing/routing_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'spec') diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 0ee1c811dfb..488dc1a63b0 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -270,6 +270,12 @@ describe "Groups", "routing" do expect(get('/1')).to route_to('groups#show', id: '1') end + + it "also display group#show with dot in the path" do + allow(Group).to receive(:find_by_path).and_return(true) + + expect(get('/group.with.dot')).to route_to('groups#show', id: 'group.with.dot') + end end describe HealthCheckController, 'routing' do -- cgit v1.2.1 From 7e3ff1852340c33f5b8853190d6a24813d5920a2 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sun, 11 Sep 2016 20:38:09 +0430 Subject: Add RTL support to markdown renderer --- spec/features/atom/users_spec.rb | 2 +- spec/lib/banzai/object_renderer_spec.rb | 6 +++--- spec/lib/banzai/pipeline/description_pipeline_spec.rb | 12 +++++++++--- spec/models/concerns/cache_markdown_field_spec.rb | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb index a8833194421..f8c3ccb416b 100644 --- a/spec/features/atom/users_spec.rb +++ b/spec/features/atom/users_spec.rb @@ -53,7 +53,7 @@ describe "User Feed", feature: true do end it 'has XHTML summaries in issue descriptions' do - expect(body).to match /we have a bug!<\/p>\n\n
    \n\n

    I guess/ + expect(body).to match /we have a bug!<\/p>\n\n


    \n\n

    I guess/ end it 'has XHTML summaries in notes' do diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index 90da78a67dd..6bcda87c999 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -24,7 +24,7 @@ describe Banzai::ObjectRenderer do with(an_instance_of(Array)). and_call_original - expect(object).to receive(:redacted_note_html=).with('

    hello

    ') + expect(object).to receive(:redacted_note_html=).with('

    hello

    ') expect(object).to receive(:user_visible_reference_count=).with(0) renderer.render([object], :note) @@ -92,10 +92,10 @@ describe Banzai::ObjectRenderer do docs = renderer.render_attributes(objects, :note) expect(docs[0]).to be_an_instance_of(Nokogiri::HTML::DocumentFragment) - expect(docs[0].to_html).to eq('

    hello

    ') + expect(docs[0].to_html).to eq('

    hello

    ') expect(docs[1]).to be_an_instance_of(Nokogiri::HTML::DocumentFragment) - expect(docs[1].to_html).to eq('

    bye

    ') + expect(docs[1].to_html).to eq('

    bye

    ') end it 'returns when no objects to render' do diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb index 76f42071810..8cce1b96698 100644 --- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -4,11 +4,11 @@ describe Banzai::Pipeline::DescriptionPipeline do def parse(html) # When we pass HTML to Redcarpet, it gets wrapped in `p` tags... # ...except when we pass it pre-wrapped text. Rabble rabble. - unwrap = !html.start_with?('

    ') + unwrap = !html.start_with?('

    (.*)

    (.*)\z}, '\1\2') if unwrap + output.gsub!(%r{\A

    (.*)

    (.*)\z}, '\1\2') if unwrap output end @@ -27,11 +27,17 @@ describe Banzai::Pipeline::DescriptionPipeline do end end - %w(b i strong em a ins del sup sub p).each do |elem| + %w(b i strong em a ins del sup sub).each do |elem| it "still allows '#{elem}' elements" do exp = act = "<#{elem}>Description" expect(parse(act).strip).to eq exp end end + + it "still allows 'p' elements" do + exp = act = "

    Description

    " + + expect(parse(act).strip).to eq exp + end end diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb index 15cd3a7ed70..2e3702f7520 100644 --- a/spec/models/concerns/cache_markdown_field_spec.rb +++ b/spec/models/concerns/cache_markdown_field_spec.rb @@ -64,7 +64,7 @@ describe CacheMarkdownField do let(:html) { "

    Foo

    " } let(:updated_markdown) { "`Bar`" } - let(:updated_html) { "

    Bar

    " } + let(:updated_html) { "

    Bar

    " } subject { ThingWithMarkdownFields.new(foo: markdown, foo_html: html) } -- cgit v1.2.1 From d78c667d581dca6b75895f70f0ae6ebdd0f5d815 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 14 Oct 2016 16:47:55 -0700 Subject: Fix broken Spinach tests caused by changes in !6550 Partial fix to #23378 --- spec/features/compare_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/compare_spec.rb b/spec/features/compare_spec.rb index 33dfd0d5b62..c22109d19b6 100644 --- a/spec/features/compare_spec.rb +++ b/spec/features/compare_spec.rb @@ -45,6 +45,6 @@ describe "Compare", js: true do dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click dropdown.fill_in("Filter by branch/tag", with: selection) - click_link selection + find_link(selection, visible: true).click end end -- cgit v1.2.1 From 913c1cd87aee7450fa0f8b6571302cff9b5f1dc1 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 16 Oct 2016 21:09:38 -0700 Subject: Fix broken rspec in compare text !6910 changed the filter text from "Filter by branch/tag" to "Filter by Git revision" --- spec/features/compare_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/compare_spec.rb b/spec/features/compare_spec.rb index c22109d19b6..43eb4000e58 100644 --- a/spec/features/compare_spec.rb +++ b/spec/features/compare_spec.rb @@ -44,7 +44,7 @@ describe "Compare", js: true do def select_using_dropdown(dropdown_type, selection) dropdown = find(".js-compare-#{dropdown_type}-dropdown") dropdown.find(".compare-dropdown-toggle").click - dropdown.fill_in("Filter by branch/tag", with: selection) + dropdown.fill_in("Filter by Git revision", with: selection) find_link(selection, visible: true).click end end -- cgit v1.2.1 From 7f7c3e1a8aeba5d21c332c8cacdf8af9067199c4 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 19:23:04 +0800 Subject: Add notification tests for it --- .../ci/send_pipeline_notification_service_spec.rb | 67 ++++++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index 288302cc94f..9c840967aed 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -11,23 +11,30 @@ describe Ci::SendPipelineNotificationService, services: true do let(:project) { create(:project) } let(:user) { create(:user) } - - subject{ described_class.new(pipeline) } + let(:pusher) { user } + let(:watcher) { pusher } describe '#execute' do before do reset_delivered_emails! + pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] end shared_examples 'sending emails' do - it 'sends an email to pipeline user' do + it 'sends emails' do perform_enqueued_jobs do subject.execute([user.email]) end - email = ActionMailer::Base.deliveries.last - expect(email.subject).to include(email_subject) - expect(email.to).to eq([user.email]) + expected_receivers = [pusher, watcher].uniq.sort_by(&:email) + actual = ActionMailer::Base.deliveries.sort_by(&:to) + + expect(expected_receivers.size).to eq(actual.size) + + actual.zip(expected_receivers).each do |(email, receiver)| + expect(email.subject).to include(email_subject) + expect(email.to).to eq([receiver.email]) + end end end @@ -36,6 +43,30 @@ describe Ci::SendPipelineNotificationService, services: true do let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with success pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with success pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end end context 'with failed pipeline' do @@ -43,6 +74,30 @@ describe Ci::SendPipelineNotificationService, services: true do let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with failed pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end end end end -- cgit v1.2.1 From 8ea702cfe590e94ea496609f85ba0f23bda2dcce Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 19:42:16 +0800 Subject: Revert "Split notification integration into another branch" This reverts commit 1404aa8677969a03ed56e8f8350257f317f576d8. --- spec/services/ci/send_pipeline_notification_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb index 9c840967aed..110e16410c5 100644 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ b/spec/services/ci/send_pipeline_notification_service_spec.rb @@ -23,7 +23,7 @@ describe Ci::SendPipelineNotificationService, services: true do shared_examples 'sending emails' do it 'sends emails' do perform_enqueued_jobs do - subject.execute([user.email]) + subject.execute end expected_receivers = [pusher, watcher].uniq.sort_by(&:email) -- cgit v1.2.1 From 9c2d40649e0792652c3d41d3c19f2e45c0db5b03 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 21:43:52 +0800 Subject: Remove pusher support because it's covered by notifications --- spec/models/project_services/pipeline_email_service_spec.rb | 8 -------- 1 file changed, 8 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 1368a2925e8..68a96b9251f 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -23,14 +23,6 @@ describe PipelinesEmailService do end it { is_expected.to validate_presence_of(:recipients) } - - context 'when pusher is added' do - before do - subject.add_pusher = true - end - - it { is_expected.not_to validate_presence_of(:recipients) } - end end context 'when service is inactive' do -- cgit v1.2.1 From 811de6ac73ea68ae3361ec49d2094d4f2006f493 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 21:57:04 +0800 Subject: Add test for sending pipeline notifications --- spec/models/ci/pipeline_spec.rb | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 550a890797e..f564a2d4fdd 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -523,4 +523,58 @@ describe Ci::Pipeline, models: true do expect(pipeline.merge_requests).to be_empty end end + + describe 'notifications when pipeline success or failed' do + before do + ActionMailer::Base.deliveries.clear + + pipeline.enqueue + pipeline.run + end + + shared_examples 'sending a notification' do + it 'sends an email' do + sent_to = ActionMailer::Base.deliveries.flat_map(&:to) + expect(sent_to).to contain_exactly(pipeline.user.email) + end + end + + shared_examples 'not sending any notification' do + it 'does not send any email' do + expect(ActionMailer::Base.deliveries).to be_empty + end + end + + context 'with success pipeline' do + before do + perform_enqueued_jobs do + pipeline.success + end + end + end + + context 'with failed pipeline' do + before do + perform_enqueued_jobs do + pipeline.drop + end + end + end + + context 'with skipped pipeline' do + before do + perform_enqueued_jobs do + pipeline.skip + end + end + end + + context 'with cancelled pipeline' do + before do + perform_enqueued_jobs do + pipeline.cancel + end + end + end + end end -- cgit v1.2.1 From aafd42c49d516d301d72a4f43d7e56d7bf168d80 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 14 Sep 2016 22:12:31 +0800 Subject: How could I forget this? --- spec/models/ci/pipeline_spec.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index f564a2d4fdd..dc1d1de12a1 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -528,6 +528,7 @@ describe Ci::Pipeline, models: true do before do ActionMailer::Base.deliveries.clear + pipeline.update(user: create(:user)) pipeline.enqueue pipeline.run end @@ -548,9 +549,11 @@ describe Ci::Pipeline, models: true do context 'with success pipeline' do before do perform_enqueued_jobs do - pipeline.success + pipeline.succeed end end + + it_behaves_like 'sending a notification' end context 'with failed pipeline' do @@ -559,6 +562,8 @@ describe Ci::Pipeline, models: true do pipeline.drop end end + + it_behaves_like 'sending a notification' end context 'with skipped pipeline' do @@ -567,6 +572,8 @@ describe Ci::Pipeline, models: true do pipeline.skip end end + + it_behaves_like 'not sending any notification' end context 'with cancelled pipeline' do @@ -575,6 +582,8 @@ describe Ci::Pipeline, models: true do pipeline.cancel end end + + it_behaves_like 'not sending any notification' end end end -- cgit v1.2.1 From d39b1959d80f857e57fe67696c8d4525cb5966d9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:47:11 +0800 Subject: Prefer methods from EmailHelpers, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_15434869 --- spec/models/ci/pipeline_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index dc1d1de12a1..03dd8867b18 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -526,7 +526,7 @@ describe Ci::Pipeline, models: true do describe 'notifications when pipeline success or failed' do before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! pipeline.update(user: create(:user)) pipeline.enqueue -- cgit v1.2.1 From 572585665f838584b9547831528f26fb60df8d0f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:54:16 +0800 Subject: Use EmailHelpers where possible, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_15434860 --- spec/models/ci/pipeline_spec.rb | 5 ++--- spec/support/email_helpers.rb | 6 +++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 03dd8867b18..050ab50f84f 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -535,14 +535,13 @@ describe Ci::Pipeline, models: true do shared_examples 'sending a notification' do it 'sends an email' do - sent_to = ActionMailer::Base.deliveries.flat_map(&:to) - expect(sent_to).to contain_exactly(pipeline.user.email) + should_only_email(pipeline.user) end end shared_examples 'not sending any notification' do it 'does not send any email' do - expect(ActionMailer::Base.deliveries).to be_empty + should_email_no_one end end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 0bfc4685532..dfb252544e7 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,6 @@ module EmailHelpers def sent_to_user?(user) - ActionMailer::Base.deliveries.map(&:to).flatten.count(user.email) == 1 + ActionMailer::Base.deliveries.flat_map(&:to).count(user.email) == 1 end def reset_delivered_emails! @@ -20,4 +20,8 @@ module EmailHelpers def should_not_email(user) expect(sent_to_user?(user)).to be_falsey end + + def should_email_no_one + expect(ActionMailer::Base.deliveries).to be_empty + end end -- cgit v1.2.1 From 230bae9d48505ac59bfdc61ae739192416d18e92 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 13:57:55 +0800 Subject: Update the other sites for reset_delivered_emails! as well --- spec/mailers/shared/notify.rb | 2 +- .../pipeline_email_service_spec.rb | 2 +- spec/services/notification_service_spec.rb | 28 +++++++++++----------- spec/workers/build_email_worker_spec.rb | 2 +- spec/workers/emails_on_push_worker_spec.rb | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) (limited to 'spec') diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 3956d05060b..49867aa5cc4 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -7,7 +7,7 @@ shared_context 'gitlab email notification' do let(:new_user_address) { 'newguy@example.com' } before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! email = recipient.emails.create(email: "notifications@example.com") recipient.update_attribute(:notification_email, email.email) stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}") diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 68a96b9251f..e2d8eaf6a1f 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -13,7 +13,7 @@ describe PipelinesEmailService do end before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe 'Validations' do diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 699b9925b4e..84c22631c67 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -17,7 +17,7 @@ describe NotificationService, services: true do it 'sends no emails when no new mentions are present' do send_notifications - expect(ActionMailer::Base.deliveries).to be_empty + should_email_no_one end it 'emails new mentions with a watch level higher than participant' do @@ -27,7 +27,7 @@ describe NotificationService, services: true do it 'does not email new mentions with a watch level equal to or less than participant' do send_notifications(@u_participating, @u_mentioned) - expect(ActionMailer::Base.deliveries).to be_empty + should_email_no_one end end @@ -79,7 +79,7 @@ describe NotificationService, services: true do # Ensure create SentNotification by noteable = issue 6 times, not noteable = note expect(SentNotification).to receive(:record).with(issue, any_args).exactly(8).times - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.new_note(note) @@ -111,7 +111,7 @@ describe NotificationService, services: true do context 'participating' do context 'by note' do before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! note.author = @u_lazy_participant note.save notification.new_note(note) @@ -134,7 +134,7 @@ describe NotificationService, services: true do @u_watcher.notification_settings_for(note.project).participating! @u_watcher.notification_settings_for(note.project.group).global! update_custom_notification(:new_note, @u_custom_global) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end it do @@ -173,7 +173,7 @@ describe NotificationService, services: true do expect(SentNotification).to receive(:record).with(confidential_issue, any_args).exactly(4).times - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.new_note(note) @@ -196,7 +196,7 @@ describe NotificationService, services: true do before do build_team(note.project) note.project.team << [note.author, :master] - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#new_note' do @@ -238,7 +238,7 @@ describe NotificationService, services: true do before do build_team(note.project) note.project.team << [note.author, :master] - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#new_note' do @@ -273,7 +273,7 @@ describe NotificationService, services: true do before do build_team(note.project) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! allow_any_instance_of(Commit).to receive(:author).and_return(@u_committer) update_custom_notification(:new_note, @u_guest_custom, project) update_custom_notification(:new_note, @u_custom_global) @@ -348,7 +348,7 @@ describe NotificationService, services: true do before do build_team(issue.project) add_users_with_subscription(issue.project, issue) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! update_custom_notification(:new_issue, @u_guest_custom, project) update_custom_notification(:new_issue, @u_custom_global) end @@ -408,7 +408,7 @@ describe NotificationService, services: true do label.toggle_subscription(guest) label.toggle_subscription(admin) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.new_issue(confidential_issue, @u_disabled) @@ -604,7 +604,7 @@ describe NotificationService, services: true do label_2.toggle_subscription(guest) label_2.toggle_subscription(admin) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! notification.relabeled_issue(confidential_issue, [label_2], @u_disabled) @@ -733,7 +733,7 @@ describe NotificationService, services: true do add_users_with_subscription(merge_request.target_project, merge_request) update_custom_notification(:new_merge_request, @u_guest_custom, project) update_custom_notification(:new_merge_request, @u_custom_global) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#new_merge_request' do @@ -1111,7 +1111,7 @@ describe NotificationService, services: true do before do build_team(project) - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end describe '#project_was_moved' do diff --git a/spec/workers/build_email_worker_spec.rb b/spec/workers/build_email_worker_spec.rb index 788b92c1b84..a1aa336361a 100644 --- a/spec/workers/build_email_worker_spec.rb +++ b/spec/workers/build_email_worker_spec.rb @@ -24,7 +24,7 @@ describe BuildEmailWorker do end it "gracefully handles an input SMTP error" do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! allow(Notify).to receive(:build_success_email).and_raise(Net::SMTPFatalError) subject.perform(build.id, [user.email], data.stringify_keys) diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index 036d037f3f9..fc652f6f4c3 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -87,7 +87,7 @@ describe EmailsOnPushWorker do context "when there is an SMTP error" do before do - ActionMailer::Base.deliveries.clear + reset_delivered_emails! allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError) allow(subject).to receive_message_chain(:logger, :info) perform @@ -112,7 +112,7 @@ describe EmailsOnPushWorker do original.call(Mail.new(mail.encoded)) end - ActionMailer::Base.deliveries.clear + reset_delivered_emails! end it "sends the mail to each of the recipients" do -- cgit v1.2.1 From beb47c257a6673addb44fc6573c176f6be6cbd1b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 19 Sep 2016 14:01:58 +0800 Subject: Try to slightly optimize EmailHeleprs --- spec/support/email_helpers.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index dfb252544e7..2931967de35 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,8 @@ module EmailHelpers - def sent_to_user?(user) - ActionMailer::Base.deliveries.flat_map(&:to).count(user.email) == 1 + def sent_to_user?(user, recipients = nil) + recipients ||= ActionMailer::Base.deliveries.flat_map(&:to) + + recipients.count(user.email) == 1 end def reset_delivered_emails! @@ -8,17 +10,19 @@ module EmailHelpers end def should_only_email(*users) - users.each {|user| should_email(user) } recipients = ActionMailer::Base.deliveries.flat_map(&:to) + + users.each { |user| should_email(user, recipients) } + expect(recipients.count).to eq(users.count) end - def should_email(user) - expect(sent_to_user?(user)).to be_truthy + def should_email(user, recipients = nil) + expect(sent_to_user?(user, recipients)).to be_truthy end - def should_not_email(user) - expect(sent_to_user?(user)).to be_falsey + def should_not_email(user, recipients = nil) + expect(sent_to_user?(user, recipients)).to be_falsey end def should_email_no_one -- cgit v1.2.1 From 612820b2964e77397b6d85f74eb96888b72c4cbd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 26 Sep 2016 19:04:02 +0800 Subject: Fix test by having a real commit --- spec/models/ci/pipeline_spec.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 050ab50f84f..787042cf055 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -525,10 +525,18 @@ describe Ci::Pipeline, models: true do end describe 'notifications when pipeline success or failed' do + let(:project) { create(:project) } + + let(:pipeline) do + create(:ci_pipeline, + project: project, + sha: project.commit('master').sha, + user: create(:user)) + end + before do reset_delivered_emails! - pipeline.update(user: create(:user)) pipeline.enqueue pipeline.run end -- cgit v1.2.1 From 9622ef64e41058b8dec97c98f568d8fdea95fd61 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 15:39:54 +0800 Subject: Introduce email_recipients and use include? Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16075554 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16075622 --- spec/support/email_helpers.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 2931967de35..caa6ab1345a 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,8 +1,6 @@ module EmailHelpers - def sent_to_user?(user, recipients = nil) - recipients ||= ActionMailer::Base.deliveries.flat_map(&:to) - - recipients.count(user.email) == 1 + def sent_to_user?(user, recipients = email_recipients) + recipients.include?(user.email) end def reset_delivered_emails! @@ -10,22 +8,26 @@ module EmailHelpers end def should_only_email(*users) - recipients = ActionMailer::Base.deliveries.flat_map(&:to) + recipients = email_recipients users.each { |user| should_email(user, recipients) } expect(recipients.count).to eq(users.count) end - def should_email(user, recipients = nil) + def should_email(user, recipients = email_recipients) expect(sent_to_user?(user, recipients)).to be_truthy end - def should_not_email(user, recipients = nil) + def should_not_email(user, recipients = email_recipients) expect(sent_to_user?(user, recipients)).to be_falsey end def should_email_no_one expect(ActionMailer::Base.deliveries).to be_empty end + + def email_recipients + ActionMailer::Base.deliveries.flat_map(&:to) + end end -- cgit v1.2.1 From eeeb96c9d0cab9c5da850809a9614e2a01fdb7d2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 17:22:06 +0800 Subject: Change service to be a worker, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_16118195 --- spec/models/ci/pipeline_spec.rb | 6 +- .../ci/send_pipeline_notification_service_spec.rb | 103 --------------------- .../send_pipeline_notification_worker_spec.rb | 103 +++++++++++++++++++++ 3 files changed, 107 insertions(+), 105 deletions(-) delete mode 100644 spec/services/ci/send_pipeline_notification_service_spec.rb create mode 100644 spec/workers/send_pipeline_notification_worker_spec.rb (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 787042cf055..6ea712ae1b3 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -537,8 +537,10 @@ describe Ci::Pipeline, models: true do before do reset_delivered_emails! - pipeline.enqueue - pipeline.run + perform_enqueued_jobs do + pipeline.enqueue + pipeline.run + end end shared_examples 'sending a notification' do diff --git a/spec/services/ci/send_pipeline_notification_service_spec.rb b/spec/services/ci/send_pipeline_notification_service_spec.rb deleted file mode 100644 index 110e16410c5..00000000000 --- a/spec/services/ci/send_pipeline_notification_service_spec.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'spec_helper' - -describe Ci::SendPipelineNotificationService, services: true do - let(:pipeline) do - create(:ci_pipeline, - project: project, - sha: project.commit('master').sha, - user: user, - status: status) - end - - let(:project) { create(:project) } - let(:user) { create(:user) } - let(:pusher) { user } - let(:watcher) { pusher } - - describe '#execute' do - before do - reset_delivered_emails! - pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] - end - - shared_examples 'sending emails' do - it 'sends emails' do - perform_enqueued_jobs do - subject.execute - end - - expected_receivers = [pusher, watcher].uniq.sort_by(&:email) - actual = ActionMailer::Base.deliveries.sort_by(&:to) - - expect(expected_receivers.size).to eq(actual.size) - - actual.zip(expected_receivers).each do |(email, receiver)| - expect(email.subject).to include(email_subject) - expect(email.to).to eq([receiver.email]) - end - end - end - - context 'with success pipeline' do - let(:status) { 'success' } - let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } - - it_behaves_like 'sending emails' - - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with success pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: true) - end - - it_behaves_like 'sending emails' - end - - context 'with success pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: false) - end - - it_behaves_like 'sending emails' - end - end - end - - context 'with failed pipeline' do - let(:status) { 'failed' } - let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } - - it_behaves_like 'sending emails' - - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with failed pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: true) - end - - it_behaves_like 'sending emails' - end - - context 'with failed pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: false) - end - - it_behaves_like 'sending emails' - end - end - end - end -end diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb new file mode 100644 index 00000000000..0670d67501a --- /dev/null +++ b/spec/workers/send_pipeline_notification_worker_spec.rb @@ -0,0 +1,103 @@ +require 'spec_helper' + +describe SendPipelineNotificationWorker, services: true do + let(:pipeline) do + create(:ci_pipeline, + project: project, + sha: project.commit('master').sha, + user: user, + status: status) + end + + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:pusher) { user } + let(:watcher) { pusher } + + describe '#execute' do + before do + reset_delivered_emails! + pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] + end + + shared_examples 'sending emails' do + it 'sends emails' do + perform_enqueued_jobs do + subject.perform(pipeline.id) + end + + expected_receivers = [pusher, watcher].uniq.sort_by(&:email) + actual = ActionMailer::Base.deliveries.sort_by(&:to) + + expect(expected_receivers.size).to eq(actual.size) + + actual.zip(expected_receivers).each do |(email, receiver)| + expect(email.subject).to include(email_subject) + expect(email.to).to eq([receiver.email]) + end + end + end + + context 'with success pipeline' do + let(:status) { 'success' } + let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } + + it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with success pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with success pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end + end + + context 'with failed pipeline' do + let(:status) { 'failed' } + let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } + + it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with failed pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end + end + end +end -- cgit v1.2.1 From c065f5360fb3c89ab66fc2b744243b0eef166355 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 28 Sep 2016 17:29:53 +0800 Subject: That's no longer a service [ci skip] --- spec/workers/send_pipeline_notification_worker_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb index 0670d67501a..f03231498a2 100644 --- a/spec/workers/send_pipeline_notification_worker_spec.rb +++ b/spec/workers/send_pipeline_notification_worker_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe SendPipelineNotificationWorker, services: true do +describe SendPipelineNotificationWorker do let(:pipeline) do create(:ci_pipeline, project: project, -- cgit v1.2.1 From 0ea7f32afe9ff806f912a25efb4e967ee5da1e10 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 15:45:39 +0800 Subject: Make cancelled pipelines being able to retry Closes #23326 --- spec/models/ci/pipeline_spec.rb | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 550a890797e..4e0ce10603d 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -88,24 +88,38 @@ describe Ci::Pipeline, models: true do context 'no failed builds' do before do - FactoryGirl.create :ci_build, name: "rspec", pipeline: pipeline, status: 'success' + create_build('rspec', 'success') end - it 'be not retryable' do + it 'is not retryable' do is_expected.to be_falsey end + + context 'one canceled job' do + before do + create_build('rubocop', 'canceled') + end + + it 'is retryable' do + is_expected.to be_truthy + end + end end context 'with failed builds' do before do - FactoryGirl.create :ci_build, name: "rspec", pipeline: pipeline, status: 'running' - FactoryGirl.create :ci_build, name: "rubocop", pipeline: pipeline, status: 'failed' + create_build('rspec', 'running') + create_build('rubocop', 'failed') end - it 'be retryable' do + it 'is retryable' do is_expected.to be_truthy end end + + def create_build(name, status) + create(:ci_build, name: name, status: status, pipeline: pipeline) + end end describe '#stages' do -- cgit v1.2.1 From a497803072edb4c8edbf9f4daf3832c122ee50e2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 09:55:47 +0200 Subject: Improve spec for pipeline metrics worker --- spec/models/ci/pipeline_spec.rb | 27 ++++++---------- spec/workers/pipeline_metrics_worker_spec.rb | 46 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 spec/workers/pipeline_metrics_worker_spec.rb (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 550a890797e..163c0b5c516 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -187,33 +187,24 @@ describe Ci::Pipeline, models: true do end end - describe "merge request metrics" do + describe 'merge request metrics' do let(:project) { FactoryGirl.create :project } let(:pipeline) { FactoryGirl.create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: project.repository.commit('master').id) } let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref) } - context 'when transitioning to running' do - it 'records the build start time' do - time = Time.now - Timecop.freeze(time) { build.run } - - expect(merge_request.reload.metrics.latest_build_started_at).to be_within(1.second).of(time) - end - - it 'clears the build end time' do - build.run + before do + expect(PipelineMetricsWorker).to receive(:perform_async).with(pipeline.id) + end - expect(merge_request.reload.metrics.latest_build_finished_at).to be_nil + context 'when transitioning to running' do + it 'schedules metrics workers' do + pipeline.run end end context 'when transitioning to success' do - it 'records the build end time' do - build.run - time = Time.now - Timecop.freeze(time) { build.success } - - expect(merge_request.reload.metrics.latest_build_finished_at).to be_within(1.second).of(time) + it 'schedules metrics workers' do + pipeline.succeed end end end diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb new file mode 100644 index 00000000000..f58df3f0d6e --- /dev/null +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe PipelineMetricsWorker do + let(:project) { create(:project) } + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref) } + + let(:pipeline) do + create(:ci_empty_pipeline, + status: status, + project: project, + ref: 'master', + sha: project.repository.commit('master').id, + started_at: 1.hour.ago, + finished_at: Time.now) + end + + describe '#perform' do + subject { described_class.new.perform(pipeline.id) } + + context 'when pipeline is running' do + let(:status) { 'running' } + + it 'records the build start time' do + subject + + expect(merge_request.reload.metrics.latest_build_started_at).to eq(pipeline.started_at) + end + + it 'clears the build end time' do + subject + + expect(merge_request.reload.metrics.latest_build_finished_at).to be_nil + end + end + + context 'when pipeline succeeded' do + let(:status) { 'success' } + + it 'records the build end time' do + subject + + expect(merge_request.reload.metrics.latest_build_finished_at).to eq(pipeline.finished_at) + end + end + end +end -- cgit v1.2.1 From 0a11d53153d692f8c2b3c5125c5cd5e5042c08b3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:03:42 +0800 Subject: Fix test failure due to bad rebase, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17043090 --- spec/workers/send_pipeline_notification_worker_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb index f03231498a2..8d358992c7c 100644 --- a/spec/workers/send_pipeline_notification_worker_spec.rb +++ b/spec/workers/send_pipeline_notification_worker_spec.rb @@ -5,7 +5,7 @@ describe SendPipelineNotificationWorker do create(:ci_pipeline, project: project, sha: project.commit('master').sha, - user: user, + user: pusher, status: status) end -- cgit v1.2.1 From 98217bc0674253f30dea3892a8e833436b89d5b9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:03:53 +0800 Subject: should_email_no_one -> should_not_email_anyone, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17039876 --- spec/models/ci/pipeline_spec.rb | 2 +- spec/services/notification_service_spec.rb | 4 ++-- spec/support/email_helpers.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 6ea712ae1b3..85820a9dc57 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -551,7 +551,7 @@ describe Ci::Pipeline, models: true do shared_examples 'not sending any notification' do it 'does not send any email' do - should_email_no_one + should_not_email_anyone end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 84c22631c67..8ce35354c22 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -17,7 +17,7 @@ describe NotificationService, services: true do it 'sends no emails when no new mentions are present' do send_notifications - should_email_no_one + should_not_email_anyone end it 'emails new mentions with a watch level higher than participant' do @@ -27,7 +27,7 @@ describe NotificationService, services: true do it 'does not email new mentions with a watch level equal to or less than participant' do send_notifications(@u_participating, @u_mentioned) - should_email_no_one + should_not_email_anyone end end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index caa6ab1345a..36f5a2d5975 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -23,7 +23,7 @@ module EmailHelpers expect(sent_to_user?(user, recipients)).to be_falsey end - def should_email_no_one + def should_not_email_anyone expect(ActionMailer::Base.deliveries).to be_empty end -- cgit v1.2.1 From 2e067480a9824228542c229a09aa4b6f006dc6f3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 17 Oct 2016 18:12:07 +0800 Subject: Rename for a more consistent pipeline worker name, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342/diffs#note_17039533 --- spec/workers/pipeline_notification_worker_spec.rb | 103 +++++++++++++++++++++ .../send_pipeline_notification_worker_spec.rb | 103 --------------------- 2 files changed, 103 insertions(+), 103 deletions(-) create mode 100644 spec/workers/pipeline_notification_worker_spec.rb delete mode 100644 spec/workers/send_pipeline_notification_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb new file mode 100644 index 00000000000..c641d7a7801 --- /dev/null +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -0,0 +1,103 @@ +require 'spec_helper' + +describe PipelineNotificationWorker do + let(:pipeline) do + create(:ci_pipeline, + project: project, + sha: project.commit('master').sha, + user: pusher, + status: status) + end + + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:pusher) { user } + let(:watcher) { pusher } + + describe '#execute' do + before do + reset_delivered_emails! + pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] + end + + shared_examples 'sending emails' do + it 'sends emails' do + perform_enqueued_jobs do + subject.perform(pipeline.id) + end + + expected_receivers = [pusher, watcher].uniq.sort_by(&:email) + actual = ActionMailer::Base.deliveries.sort_by(&:to) + + expect(expected_receivers.size).to eq(actual.size) + + actual.zip(expected_receivers).each do |(email, receiver)| + expect(email.subject).to include(email_subject) + expect(email.to).to eq([receiver.email]) + end + end + end + + context 'with success pipeline' do + let(:status) { 'success' } + let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } + + it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with success pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with success pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end + end + + context 'with failed pipeline' do + let(:status) { 'failed' } + let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } + + it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + + context 'with failed pipeline notification on' do + let(:watcher) { user } + + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline notification off' do + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end + end + end +end diff --git a/spec/workers/send_pipeline_notification_worker_spec.rb b/spec/workers/send_pipeline_notification_worker_spec.rb deleted file mode 100644 index 8d358992c7c..00000000000 --- a/spec/workers/send_pipeline_notification_worker_spec.rb +++ /dev/null @@ -1,103 +0,0 @@ -require 'spec_helper' - -describe SendPipelineNotificationWorker do - let(:pipeline) do - create(:ci_pipeline, - project: project, - sha: project.commit('master').sha, - user: pusher, - status: status) - end - - let(:project) { create(:project) } - let(:user) { create(:user) } - let(:pusher) { user } - let(:watcher) { pusher } - - describe '#execute' do - before do - reset_delivered_emails! - pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] - end - - shared_examples 'sending emails' do - it 'sends emails' do - perform_enqueued_jobs do - subject.perform(pipeline.id) - end - - expected_receivers = [pusher, watcher].uniq.sort_by(&:email) - actual = ActionMailer::Base.deliveries.sort_by(&:to) - - expect(expected_receivers.size).to eq(actual.size) - - actual.zip(expected_receivers).each do |(email, receiver)| - expect(email.subject).to include(email_subject) - expect(email.to).to eq([receiver.email]) - end - end - end - - context 'with success pipeline' do - let(:status) { 'success' } - let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } - - it_behaves_like 'sending emails' - - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with success pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: true) - end - - it_behaves_like 'sending emails' - end - - context 'with success pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: false) - end - - it_behaves_like 'sending emails' - end - end - end - - context 'with failed pipeline' do - let(:status) { 'failed' } - let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } - - it_behaves_like 'sending emails' - - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with failed pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: true) - end - - it_behaves_like 'sending emails' - end - - context 'with failed pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: false) - end - - it_behaves_like 'sending emails' - end - end - end - end -end -- cgit v1.2.1 From 7762d8f5a350c92295fc11cdffa703b3cb498974 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 17 Oct 2016 14:10:04 +0300 Subject: Fix Test Env (proper error handling when gitlab-shell is not clonned) --- spec/support/test_env.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index ad8ae763f6d..725299031d0 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -98,7 +98,9 @@ module TestEnv def setup_gitlab_shell unless File.directory?(Gitlab.config.gitlab_shell.path) - `rake gitlab:shell:install` + unless system('rake', 'gitlab:shell:install') + raise 'Can`t clone gitlab-shell' + end end end -- cgit v1.2.1 From 009da2fc80924778ba61c6363b6e12d7daf1fa75 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 14:31:43 +0200 Subject: Fix broken specs on MySQL after https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6896 --- spec/workers/pipeline_metrics_worker_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb index f58df3f0d6e..232478c9735 100644 --- a/spec/workers/pipeline_metrics_worker_spec.rb +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -23,7 +23,7 @@ describe PipelineMetricsWorker do it 'records the build start time' do subject - expect(merge_request.reload.metrics.latest_build_started_at).to eq(pipeline.started_at) + expect(merge_request.reload.metrics.latest_build_started_at).to be_within(1.second).of(pipeline.started_at) end it 'clears the build end time' do @@ -39,7 +39,7 @@ describe PipelineMetricsWorker do it 'records the build end time' do subject - expect(merge_request.reload.metrics.latest_build_finished_at).to eq(pipeline.finished_at) + expect(merge_request.reload.metrics.latest_build_finished_at).to be_within(1.second).of(pipeline.finished_at) end end end -- cgit v1.2.1 From bfb20200e9d1e7edd82a27d18d849ffba043845a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 17 Oct 2016 13:40:02 +0100 Subject: Add a be_like_time matcher and use it in specs The amount of precision times have in databases is variable, so we need tolerances when comparing in specs. It's better to have the tolerance defined in one place than several. --- spec/models/issue/metrics_spec.rb | 8 ++++---- spec/models/merge_request/metrics_spec.rb | 2 +- spec/requests/api/issues_spec.rb | 4 ++-- spec/requests/api/notes_spec.rb | 2 +- spec/services/create_deployment_service_spec.rb | 6 +++--- spec/services/git_push_service_spec.rb | 2 +- spec/support/matchers/be_like_time.rb | 13 +++++++++++++ spec/workers/pipeline_metrics_worker_spec.rb | 4 ++-- 8 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 spec/support/matchers/be_like_time.rb (limited to 'spec') diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb index e170b087ebc..2459a49f095 100644 --- a/spec/models/issue/metrics_spec.rb +++ b/spec/models/issue/metrics_spec.rb @@ -13,7 +13,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_associated_with_milestone_at).to be_within(1.second).of(time) + expect(metrics.first_associated_with_milestone_at).to be_like_time(time) end it "does not record the second time an issue is associated with a milestone" do @@ -24,7 +24,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_associated_with_milestone_at).to be_within(1.second).of(time) + expect(metrics.first_associated_with_milestone_at).to be_like_time(time) end end @@ -36,7 +36,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_added_to_board_at).to be_within(1.second).of(time) + expect(metrics.first_added_to_board_at).to be_like_time(time) end it "does not record the second time an issue is associated with a list label" do @@ -48,7 +48,7 @@ describe Issue::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.first_added_to_board_at).to be_within(1.second).of(time) + expect(metrics.first_added_to_board_at).to be_like_time(time) end end end diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb index a79dd215d41..255db41cb19 100644 --- a/spec/models/merge_request/metrics_spec.rb +++ b/spec/models/merge_request/metrics_spec.rb @@ -12,7 +12,7 @@ describe MergeRequest::Metrics, models: true do metrics = subject.metrics expect(metrics).to be_present - expect(metrics.merged_at).to be_within(1.second).of(time) + expect(metrics.merged_at).to be_like_time(time) end end end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index f840778ae9b..beed53d1e5c 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -694,7 +694,7 @@ describe API::API, api: true do title: 'new issue', labels: 'label, label2', created_at: creation_time expect(response).to have_http_status(201) - expect(Time.parse(json_response['created_at'])).to be_within(1.second).of(creation_time) + expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time) end end end @@ -895,7 +895,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response['labels']).to include 'label3' - expect(Time.parse(json_response['updated_at'])).to be_within(1.second).of(update_time) + expect(Time.parse(json_response['updated_at'])).to be_like_time(update_time) end end end diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 063a8706e76..d58bedc3bf7 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -217,7 +217,7 @@ describe API::API, api: true do expect(response).to have_http_status(201) expect(json_response['body']).to eq('hi!') expect(json_response['author']['username']).to eq(user.username) - expect(Time.parse(json_response['created_at'])).to be_within(1.second).of(creation_time) + expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time) end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 5fe56e7725f..0b84c7262c3 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -201,7 +201,7 @@ describe CreateDeploymentService, services: true do time = Time.now Timecop.freeze(time) { service.execute } - expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(time) end it "doesn't set the time if the deploy's environment is not 'production'" do @@ -227,13 +227,13 @@ describe CreateDeploymentService, services: true do time = Time.now Timecop.freeze(time) { service.execute } - expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(time) # Current deploy service = described_class.new(project, user, params) Timecop.freeze(time + 12.hours) { service.execute } - expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_within(1.second).of(time) + expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(time) end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index dd2a9e9903a..8dda34c7a03 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -364,7 +364,7 @@ describe GitPushService, services: true do it 'sets the metric for referenced issues' do execute_service(project, user, @oldrev, @newrev, @ref) - expect(issue.reload.metrics.first_mentioned_in_commit_at).to be_within(1.second).of(commit_time) + expect(issue.reload.metrics.first_mentioned_in_commit_at).to be_like_time(commit_time) end it 'does not set the metric for non-referenced issues' do diff --git a/spec/support/matchers/be_like_time.rb b/spec/support/matchers/be_like_time.rb new file mode 100644 index 00000000000..1f27390eab7 --- /dev/null +++ b/spec/support/matchers/be_like_time.rb @@ -0,0 +1,13 @@ +RSpec::Matchers.define :be_like_time do |expected| + match do |actual| + expect(actual).to be_within(1.second).of(expected) + end + + description do + "within one second of #{expected}" + end + + failure_message do |actual| + "expected #{actual} to be within one second of #{expected}" + end +end diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb index 232478c9735..2c9e7c2cd02 100644 --- a/spec/workers/pipeline_metrics_worker_spec.rb +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -23,7 +23,7 @@ describe PipelineMetricsWorker do it 'records the build start time' do subject - expect(merge_request.reload.metrics.latest_build_started_at).to be_within(1.second).of(pipeline.started_at) + expect(merge_request.reload.metrics.latest_build_started_at).to be_like_time(pipeline.started_at) end it 'clears the build end time' do @@ -39,7 +39,7 @@ describe PipelineMetricsWorker do it 'records the build end time' do subject - expect(merge_request.reload.metrics.latest_build_finished_at).to be_within(1.second).of(pipeline.finished_at) + expect(merge_request.reload.metrics.latest_build_finished_at).to be_like_time(pipeline.finished_at) end end end -- cgit v1.2.1 From 9b790f1cf97157240178601c62d2e557a404503e Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 16:13:19 +0200 Subject: Improve after code review --- spec/lib/gitlab/ci/config/node/environment_spec.rb | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/node/environment_spec.rb b/spec/lib/gitlab/ci/config/node/environment_spec.rb index df453223da7..430e18a816f 100644 --- a/spec/lib/gitlab/ci/config/node/environment_spec.rb +++ b/spec/lib/gitlab/ci/config/node/environment_spec.rb @@ -87,6 +87,68 @@ describe Gitlab::Ci::Config::Node::Environment do end end + context 'when valid action is used' do + let(:config) do + { name: 'production', + action: 'start' } + end + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when invalid action is used' do + let(:config) do + { name: 'production', + action: false } + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'contains error about invalid action' do + expect(entry.errors) + .to include 'environment action should be start or stop' + end + end + end + + context 'when on_stop is used' do + let(:config) do + { name: 'production', + on_stop: 'close_app' } + end + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when invalid on_stop is used' do + let(:config) do + { name: 'production', + on_stop: false } + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'contains error about invalid action' do + expect(entry.errors) + .to include 'environment action should be start or stop' + end + end + end + context 'when variables are used for environment' do let(:config) do { name: 'review/$CI_BUILD_REF_NAME', -- cgit v1.2.1 From 25dd1712ca01d017fd3b9c2d230a62e82444b5a1 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 16:23:17 +0200 Subject: Add specs to test on_stop and action on environments --- spec/lib/gitlab/ci/config/node/environment_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/node/environment_spec.rb b/spec/lib/gitlab/ci/config/node/environment_spec.rb index 430e18a816f..dbeb28c8aad 100644 --- a/spec/lib/gitlab/ci/config/node/environment_spec.rb +++ b/spec/lib/gitlab/ci/config/node/environment_spec.rb @@ -101,7 +101,7 @@ describe Gitlab::Ci::Config::Node::Environment do context 'when invalid action is used' do let(:config) do { name: 'production', - action: false } + action: 'invalid' } end describe '#valid?' do @@ -144,7 +144,7 @@ describe Gitlab::Ci::Config::Node::Environment do describe '#errors' do it 'contains error about invalid action' do expect(entry.errors) - .to include 'environment action should be start or stop' + .to include 'environment on stop should be a string' end end end -- cgit v1.2.1 From 4a369185d77013b2138f2daf6d85b1358425e75c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 17:10:26 +0200 Subject: Work on specs --- spec/models/deployment_spec.rb | 46 +++++++++++++++++++ spec/models/environment_spec.rb | 32 +++++++++++++ spec/services/create_deployment_service_spec.rb | 61 ++++++++++++++++++++++++- 3 files changed, 138 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index 01a4a53a264..ca594a320c0 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -48,4 +48,50 @@ describe Deployment, models: true do end end end + + describe '#stop_action' do + let(:build) { create(:ci_build) } + + subject { deployment.stop_action } + + context 'when no other actions' do + let(:deployment) { FactoryGirl.build(:deployment, deployable: build) } + + it { is_expected.to be_nil } + end + + context 'with other actions' do + let!(:close_action) { create(:ci_build, pipeline: build.pipeline, name: 'close_app', when: :manual) } + + context 'when matching action is defined' do + let(:deployment) { FactoryGirl.build(:deployment, deployable: build, on_stop: 'close_other_app') } + + it { is_expected.to be_nil } + end + + context 'when no matching action is defined' do + let(:deployment) { FactoryGirl.build(:deployment, deployable: build, on_stop: 'close_app') } + + it { is_expected.to eq(close_action) } + end + end + end + + describe '#stoppable?' do + subject { deployment.stoppable? } + + context 'when no other actions' do + let(:deployment) { build(:deployment) } + + it { is_expected.to be_falsey } + end + + context 'when matching action is defined' do + let(:build) { create(:ci_build) } + let(:deployment) { FactoryGirl.build(:deployment, deployable: build, on_stop: 'close_app') } + let!(:close_action) { create(:ci_build, pipeline: build.pipeline, name: 'close_app', when: :manual) } + + it { is_expected.to be_truthy } + end + end end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index e172ee8e590..b019f2ddb77 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -8,6 +8,8 @@ describe Environment, models: true do it { is_expected.to delegate_method(:last_deployment).to(:deployments).as(:last) } + it { is_expected.to delegate_method(:stop_action).to(:last_deployment).as(:last) } + it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) } it { is_expected.to validate_length_of(:name).is_within(0..255) } @@ -96,4 +98,34 @@ describe Environment, models: true do is_expected.to be_nil end end + + describe '#stoppable?' do + subject { environment.stoppable? } + + context 'when no other actions' do + it { is_expected.to be_falsey } + end + + context 'when matching action is defined' do + let(:build) { create(:ci_build) } + let!(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + let!(:close_action) { create(:ci_build, pipeline: build.pipeline, name: 'close_app', when: :manual) } + + context 'when environment is available' do + before do + environment.start + end + + it { is_expected.to be_truthy } + end + + context 'when environment is stopped' do + before do + environment.stop + end + + it { is_expected.to be_falsey } + end + end + end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index 5fe56e7725f..d4ceb83caf8 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -7,11 +7,13 @@ describe CreateDeploymentService, services: true do let(:service) { described_class.new(project, user, params) } describe '#execute' do + let(:options) { nil } let(:params) do { environment: 'production', ref: 'master', tag: false, sha: '97de212e80737a608d939f648d959671fb0a0142', + options: options } end @@ -28,7 +30,7 @@ describe CreateDeploymentService, services: true do end context 'when environment exist' do - before { create(:environment, project: project, name: 'production') } + let!(:environment) { create(:environment, project: project, name: 'production') } it 'does not create a new environment' do expect { subject }.not_to change { Environment.count } @@ -37,6 +39,46 @@ describe CreateDeploymentService, services: true do it 'does create a deployment' do expect(subject).to be_persisted end + + context 'and start action is defined' do + let(:options) { { action: 'start' } } + + context 'and environment is stopped' do + before do + environment.stop + end + + it 'makes environment available' do + subject + + expect(environment.reload).to be_available + end + + it 'does not create a deployment' do + expect(subject).not_to be_persisted + end + end + end + + context 'and stop action is defined' do + let(:options) { { action: 'stop' } } + + context 'and environment is available' do + before do + environment.start + end + + it 'makes environment stopped' do + subject + + expect(environment.reload).to be_stopped + end + + it 'does not create a deployment' do + expect(subject).to be_nil + end + end + end end context 'for environment with invalid name' do @@ -83,6 +125,23 @@ describe CreateDeploymentService, services: true do it 'does create a new deployment' do expect(subject).to be_persisted end + + context 'and environment exist' do + it 'does not create a new environment' do + expect { subject }.not_to change { Environment.count } + end + + it 'updates external url' do + subject + + expect(subject.environment.name).to eq('review-apps/feature-review-apps') + expect(subject.environment.external_url).to eq('http://feature-review-apps.review-apps.gitlab.com') + end + + it 'does create a new deployment' do + expect(subject).to be_persisted + end + end end context 'when project was removed' do -- cgit v1.2.1 From f91df171c53f230937b538ffdec04d12f7726ffc Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 17 Oct 2016 16:55:34 +0100 Subject: Fixed find file keyboard navigation Closes #23423 --- .../projects/files/find_file_keyboard_spec.rb | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 spec/features/projects/files/find_file_keyboard_spec.rb (limited to 'spec') diff --git a/spec/features/projects/files/find_file_keyboard_spec.rb b/spec/features/projects/files/find_file_keyboard_spec.rb new file mode 100644 index 00000000000..fc88fd74af8 --- /dev/null +++ b/spec/features/projects/files/find_file_keyboard_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +feature 'Find file keyboard shortcuts', feature: true, js: true do + include WaitForAjax + + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + project.team << [user, :master] + login_as user + + visit namespace_project_find_file_path(project.namespace, project, project.repository.root_ref) + + wait_for_ajax + end + + it 'opens file when pressing enter key' do + fill_in 'file_find', with: 'CHANGELOG' + + find('#file_find').native.send_keys(:enter) + + expect(page).to have_selector('.blob-content-holder') + + page.within('.file-title') do + expect(page).to have_content('CHANGELOG') + end + end + + it 'navigates files with arrow keys' do + fill_in 'file_find', with: 'application.' + + find('#file_find').native.send_keys(:down) + find('#file_find').native.send_keys(:enter) + + expect(page).to have_selector('.blob-content-holder') + + page.within('.file-title') do + expect(page).to have_content('application.js') + end + end +end -- cgit v1.2.1 From 22ef066862bffc443baf8a630b0752ce37dab01c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 14 Oct 2016 11:30:06 +0200 Subject: Avoid race condition when expiring artifacts It may happen that job meant to remove expired artifacts will be executed asynchronously when, in the meantime, project associated with given build gets removed by another asynchronous job. In that case we should not remove artifacts because such build will be removed anyway, when project removal is complete. --- .../expire_build_instance_artifacts_worker_spec.rb | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/workers/expire_build_instance_artifacts_worker_spec.rb b/spec/workers/expire_build_instance_artifacts_worker_spec.rb index 2b140f2ba28..d202b3de77e 100644 --- a/spec/workers/expire_build_instance_artifacts_worker_spec.rb +++ b/spec/workers/expire_build_instance_artifacts_worker_spec.rb @@ -6,28 +6,48 @@ describe ExpireBuildInstanceArtifactsWorker do let(:worker) { described_class.new } describe '#perform' do - before { build } - - subject! { worker.perform(build.id) } + before do + worker.perform(build.id) + end context 'with expired artifacts' do - let(:build) { create(:ci_build, :artifacts, artifacts_expire_at: Time.now - 7.days) } + let(:artifacts_expiry) { { artifacts_expire_at: Time.now - 7.days } } - it 'does expire' do - expect(build.reload.artifacts_expired?).to be_truthy - end + context 'when associated project is valid' do + let(:build) do + create(:ci_build, :artifacts, artifacts_expiry) + end - it 'does remove files' do - expect(build.reload.artifacts_file.exists?).to be_falsey + it 'does expire' do + expect(build.reload.artifacts_expired?).to be_truthy + end + + it 'does remove files' do + expect(build.reload.artifacts_file.exists?).to be_falsey + end + + it 'does nullify artifacts_file column' do + expect(build.reload.artifacts_file_identifier).to be_nil + end end - it 'does nullify artifacts_file column' do - expect(build.reload.artifacts_file_identifier).to be_nil + context 'when associated project was removed' do + let(:build) do + create(:ci_build, :artifacts, artifacts_expiry) do |build| + build.project.delete + end + end + + it 'does not remove artifacts' do + expect(build.reload.artifacts_file.exists?).to be_truthy + end end end context 'with not yet expired artifacts' do - let(:build) { create(:ci_build, :artifacts, artifacts_expire_at: Time.now + 7.days) } + let(:build) do + create(:ci_build, :artifacts, artifacts_expire_at: Time.now + 7.days) + end it 'does not expire' do expect(build.reload.artifacts_expired?).to be_falsey -- cgit v1.2.1 From e9880722076081df1576a3fb01e2c30feb6208ba Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 21:06:10 +0200 Subject: Fix environments specs --- spec/features/environments_spec.rb | 76 ++++++++++++++++++------- spec/services/create_deployment_service_spec.rb | 8 ++- 2 files changed, 62 insertions(+), 22 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 35f5706f920..1b51bf9ef66 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -35,7 +35,7 @@ feature 'Environments', feature: true do end scenario 'does show 0 as counter for environments in both tabs' do - expect(page.find('.js-avaibale-environments-count').text).to eq('0') + expect(page.find('.js-available-environments-count').text).to eq('0') expect(page.find('.js-stopped-environments-count').text).to eq('0') end end @@ -48,7 +48,7 @@ feature 'Environments', feature: true do end scenario 'does show number of opened environments in Availabe tab' do - expect(page.find('.js-avaibale-environments-count').text).to eq('1') + expect(page.find('.js-available-environments-count').text).to eq('1') end scenario 'does show number of closed environments in Stopped tab' do @@ -92,6 +92,14 @@ feature 'Environments', feature: true do scenario 'does show build name and id' do expect(page).to have_link("#{build.name} (##{build.id})") end + + scenario 'does not show stop button' do + expect(page).not_to have_selector('.close-env-link') + end + + scenario 'does not show external link button' do + expect(page).not_to have_css('external-url') + end context 'with external_url' do given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } @@ -103,14 +111,27 @@ feature 'Environments', feature: true do end end - scenario 'does show close button' do - # TODO: Add test to verify if close button is visible - # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? - end - - scenario 'does allow to close environment' do - # TODO: Add test to verify if close environment works - # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? + context 'with stop action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + scenario 'does show stop button' do + expect(page).to have_selector('.close-env-link') + end + + scenario 'does allow to stop environment' do + first('.close-env-link').click + + expect(page).to have_content('close_app') + end + + context 'for reporter' do + let(:role) { :reporter } + + scenario 'does not show stop button' do + expect(page).not_to have_selector('.close-env-link') + end + end end end end @@ -160,6 +181,10 @@ feature 'Environments', feature: true do expect(page).to have_link('Re-deploy') end + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop') + end + context 'with manual action' do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } @@ -178,20 +203,33 @@ feature 'Environments', feature: true do given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } - + scenario 'does show an external link button' do expect(page).to have_link(nil, href: environment.external_url) end end - scenario 'does show close button' do - # TODO: Add test to verify if close button is visible - # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? - end - - scenario 'does allow to close environment' do - # TODO: Add test to verify if close environment works - # This needs to be true: if local_assigns.fetch(:allow_close, false) && deployment.closeable? + context 'with stop action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + scenario 'does show stop button' do + expect(page).to have_link('Stop') + end + + scenario 'does allow to stop environment' do + click_link('Stop') + + expect(page).to have_content('close_app') + end + + context 'for reporter' do + let(:role) { :reporter } + + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop') + end + end end end end diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index d4ceb83caf8..5a4562b939b 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -54,8 +54,8 @@ describe CreateDeploymentService, services: true do expect(environment.reload).to be_available end - it 'does not create a deployment' do - expect(subject).not_to be_persisted + it 'does create a deployment' do + expect(subject).to be_persisted end end end @@ -95,7 +95,7 @@ describe CreateDeploymentService, services: true do end it 'does not create a deployment' do - expect(subject).not_to be_persisted + expect(subject).to be_nil end end @@ -127,6 +127,8 @@ describe CreateDeploymentService, services: true do end context 'and environment exist' do + let!(:environment) { create(:environment, project: project, name: 'review-apps/feature-review-apps') } + it 'does not create a new environment' do expect { subject }.not_to change { Environment.count } end -- cgit v1.2.1 From 34e19b9b8dccd7cd2e6c2bb408e75c70f3b6f3b9 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 22:01:56 +0200 Subject: Fix specs --- spec/features/environments_spec.rb | 42 +------------------ .../merge_when_build_succeeds_spec.rb | 9 ----- .../merge_requests/widget_deployments_spec.rb | 47 ++++++++++++++++++---- 3 files changed, 42 insertions(+), 56 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 1b51bf9ef66..16c44e42f63 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -119,7 +119,7 @@ feature 'Environments', feature: true do expect(page).to have_selector('.close-env-link') end - scenario 'does allow to stop environment' do + scenario 'starts build when stop button clicked' do first('.close-env-link').click expect(page).to have_content('close_app') @@ -217,7 +217,7 @@ feature 'Environments', feature: true do expect(page).to have_link('Stop') end - scenario 'does allow to stop environment' do + scenario ' scenario 'does allow to stop environment' do' do click_link('Stop') expect(page).to have_content('close_app') @@ -277,42 +277,4 @@ feature 'Environments', feature: true do end end end - - describe 'when deleting existing environment' do - given(:environment) { create(:environment, project: project) } - - before do - visit namespace_project_environment_path(project.namespace, project, environment) - end - - context 'when logged as master' do - given(:role) { :master } - - scenario 'does not have a Close link' do - expect(page).not_to have_link('Close') - end - - context 'when environment is opened and can be closed' do - let(:project) { create(:project) } - let(:environment) { create(:environment, project: project) } - - let!(:deployment) do - create(:deployment, environment: environment, sha: project.commit('master').id) - end - - scenario 'does have a Close link' do - # TODO: Add missing validation. In order to have Close link - # this must be true: last_deployment.try(:close_action) - end - end - end - - context 'when logged as developer' do - given(:role) { :developer } - - scenario 'does not have a Close link' do - expect(page).not_to have_link('Close') - end - end - end end diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb index 5d6ce6e1830..c3c3ab33872 100644 --- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb @@ -101,15 +101,6 @@ feature 'Merge When Build Succeeds', feature: true, js: true do expect(page).not_to have_link "Merge When Build Succeeds" end end - - context 'Has Environment' do - let(:environment) { create(:environment, project: project) } - - it 'does show link to close the environment' do - # TODO add test to verify if the button is visible when this condition - # is met: if environment.closeable? - end - end def visit_merge_request(merge_request) visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) diff --git a/spec/features/merge_requests/widget_deployments_spec.rb b/spec/features/merge_requests/widget_deployments_spec.rb index 8e23ec50d4a..0c8ee844b47 100644 --- a/spec/features/merge_requests/widget_deployments_spec.rb +++ b/spec/features/merge_requests/widget_deployments_spec.rb @@ -4,23 +4,56 @@ feature 'Widget Deployments Header', feature: true, js: true do include WaitForAjax describe 'when deployed to an environment' do - let(:project) { merge_request.target_project } - let(:merge_request) { create(:merge_request, :merged) } - let(:environment) { create(:environment, project: project) } - let!(:deployment) do + given(:user) { create(:user) } + given(:project) { merge_request.target_project } + given(:merge_request) { create(:merge_request, :merged) } + given(:environment) { create(:environment, project: project) } + given(:role) { :developer } + given!(:deployment) do create(:deployment, environment: environment, sha: project.commit('master').id) end + given!(:manual) { } - before do - login_as :admin + background do + login_as(user) + project.team << [user, role] visit namespace_project_merge_request_path(project.namespace, project, merge_request) end - it 'displays that the environment is deployed' do + scenario 'displays that the environment is deployed' do wait_for_ajax expect(page).to have_content("Deployed to #{environment.name}") expect(find('.ci_widget > span > span')['data-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium)) end + + context 'with stop action' do + given(:pipeline) { create(:ci_pipeline, project: project) } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + background do + wait_for_ajax + end + + scenario 'does show stop button' do + expect(page).to have_link('Stop environment') + end + + scenario 'does start build when stop button clicked' do + click_link('Stop environment') + + expect(page).to have_content('close_app') + end + + context 'for reporter' do + given(:role) { :reporter } + + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop environment') + end + end + end end end -- cgit v1.2.1 From da07c2e4d3d382c05ec287ee60f639b870074fe7 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 16 Sep 2016 16:15:39 -0300 Subject: Add visibility level to project repository --- spec/controllers/projects_controller_spec.rb | 40 ++++++++++++++++++++++ spec/factories/projects.rb | 2 ++ spec/features/projects/features_visibility_spec.rb | 30 ++++++++++++++++ .../gitlab/import_export/safe_model_attributes.yml | 1 + spec/models/project_feature_spec.rb | 23 ++++++++++++- 5 files changed, 95 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index da0fdce39db..8eefa284ba0 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -41,6 +41,46 @@ describe ProjectsController do end end end + + describe "when project repository is disabled" do + render_views + + before do + project.team << [user, :developer] + project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED) + end + + it 'shows wiki homepage' do + get :show, namespace_id: project.namespace.path, id: project.path + + expect(response).to render_template('projects/_wiki') + end + + it 'shows issues list page if wiki is disabled' do + project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED) + + get :show, namespace_id: project.namespace.path, id: project.path + + expect(response).to render_template('projects/issues/_issues') + end + + it 'shows customize workflow page if wiki and issues are disabled' do + project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED) + project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) + + get :show, namespace_id: project.namespace.path, id: project.path + + expect(response).to render_template("projects/_customize_workflow") + end + + it 'shows activity if enabled by user' do + user.update_attribute(:project_view, 'activity') + + get :show, namespace_id: project.namespace.path, id: project.path + + expect(response).to render_template("projects/_activity") + end + end end context "project with empty repo" do diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 719ef17f57e..4065e2defbc 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -45,6 +45,7 @@ FactoryGirl.define do snippets_access_level ProjectFeature::ENABLED issues_access_level ProjectFeature::ENABLED merge_requests_access_level ProjectFeature::ENABLED + repository_access_level ProjectFeature::ENABLED end after(:create) do |project, evaluator| @@ -55,6 +56,7 @@ FactoryGirl.define do snippets_access_level: evaluator.snippets_access_level, issues_access_level: evaluator.issues_access_level, merge_requests_access_level: evaluator.merge_requests_access_level, + repository_access_level: evaluator.repository_access_level ) end end diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index 9b487e350f2..1d4484a9edd 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -2,8 +2,11 @@ require 'spec_helper' include WaitForAjax describe 'Edit Project Settings', feature: true do + include WaitForAjax + let(:member) { create(:user) } let!(:project) { create(:project, :public, path: 'gitlab', name: 'sample') } + let!(:issue) { create(:issue, project: project) } let(:non_member) { create(:user) } describe 'project features visibility selectors', js: true do @@ -119,4 +122,31 @@ describe 'Edit Project Settings', feature: true do end end end + + describe 'repository visibility', js: true do + before do + project.team << [member, :master] + login_as(member) + visit edit_namespace_project_path(project.namespace, project) + end + + it "disables repository related features" do + select "Disabled", from: "project_project_feature_attributes_repository_access_level" + + expect(find(".edit-project")).to have_selector("select.disabled", count: 2) + end + + it "shows empty features project homepage" do + select "Disabled", from: "project_project_feature_attributes_repository_access_level" + select "Disabled", from: "project_project_feature_attributes_issues_access_level" + select "Disabled", from: "project_project_feature_attributes_wiki_access_level" + + click_button "Save changes" + wait_for_ajax + + visit namespace_project_path(project.namespace, project) + + expect(page).to have_content "Customize your workflow!" + end + end end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 8bccd313d6c..8c8be66df9f 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -307,6 +307,7 @@ ProjectFeature: - wiki_access_level - snippets_access_level - builds_access_level +- repository_access_level - created_at - updated_at ProtectedBranch::MergeAccessLevel: diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index 8d554a01be5..a55d43ab2f9 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -5,7 +5,7 @@ describe ProjectFeature do let(:user) { create(:user) } describe '#feature_available?' do - let(:features) { %w(issues wiki builds merge_requests snippets) } + let(:features) { %w(issues wiki builds merge_requests snippets repository) } context 'when features are disabled' do it "returns false" do @@ -64,6 +64,27 @@ describe ProjectFeature do end end + context 'repository related features' do + before do + project.project_feature.update_attributes( + merge_requests_access_level: ProjectFeature::DISABLED, + builds_access_level: ProjectFeature::DISABLED, + repository_access_level: ProjectFeature::PRIVATE + ) + end + + it "does not allow repository related features have higher level" do + features = %w(builds merge_requests) + project_feature = project.project_feature + + features.each do |feature| + field = "#{feature}_access_level".to_sym + project_feature.update_attribute(field, ProjectFeature::ENABLED) + expect(project_feature.valid?).to be_falsy + end + end + end + describe '#*_enabled?' do let(:features) { %w(wiki builds merge_requests) } -- cgit v1.2.1 From c3cf103fee47c056c7258d2921a34cf68a02022c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 17 Oct 2016 22:10:43 +0100 Subject: Updates class name for consistency --- spec/features/environments_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 16c44e42f63..c4f230d2007 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -94,7 +94,7 @@ feature 'Environments', feature: true do end scenario 'does not show stop button' do - expect(page).not_to have_selector('.close-env-link') + expect(page).not_to have_selector('.stop-env-link') end scenario 'does not show external link button' do @@ -116,11 +116,11 @@ feature 'Environments', feature: true do given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } scenario 'does show stop button' do - expect(page).to have_selector('.close-env-link') + expect(page).to have_selector('.stop-env-link') end scenario 'starts build when stop button clicked' do - first('.close-env-link').click + first('.stop-env-link').click expect(page).to have_content('close_app') end @@ -129,7 +129,7 @@ feature 'Environments', feature: true do let(:role) { :reporter } scenario 'does not show stop button' do - expect(page).not_to have_selector('.close-env-link') + expect(page).not_to have_selector('.stop-env-link') end end end -- cgit v1.2.1 From 5a46e22a6521af8058078e00a8e6f2252b21e8f7 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 17 Oct 2016 22:12:26 +0100 Subject: Fixes typo --- spec/features/environments_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index c4f230d2007..7f67ff7df92 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -47,7 +47,7 @@ feature 'Environments', feature: true do expect(page).to have_link(environment.name) end - scenario 'does show number of opened environments in Availabe tab' do + scenario 'does show number of opened environments in Available tab' do expect(page.find('.js-available-environments-count').text).to eq('1') end -- cgit v1.2.1 From bebfceb1df03e8afa10af5aead8e657654a14f01 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 17 Oct 2016 23:40:44 +0200 Subject: Fix specs --- spec/features/environments_spec.rb | 18 +++++++++--------- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 2 +- spec/lib/gitlab/ci/config/node/environment_spec.rb | 2 +- spec/models/environment_spec.rb | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 7f67ff7df92..7200e9ad4c1 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -18,7 +18,7 @@ feature 'Environments', feature: true do before do visit namespace_project_environments_path(project.namespace, project) end - + context 'shows two tabs' do scenario 'does show Available tab with link' do expect(page).to have_link('Available') @@ -33,7 +33,7 @@ feature 'Environments', feature: true do scenario 'does show no environments' do expect(page).to have_content('You don\'t have any environments right now.') end - + scenario 'does show 0 as counter for environments in both tabs' do expect(page.find('.js-available-environments-count').text).to eq('0') expect(page.find('.js-stopped-environments-count').text).to eq('0') @@ -46,7 +46,7 @@ feature 'Environments', feature: true do scenario 'does show environment name' do expect(page).to have_link(environment.name) end - + scenario 'does show number of opened environments in Available tab' do expect(page.find('.js-available-environments-count').text).to eq('1') end @@ -67,7 +67,7 @@ feature 'Environments', feature: true do scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) end - + scenario 'does show deployment internal id' do expect(page).to have_content(deployment.iid) end @@ -88,7 +88,7 @@ feature 'Environments', feature: true do expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end - + scenario 'does show build name and id' do expect(page).to have_link("#{build.name} (##{build.id})") end @@ -100,12 +100,12 @@ feature 'Environments', feature: true do scenario 'does not show external link button' do expect(page).not_to have_css('external-url') end - + context 'with external_url' do given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } - + scenario 'does show an external link button' do expect(page).to have_link(nil, href: environment.external_url) end @@ -198,7 +198,7 @@ feature 'Environments', feature: true do expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end - + context 'with external_url' do given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } given(:build) { create(:ci_build, pipeline: pipeline) } @@ -217,7 +217,7 @@ feature 'Environments', feature: true do expect(page).to have_link('Stop') end - scenario ' scenario 'does allow to stop environment' do' do + scenario 'does allow to stop environment' do click_link('Stop') expect(page).to have_content('close_app') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 6dedd25e9d3..a46ff07f625 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -754,7 +754,7 @@ module Ci it 'does return production' do expect(builds.size).to eq(1) expect(builds.first[:environment]).to eq(environment) - expect(builds.first[:options]).to include(environment: { name: environment }) + expect(builds.first[:options]).to include(environment: { name: environment, action: "start" }) end end diff --git a/spec/lib/gitlab/ci/config/node/environment_spec.rb b/spec/lib/gitlab/ci/config/node/environment_spec.rb index dbeb28c8aad..df925ff1afd 100644 --- a/spec/lib/gitlab/ci/config/node/environment_spec.rb +++ b/spec/lib/gitlab/ci/config/node/environment_spec.rb @@ -28,7 +28,7 @@ describe Gitlab::Ci::Config::Node::Environment do describe '#value' do it 'returns valid hash' do - expect(entry.value).to eq(name: 'production') + expect(entry.value).to include(name: 'production') end end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index b019f2ddb77..1c1fef57fc4 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -8,7 +8,7 @@ describe Environment, models: true do it { is_expected.to delegate_method(:last_deployment).to(:deployments).as(:last) } - it { is_expected.to delegate_method(:stop_action).to(:last_deployment).as(:last) } + it { is_expected.to delegate_method(:stop_action).to(:last_deployment) } it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) } -- cgit v1.2.1 From 60e6eca0d0b0926aeb248332c88be886f2f8e69f Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Mon, 17 Oct 2016 19:53:33 +0200 Subject: Fix login tests for crowd to use #crowd. --- spec/views/devise/shared/_signin_box.html.haml_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/views/devise/shared/_signin_box.html.haml_spec.rb b/spec/views/devise/shared/_signin_box.html.haml_spec.rb index ee362e6fcb3..1397bfa5864 100644 --- a/spec/views/devise/shared/_signin_box.html.haml_spec.rb +++ b/spec/views/devise/shared/_signin_box.html.haml_spec.rb @@ -12,13 +12,13 @@ describe 'devise/shared/_signin_box' do render - expect(rendered).to have_selector('#tab-crowd form') + expect(rendered).to have_selector('#crowd form') end it 'is not shown when Crowd is disabled' do render - expect(rendered).not_to have_selector('#tab-crowd') + expect(rendered).not_to have_selector('#crowd') end end -- cgit v1.2.1 From 829a708a970b31afdcda21fff072eda0c61dfd4c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 18 Oct 2016 11:22:22 +0200 Subject: Fix remaining specs failures --- spec/features/merge_requests/widget_deployments_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/widget_deployments_spec.rb b/spec/features/merge_requests/widget_deployments_spec.rb index 0c8ee844b47..1be35b27d84 100644 --- a/spec/features/merge_requests/widget_deployments_spec.rb +++ b/spec/features/merge_requests/widget_deployments_spec.rb @@ -9,9 +9,8 @@ feature 'Widget Deployments Header', feature: true, js: true do given(:merge_request) { create(:merge_request, :merged) } given(:environment) { create(:environment, project: project) } given(:role) { :developer } - given!(:deployment) do - create(:deployment, environment: environment, sha: project.commit('master').id) - end + given(:sha) { project.commit('master').id } + given!(:deployment) { create(:deployment, environment: environment, sha: sha) } given!(:manual) { } background do @@ -31,7 +30,10 @@ feature 'Widget Deployments Header', feature: true, js: true do given(:pipeline) { create(:ci_pipeline, project: project) } given(:build) { create(:ci_build, pipeline: pipeline) } given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } - given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + given(:deployment) do + create(:deployment, environment: environment, ref: merge_request.target_branch, + sha: sha, deployable: build, on_stop: 'close_app') + end background do wait_for_ajax -- cgit v1.2.1 From 0aa232704c5df68f0ed111e355a07cfaf241e8a9 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 18 Oct 2016 12:02:50 +0200 Subject: Add `stop!` to `environment` --- spec/models/environment_spec.rb | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'spec') diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 1c1fef57fc4..e1755f940b3 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -128,4 +128,41 @@ describe Environment, models: true do end end end + + describe '#stop!' do + let(:user) { create(:user) } + + subject { environment.stop!(user) } + + before do + expect(environment).to receive(:stoppable?).and_call_original + end + + context 'when no other actions' do + it { is_expected.to be_nil } + end + + context 'when matching action is defined' do + let(:build) { create(:ci_build) } + let!(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + context 'when action did not yet finish' do + let!(:close_action) { create(:ci_build, :manual, pipeline: build.pipeline, name: 'close_app') } + + it 'returns the same action' do + is_expected.to eq(close_action) + is_expected.to include(user: user) + end + end + + context 'if action did finish' do + let!(:close_action) { create(:ci_build, :manual, :success, pipeline: build.pipeline, name: 'close_app') } + + it 'returns a new action of the same type' do + is_expected.to be_persisted + is_expected.to include(name: close_action.name, user: user) + end + end + end + end end -- cgit v1.2.1 From ad85928752ea6c41863c6b8225ff2279e3044bef Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 18 Oct 2016 12:22:51 +0200 Subject: Add logical validation to gitlab-ci.yml --- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'spec') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index a46ff07f625..84f21631719 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -796,6 +796,52 @@ module Ci expect { builds }.to raise_error("jobs:deploy_to_production:environment name #{Gitlab::Regex.environment_name_regex_message}") end end + + context 'when on_stop is specified' do + let(:review) { { stage: 'deploy', script: 'test', environment: { name: 'review', on_stop: 'close_review' } } } + let(:config) { { review: review, close_review: close_review }.compact } + + context 'with matching job' do + let(:close_review) { { stage: 'deploy', script: 'test', environment: { name: 'review', action: 'stop' } } } + + it 'does return a list of builds' do + expect(builds.size).to eq(2) + expect(builds.first[:environment]).to eq('review') + end + end + + context 'without matching job' do + let(:close_review) { nil } + + it 'raises error' do + expect { builds }.to raise_error('review job: on_stop job close_review is not defined') + end + end + + context 'with close job without environment' do + let(:close_review) { { stage: 'deploy', script: 'test' } } + + it 'raises error' do + expect { builds }.to raise_error('review job: on_stop job close_review does not have environment defined') + end + end + + context 'with close job for different environment' do + let(:close_review) { { stage: 'deploy', script: 'test', environment: 'production' } } + + it 'raises error' do + expect { builds }.to raise_error('review job: on_stop job close_review have different environment name') + end + end + + context 'with close job without stop action' do + let(:close_review) { { stage: 'deploy', script: 'test', environment: { name: 'review' } } } + + it 'raises error' do + expect { builds }.to raise_error('review job: on_stop job close_review needs to have action stop defined') + end + end + end end describe "Dependencies" do -- cgit v1.2.1 From 4622f7e298edeb7211b94f3634f79dfc78db3918 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 18 Oct 2016 12:53:30 +0200 Subject: Reload pipeline settings when saving new settings --- spec/features/pipelines_settings_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/pipelines_settings_spec.rb b/spec/features/pipelines_settings_spec.rb index dcc364a3d01..76cb240ea98 100644 --- a/spec/features/pipelines_settings_spec.rb +++ b/spec/features/pipelines_settings_spec.rb @@ -24,11 +24,12 @@ feature "Pipelines settings", feature: true do context 'for master' do given(:role) { :master } - scenario 'be allowed to change' do + scenario 'be allowed to change', js: true do fill_in('Test coverage parsing', with: 'coverage_regex') click_on 'Save changes' expect(page.status_code).to eq(200) + expect(page).to have_button('Save changes', disabled: false) expect(page).to have_field('Test coverage parsing', with: 'coverage_regex') end end -- cgit v1.2.1 From b8a49e574a5cf513042f8e12d536d25fe08da801 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 18 Oct 2016 12:58:11 +0200 Subject: Move specs for project pipeline settings page --- spec/features/pipelines_settings_spec.rb | 36 ---------------------- .../projects/settings/pipelines_settings_spec.rb | 36 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 36 deletions(-) delete mode 100644 spec/features/pipelines_settings_spec.rb create mode 100644 spec/features/projects/settings/pipelines_settings_spec.rb (limited to 'spec') diff --git a/spec/features/pipelines_settings_spec.rb b/spec/features/pipelines_settings_spec.rb deleted file mode 100644 index 76cb240ea98..00000000000 --- a/spec/features/pipelines_settings_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -require 'spec_helper' - -feature "Pipelines settings", feature: true do - include GitlabRoutingHelper - - let(:project) { create(:empty_project) } - let(:user) { create(:user) } - let(:role) { :developer } - - background do - login_as(user) - project.team << [user, role] - visit namespace_project_pipelines_settings_path(project.namespace, project) - end - - context 'for developer' do - given(:role) { :developer } - - scenario 'to be disallowed to view' do - expect(page.status_code).to eq(404) - end - end - - context 'for master' do - given(:role) { :master } - - scenario 'be allowed to change', js: true do - fill_in('Test coverage parsing', with: 'coverage_regex') - click_on 'Save changes' - - expect(page.status_code).to eq(200) - expect(page).to have_button('Save changes', disabled: false) - expect(page).to have_field('Test coverage parsing', with: 'coverage_regex') - end - end -end diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb new file mode 100644 index 00000000000..76cb240ea98 --- /dev/null +++ b/spec/features/projects/settings/pipelines_settings_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +feature "Pipelines settings", feature: true do + include GitlabRoutingHelper + + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:role) { :developer } + + background do + login_as(user) + project.team << [user, role] + visit namespace_project_pipelines_settings_path(project.namespace, project) + end + + context 'for developer' do + given(:role) { :developer } + + scenario 'to be disallowed to view' do + expect(page.status_code).to eq(404) + end + end + + context 'for master' do + given(:role) { :master } + + scenario 'be allowed to change', js: true do + fill_in('Test coverage parsing', with: 'coverage_regex') + click_on 'Save changes' + + expect(page.status_code).to eq(200) + expect(page).to have_button('Save changes', disabled: false) + expect(page).to have_field('Test coverage parsing', with: 'coverage_regex') + end + end +end -- cgit v1.2.1 From c4e45d89d407016c89c5217cb91a7a82cf8710f1 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 18 Oct 2016 13:51:12 +0200 Subject: Fix remaining offenses --- spec/features/merge_requests/widget_deployments_spec.rb | 2 +- spec/models/environment_spec.rb | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/widget_deployments_spec.rb b/spec/features/merge_requests/widget_deployments_spec.rb index 1be35b27d84..6676821b807 100644 --- a/spec/features/merge_requests/widget_deployments_spec.rb +++ b/spec/features/merge_requests/widget_deployments_spec.rb @@ -32,7 +32,7 @@ feature 'Widget Deployments Header', feature: true, js: true do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } given(:deployment) do create(:deployment, environment: environment, ref: merge_request.target_branch, - sha: sha, deployable: build, on_stop: 'close_app') + sha: sha, deployable: build, on_stop: 'close_app') end background do diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index e1755f940b3..a94e6d0165f 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -150,8 +150,8 @@ describe Environment, models: true do let!(:close_action) { create(:ci_build, :manual, pipeline: build.pipeline, name: 'close_app') } it 'returns the same action' do - is_expected.to eq(close_action) - is_expected.to include(user: user) + expect(subject).to eq(close_action) + expect(subject.user).to eq(user) end end @@ -160,7 +160,8 @@ describe Environment, models: true do it 'returns a new action of the same type' do is_expected.to be_persisted - is_expected.to include(name: close_action.name, user: user) + expect(subject.name).to eq(close_action.name) + expect(subject.user).to eq(user) end end end -- cgit v1.2.1 From 045c6715330d25adff95304a3de908037c63a163 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 18 Oct 2016 20:02:35 +0800 Subject: Use bcc for pipeline emails because: We use bcc here because we don't want to generate this emails for a thousand times. This could be potentially expensive in a loop, and recipients would contain all project watchers so it could be a lot. --- spec/models/ci/pipeline_spec.rb | 2 +- spec/support/email_helpers.rb | 8 ++++---- spec/workers/pipeline_notification_worker_spec.rb | 14 ++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index caf191e11ae..4032029b80b 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -536,7 +536,7 @@ describe Ci::Pipeline, models: true do shared_examples 'sending a notification' do it 'sends an email' do - should_only_email(pipeline.user) + should_only_email(pipeline.user, kind: :bcc) end end diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index 36f5a2d5975..a946f10f71a 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -7,8 +7,8 @@ module EmailHelpers ActionMailer::Base.deliveries.clear end - def should_only_email(*users) - recipients = email_recipients + def should_only_email(*users, kind: :to) + recipients = email_recipients(kind: kind) users.each { |user| should_email(user, recipients) } @@ -27,7 +27,7 @@ module EmailHelpers expect(ActionMailer::Base.deliveries).to be_empty end - def email_recipients - ActionMailer::Base.deliveries.flat_map(&:to) + def email_recipients(kind: :to) + ActionMailer::Base.deliveries.flat_map(&kind) end end diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb index c641d7a7801..c334b2057a6 100644 --- a/spec/workers/pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -26,15 +26,13 @@ describe PipelineNotificationWorker do subject.perform(pipeline.id) end - expected_receivers = [pusher, watcher].uniq.sort_by(&:email) - actual = ActionMailer::Base.deliveries.sort_by(&:to) + emails = ActionMailer::Base.deliveries + actual = emails.flat_map(&:bcc).sort + expected_receivers = [pusher, watcher].map(&:email).uniq.sort - expect(expected_receivers.size).to eq(actual.size) - - actual.zip(expected_receivers).each do |(email, receiver)| - expect(email.subject).to include(email_subject) - expect(email.to).to eq([receiver.email]) - end + expect(actual).to eq(expected_receivers) + expect(emails.size).to eq(1) + expect(emails.last.subject).to include(email_subject) end end -- cgit v1.2.1 From 9c8c5e9dc050f32cec05f6903105ff34d726979b Mon Sep 17 00:00:00 2001 From: amaia Date: Mon, 17 Oct 2016 05:53:12 -0700 Subject: fix: commit messages being double-escaped in activies tab --- spec/lib/banzai/filter/html_entity_filter_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'spec') diff --git a/spec/lib/banzai/filter/html_entity_filter_spec.rb b/spec/lib/banzai/filter/html_entity_filter_spec.rb index 4c68ce6d6e4..f9e6bd609f0 100644 --- a/spec/lib/banzai/filter/html_entity_filter_spec.rb +++ b/spec/lib/banzai/filter/html_entity_filter_spec.rb @@ -11,4 +11,9 @@ describe Banzai::Filter::HtmlEntityFilter, lib: true do expect(output).to eq(escaped) end + + it 'does not double-escape' do + escaped = ERB::Util.html_escape("Merge branch 'blabla' into 'master'") + expect(filter(escaped)).to eq(escaped) + end end -- cgit v1.2.1 From 4012c695cb17f77f3fc928e9eef5c2fd679defc1 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Mon, 17 Oct 2016 11:07:44 +0100 Subject: Stop event_commit_title from escaping its output Return a non-html-safe, unescaped String instead of ActiveSupport::SafeBuffer to preserve safety when the output is misused. Currently there's oly one user, which does the right thing. Closes #23311 --- spec/helpers/events_helper_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'spec') diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb index 022aba0c0d0..594b40303bc 100644 --- a/spec/helpers/events_helper_spec.rb +++ b/spec/helpers/events_helper_spec.rb @@ -62,4 +62,21 @@ describe EventsHelper do expect(helper.event_note(input)).to eq(expected) end end + + describe '#event_commit_title' do + let(:message) { "foo & bar " + "A" * 70 + "\n" + "B" * 80 } + subject { helper.event_commit_title(message) } + + it "returns the first line, truncated to 70 chars" do + is_expected.to eq(message[0..66] + "...") + end + + it "is not html-safe" do + is_expected.not_to be_a(ActiveSupport::SafeBuffer) + end + + it "handles empty strings" do + expect(helper.event_commit_title("")).to eq("") + end + end end -- cgit v1.2.1 From cefc7eb15bd7526a7c40fc0a1ca3534c2a12a0ef Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 18 Oct 2016 20:53:28 +0800 Subject: Fix test for bcc changes --- spec/models/project_services/pipeline_email_service_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index e2d8eaf6a1f..57baff3354f 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -58,8 +58,7 @@ describe PipelinesEmailService do end it 'sends email' do - sent_to = ActionMailer::Base.deliveries.flat_map(&:to) - expect(sent_to).to contain_exactly(recipient) + should_only_email(double(email: recipient), kind: :bcc) end end @@ -71,7 +70,7 @@ describe PipelinesEmailService do end it 'does not send email' do - expect(ActionMailer::Base.deliveries).to be_empty + should_not_email_anyone end end -- cgit v1.2.1 From 3db585d27c005397aab3fa05cbe77853bc1019be Mon Sep 17 00:00:00 2001 From: the-undefined Date: Wed, 12 Oct 2016 06:12:31 +0100 Subject: Add Nofollow for uppercased scheme in external url Ensure that external URLs with non-lowercase protocols will be attributed with 'nofollow noreferrer' and open up in a new window. Covers the edge cases to skip: - HTTPS schemes - relative links Closes #22782 --- .../lib/banzai/filter/external_link_filter_spec.rb | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'spec') diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb index 695a5bc6fd4..167397c736b 100644 --- a/spec/lib/banzai/filter/external_link_filter_spec.rb +++ b/spec/lib/banzai/filter/external_link_filter_spec.rb @@ -46,4 +46,38 @@ describe Banzai::Filter::ExternalLinkFilter, lib: true do expect(doc.at_css('a')['rel']).to include 'noreferrer' end end + + context 'for non-lowercase scheme links' do + let(:doc_with_http) { filter %q(

    Google

    ) } + let(:doc_with_https) { filter %q(

    Google

    ) } + + it 'adds rel="nofollow" to external links' do + expect(doc_with_http.at_css('a')).to have_attribute('rel') + expect(doc_with_https.at_css('a')).to have_attribute('rel') + + expect(doc_with_http.at_css('a')['rel']).to include 'nofollow' + expect(doc_with_https.at_css('a')['rel']).to include 'nofollow' + end + + it 'adds rel="noreferrer" to external links' do + expect(doc_with_http.at_css('a')).to have_attribute('rel') + expect(doc_with_https.at_css('a')).to have_attribute('rel') + + expect(doc_with_http.at_css('a')['rel']).to include 'noreferrer' + expect(doc_with_https.at_css('a')['rel']).to include 'noreferrer' + end + + it 'skips internal links' do + internal_link = Gitlab.config.gitlab.url + "/sign_in" + url = internal_link.gsub(/\Ahttp/, 'HtTp') + act = %Q(Login) + exp = %Q(Login) + expect(filter(act).to_html).to eq(exp) + end + + it 'skips relative links' do + exp = act = %q(Relative URL) + expect(filter(act).to_html).to eq(exp) + end + end end -- cgit v1.2.1 From 2115c360d0e096ca945bb2a39862ae8d14abfa4f Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Fri, 14 Oct 2016 09:20:55 -0500 Subject: Remove unnecessary retried check & fix test failures --- spec/features/projects/pipelines_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/projects/pipelines_spec.rb b/spec/features/projects/pipelines_spec.rb index 47482bc3cc9..db56a50e058 100644 --- a/spec/features/projects/pipelines_spec.rb +++ b/spec/features/projects/pipelines_spec.rb @@ -177,7 +177,7 @@ describe "Pipelines" do before { click_on 'Retry failed' } it { expect(page).not_to have_content('Retry failed') } - it { expect(page).to have_content('retried') } + it { expect(page).to have_selector('.retried') } end end -- cgit v1.2.1 From ab8ef17fb2a2aa85a76d9106894280be9b910fda Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 17 Oct 2016 15:31:21 +0200 Subject: Extend merge request tests for all commits method --- spec/models/merge_request_spec.rb | 58 +++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 91a423b670c..344f69a703e 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -640,32 +640,56 @@ describe MergeRequest, models: true do end describe '#all_commits_sha' do - let(:all_commits_sha) do - subject.merge_request_diffs.flat_map(&:commits).map(&:sha).uniq - end + context 'when merge request is persisted' do + let(:all_commits_sha) do + subject.merge_request_diffs.flat_map(&:commits).map(&:sha).uniq + end - shared_examples 'returning all SHA' do - it 'returns all SHA from all merge_request_diffs' do - expect(subject.merge_request_diffs.size).to eq(2) - expect(subject.all_commits_sha).to eq(all_commits_sha) + shared_examples 'returning all SHA' do + it 'returns all SHA from all merge_request_diffs' do + expect(subject.merge_request_diffs.size).to eq(2) + expect(subject.all_commits_sha).to eq(all_commits_sha) + end end - end - context 'with a completely different branch' do - before do - subject.update(target_branch: 'v1.0.0') + context 'with a completely different branch' do + before do + subject.update(target_branch: 'v1.0.0') + end + + it_behaves_like 'returning all SHA' end - it_behaves_like 'returning all SHA' + context 'with a branch having no difference' do + before do + subject.update(target_branch: 'v1.1.0') + subject.reload # make sure commits were not cached + end + + it_behaves_like 'returning all SHA' + end end - context 'with a branch having no difference' do - before do - subject.update(target_branch: 'v1.1.0') - subject.reload # make sure commits were not cached + context 'when merge request is not persisted' do + context 'when compare commits are set in the service' do + let(:commit) { spy('commit') } + + subject do + build(:merge_request, compare_commits: [commit, commit]) + end + + it 'returns commits from compare commits temporary data' do + expect(subject.all_commits_sha).to eq [commit, commit] + end end - it_behaves_like 'returning all SHA' + context 'when compare commits are not set in the service' do + subject { build(:merge_request) } + + it 'returns array with diff head sha element only' do + expect(subject.all_commits_sha).to eq [subject.diff_head_sha] + end + end end end -- cgit v1.2.1 From 3032a0ca891808c9aa1ba69d540bf97e40a84670 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 18 Oct 2016 16:46:19 +0200 Subject: Merge two scenarios into one --- spec/features/environments_spec.rb | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 7200e9ad4c1..b565586ee14 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -20,11 +20,8 @@ feature 'Environments', feature: true do end context 'shows two tabs' do - scenario 'does show Available tab with link' do + scenario 'shows "Available" and "Stopped" tab with links' do expect(page).to have_link('Available') - end - - scenario 'does show Stopped tab with link' do expect(page).to have_link('Stopped') end end @@ -47,11 +44,8 @@ feature 'Environments', feature: true do expect(page).to have_link(environment.name) end - scenario 'does show number of opened environments in Available tab' do + scenario 'does show number of available and stopped environments' do expect(page.find('.js-available-environments-count').text).to eq('1') - end - - scenario 'does show number of closed environments in Stopped tab' do expect(page.find('.js-stopped-environments-count').text).to eq('0') end -- cgit v1.2.1 From 82033e2edc43b34823625f886f229e5ae944d4d6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 18 Oct 2016 18:55:11 +0300 Subject: Wait for ajax for every merge request spinach test Signed-off-by: Dmitriy Zaporozhets --- spec/support/wait_for_ajax.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/support/wait_for_ajax.rb b/spec/support/wait_for_ajax.rb index b90fc112671..0f9dc2dee75 100644 --- a/spec/support/wait_for_ajax.rb +++ b/spec/support/wait_for_ajax.rb @@ -8,4 +8,8 @@ module WaitForAjax def finished_all_ajax_requests? page.evaluate_script('jQuery.active').zero? end + + def javascript_test? + [:selenium, :webkit, :chrome, :poltergeist].include?(Capybara.current_driver) + end end -- cgit v1.2.1 From cc6d42861bed8fc4c050ee8906d77bdb49783de5 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 18 Oct 2016 17:28:57 +0100 Subject: Backport git access spec changes from EE These were introduced in: --- spec/lib/gitlab/git_access_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index de68e32e5b4..a5aa387f4f7 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -185,6 +185,7 @@ describe Gitlab::GitAccess, lib: true do end end + # Run permission checks for a user def self.run_permission_checks(permissions_matrix) permissions_matrix.keys.each do |role| describe "#{role} access" do @@ -194,13 +195,12 @@ describe Gitlab::GitAccess, lib: true do else project.team << [user, role] end - end - - permissions_matrix[role].each do |action, allowed| - context action do - subject { access.push_access_check(changes[action]) } - it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey } + permissions_matrix[role].each do |action, allowed| + context action do + subject { access.push_access_check(changes[action]) } + it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey } + end end end end -- cgit v1.2.1 From b3fb7f5d5746d95db718d5b418f015b7e45ecbeb Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 18 Oct 2016 16:12:26 -0700 Subject: Add spec for toggling award emoji on issue notes --- spec/features/issues/award_emoji_spec.rb | 46 ++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index 79cc50bc18e..ef00f209998 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' describe 'Awards Emoji', feature: true do + include WaitForAjax + let!(:project) { create(:project) } let!(:user) { create(:user) } @@ -16,20 +18,22 @@ describe 'Awards Emoji', feature: true do project: project) end + let!(:note) { create(:note_on_issue, noteable: issue, project: issue.project, note: "Hello world") } + before do visit namespace_project_issue_path(project.namespace, project, issue) end it 'increments the thumbsdown emoji', js: true do find('[data-emoji="thumbsdown"]').click - sleep 2 + wait_for_ajax expect(thumbsdown_emoji).to have_text("1") end context 'click the thumbsup emoji' do it 'increments the thumbsup emoji', js: true do find('[data-emoji="thumbsup"]').click - sleep 2 + wait_for_ajax expect(thumbsup_emoji).to have_text("1") end @@ -41,7 +45,7 @@ describe 'Awards Emoji', feature: true do context 'click the thumbsdown emoji' do it 'increments the thumbsdown emoji', js: true do find('[data-emoji="thumbsdown"]').click - sleep 2 + wait_for_ajax expect(thumbsdown_emoji).to have_text("1") end @@ -49,13 +53,45 @@ describe 'Awards Emoji', feature: true do expect(thumbsup_emoji).to have_text("0") end end + + it 'toggles the smiley emoji on a note', js: true do + toggle_smiley_emoji(true) + + within('.note-awards') do + expect(find(emoji_counter)).to have_text("1") + end + + toggle_smiley_emoji(false) + + within('.note-awards') do + expect(page).not_to have_selector(emoji_counter) + end + end end def thumbsup_emoji - page.all('span.js-counter').first + page.all(emoji_counter).first end def thumbsdown_emoji - page.all('span.js-counter').last + page.all(emoji_counter).last + end + + def emoji_counter + 'span.js-counter' + end + + def toggle_smiley_emoji(status) + within('.note') do + find('.note-emoji-button').click + end + + unless status + first('[data-emoji="smiley"]').click + else + find('[data-emoji="smiley"]').click + end + + wait_for_ajax end end -- cgit v1.2.1 From 47b0edbe746d5ca2a1502d3f0bf0213fe1789567 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 18 Oct 2016 21:26:20 -0700 Subject: Improve error logging of MergeService Relates to #23505 --- spec/services/merge_requests/merge_service_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index ee53e110aee..9163c0c104e 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -120,13 +120,13 @@ describe MergeRequests::MergeService, services: true do let(:service) { MergeRequests::MergeService.new(project, user, commit_message: 'Awesome message') } it 'saves error if there is an exception' do - allow(service).to receive(:repository).and_raise("error") + allow(service).to receive(:repository).and_raise("error message") allow(service).to receive(:execute_hooks) service.execute(merge_request) - expect(merge_request.merge_error).to eq("Something went wrong during merge") + expect(merge_request.merge_error).to eq("Something went wrong during merge: error message") end it 'saves error if there is an PreReceiveError exception' do -- cgit v1.2.1 From a0f6526f02ac855027d7dfe763aab4b2a9978dca Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 19 Oct 2016 10:26:28 +0100 Subject: Tests update --- spec/features/boards/sidebar_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 905d720705d..f160052a844 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -4,7 +4,8 @@ describe 'Issue Boards', feature: true, js: true do include WaitForAjax include WaitForVueResource - let(:project) { create(:project_with_board, :public) } + let(:project) { create(:empty_project, :public) } + let(:board) { create(:board, project: project) } let(:user) { create(:user) } let!(:label) { create(:label, project: project) } let!(:label2) { create(:label, project: project) } @@ -17,7 +18,7 @@ describe 'Issue Boards', feature: true, js: true do login_as(user) - visit namespace_project_board_path(project.namespace, project) + visit namespace_project_board_path(project.namespace, project, board) wait_for_vue_resource end -- cgit v1.2.1 From c7282f89596293423c61d6676db60a9a347d09ef Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 14 Oct 2016 10:45:23 +0200 Subject: Grapify the commit status API --- spec/requests/api/commit_statuses_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb index 7aa7e85a9e2..335efc4db6c 100644 --- a/spec/requests/api/commit_statuses_spec.rb +++ b/spec/requests/api/commit_statuses_spec.rb @@ -196,7 +196,7 @@ describe API::CommitStatuses, api: true do end context 'reporter user' do - before { post api(post_url, reporter) } + before { post api(post_url, reporter), state: 'running' } it 'does not create commit status' do expect(response).to have_http_status(403) @@ -204,7 +204,7 @@ describe API::CommitStatuses, api: true do end context 'guest user' do - before { post api(post_url, guest) } + before { post api(post_url, guest), state: 'running' } it 'does not create commit status' do expect(response).to have_http_status(403) -- cgit v1.2.1 From fa075771a62a6fdb1c0ce505a14a4eee87ff55a0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 19 Oct 2016 14:13:44 +0300 Subject: Refactor group_members_controller_spec Signed-off-by: Dmitriy Zaporozhets --- .../groups/group_members_controller_spec.rb | 120 ++++++--------------- spec/factories/group_members.rb | 1 + 2 files changed, 35 insertions(+), 86 deletions(-) (limited to 'spec') diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index a0870891cf4..ad15b3f8f40 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -2,16 +2,10 @@ require 'spec_helper' describe Groups::GroupMembersController do let(:user) { create(:user) } + let(:group) { create(:group, :public) } - describe '#index' do - let(:group) { create(:group) } - - before do - group.add_owner(user) - stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) - end - - it 'renders index with group members' do + describe 'GET index' do + it 'renders index with 200 status code' do get :index, group_id: group expect(response).to have_http_status(200) @@ -19,74 +13,56 @@ describe Groups::GroupMembersController do end end - describe '#destroy' do - let(:group) { create(:group, :public) } + describe 'DELETE destroy' do + let(:member) { create(:group_member, :developer, group: group) } + + before { sign_in(user) } context 'when member is not found' do it 'returns 403' do - delete :destroy, group_id: group, - id: 42 + delete :destroy, group_id: group, id: 42 expect(response).to have_http_status(403) end end context 'when member is found' do - let(:user) { create(:user) } - let(:group_user) { create(:user) } - let(:member) do - group.add_developer(group_user) - group.members.find_by(user_id: group_user) - end - context 'when user does not have enough rights' do - before do - group.add_developer(user) - sign_in(user) - end + before { group.add_developer(user) } it 'returns 403' do - delete :destroy, group_id: group, - id: member + delete :destroy, group_id: group, id: member expect(response).to have_http_status(403) - expect(group.users).to include group_user + expect(group.members).to include member end end context 'when user has enough rights' do - before do - group.add_owner(user) - sign_in(user) - end + before { group.add_owner(user) } it '[HTML] removes user from members' do - delete :destroy, group_id: group, - id: member + delete :destroy, group_id: group, id: member expect(response).to set_flash.to 'User was successfully removed from group.' expect(response).to redirect_to(group_group_members_path(group)) - expect(group.users).not_to include group_user + expect(group.members).not_to include member end it '[JS] removes user from members' do - xhr :delete, :destroy, group_id: group, - id: member + xhr :delete, :destroy, group_id: group, id: member expect(response).to be_success - expect(group.users).not_to include group_user + expect(group.members).not_to include member end end end end - describe '#leave' do - let(:group) { create(:group, :public) } - let(:user) { create(:user) } + describe 'DELETE leave' do + before { sign_in(user) } context 'when member is not found' do - before { sign_in(user) } - it 'returns 404' do delete :leave, group_id: group @@ -96,10 +72,7 @@ describe Groups::GroupMembersController do context 'when member is found' do context 'and is not an owner' do - before do - group.add_developer(user) - sign_in(user) - end + before { group.add_developer(user) } it 'removes user from members' do delete :leave, group_id: group @@ -111,10 +84,7 @@ describe Groups::GroupMembersController do end context 'and is an owner' do - before do - group.add_owner(user) - sign_in(user) - end + before { group.add_owner(user) } it 'cannot removes himself from the group' do delete :leave, group_id: group @@ -124,10 +94,7 @@ describe Groups::GroupMembersController do end context 'and is a requester' do - before do - group.request_access(user) - sign_in(user) - end + before { group.request_access(user) } it 'removes user from members' do delete :leave, group_id: group @@ -141,13 +108,8 @@ describe Groups::GroupMembersController do end end - describe '#request_access' do - let(:group) { create(:group, :public) } - let(:user) { create(:user) } - - before do - sign_in(user) - end + describe 'POST request_access' do + before { sign_in(user) } it 'creates a new GroupMember that is not a team member' do post :request_access, group_id: group @@ -159,53 +121,39 @@ describe Groups::GroupMembersController do end end - describe '#approve_access_request' do - let(:group) { create(:group, :public) } + describe 'POST approve_access_request' do + let(:member) { create(:group_member, :access_request, group: group) } + + before { sign_in(user) } context 'when member is not found' do it 'returns 403' do - post :approve_access_request, group_id: group, - id: 42 + post :approve_access_request, group_id: group, id: 42 expect(response).to have_http_status(403) end end context 'when member is found' do - let(:user) { create(:user) } - let(:group_requester) { create(:user) } - let(:member) do - group.request_access(group_requester) - group.requesters.find_by(user_id: group_requester) - end - context 'when user does not have enough rights' do - before do - group.add_developer(user) - sign_in(user) - end + before { group.add_developer(user) } it 'returns 403' do - post :approve_access_request, group_id: group, - id: member + post :approve_access_request, group_id: group, id: member expect(response).to have_http_status(403) - expect(group.users).not_to include group_requester + expect(group.members).not_to include member end end context 'when user has enough rights' do - before do - group.add_owner(user) - sign_in(user) - end + before { group.add_owner(user) } it 'adds user to members' do - post :approve_access_request, group_id: group, - id: member + post :approve_access_request, group_id: group, id: member expect(response).to redirect_to(group_group_members_path(group)) - expect(group.users).to include group_requester + expect(group.members).to include member end end end diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb index 795df5dfda9..080b2e75ea1 100644 --- a/spec/factories/group_members.rb +++ b/spec/factories/group_members.rb @@ -9,5 +9,6 @@ FactoryGirl.define do trait(:developer) { access_level GroupMember::DEVELOPER } trait(:master) { access_level GroupMember::MASTER } trait(:owner) { access_level GroupMember::OWNER } + trait(:access_request) { requested_at Time.now } end end -- cgit v1.2.1 From 357c794a49843ca9984642ddd091612e3200a8e3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 19 Oct 2016 15:13:59 +0300 Subject: Refactor project_members_controller_spec Signed-off-by: Dmitriy Zaporozhets --- .../projects/project_members_controller_spec.rb | 113 +++++++-------------- spec/factories/project_members.rb | 1 + 2 files changed, 36 insertions(+), 78 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 074f85157de..ea56bd72912 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -1,10 +1,11 @@ require('spec_helper') describe Projects::ProjectMembersController do - describe '#apply_import' do - let(:project) { create(:project) } + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + + describe 'POST apply_import' do let(:another_project) { create(:project, :private) } - let(:user) { create(:user) } let(:member) { create(:user) } before do @@ -47,23 +48,19 @@ describe Projects::ProjectMembersController do end end - describe '#index' do - context 'when user is member' do - before do - project = create(:project, :private) - member = create(:user) - project.team << [member, :guest] - sign_in(member) - - get :index, namespace_id: project.namespace, project_id: project - end + describe 'GET index' do + it 'renders index with 200 status code' do + get :index, namespace_id: project.namespace, project_id: project - it { expect(response).to have_http_status(200) } + expect(response).to have_http_status(200) + expect(response).to render_template(:index) end end - describe '#destroy' do - let(:project) { create(:project, :public) } + describe 'DELETE destroy' do + let(:member) { create(:project_member, :developer, project: project) } + + before { sign_in(user) } context 'when member is not found' do it 'returns 404' do @@ -76,18 +73,8 @@ describe Projects::ProjectMembersController do end context 'when member is found' do - let(:user) { create(:user) } - let(:team_user) { create(:user) } - let(:member) do - project.team << [team_user, :developer] - project.members.find_by(user_id: team_user.id) - end - context 'when user does not have enough rights' do - before do - project.team << [user, :developer] - sign_in(user) - end + before { project.team << [user, :developer] } it 'returns 404' do delete :destroy, namespace_id: project.namespace, @@ -95,15 +82,12 @@ describe Projects::ProjectMembersController do id: member expect(response).to have_http_status(404) - expect(project.users).to include team_user + expect(project.members).to include member end end context 'when user has enough rights' do - before do - project.team << [user, :master] - sign_in(user) - end + before { project.team << [user, :master] } it '[HTML] removes user from members' do delete :destroy, namespace_id: project.namespace, @@ -113,7 +97,7 @@ describe Projects::ProjectMembersController do expect(response).to redirect_to( namespace_project_project_members_path(project.namespace, project) ) - expect(project.users).not_to include team_user + expect(project.members).not_to include member end it '[JS] removes user from members' do @@ -122,19 +106,16 @@ describe Projects::ProjectMembersController do id: member expect(response).to be_success - expect(project.users).not_to include team_user + expect(project.members).not_to include member end end end end - describe '#leave' do - let(:project) { create(:project, :public) } - let(:user) { create(:user) } + describe 'DELETE leave' do + before { sign_in(user) } context 'when member is not found' do - before { sign_in(user) } - it 'returns 404' do delete :leave, namespace_id: project.namespace, project_id: project @@ -145,10 +126,7 @@ describe Projects::ProjectMembersController do context 'when member is found' do context 'and is not an owner' do - before do - project.team << [user, :developer] - sign_in(user) - end + before { project.team << [user, :developer] } it 'removes user from members' do delete :leave, namespace_id: project.namespace, @@ -161,11 +139,9 @@ describe Projects::ProjectMembersController do end context 'and is an owner' do - before do - project.update(namespace_id: user.namespace_id) - project.team << [user, :master, user] - sign_in(user) - end + let(:project) { create(:project, namespace: user.namespace) } + + before { project.team << [user, :master] } it 'cannot remove himself from the project' do delete :leave, namespace_id: project.namespace, @@ -176,10 +152,7 @@ describe Projects::ProjectMembersController do end context 'and is a requester' do - before do - project.request_access(user) - sign_in(user) - end + before { project.request_access(user) } it 'removes user from members' do delete :leave, namespace_id: project.namespace, @@ -194,13 +167,8 @@ describe Projects::ProjectMembersController do end end - describe '#request_access' do - let(:project) { create(:project, :public) } - let(:user) { create(:user) } - - before do - sign_in(user) - end + describe 'POST request_access' do + before { sign_in(user) } it 'creates a new ProjectMember that is not a team member' do post :request_access, namespace_id: project.namespace, @@ -215,8 +183,10 @@ describe Projects::ProjectMembersController do end end - describe '#approve' do - let(:project) { create(:project, :public) } + describe 'POST approve' do + let(:member) { create(:project_member, :access_request, project: project) } + + before { sign_in(user) } context 'when member is not found' do it 'returns 404' do @@ -229,18 +199,8 @@ describe Projects::ProjectMembersController do end context 'when member is found' do - let(:user) { create(:user) } - let(:team_requester) { create(:user) } - let(:member) do - project.request_access(team_requester) - project.requesters.find_by(user_id: team_requester.id) - end - context 'when user does not have enough rights' do - before do - project.team << [user, :developer] - sign_in(user) - end + before { project.team << [user, :developer] } it 'returns 404' do post :approve_access_request, namespace_id: project.namespace, @@ -248,15 +208,12 @@ describe Projects::ProjectMembersController do id: member expect(response).to have_http_status(404) - expect(project.users).not_to include team_requester + expect(project.members).not_to include member end end context 'when user has enough rights' do - before do - project.team << [user, :master] - sign_in(user) - end + before { project.team << [user, :master] } it 'adds user to members' do post :approve_access_request, namespace_id: project.namespace, @@ -266,7 +223,7 @@ describe Projects::ProjectMembersController do expect(response).to redirect_to( namespace_project_project_members_path(project.namespace, project) ) - expect(project.users).to include team_requester + expect(project.members).to include member end end end diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb index 1ddb305a8af..c21927640d1 100644 --- a/spec/factories/project_members.rb +++ b/spec/factories/project_members.rb @@ -8,5 +8,6 @@ FactoryGirl.define do trait(:reporter) { access_level ProjectMember::REPORTER } trait(:developer) { access_level ProjectMember::DEVELOPER } trait(:master) { access_level ProjectMember::MASTER } + trait(:access_request) { requested_at Time.now } end end -- cgit v1.2.1 From 8e4301d982ce28d80e711865ac294a98ddce3ec6 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 6 Oct 2016 19:05:27 -0300 Subject: Prevent wrong markdown on issue ids when project has Jira service activated --- .../filter/external_issue_reference_filter_spec.rb | 72 +++++++++++++++++++--- .../banzai/filter/issue_reference_filter_spec.rb | 17 +---- spec/models/external_issue_spec.rb | 15 ----- spec/models/project_services/jira_service_spec.rb | 9 +++ .../project_services/redmine_service_spec.rb | 8 +++ spec/services/git_push_service_spec.rb | 60 +++++++++++------- spec/services/merge_requests/merge_service_spec.rb | 12 ++++ .../issue_tracker_service_shared_example.rb | 15 +++++ 8 files changed, 145 insertions(+), 63 deletions(-) (limited to 'spec') diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb index 7116c09fb21..2f9343fadaf 100644 --- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb @@ -7,12 +7,7 @@ describe Banzai::Filter::ExternalIssueReferenceFilter, lib: true do IssuesHelper end - let(:project) { create(:jira_project) } - - context 'JIRA issue references' do - let(:issue) { ExternalIssue.new('JIRA-123', project) } - let(:reference) { issue.to_reference } - + shared_examples_for "external issue tracker" do it 'requires project context' do expect { described_class.call('') }.to raise_error(ArgumentError, /:project/) end @@ -20,6 +15,7 @@ describe Banzai::Filter::ExternalIssueReferenceFilter, lib: true do %w(pre code a style).each do |elem| it "ignores valid references contained inside '#{elem}' element" do exp = act = "<#{elem}>Issue #{reference}" + expect(filter(act).to_html).to eq exp end end @@ -33,25 +29,30 @@ describe Banzai::Filter::ExternalIssueReferenceFilter, lib: true do it 'links to a valid reference' do doc = filter("Issue #{reference}") + issue_id = doc.css('a').first.attr("data-external-issue") + expect(doc.css('a').first.attr('href')) - .to eq helper.url_for_issue(reference, project) + .to eq helper.url_for_issue(issue_id, project) end it 'links to the external tracker' do doc = filter("Issue #{reference}") + link = doc.css('a').first.attr('href') + issue_id = doc.css('a').first.attr("data-external-issue") - expect(link).to eq "http://jira.example/browse/#{reference}" + expect(link).to eq(helper.url_for_issue(issue_id, project)) end it 'links with adjacent text' do doc = filter("Issue (#{reference}.)") + expect(doc.to_html).to match(/\(#{reference}<\/a>\.\)/) end it 'includes a title attribute' do doc = filter("Issue #{reference}") - expect(doc.css('a').first.attr('title')).to eq "Issue in JIRA tracker" + expect(doc.css('a').first.attr('title')).to include("Issue in #{project.issues_tracker.title}") end it 'escapes the title attribute' do @@ -69,9 +70,60 @@ describe Banzai::Filter::ExternalIssueReferenceFilter, lib: true do it 'supports an :only_path context' do doc = filter("Issue #{reference}", only_path: true) + link = doc.css('a').first.attr('href') + issue_id = doc.css('a').first["data-external-issue"] + + expect(link).to eq helper.url_for_issue(issue_id, project, only_path: true) + end + + context 'with RequestStore enabled' do + let(:reference_filter) { HTML::Pipeline.new([described_class]) } + + before { allow(RequestStore).to receive(:active?).and_return(true) } + + it 'queries the collection on the first call' do + expect_any_instance_of(Project).to receive(:default_issues_tracker?).once.and_call_original + expect_any_instance_of(Project).to receive(:issue_reference_pattern).once.and_call_original + + not_cached = reference_filter.call("look for #{reference}", { project: project }) + + expect_any_instance_of(Project).not_to receive(:default_issues_tracker?) + expect_any_instance_of(Project).not_to receive(:issue_reference_pattern) + + cached = reference_filter.call("look for #{reference}", { project: project }) - expect(link).to eq helper.url_for_issue("#{reference}", project, only_path: true) + # Links must be the same + expect(cached[:output].css('a').first[:href]).to eq(not_cached[:output].css('a').first[:href]) + end + end + end + + context "redmine project" do + let(:project) { create(:redmine_project) } + let(:issue) { ExternalIssue.new("#123", project) } + let(:reference) { issue.to_reference } + + it_behaves_like "external issue tracker" + end + + context "jira project" do + let(:project) { create(:jira_project) } + let(:reference) { issue.to_reference } + + context "with right markdown" do + let(:issue) { ExternalIssue.new("JIRA-123", project) } + + it_behaves_like "external issue tracker" + end + + context "with wrong markdown" do + let(:issue) { ExternalIssue.new("#123", project) } + + it "ignores reference" do + exp = act = "Issue #{reference}" + expect(filter(act).to_html).to eq exp + end end end end diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb index fce86a9b6ad..a2025672ad9 100644 --- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb @@ -25,9 +25,7 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do let(:reference) { issue.to_reference } it 'ignores valid references when using non-default tracker' do - expect_any_instance_of(described_class).to receive(:find_object). - with(project, issue.iid). - and_return(nil) + allow(project).to receive(:default_issues_tracker?).and_return(false) exp = act = "Issue #{reference}" expect(reference_filter(act).to_html).to eq exp @@ -199,19 +197,6 @@ describe Banzai::Filter::IssueReferenceFilter, lib: true do end end - context 'referencing external issues' do - let(:project) { create(:redmine_project) } - - it 'renders internal issue IDs as external issue links' do - doc = reference_filter('#1') - link = doc.css('a').first - - expect(link.attr('data-reference-type')).to eq('external_issue') - expect(link.attr('title')).to eq('Issue in Redmine') - expect(link.attr('data-external-issue')).to eq('1') - end - end - describe '#issues_per_Project' do context 'using an internal issue tracker' do it 'returns a Hash containing the issues per project' do diff --git a/spec/models/external_issue_spec.rb b/spec/models/external_issue_spec.rb index 4fc3b065592..ebba6e14578 100644 --- a/spec/models/external_issue_spec.rb +++ b/spec/models/external_issue_spec.rb @@ -10,21 +10,6 @@ describe ExternalIssue, models: true do it { is_expected.to include_module(Referable) } end - describe '.reference_pattern' do - it 'allows underscores in the project name' do - expect(ExternalIssue.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234' - end - - it 'allows numbers in the project name' do - expect(ExternalIssue.reference_pattern.match('EXT3_EXT-1234')[0]).to eq 'EXT3_EXT-1234' - end - - it 'requires the project name to begin with A-Z' do - expect(ExternalIssue.reference_pattern.match('3EXT_EXT-1234')).to eq nil - expect(ExternalIssue.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234' - end - end - describe '#to_reference' do it 'returns a String reference to the object' do expect(issue.to_reference).to eq issue.id diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index b48a3176007..6ff32aea018 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -30,6 +30,15 @@ describe JiraService, models: true do end end + describe '#reference_pattern' do + it_behaves_like 'allows project key on reference pattern' + + it 'does not allow # on the code' do + expect(subject.reference_pattern.match('#123')).to be_nil + expect(subject.reference_pattern.match('1#23#12')).to be_nil + end + end + describe "Execute" do let(:user) { create(:user) } let(:project) { create(:project) } diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb index b8679cd2563..0a7b237a051 100644 --- a/spec/models/project_services/redmine_service_spec.rb +++ b/spec/models/project_services/redmine_service_spec.rb @@ -26,4 +26,12 @@ describe RedmineService, models: true do it { is_expected.not_to validate_presence_of(:new_issue_url) } end end + + describe '#reference_pattern' do + it_behaves_like 'allows project key on reference pattern' + + it 'does allow # on the reference' do + expect(subject.reference_pattern.match('#123')[:issue]).to eq('123') + end + end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 8dda34c7a03..ad5170afc21 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -415,7 +415,7 @@ describe GitPushService, services: true do it "doesn't close issues when external issue tracker is in use" do allow_any_instance_of(Project).to receive(:default_issues_tracker?). and_return(false) - external_issue_tracker = double(title: 'My Tracker', issue_path: issue.iid) + external_issue_tracker = double(title: 'My Tracker', issue_path: issue.iid, reference_pattern: project.issue_reference_pattern) allow_any_instance_of(Project).to receive(:external_issue_tracker).and_return(external_issue_tracker) # The push still shouldn't create cross-reference notes. @@ -484,30 +484,46 @@ describe GitPushService, services: true do end context "closing an issue" do - let(:message) { "this is some work.\n\ncloses JIRA-1" } - - it "initiates one api call to jira server to close the issue" do - transition_body = { - transition: { - id: '2' - } - }.to_json - - execute_service(project, commit_author, @oldrev, @newrev, @ref ) - expect(WebMock).to have_requested(:post, jira_api_transition_url).with( - body: transition_body - ).once + let(:message) { "this is some work.\n\ncloses JIRA-1" } + let(:transition_body) { { transition: { id: '2' } }.to_json } + let(:comment_body) { { body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." }.to_json } + + context "using right markdown" do + it "initiates one api call to jira server to close the issue" do + execute_service(project, commit_author, @oldrev, @newrev, @ref ) + + expect(WebMock).to have_requested(:post, jira_api_transition_url).with( + body: transition_body + ).once + end + + it "initiates one api call to jira server to comment on the issue" do + execute_service(project, commit_author, @oldrev, @newrev, @ref ) + + expect(WebMock).to have_requested(:post, jira_api_comment_url).with( + body: comment_body + ).once + end end - it "initiates one api call to jira server to comment on the issue" do - comment_body = { - body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." - }.to_json + context "using wrong markdown" do + let(:message) { "this is some work.\n\ncloses #1" } - execute_service(project, commit_author, @oldrev, @newrev, @ref ) - expect(WebMock).to have_requested(:post, jira_api_comment_url).with( - body: comment_body - ).once + it "does not initiates one api call to jira server to close the issue" do + execute_service(project, commit_author, @oldrev, @newrev, @ref ) + + expect(WebMock).not_to have_requested(:post, jira_api_transition_url).with( + body: transition_body + ) + end + + it "does not initiates one api call to jira server to comment on the issue" do + execute_service(project, commit_author, @oldrev, @newrev, @ref ) + + expect(WebMock).not_to have_requested(:post, jira_api_comment_url).with( + body: comment_body + ).once + end end end end diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 9163c0c104e..f93d7732a9a 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -74,6 +74,18 @@ describe MergeRequests::MergeService, services: true do service.execute(merge_request) end + + context "wrong issue markdown" do + it 'does not close issues on JIRA issue tracker' do + jira_issue = ExternalIssue.new('#123', project) + commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}") + allow(merge_request).to receive(:commits).and_return([commit]) + + expect_any_instance_of(JiraService).not_to receive(:close_issue) + + service.execute(merge_request) + end + end end end diff --git a/spec/support/issue_tracker_service_shared_example.rb b/spec/support/issue_tracker_service_shared_example.rb index b6d7436c360..e70b3963d9d 100644 --- a/spec/support/issue_tracker_service_shared_example.rb +++ b/spec/support/issue_tracker_service_shared_example.rb @@ -5,3 +5,18 @@ RSpec.shared_examples 'issue tracker service URL attribute' do |url_attr| it { is_expected.not_to allow_value('ftp://example.com').for(url_attr) } it { is_expected.not_to allow_value('herp-and-derp').for(url_attr) } end + +RSpec.shared_examples 'allows project key on reference pattern' do |url_attr| + it 'allows underscores in the project name' do + expect(subject.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234' + end + + it 'allows numbers in the project name' do + expect(subject.reference_pattern.match('EXT3_EXT-1234')[0]).to eq 'EXT3_EXT-1234' + end + + it 'requires the project name to begin with A-Z' do + expect(subject.reference_pattern.match('3EXT_EXT-1234')).to eq nil + expect(subject.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234' + end +end -- cgit v1.2.1 From d820c090ec85f8118e4cea75bd63d800e812ea25 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 19 Sep 2016 12:04:38 -0300 Subject: Add GroupLabel model --- spec/models/group_label_spec.rb | 11 +++++++++++ spec/models/group_spec.rb | 1 + 2 files changed, 12 insertions(+) create mode 100644 spec/models/group_label_spec.rb (limited to 'spec') diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb new file mode 100644 index 00000000000..a82d23bcc0b --- /dev/null +++ b/spec/models/group_label_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe GroupLabel, models: true do + describe 'relationships' do + it { is_expected.to belong_to(:group) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:group) } + end +end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 0b3ef9b98fd..ac862055ebc 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -12,6 +12,7 @@ describe Group, models: true do it { is_expected.to have_many(:project_group_links).dependent(:destroy) } it { is_expected.to have_many(:shared_projects).through(:project_group_links) } it { is_expected.to have_many(:notification_settings).dependent(:destroy) } + it { is_expected.to have_many(:labels).class_name('GroupLabel') } describe '#members & #requesters' do let(:requester) { create(:user) } -- cgit v1.2.1 From 398ab263fd08a5d9d7b19c5b3d06f33814a474eb Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 19 Sep 2016 17:21:39 -0300 Subject: Allow users to apply group labels on Issues/MRs --- spec/services/issues/create_service_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'spec') diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 1050502fa19..5c0331ebe66 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -67,6 +67,27 @@ describe Issues::CreateService, services: true do expect(Todo.where(attributes).count).to eq 1 end + context 'when label belongs to project group' do + let(:group) { create(:group) } + let(:group_labels) { create_pair(:group_label, group: group) } + + let(:opts) do + { + title: 'Title', + description: 'Description', + label_ids: group_labels.map(&:id) + } + end + + before do + project.update(group: group) + end + + it 'assigns group labels' do + expect(issue.labels).to match_array group_labels + end + end + context 'when label belongs to different project' do let(:label) { create(:label) } -- cgit v1.2.1 From bf9d928b45516e716b0f7f099361ca03aa1454f8 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 19 Sep 2016 17:34:27 -0300 Subject: Allow user to create a board list based on a group label --- spec/services/boards/lists/create_service_spec.rb | 4 ++++ spec/services/boards/lists/generate_service_spec.rb | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'spec') diff --git a/spec/services/boards/lists/create_service_spec.rb b/spec/services/boards/lists/create_service_spec.rb index e7806add916..a7e9efcf93f 100644 --- a/spec/services/boards/lists/create_service_spec.rb +++ b/spec/services/boards/lists/create_service_spec.rb @@ -9,6 +9,10 @@ describe Boards::Lists::CreateService, services: true do subject(:service) { described_class.new(project, user, label_id: label.id) } + before do + project.team << [user, :developer] + end + context 'when board lists is empty' do it 'creates a new list at beginning of the list' do list = service.execute(board) diff --git a/spec/services/boards/lists/generate_service_spec.rb b/spec/services/boards/lists/generate_service_spec.rb index 8b2f5e81338..ed0337662af 100644 --- a/spec/services/boards/lists/generate_service_spec.rb +++ b/spec/services/boards/lists/generate_service_spec.rb @@ -8,6 +8,10 @@ describe Boards::Lists::GenerateService, services: true do subject(:service) { described_class.new(project, user) } + before do + project.team << [user, :developer] + end + context 'when board lists is empty' do it 'creates the default lists' do expect { service.execute(board) }.to change(board.lists, :count).by(2) -- cgit v1.2.1 From bdb7bf4b5188ffd68e54cbf671ba9ce1a4ffb1d1 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 20 Sep 2016 00:09:57 -0300 Subject: List group labels on project labels page --- .../projects/labels/update_prioritization_spec.rb | 104 +++++++++++++-------- 1 file changed, 66 insertions(+), 38 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb index cb7495da8eb..21896f0a787 100644 --- a/spec/features/projects/labels/update_prioritization_spec.rb +++ b/spec/features/projects/labels/update_prioritization_spec.rb @@ -3,76 +3,106 @@ require 'spec_helper' feature 'Prioritize labels', feature: true do include WaitForAjax - context 'when project belongs to user' do - let(:user) { create(:user) } - let(:project) { create(:project, name: 'test', namespace: user.namespace) } + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let!(:bug) { create(:label, project: project, title: 'bug') } + let!(:wontfix) { create(:label, project: project, title: 'wontfix') } + let!(:feature) { create(:group_label, group: group, title: 'feature') } - scenario 'user can prioritize a label', js: true do - bug = create(:label, title: 'bug') - wontfix = create(:label, title: 'wontfix') - - project.labels << bug - project.labels << wontfix + context 'when user belongs to project team' do + before do + project.team << [user, :developer] login_as user + end + + scenario 'user can prioritize a group label', js: true do visit namespace_project_labels_path(project.namespace, project) expect(page).to have_content('No prioritized labels yet') - page.within('.other-labels') do + page.within('.group-labels') do first('.js-toggle-priority').click wait_for_ajax - expect(page).not_to have_content('bug') + expect(page).not_to have_content('feature') end page.within('.prioritized-labels') do expect(page).not_to have_content('No prioritized labels yet') - expect(page).to have_content('bug') + expect(page).to have_content('feature') end end - scenario 'user can unprioritize a label', js: true do - bug = create(:label, title: 'bug', priority: 1) - wontfix = create(:label, title: 'wontfix') + scenario 'user can unprioritize a group label', js: true do + feature.update(priority: 1) - project.labels << bug - project.labels << wontfix + visit namespace_project_labels_path(project.namespace, project) - login_as user + page.within('.prioritized-labels') do + expect(page).to have_content('feature') + + first('.js-toggle-priority').click + wait_for_ajax + expect(page).not_to have_content('bug') + end + + page.within('.group-labels') do + expect(page).to have_content('feature') + end + end + + scenario 'user can prioritize a project label', js: true do visit namespace_project_labels_path(project.namespace, project) - expect(page).to have_content('bug') + expect(page).to have_content('No prioritized labels yet') + + page.within('.project-labels') do + first('.js-toggle-priority').click + wait_for_ajax + expect(page).not_to have_content('bug') + end + + page.within('.prioritized-labels') do + expect(page).not_to have_content('No prioritized labels yet') + expect(page).to have_content('bug') + end + end + + scenario 'user can unprioritize a project label', js: true do + bug.update(priority: 1) + + visit namespace_project_labels_path(project.namespace, project) page.within('.prioritized-labels') do + expect(page).to have_content('bug') + first('.js-toggle-priority').click wait_for_ajax expect(page).not_to have_content('bug') end - page.within('.other-labels') do + page.within('.project-labels') do expect(page).to have_content('bug') expect(page).to have_content('wontfix') end end scenario 'user can sort prioritized labels and persist across reloads', js: true do - bug = create(:label, title: 'bug', priority: 1) - wontfix = create(:label, title: 'wontfix', priority: 2) - - project.labels << bug - project.labels << wontfix + bug.update(priority: 1) + feature.update(priority: 2) - login_as user visit namespace_project_labels_path(project.namespace, project) expect(page).to have_content 'bug' + expect(page).to have_content 'feature' expect(page).to have_content 'wontfix' # Sort labels - find("#label_#{bug.id}").drag_to find("#label_#{wontfix.id}") + find("#project_label_#{bug.id}").drag_to find("#group_label_#{feature.id}") page.within('.prioritized-labels') do - expect(first('li')).to have_content('wontfix') + expect(first('li')).to have_content('feature') expect(page.all('li').last).to have_content('bug') end @@ -80,7 +110,7 @@ feature 'Prioritize labels', feature: true do wait_for_ajax page.within('.prioritized-labels') do - expect(first('li')).to have_content('wontfix') + expect(first('li')).to have_content('feature') expect(page.all('li').last).to have_content('bug') end end @@ -88,28 +118,26 @@ feature 'Prioritize labels', feature: true do context 'as a guest' do it 'does not prioritize labels' do - user = create(:user) guest = create(:user) - project = create(:project, name: 'test', namespace: user.namespace) - - create(:label, title: 'bug') login_as guest + visit namespace_project_labels_path(project.namespace, project) + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content 'feature' expect(page).not_to have_css('.prioritized-labels') end end context 'as a non signed in user' do it 'does not prioritize labels' do - user = create(:user) - project = create(:project, name: 'test', namespace: user.namespace) - - create(:label, title: 'bug') - visit namespace_project_labels_path(project.namespace, project) + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content 'feature' expect(page).not_to have_css('.prioritized-labels') end end -- cgit v1.2.1 From 9463551ece6c12574559a4768943ab90db7f617b Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 20 Sep 2016 00:17:04 -0300 Subject: Validates uniqueness of title unless label is a template --- spec/models/label_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 5a5d1a5d60c..894021dc8e6 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -19,6 +19,7 @@ describe Label, models: true do describe 'validation' do it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_uniqueness_of(:title) } it 'validates color code' do expect(label).not_to allow_value('G-ITLAB').for(:color) -- cgit v1.2.1 From baf47a0bd0e0563cbc99b3ae4b1336b8b3b4380a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 20 Sep 2016 11:03:41 -0300 Subject: Remove project_labels from Projects::ApplicationController --- .../controllers/projects/labels_controller_spec.rb | 80 ++++++++++++++++------ 1 file changed, 60 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 3492b6ffbbb..2b39f9cf0d1 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -1,52 +1,92 @@ require 'spec_helper' describe Projects::LabelsController do - let(:project) { create(:project) } + let(:group) { create(:group) } + let(:project) { create(:project, namespace: group) } let(:user) { create(:user) } before do project.team << [user, :master] + sign_in(user) end describe 'GET #index' do - def create_label(attributes) - create(:label, attributes.merge(project: project)) - end + let!(:label_1) { create(:label, project: project, priority: 1, title: 'Label 1') } + let!(:label_2) { create(:label, project: project, priority: 3, title: 'Label 2') } + let!(:label_3) { create(:label, project: project, priority: 1, title: 'Label 3') } + let!(:label_4) { create(:label, project: project, priority: nil, title: 'Label 4') } + let!(:label_5) { create(:label, project: project, priority: nil, title: 'Label 5') } - before do - 15.times { |i| create_label(priority: (i % 3) + 1, title: "label #{15 - i}") } - 5.times { |i| create_label(title: "label #{100 - i}") } - - get :index, namespace_id: project.namespace.to_param, project_id: project.to_param - end + let!(:group_label_1) { create(:group_label, group: group, priority: 3, title: 'Group Label 1') } + let!(:group_label_2) { create(:group_label, group: group, priority: 1, title: 'Group Label 2') } + let!(:group_label_3) { create(:group_label, group: group, priority: nil, title: 'Group Label 3') } + let!(:group_label_4) { create(:group_label, group: group, priority: nil, title: 'Group Label 4') } context '@prioritized_labels' do - let(:prioritized_labels) { assigns(:prioritized_labels) } + before do + list_labels + end it 'contains only prioritized labels' do - expect(prioritized_labels).to all(have_attributes(priority: a_value > 0)) + expect(assigns(:prioritized_labels)).to all(have_attributes(priority: a_value > 0)) end it 'is sorted by priority, then label title' do - priorities_and_titles = prioritized_labels.pluck(:priority, :title) - - expect(priorities_and_titles.sort).to eq(priorities_and_titles) + expect(assigns(:prioritized_labels)).to match_array [group_label_2, label_1, label_3, group_label_1, label_2] end end - context '@labels' do - let(:labels) { assigns(:labels) } + context '@group_labels' do + it 'contains only group labels' do + list_labels + + expect(assigns(:group_labels)).to all(have_attributes(group_id: a_value > 0)) + end it 'contains only unprioritized labels' do - expect(labels).to all(have_attributes(priority: nil)) + list_labels + + expect(assigns(:group_labels)).to all(have_attributes(priority: nil)) end it 'is sorted by label title' do - titles = labels.pluck(:title) + list_labels - expect(titles.sort).to eq(titles) + expect(assigns(:group_labels)).to match_array [group_label_3, group_label_4] end + + it 'is nil when project does not belong to a group' do + project.update(namespace: create(:namespace)) + + list_labels + + expect(assigns(:group_labels)).to be_nil + end + end + + context '@project_labels' do + before do + list_labels + end + + it 'contains only project labels' do + list_labels + + expect(assigns(:project_labels)).to all(have_attributes(project_id: a_value > 0)) + end + + it 'contains only unprioritized labels' do + expect(assigns(:project_labels)).to all(have_attributes(priority: nil)) + end + + it 'is sorted by label title' do + expect(assigns(:project_labels)).to match_array [label_4, label_5] + end + end + + def list_labels + get :index, namespace_id: project.namespace.to_param, project_id: project.to_param end end end -- cgit v1.2.1 From cfedd42badc6b84457d1de35cb31988777462d5a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 20 Sep 2016 17:07:56 -0300 Subject: Add ProjectLabel model --- spec/factories/labels.rb | 2 +- spec/models/label_spec.rb | 52 ++++++++++++++++++--------------------- spec/models/project_label_spec.rb | 11 +++++++++ spec/models/project_spec.rb | 2 +- 4 files changed, 37 insertions(+), 30 deletions(-) create mode 100644 spec/models/project_label_spec.rb (limited to 'spec') diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index eb489099854..ec4c56457ea 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -1,5 +1,5 @@ FactoryGirl.define do - factory :label do + factory :label, class: ProjectLabel do sequence(:title) { |n| "label#{n}" } color "#990000" project diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 894021dc8e6..1f1fe45d5a7 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -1,47 +1,41 @@ require 'spec_helper' describe Label, models: true do - let(:label) { create(:label) } + describe 'modules' do + it { is_expected.to include_module(Referable) } + it { is_expected.to include_module(Subscribable) } + end describe 'associations' do - it { is_expected.to belong_to(:project) } - - it { is_expected.to have_many(:label_links).dependent(:destroy) } it { is_expected.to have_many(:issues).through(:label_links).source(:target) } + it { is_expected.to have_many(:label_links).dependent(:destroy) } it { is_expected.to have_many(:lists).dependent(:destroy) } end - describe 'modules' do - subject { described_class } - - it { is_expected.to include_module(Referable) } - end - describe 'validation' do - it { is_expected.to validate_presence_of(:project) } it { is_expected.to validate_uniqueness_of(:title) } it 'validates color code' do - expect(label).not_to allow_value('G-ITLAB').for(:color) - expect(label).not_to allow_value('AABBCC').for(:color) - expect(label).not_to allow_value('#AABBCCEE').for(:color) - expect(label).not_to allow_value('GGHHII').for(:color) - expect(label).not_to allow_value('#').for(:color) - expect(label).not_to allow_value('').for(:color) - - expect(label).to allow_value('#AABBCC').for(:color) - expect(label).to allow_value('#abcdef').for(:color) + is_expected.not_to allow_value('G-ITLAB').for(:color) + is_expected.not_to allow_value('AABBCC').for(:color) + is_expected.not_to allow_value('#AABBCCEE').for(:color) + is_expected.not_to allow_value('GGHHII').for(:color) + is_expected.not_to allow_value('#').for(:color) + is_expected.not_to allow_value('').for(:color) + + is_expected.to allow_value('#AABBCC').for(:color) + is_expected.to allow_value('#abcdef').for(:color) end it 'validates title' do - expect(label).not_to allow_value('G,ITLAB').for(:title) - expect(label).not_to allow_value('').for(:title) - - expect(label).to allow_value('GITLAB').for(:title) - expect(label).to allow_value('gitlab').for(:title) - expect(label).to allow_value('G?ITLAB').for(:title) - expect(label).to allow_value('G&ITLAB').for(:title) - expect(label).to allow_value("customer's request").for(:title) + is_expected.not_to allow_value('G,ITLAB').for(:title) + is_expected.not_to allow_value('').for(:title) + + is_expected.to allow_value('GITLAB').for(:title) + is_expected.to allow_value('gitlab').for(:title) + is_expected.to allow_value('G?ITLAB').for(:title) + is_expected.to allow_value('G&ITLAB').for(:title) + is_expected.to allow_value("customer's request").for(:title) end end @@ -53,6 +47,8 @@ describe Label, models: true do end describe '#to_reference' do + let(:label) { create(:label) } + context 'using id' do it 'returns a String reference to the object' do expect(label.to_reference).to eq "~#{label.id}" diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb new file mode 100644 index 00000000000..93062b9d402 --- /dev/null +++ b/spec/models/project_label_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe ProjectLabel, models: true do + describe 'relationships' do + it { is_expected.to belong_to(:project) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:project) } + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 67dbcc362f6..e6d98e25d0b 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -56,7 +56,7 @@ describe Project, models: true do it { is_expected.to have_many(:runners) } it { is_expected.to have_many(:variables) } it { is_expected.to have_many(:triggers) } - it { is_expected.to have_many(:labels).dependent(:destroy) } + it { is_expected.to have_many(:labels).class_name('ProjectLabel').dependent(:destroy) } it { is_expected.to have_many(:users_star_projects).dependent(:destroy) } it { is_expected.to have_many(:environments).dependent(:destroy) } it { is_expected.to have_many(:deployments).dependent(:destroy) } -- cgit v1.2.1 From e28058c4107ce454a84b3e3b5750f936dace7db1 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 21 Sep 2016 17:47:58 -0300 Subject: Validate if project label title does not exist at group level --- spec/factories/labels.rb | 6 ++++++ spec/models/label_spec.rb | 2 +- spec/models/project_label_spec.rb | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index ec4c56457ea..5c789d72bac 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -4,4 +4,10 @@ FactoryGirl.define do color "#990000" project end + + factory :group_label, class: GroupLabel do + sequence(:title) { |n| "label#{n}" } + color "#990000" + group + end end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 1f1fe45d5a7..ab640e216cf 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -13,7 +13,7 @@ describe Label, models: true do end describe 'validation' do - it { is_expected.to validate_uniqueness_of(:title) } + it { is_expected.to validate_uniqueness_of(:title).scoped_to([:group_id, :project_id]) } it 'validates color code' do is_expected.not_to allow_value('G-ITLAB').for(:color) diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index 93062b9d402..355bb2a938c 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -7,5 +7,39 @@ describe ProjectLabel, models: true do describe 'validations' do it { is_expected.to validate_presence_of(:project) } + + context 'validates if title must not exist at group level' do + let(:group) { create(:group, name: 'gitlab-org') } + let(:project) { create(:empty_project, group: group) } + + before do + create(:group_label, group: group, title: 'Bug') + end + + it 'returns error if title already exists at group level' do + label = described_class.new(project: project, title: 'Bug') + + label.valid? + + expect(label.errors[:title]).to include 'already exists at group level for gitlab-org. Please choose another one.' + end + + it 'does not returns error if title does not exist at group level' do + label = described_class.new(project: project, title: 'Security') + + label.valid? + + expect(label.errors[:title]).to be_empty + end + + it 'does not returns error if project does not belong to group' do + another_project = create(:empty_project) + label = described_class.new(project: another_project, title: 'Bug') + + label.valid? + + expect(label.errors[:title]).to be_empty + end + end end end -- cgit v1.2.1 From 8522ef44bf4298a750d352ff17832b3f4fc6756d Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 26 Sep 2016 17:10:54 -0300 Subject: Recreates missing group labels when moving project to another group --- spec/factories/merge_requests.rb | 10 ++++++ spec/services/labels/transfer_service_spec.rb | 41 +++++++++++++++++++++++++ spec/services/projects/transfer_service_spec.rb | 10 ++++++ 3 files changed, 61 insertions(+) create mode 100644 spec/services/labels/transfer_service_spec.rb (limited to 'spec') diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index c6a08d78b78..f780e01253c 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -68,5 +68,15 @@ FactoryGirl.define do factory :closed_merge_request, traits: [:closed] factory :reopened_merge_request, traits: [:reopened] factory :merge_request_with_diffs, traits: [:with_diffs] + + factory :labeled_merge_request do + transient do + labels [] + end + + after(:create) do |merge_request, evaluator| + merge_request.update_attributes(labels: evaluator.labels) + end + end end end diff --git a/spec/services/labels/transfer_service_spec.rb b/spec/services/labels/transfer_service_spec.rb new file mode 100644 index 00000000000..a72a05f6c99 --- /dev/null +++ b/spec/services/labels/transfer_service_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe Labels::TransferService, services: true do + describe '#execute' do + let(:user) { create(:user) } + let(:group_1) { create(:group) } + let(:group_2) { create(:group) } + let(:project) { create(:project, namespace: group_2) } + + let(:group_label_1) { create(:group_label, group: group_1, name: 'Group Label 1') } + let(:group_label_2) { create(:group_label, group: group_1, name: 'Group Label 2') } + let(:group_label_3) { create(:group_label, group: group_1, name: 'Group Label 3') } + let(:group_label_4) { create(:group_label, group: group_2, name: 'Group Label 4') } + let(:project_label_1) { create(:label, project: project, name: 'Project Label 1') } + + subject(:service) { described_class.new(user, group_1, project) } + + before do + create(:labeled_issue, project: project, labels: [group_label_1]) + create(:labeled_issue, project: project, labels: [group_label_4]) + create(:labeled_issue, project: project, labels: [project_label_1]) + create(:labeled_merge_request, source_project: project, labels: [group_label_1, group_label_2]) + end + + it 'recreates the missing group labels at project level' do + expect { service.execute }.to change(project.labels, :count).by(2) + end + + it 'does not recreate missing group labels that are not applied to issues or merge requests' do + service.execute + + expect(project.labels.where(title: group_label_3.title)).to be_empty + end + + it 'does not recreate missing group labels that already exist in the project group' do + service.execute + + expect(project.labels.where(title: group_label_4.title)).to be_empty + end + end +end diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb index 57c71544dff..1540b90163a 100644 --- a/spec/services/projects/transfer_service_spec.rb +++ b/spec/services/projects/transfer_service_spec.rb @@ -71,4 +71,14 @@ describe Projects::TransferService, services: true do it { expect(private_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) } end end + + context 'missing group labels applied to issues or merge requests' do + it 'delegates tranfer to Labels::TransferService' do + group.add_owner(user) + + expect_any_instance_of(Labels::TransferService).to receive(:execute).once.and_call_original + + transfer_project(project, user, group) + end + end end -- cgit v1.2.1 From b654229dcd3e4460ad7305ee7714395f044a72aa Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 26 Sep 2016 19:58:36 -0300 Subject: Fix LabelsHelper#link_to_label to use the subject argument --- spec/helpers/labels_helper_spec.rb | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'spec') diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb index 501f150cfda..d30daf47543 100644 --- a/spec/helpers/labels_helper_spec.rb +++ b/spec/helpers/labels_helper_spec.rb @@ -5,27 +5,26 @@ describe LabelsHelper do let(:project) { create(:empty_project) } let(:label) { create(:label, project: project) } - context 'with @project set' do - before do - @project = project - end - - it 'uses the instance variable' do - expect(link_to_label(label)).to match %r{} + context 'without subject' do + it "uses the label's project" do + expect(link_to_label(label)).to match %r{.*} end end - context 'without @project set' do - it "uses the label's project" do - expect(link_to_label(label)).to match %r{.*} + context 'with a project as subject' do + let(:namespace) { build(:namespace, name: 'foo3') } + let(:another_project) { build(:empty_project, namespace: namespace, name: 'bar3') } + + it 'links to project issues page' do + expect(link_to_label(label, subject: another_project)).to match %r{.*} end end - context 'with a project argument' do - let(:another_project) { double('project', namespace: 'foo3', to_param: 'bar3') } + context 'with a group as subject' do + let(:group) { build(:group, name: 'bar') } - it 'links to merge requests page' do - expect(link_to_label(label, project: another_project)).to match %r{.*} + it 'links to group issues page' do + expect(link_to_label(label, subject: group)).to match %r{.*} end end -- cgit v1.2.1 From e00c739f975672eaba474824436ec70d979e1fcc Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 26 Sep 2016 23:36:31 -0300 Subject: Add Label attributes: type, and group_id to safe model attributes --- spec/lib/gitlab/import_export/safe_model_attributes.yml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 8c8be66df9f..26049914bac 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -64,7 +64,9 @@ Label: - id - title - color +- group_id - project_id +- type - created_at - updated_at - template -- cgit v1.2.1 From 1644276bac361c43a56936cbbadef2a15fe646a6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 27 Sep 2016 23:57:41 -0300 Subject: Add tests to LabelsFinder --- spec/finders/labels_finder_spec.rb | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 spec/finders/labels_finder_spec.rb (limited to 'spec') diff --git a/spec/finders/labels_finder_spec.rb b/spec/finders/labels_finder_spec.rb new file mode 100644 index 00000000000..27acc464ea2 --- /dev/null +++ b/spec/finders/labels_finder_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +describe LabelsFinder do + describe '#execute' do + let(:group_1) { create(:group) } + let(:group_2) { create(:group) } + let(:group_3) { create(:group) } + + let(:project_1) { create(:empty_project, namespace: group_1) } + let(:project_2) { create(:empty_project, namespace: group_2) } + let(:project_3) { create(:empty_project) } + let(:project_4) { create(:empty_project, :public) } + let(:project_5) { create(:empty_project, namespace: group_1) } + + let!(:project_label_1) { create(:label, project: project_1, title: 'Label 1') } + let!(:project_label_2) { create(:label, project: project_2, title: 'Label 2') } + let!(:project_label_4) { create(:label, project: project_4, title: 'Label 4') } + let!(:project_label_5) { create(:label, project: project_5, title: 'Label 5') } + + let!(:group_label_1) { create(:group_label, group: group_1, title: 'Label 1') } + let!(:group_label_2) { create(:group_label, group: group_1, title: 'Group Label 2') } + let!(:group_label_3) { create(:group_label, group: group_2, title: 'Group Label 3') } + + let(:user) { create(:user) } + + before do + create(:label, project: project_3, title: 'Label 3') + create(:group_label, group: group_3, title: 'Group Label 4') + + project_1.team << [user, :developer] + end + + context 'with no filter' do + it 'returns labels from projects the user have access' do + group_2.add_developer(user) + + finder = described_class.new(user) + + expect(finder.execute).to eq [group_label_2, group_label_3, project_label_1, group_label_1, project_label_2, project_label_4] + end + end + + context 'filtering by group_id' do + it 'returns labels available for any project within the group' do + group_1.add_developer(user) + + finder = described_class.new(user, group_id: group_1.id) + + expect(finder.execute).to eq [group_label_2, project_label_1, group_label_1, project_label_5] + end + end + + context 'filtering by project_id' do + it 'returns labels available for the project' do + finder = described_class.new(user, project_id: project_1.id) + + expect(finder.execute).to eq [group_label_2, project_label_1, group_label_1] + end + end + + context 'filtering by title' do + it 'returns label with that title' do + finder = described_class.new(user, title: 'Group Label 2') + + expect(finder.execute).to eq [group_label_2] + end + end + end +end -- cgit v1.2.1 From fd0ba37276f6246c4095c4879bf9e1186f7c5ad8 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 28 Sep 2016 11:23:42 -0300 Subject: Update project test file for project import integration test --- .../import_export/test_project_export.tar.gz | Bin 1363770 -> 680875 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz index d04bdea0fe4..50b42bcec13 100644 Binary files a/spec/features/projects/import_export/test_project_export.tar.gz and b/spec/features/projects/import_export/test_project_export.tar.gz differ -- cgit v1.2.1 From 07709c5576a06179c5365b0d7fe154c5f67ca7e5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 29 Sep 2016 00:21:47 -0300 Subject: Unfold references for group labels when moving issue to another project --- .../banzai/filter/label_reference_filter_spec.rb | 82 ++++++++++++++++++++++ spec/lib/gitlab/gfm/reference_rewriter_spec.rb | 26 ++++++- spec/models/group_label_spec.rb | 28 ++++++++ spec/models/label_spec.rb | 46 ------------ spec/models/project_label_spec.rb | 46 ++++++++++++ 5 files changed, 179 insertions(+), 49 deletions(-) (limited to 'spec') diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb index 908ccebbf87..9c09f00ae8a 100644 --- a/spec/lib/banzai/filter/label_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb @@ -305,6 +305,58 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do end end + describe 'group label references' do + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:group_label) { create(:group_label, name: 'gfm references', group: group) } + + context 'without project reference' do + let(:reference) { group_label.to_reference(format: :name) } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}", project: project) + + expect(doc.css('a').first.attr('href')).to eq urls. + namespace_project_issues_url(project.namespace, project, label_name: group_label.name) + expect(doc.text).to eq 'See gfm references' + end + + it 'links with adjacent text' do + doc = reference_filter("Label (#{reference}.)") + expect(doc.to_html).to match(%r(\(#{group_label.name}\.\))) + end + + it 'ignores invalid label names' do + exp = act = %(Label #{Label.reference_prefix}"#{group_label.name.reverse}") + + expect(reference_filter(act).to_html).to eq exp + end + end + + context 'with project reference' do + let(:reference) { project.to_reference + group_label.to_reference(format: :name) } + + it 'links to a valid reference' do + doc = reference_filter("See #{reference}", project: project) + + expect(doc.css('a').first.attr('href')).to eq urls. + namespace_project_issues_url(project.namespace, project, label_name: group_label.name) + expect(doc.text).to eq 'See gfm references' + end + + it 'links with adjacent text' do + doc = reference_filter("Label (#{reference}.)") + expect(doc.to_html).to match(%r(\(#{group_label.name}\.\))) + end + + it 'ignores invalid label names' do + exp = act = %(Label #{project.to_reference}#{Label.reference_prefix}"#{group_label.name.reverse}") + + expect(reference_filter(act).to_html).to eq exp + end + end + end + describe 'cross project label references' do context 'valid project referenced' do let(:another_project) { create(:empty_project, :public) } @@ -339,4 +391,34 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do end end end + + describe 'cross group label references' do + context 'valid project referenced' do + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:another_group) { create(:group) } + let(:another_project) { create(:empty_project, :public, namespace: another_group) } + let(:project_name) { another_project.name_with_namespace } + let(:group_label) { create(:group_label, group: another_group, color: '#00ff00') } + let(:reference) { another_project.to_reference + group_label.to_reference } + + let!(:result) { reference_filter("See #{reference}", project: project) } + + it 'points to referenced project issues page' do + expect(result.css('a').first.attr('href')) + .to eq urls.namespace_project_issues_url(another_project.namespace, + another_project, + label_name: group_label.name) + end + + it 'has valid color' do + expect(result.css('a span').first.attr('style')) + .to match /background-color: #00ff00/ + end + + it 'contains cross project content' do + expect(result.css('a').first.text).to eq "#{group_label.name} in #{project_name}" + end + end + end end diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index 0af249d8690..f045463c1cb 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe Gitlab::Gfm::ReferenceRewriter do let(:text) { 'some text' } - let(:old_project) { create(:project) } - let(:new_project) { create(:project) } + let(:old_project) { create(:project, name: 'old') } + let(:new_project) { create(:project, name: 'new') } let(:user) { create(:user) } before { old_project.team << [user, :guest] } @@ -62,7 +62,7 @@ describe Gitlab::Gfm::ReferenceRewriter do it { is_expected.to eq "#{ref}, `#1`, #{ref}, `#1`" } end - context 'description with labels' do + context 'description with project labels' do let!(:label) { create(:label, id: 123, name: 'test', project: old_project) } let(:project_ref) { old_project.to_reference } @@ -76,6 +76,26 @@ describe Gitlab::Gfm::ReferenceRewriter do it { is_expected.to eq %Q{#{project_ref}#1 and #{project_ref}~123} } end end + + context 'description with group labels' do + let(:old_group) { create(:group) } + let!(:group_label) { create(:group_label, id: 321, name: 'group label', group: old_group) } + let(:project_ref) { old_project.to_reference } + + before do + old_project.update(namespace: old_group) + end + + context 'label referenced by id' do + let(:text) { '#1 and ~321' } + it { is_expected.to eq %Q{#{project_ref}#1 and #{project_ref}~321} } + end + + context 'label referenced by text' do + let(:text) { '#1 and ~"group label"' } + it { is_expected.to eq %Q{#{project_ref}#1 and #{project_ref}~321} } + end + end end context 'reference contains milestone' do diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb index a82d23bcc0b..92b07a3cd44 100644 --- a/spec/models/group_label_spec.rb +++ b/spec/models/group_label_spec.rb @@ -8,4 +8,32 @@ describe GroupLabel, models: true do describe 'validations' do it { is_expected.to validate_presence_of(:group) } end + + describe '#to_reference' do + let(:label) { create(:group_label) } + + context 'using id' do + it 'returns a String reference to the object' do + expect(label.to_reference).to eq "~#{label.id}" + end + end + + context 'using name' do + it 'returns a String reference to the object' do + expect(label.to_reference(format: :name)).to eq %(~"#{label.name}") + end + + it 'uses id when name contains double quote' do + label = create(:label, name: %q{"irony"}) + expect(label.to_reference(format: :name)).to eq "~#{label.id}" + end + end + + context 'using invalid format' do + it 'raises error' do + expect { label.to_reference(format: :invalid) } + .to raise_error StandardError, /Unknown format/ + end + end + end end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index ab640e216cf..c6e1ea19987 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -45,50 +45,4 @@ describe Label, models: true do expect(label.title).to eq('foo & bar?') end end - - describe '#to_reference' do - let(:label) { create(:label) } - - context 'using id' do - it 'returns a String reference to the object' do - expect(label.to_reference).to eq "~#{label.id}" - end - end - - context 'using name' do - it 'returns a String reference to the object' do - expect(label.to_reference(format: :name)).to eq %(~"#{label.name}") - end - - it 'uses id when name contains double quote' do - label = create(:label, name: %q{"irony"}) - expect(label.to_reference(format: :name)).to eq "~#{label.id}" - end - end - - context 'using invalid format' do - it 'raises error' do - expect { label.to_reference(format: :invalid) } - .to raise_error StandardError, /Unknown format/ - end - end - - context 'cross project reference' do - let(:project) { create(:project) } - - context 'using name' do - it 'returns cross reference with label name' do - expect(label.to_reference(project, format: :name)) - .to eq %Q(#{label.project.to_reference}~"#{label.name}") - end - end - - context 'using id' do - it 'returns cross reference with label id' do - expect(label.to_reference(project, format: :id)) - .to eq %Q(#{label.project.to_reference}~#{label.id}) - end - end - end - end end diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index 355bb2a938c..7966c52c38d 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -42,4 +42,50 @@ describe ProjectLabel, models: true do end end end + + describe '#to_reference' do + let(:label) { create(:label) } + + context 'using id' do + it 'returns a String reference to the object' do + expect(label.to_reference).to eq "~#{label.id}" + end + end + + context 'using name' do + it 'returns a String reference to the object' do + expect(label.to_reference(format: :name)).to eq %(~"#{label.name}") + end + + it 'uses id when name contains double quote' do + label = create(:label, name: %q{"irony"}) + expect(label.to_reference(format: :name)).to eq "~#{label.id}" + end + end + + context 'using invalid format' do + it 'raises error' do + expect { label.to_reference(format: :invalid) } + .to raise_error StandardError, /Unknown format/ + end + end + + context 'cross project reference' do + let(:project) { create(:project) } + + context 'using name' do + it 'returns cross reference with label name' do + expect(label.to_reference(project, format: :name)) + .to eq %Q(#{label.project.to_reference}~"#{label.name}") + end + end + + context 'using id' do + it 'returns cross reference with label id' do + expect(label.to_reference(project, format: :id)) + .to eq %Q(#{label.project.to_reference}~#{label.id}) + end + end + end + end end -- cgit v1.2.1 From 0bfa39d5bdb9f53bfc319b9351230b3eb405b619 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 29 Sep 2016 01:03:28 -0300 Subject: Remove scopes/types for labels --- .../controllers/projects/labels_controller_spec.rb | 38 ++++------------------ .../projects/labels/update_prioritization_spec.rb | 10 +++--- 2 files changed, 11 insertions(+), 37 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 2b39f9cf0d1..29251f49810 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -33,55 +33,29 @@ describe Projects::LabelsController do end it 'is sorted by priority, then label title' do - expect(assigns(:prioritized_labels)).to match_array [group_label_2, label_1, label_3, group_label_1, label_2] + expect(assigns(:prioritized_labels)).to eq [group_label_2, label_1, label_3, group_label_1, label_2] end end - context '@group_labels' do - it 'contains only group labels' do - list_labels - - expect(assigns(:group_labels)).to all(have_attributes(group_id: a_value > 0)) - end - + context '@labels' do it 'contains only unprioritized labels' do list_labels - expect(assigns(:group_labels)).to all(have_attributes(priority: nil)) + expect(assigns(:labels)).to all(have_attributes(priority: nil)) end it 'is sorted by label title' do list_labels - expect(assigns(:group_labels)).to match_array [group_label_3, group_label_4] + expect(assigns(:labels)).to eq [group_label_3, group_label_4, label_4, label_5] end - it 'is nil when project does not belong to a group' do + it 'does not include group labels when project does not belong to a group' do project.update(namespace: create(:namespace)) list_labels - expect(assigns(:group_labels)).to be_nil - end - end - - context '@project_labels' do - before do - list_labels - end - - it 'contains only project labels' do - list_labels - - expect(assigns(:project_labels)).to all(have_attributes(project_id: a_value > 0)) - end - - it 'contains only unprioritized labels' do - expect(assigns(:project_labels)).to all(have_attributes(priority: nil)) - end - - it 'is sorted by label title' do - expect(assigns(:project_labels)).to match_array [label_4, label_5] + expect(assigns(:labels)).not_to include(group_label_3, group_label_4) end end diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb index 21896f0a787..84a12a38c26 100644 --- a/spec/features/projects/labels/update_prioritization_spec.rb +++ b/spec/features/projects/labels/update_prioritization_spec.rb @@ -22,8 +22,8 @@ feature 'Prioritize labels', feature: true do expect(page).to have_content('No prioritized labels yet') - page.within('.group-labels') do - first('.js-toggle-priority').click + page.within('.other-labels') do + all('.js-toggle-priority')[1].click wait_for_ajax expect(page).not_to have_content('feature') end @@ -47,7 +47,7 @@ feature 'Prioritize labels', feature: true do expect(page).not_to have_content('bug') end - page.within('.group-labels') do + page.within('.other-labels') do expect(page).to have_content('feature') end end @@ -57,7 +57,7 @@ feature 'Prioritize labels', feature: true do expect(page).to have_content('No prioritized labels yet') - page.within('.project-labels') do + page.within('.other-labels') do first('.js-toggle-priority').click wait_for_ajax expect(page).not_to have_content('bug') @@ -82,7 +82,7 @@ feature 'Prioritize labels', feature: true do expect(page).not_to have_content('bug') end - page.within('.project-labels') do + page.within('.other-labels') do expect(page).to have_content('bug') expect(page).to have_content('wontfix') end -- cgit v1.2.1 From 848a146fc3bd34ec94a206f2ed6ef33d539bfce5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 29 Sep 2016 09:51:12 +0200 Subject: Fix import test --- .../import_export/test_project_export.tar.gz | Bin 680875 -> 680856 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz index 50b42bcec13..8f683cf89aa 100644 Binary files a/spec/features/projects/import_export/test_project_export.tar.gz and b/spec/features/projects/import_export/test_project_export.tar.gz differ -- cgit v1.2.1 From 77b7bfd463bf57d38cb6aa30f277cd19ffbb6504 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 29 Sep 2016 13:15:18 +0200 Subject: Fix import/export labels to cope with project and group labels. Added relevant specs. --- spec/lib/gitlab/import_export/project.json | 27 ++++++++++++++++++-- .../import_export/project_tree_restorer_spec.rb | 29 +++++++++++++++++++++- .../import_export/project_tree_saver_spec.rb | 16 +++++++++--- 3 files changed, 66 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 98323fe6be4..bf9dc279f7d 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -64,7 +64,29 @@ "updated_at": "2016-07-22T08:55:44.161Z", "template": false, "description": "", - "priority": null + "priority": null, + "type": "ProjectLabel" + } + }, + { + "id": 3, + "label_id": 3, + "target_id": 40, + "target_type": "Issue", + "created_at": "2016-07-22T08:57:02.841Z", + "updated_at": "2016-07-22T08:57:02.841Z", + "label": { + "id": 3, + "title": "test3", + "color": "#428bca", + "group_id": 8, + "created_at": "2016-07-22T08:55:44.161Z", + "updated_at": "2016-07-22T08:55:44.161Z", + "template": false, + "description": "", + "priority": null, + "project_id": null, + "type": "GroupLabel" } } ], @@ -536,7 +558,8 @@ "updated_at": "2016-07-22T08:55:44.161Z", "template": false, "description": "", - "priority": null + "priority": null, + "type": "ProjectLabel" } } ], diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 7582a732cdf..365d08940ba 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -32,7 +32,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do it 'has the same label associated to two issues' do restored_project_json - expect(Label.first.issues.count).to eq(2) + expect(ProjectLabel.find_by_title('test2').issues.count).to eq(2) end it 'has milestones associated to two separate issues' do @@ -107,6 +107,33 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(Label.first.label_links.first.target).not_to be_nil end + it 'has project labels' do + restored_project_json + + expect(ProjectLabel.count).to eq(2) + end + + it 'has no group labels' do + restored_project_json + + expect(GroupLabel.count).to eq(0) + end + + context 'with group' do + let!(:project) { create(:empty_project, + name: 'project', + path: 'project', + builds_access_level: ProjectFeature::DISABLED, + issues_access_level: ProjectFeature::DISABLED, + group: create(:group)) } + + it 'has group labels' do + restored_project_json + + expect(GroupLabel.count).to eq(1) + end + end + it 'has a project feature' do restored_project_json diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index cf8f2200c57..9a8ba61559b 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -111,6 +111,12 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do expect(saved_project_json['issues'].first['label_links'].first['label']).not_to be_empty end + it 'has project and group labels' do + label_types = saved_project_json['issues'].first['label_links'].map { |link| link['label']['type']} + + expect(label_types).to match(['ProjectLabel', 'GroupLabel']) + end + it 'saves the correct service type' do expect(saved_project_json['services'].first['type']).to eq('CustomIssueTrackerService') end @@ -135,15 +141,19 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do issue = create(:issue, assignee: user) snippet = create(:project_snippet) release = create(:release) + group = create(:group) project = create(:project, :public, issues: [issue], snippets: [snippet], - releases: [release] + releases: [release], + group: group ) - label = create(:label, project: project) - create(:label_link, label: label, target: issue) + project_label = create(:label, project: project) + group_label = create(:group_label, group: group) + create(:label_link, label: project_label, target: issue) + create(:label_link, label: group_label, target: issue) milestone = create(:milestone, project: project) merge_request = create(:merge_request, source_project: project, milestone: milestone) commit_status = create(:commit_status, project: project) -- cgit v1.2.1 From 723e576782aefa339a4db8916908c7ebe5a92f48 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 29 Sep 2016 15:06:10 +0200 Subject: fix rubocop warning --- spec/lib/gitlab/import_export/project_tree_restorer_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 365d08940ba..6312b990a66 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -120,12 +120,14 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do end context 'with group' do - let!(:project) { create(:empty_project, + let!(:project) do + create(:empty_project, name: 'project', path: 'project', builds_access_level: ProjectFeature::DISABLED, issues_access_level: ProjectFeature::DISABLED, - group: create(:group)) } + group: create(:group)) + end it 'has group labels' do restored_project_json -- cgit v1.2.1 From 7e11ca86fdb23c967c25b19735770f99f936b32c Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 3 Oct 2016 18:41:46 -0300 Subject: Reuse LabelsFinder on Issueable#add_labels_by_names --- spec/lib/gitlab/google_code_import/importer_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/google_code_import/importer_spec.rb b/spec/lib/gitlab/google_code_import/importer_spec.rb index 54f85f8cffc..097861fd34d 100644 --- a/spec/lib/gitlab/google_code_import/importer_spec.rb +++ b/spec/lib/gitlab/google_code_import/importer_spec.rb @@ -15,6 +15,7 @@ describe Gitlab::GoogleCodeImport::Importer, lib: true do subject { described_class.new(project) } before do + project.team << [project.creator, :master] project.create_import_data(data: import_data) end @@ -31,9 +32,9 @@ describe Gitlab::GoogleCodeImport::Importer, lib: true do subject.execute %w( - Type-Defect Type-Enhancement Type-Task Type-Review Type-Other Milestone-0.12 Priority-Critical - Priority-High Priority-Medium Priority-Low OpSys-All OpSys-Windows OpSys-Linux OpSys-OSX Security - Performance Usability Maintainability Component-Panel Component-Taskbar Component-Battery + Type-Defect Type-Enhancement Type-Task Type-Review Type-Other Milestone-0.12 Priority-Critical + Priority-High Priority-Medium Priority-Low OpSys-All OpSys-Windows OpSys-Linux OpSys-OSX Security + Performance Usability Maintainability Component-Panel Component-Taskbar Component-Battery Component-Systray Component-Clock Component-Launcher Component-Tint2conf Component-Docs Component-New ).each do |label| label.sub!("-", ": ") -- cgit v1.2.1 From cece77f273407da4a9ed66acda53e9ac4117dbaf Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 13 Oct 2016 17:45:39 -0300 Subject: Fix validation to allow updates to description/color of project label --- spec/models/project_label_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index 7966c52c38d..c861d4b73bb 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -40,6 +40,16 @@ describe ProjectLabel, models: true do expect(label.errors[:title]).to be_empty end + + it 'does not returns error when title does not change' do + project_label = create(:label, project: project, name: 'Security') + create(:group_label, group: group, name: 'Security') + project_label.description = 'Security related stuff.' + + project_label.valid? + + expect(project_label .errors[:title]).to be_empty + end end end -- cgit v1.2.1 From 68f30b2fff362805568588f416709e7000d75ce3 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 13 Oct 2016 18:48:59 -0300 Subject: Add support to group labels on issues board API --- spec/requests/api/boards_spec.rb | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb index f4b04445c6c..4f5c09a3029 100644 --- a/spec/requests/api/boards_spec.rb +++ b/spec/requests/api/boards_spec.rb @@ -106,9 +106,20 @@ describe API::API, api: true do describe "POST /projects/:id/board/lists" do let(:base_url) { "/projects/#{project.id}/boards/#{board.id}/lists" } - it 'creates a new issue board list' do - post api(base_url, user), - label_id: ux_label.id + it 'creates a new issue board list for group labels' do + group = create(:group) + group_label = create(:group_label, group: group) + project.update(group: group) + + post api(base_url, user), label_id: group_label.id + + expect(response).to have_http_status(201) + expect(json_response['label']['name']).to eq(group_label.title) + expect(json_response['position']).to eq(3) + end + + it 'creates a new issue board list for project labels' do + post api(base_url, user), label_id: ux_label.id expect(response).to have_http_status(201) expect(json_response['label']['name']).to eq(ux_label.title) @@ -116,15 +127,13 @@ describe API::API, api: true do end it 'returns 400 when creating a new list if label_id is invalid' do - post api(base_url, user), - label_id: 23423 + post api(base_url, user), label_id: 23423 expect(response).to have_http_status(400) end - it "returns 403 for project members with guest role" do - put api("#{base_url}/#{test_list.id}", guest), - position: 1 + it 'returns 403 for project members with guest role' do + put api("#{base_url}/#{test_list.id}", guest), position: 1 expect(response).to have_http_status(403) end -- cgit v1.2.1 From 9b288238549dac5b59fd467f6ee1fdc53b6c783e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 13 Oct 2016 18:53:06 -0300 Subject: List all available labels to the project on the labels API --- spec/requests/api/labels_spec.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 83789223019..1da9988978b 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -12,12 +12,18 @@ describe API::API, api: true do end describe 'GET /projects/:id/labels' do - it 'returns project labels' do + it 'returns all available labels to the project' do + group = create(:group) + group_label = create(:group_label, group: group) + project.update(group: group) + get api("/projects/#{project.id}/labels", user) + expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first['name']).to eq(label1.name) + expect(json_response.size).to eq(2) + expect(json_response.first['name']).to eq(group_label.name) + expect(json_response.second['name']).to eq(label1.name) end end -- cgit v1.2.1 From 297892011330ecdd2fa7cbe47fbc6fd4f3b62171 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 14 Oct 2016 16:12:07 -0300 Subject: Add LabelPriority model --- spec/factories/label_priorities.rb | 7 +++++++ spec/models/label_priority_spec.rb | 21 +++++++++++++++++++++ spec/models/label_spec.rb | 1 + 3 files changed, 29 insertions(+) create mode 100644 spec/factories/label_priorities.rb create mode 100644 spec/models/label_priority_spec.rb (limited to 'spec') diff --git a/spec/factories/label_priorities.rb b/spec/factories/label_priorities.rb new file mode 100644 index 00000000000..f25939d2d3e --- /dev/null +++ b/spec/factories/label_priorities.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :label_priority do + project factory: :empty_project + label + sequence(:priority) + end +end diff --git a/spec/models/label_priority_spec.rb b/spec/models/label_priority_spec.rb new file mode 100644 index 00000000000..5f7fa3aa047 --- /dev/null +++ b/spec/models/label_priority_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe LabelPriority, models: true do + describe 'relationships' do + it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:label) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:label) } + it { is_expected.to validate_presence_of(:priority) } + it { is_expected.to validate_numericality_of(:priority).only_integer.is_greater_than_or_equal_to(0) } + + it 'validates uniqueness of label_id scoped to project_id' do + create(:label_priority) + + expect(subject).to validate_uniqueness_of(:label_id).scoped_to(:project_id) + end + end +end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index c6e1ea19987..4af0fb6afa9 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -10,6 +10,7 @@ describe Label, models: true do it { is_expected.to have_many(:issues).through(:label_links).source(:target) } it { is_expected.to have_many(:label_links).dependent(:destroy) } it { is_expected.to have_many(:lists).dependent(:destroy) } + it { is_expected.to have_many(:priorities).class_name('LabelPriority') } end describe 'validation' do -- cgit v1.2.1 From 67314e95ae836365fa1989439a6379aac781a0b4 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 14 Oct 2016 18:32:44 -0300 Subject: Add support to group labels prioritization on project level --- spec/features/projects/labels/update_prioritization_spec.rb | 8 ++++---- spec/models/label_priority_spec.rb | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/labels/update_prioritization_spec.rb b/spec/features/projects/labels/update_prioritization_spec.rb index 84a12a38c26..c9fa8315e79 100644 --- a/spec/features/projects/labels/update_prioritization_spec.rb +++ b/spec/features/projects/labels/update_prioritization_spec.rb @@ -35,7 +35,7 @@ feature 'Prioritize labels', feature: true do end scenario 'user can unprioritize a group label', js: true do - feature.update(priority: 1) + create(:label_priority, project: project, label: feature, priority: 1) visit namespace_project_labels_path(project.namespace, project) @@ -70,7 +70,7 @@ feature 'Prioritize labels', feature: true do end scenario 'user can unprioritize a project label', js: true do - bug.update(priority: 1) + create(:label_priority, project: project, label: bug, priority: 1) visit namespace_project_labels_path(project.namespace, project) @@ -89,8 +89,8 @@ feature 'Prioritize labels', feature: true do end scenario 'user can sort prioritized labels and persist across reloads', js: true do - bug.update(priority: 1) - feature.update(priority: 2) + create(:label_priority, project: project, label: bug, priority: 1) + create(:label_priority, project: project, label: feature, priority: 2) visit namespace_project_labels_path(project.namespace, project) diff --git a/spec/models/label_priority_spec.rb b/spec/models/label_priority_spec.rb index 5f7fa3aa047..d18c2f7949a 100644 --- a/spec/models/label_priority_spec.rb +++ b/spec/models/label_priority_spec.rb @@ -9,7 +9,6 @@ describe LabelPriority, models: true do describe 'validations' do it { is_expected.to validate_presence_of(:project) } it { is_expected.to validate_presence_of(:label) } - it { is_expected.to validate_presence_of(:priority) } it { is_expected.to validate_numericality_of(:priority).only_integer.is_greater_than_or_equal_to(0) } it 'validates uniqueness of label_id scoped to project_id' do -- cgit v1.2.1 From 99e928f103182b58156edb107b55344eaafc6772 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 14 Oct 2016 18:51:34 -0300 Subject: Add restriction to number of permitted priorities per project label --- spec/models/project_label_spec.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index c861d4b73bb..cd4732fb737 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -48,7 +48,18 @@ describe ProjectLabel, models: true do project_label.valid? - expect(project_label .errors[:title]).to be_empty + expect(project_label.errors[:title]).to be_empty + end + end + + context 'when attempting to add more than one priority to the project label' do + it 'returns error' do + subject.priorities.build + subject.priorities.build + + subject.valid? + + expect(subject.errors[:priorities]).to include 'Number of permitted priorities exceeded' end end end -- cgit v1.2.1 From 3c2aaec1f2624ad4817e7ac52120985682afa448 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 14 Oct 2016 20:06:26 -0300 Subject: Fix sorting by label priorities --- .../controllers/projects/labels_controller_spec.rb | 31 +++++++++++++--------- spec/factories/labels.rb | 10 +++++++ 2 files changed, 29 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 29251f49810..622ab154493 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -15,21 +15,28 @@ describe Projects::LabelsController do let!(:label_1) { create(:label, project: project, priority: 1, title: 'Label 1') } let!(:label_2) { create(:label, project: project, priority: 3, title: 'Label 2') } let!(:label_3) { create(:label, project: project, priority: 1, title: 'Label 3') } - let!(:label_4) { create(:label, project: project, priority: nil, title: 'Label 4') } - let!(:label_5) { create(:label, project: project, priority: nil, title: 'Label 5') } + let!(:label_4) { create(:label, project: project, title: 'Label 4') } + let!(:label_5) { create(:label, project: project, title: 'Label 5') } - let!(:group_label_1) { create(:group_label, group: group, priority: 3, title: 'Group Label 1') } - let!(:group_label_2) { create(:group_label, group: group, priority: 1, title: 'Group Label 2') } - let!(:group_label_3) { create(:group_label, group: group, priority: nil, title: 'Group Label 3') } - let!(:group_label_4) { create(:group_label, group: group, priority: nil, title: 'Group Label 4') } + let!(:group_label_1) { create(:group_label, group: group, title: 'Group Label 1') } + let!(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') } + let!(:group_label_3) { create(:group_label, group: group, title: 'Group Label 3') } + let!(:group_label_4) { create(:group_label, group: group, title: 'Group Label 4') } + + before do + create(:label_priority, project: project, label: group_label_1, priority: 3) + create(:label_priority, project: project, label: group_label_2, priority: 1) + end context '@prioritized_labels' do before do list_labels end - it 'contains only prioritized labels' do - expect(assigns(:prioritized_labels)).to all(have_attributes(priority: a_value > 0)) + it 'does not include labels without priority' do + list_labels + + expect(assigns(:prioritized_labels)).not_to include(group_label_3, group_label_4, label_4, label_5) end it 'is sorted by priority, then label title' do @@ -38,16 +45,16 @@ describe Projects::LabelsController do end context '@labels' do - it 'contains only unprioritized labels' do + it 'is sorted by label title' do list_labels - expect(assigns(:labels)).to all(have_attributes(priority: nil)) + expect(assigns(:labels)).to eq [group_label_3, group_label_4, label_4, label_5] end - it 'is sorted by label title' do + it 'does not include labels with priority' do list_labels - expect(assigns(:labels)).to eq [group_label_3, group_label_4, label_4, label_5] + expect(assigns(:labels)).not_to include(group_label_2, label_1, label_3, group_label_1, label_2) end it 'does not include group labels when project does not belong to a group' do diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb index 5c789d72bac..3e8822faf97 100644 --- a/spec/factories/labels.rb +++ b/spec/factories/labels.rb @@ -3,6 +3,16 @@ FactoryGirl.define do sequence(:title) { |n| "label#{n}" } color "#990000" project + + transient do + priority nil + end + + after(:create) do |label, evaluator| + if evaluator.priority + label.priorities.create(project: label.project, priority: evaluator.priority) + end + end end factory :group_label, class: GroupLabel do -- cgit v1.2.1 From 86e0b5d643df21503281115774da550e06a4e878 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 14 Oct 2016 20:51:41 -0300 Subject: Fix issue board related controllers to expose label priority per project --- spec/fixtures/api/schemas/list.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/fixtures/api/schemas/list.json b/spec/fixtures/api/schemas/list.json index f070fa3b254..8d94cf26ecb 100644 --- a/spec/fixtures/api/schemas/list.json +++ b/spec/fixtures/api/schemas/list.json @@ -13,7 +13,7 @@ "enum": ["backlog", "label", "done"] }, "label": { - "type": ["object"], + "type": ["object", "null"], "required": [ "id", "color", -- cgit v1.2.1 From 530aae9080942646b130510e970d9d82c009d8e5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 17 Oct 2016 16:34:22 -0200 Subject: Abstract LabelPriority away into methods on Label model --- spec/models/label_spec.rb | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'spec') diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 4af0fb6afa9..0c163659a71 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -46,4 +46,62 @@ describe Label, models: true do expect(label.title).to eq('foo & bar?') end end + + describe 'priorization' do + subject(:label) { create(:label) } + + let(:project) { label.project } + + describe '#prioritize!' do + context 'when label is not prioritized' do + it 'creates a label priority' do + expect { label.prioritize!(project, 1) }.to change(label.priorities, :count).by(1) + end + + it 'sets label priority' do + label.prioritize!(project, 1) + + expect(label.priorities.first.priority).to eq 1 + end + end + + context 'when label is prioritized' do + let!(:priority) { create(:label_priority, project: project, label: label, priority: 0) } + + it 'does not create a label priority' do + expect { label.prioritize!(project, 1) }.not_to change(label.priorities, :count) + end + + it 'updates label priority' do + label.prioritize!(project, 1) + + expect(priority.reload.priority).to eq 1 + end + end + end + + describe '#unprioritize!' do + it 'removes label priority' do + create(:label_priority, project: project, label: label, priority: 0) + + expect { label.unprioritize!(project) }.to change(label.priorities, :count).by(-1) + end + end + + describe '#priority' do + context 'when label is not prioritized' do + it 'returns nil' do + expect(label.priority(project)).to be_nil + end + end + + context 'when label is prioritized' do + it 'returns label priority' do + create(:label_priority, project: project, label: label, priority: 1) + + expect(label.priority(project)).to eq 1 + end + end + end + end end -- cgit v1.2.1 From 8379fbcd47930320bf4dd6a3ac41c6efd427a91a Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 17 Oct 2016 17:48:46 -0200 Subject: Add subject to group and projects labels which return group/project --- spec/models/group_label_spec.rb | 8 ++++++++ spec/models/project_label_spec.rb | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'spec') diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb index 92b07a3cd44..85eb889225b 100644 --- a/spec/models/group_label_spec.rb +++ b/spec/models/group_label_spec.rb @@ -9,6 +9,14 @@ describe GroupLabel, models: true do it { is_expected.to validate_presence_of(:group) } end + describe '#subject' do + it 'aliases group to subject' do + subject = described_class.new(group: build(:group)) + + expect(subject.subject).to be(subject.group) + end + end + describe '#to_reference' do let(:label) { create(:group_label) } diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index cd4732fb737..18c9d449ee5 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -64,6 +64,14 @@ describe ProjectLabel, models: true do end end + describe '#subject' do + it 'aliases project to subject' do + subject = described_class.new(project: build(:empty_project)) + + expect(subject.subject).to be(subject.project) + end + end + describe '#to_reference' do let(:label) { create(:label) } -- cgit v1.2.1 From 49ec98d1b2ca6f57f3f9434a0be0018fa5a53681 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 17 Oct 2016 22:39:21 -0200 Subject: Recreates the label priorities when moving project to another group --- spec/services/labels/transfer_service_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/services/labels/transfer_service_spec.rb b/spec/services/labels/transfer_service_spec.rb index a72a05f6c99..cb09c16698a 100644 --- a/spec/services/labels/transfer_service_spec.rb +++ b/spec/services/labels/transfer_service_spec.rb @@ -26,6 +26,16 @@ describe Labels::TransferService, services: true do expect { service.execute }.to change(project.labels, :count).by(2) end + it 'recreates label priorities related to the missing group labels' do + create(:label_priority, project: project, label: group_label_1, priority: 1) + + service.execute + + new_project_label = project.labels.find_by(title: group_label_1.title) + expect(new_project_label.id).not_to eq group_label_1.id + expect(new_project_label.priorities).not_to be_empty + end + it 'does not recreate missing group labels that are not applied to issues or merge requests' do service.execute -- cgit v1.2.1 From 6c189dcc8e76d5ddb348832500b003bf0d1b49a6 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 18 Oct 2016 00:11:33 -0200 Subject: Add service to create project labels --- spec/services/labels/create_service_spec.rb | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 spec/services/labels/create_service_spec.rb (limited to 'spec') diff --git a/spec/services/labels/create_service_spec.rb b/spec/services/labels/create_service_spec.rb new file mode 100644 index 00000000000..1e4bc294b46 --- /dev/null +++ b/spec/services/labels/create_service_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe Labels::CreateService, services: true do + describe '#execute' do + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:project) { create(:project, namespace: group) } + + let(:params) do + { + title: 'Security', + description: 'Security related stuff.', + color: '#FF0000' + } + end + + subject(:service) { described_class.new(user, project, params) } + + before do + project.team << [user, :developer] + end + + context 'when label does not exist at group level' do + it 'creates a new label at project level' do + expect { service.execute }.to change(project.labels, :count).by(1) + end + end + + context 'when label exists at group level' do + it 'returns the group label' do + group_label = create(:group_label, group: group, title: 'Security') + + expect(service.execute).to eq group_label + end + end + + context 'when label does not exist at group level' do + it 'creates a new label at project leve' do + expect { service.execute }.to change(project.labels, :count).by(1) + end + end + + context 'when label exists at project level' do + it 'returns the project label' do + project_label = create(:label, project: project, title: 'Security') + + expect(service.execute).to eq project_label + end + end + end +end -- cgit v1.2.1 From f0ad0ceff5236f3ee5babee47bfec217a54c3b07 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 18 Oct 2016 06:26:16 -0200 Subject: Fix GitHub importer spec --- spec/lib/gitlab/github_import/importer_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/importer_spec.rb b/spec/lib/gitlab/github_import/importer_spec.rb index 8854c8431b5..1af553f8f03 100644 --- a/spec/lib/gitlab/github_import/importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer_spec.rb @@ -157,7 +157,7 @@ describe Gitlab::GithubImport::Importer, lib: true do { type: :pull_request, url: "https://api.github.com/repos/octocat/Hello-World/pulls/1347", errors: "Validation failed: Validate branches Cannot Create: This merge request already exists: [\"New feature\"]" }, { type: :wiki, errors: "Gitlab::Shell::Error" }, { type: :release, url: 'https://api.github.com/repos/octocat/Hello-World/releases/2', errors: "Validation failed: Description can't be blank" } - ] + ] } described_class.new(project).execute -- cgit v1.2.1 From 891e5f4851c2067daba12a1750651170a1583481 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 18 Oct 2016 19:31:10 +0200 Subject: Update specs to cope with new label types and priorities Fixed all related specs and also changed the logic to handle edge cases. This includes exporting and exporting of group labels, which will get associated with the new group (if any) or they will become normal project labels otherwise. Found other issues to do with not being able to import all labels at once in the beginning of the JSON - code was much simpler when we import all labels and milestones associated to a project first, then the associations will find the already created labels instead of creating them from the associations themselves. --- .../import_export/test_project_export.tar.gz | Bin 680856 -> 681774 bytes spec/lib/gitlab/import_export/all_models.yml | 3 ++ spec/lib/gitlab/import_export/project.json | 33 ++++++++++++++++----- .../import_export/project_tree_restorer_spec.rb | 6 ++++ .../import_export/project_tree_saver_spec.rb | 9 +++++- .../gitlab/import_export/safe_model_attributes.yml | 9 +++++- 6 files changed, 51 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/test_project_export.tar.gz b/spec/features/projects/import_export/test_project_export.tar.gz index 8f683cf89aa..bfe59bdb90e 100644 Binary files a/spec/features/projects/import_export/test_project_export.tar.gz and b/spec/features/projects/import_export/test_project_export.tar.gz differ diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 8fcbf12eab8..02b11bd999a 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -38,6 +38,7 @@ label: - label_links - issues - merge_requests +- priorities milestone: - project - issues @@ -186,3 +187,5 @@ project: award_emoji: - awardable - user +priorities: +- label \ No newline at end of file diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index bf9dc279f7d..ed9df468ced 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -2,6 +2,21 @@ "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", "visibility_level": 10, "archived": false, + "labels": [ + { + "id": 2, + "title": "test2", + "color": "#428bca", + "project_id": 8, + "created_at": "2016-07-22T08:55:44.161Z", + "updated_at": "2016-07-22T08:55:44.161Z", + "template": false, + "description": "", + "type": "ProjectLabel", + "priorities": [ + ] + } + ], "issues": [ { "id": 40, @@ -64,7 +79,6 @@ "updated_at": "2016-07-22T08:55:44.161Z", "template": false, "description": "", - "priority": null, "type": "ProjectLabel" } }, @@ -84,9 +98,18 @@ "updated_at": "2016-07-22T08:55:44.161Z", "template": false, "description": "", - "priority": null, "project_id": null, - "type": "GroupLabel" + "type": "GroupLabel", + "priorities": [ + { + "id": 1, + "project_id": 5, + "label_id": 1, + "priority": 1, + "created_at": "2016-10-18T09:35:43.338Z", + "updated_at": "2016-10-18T09:35:43.338Z" + } + ] } } ], @@ -558,7 +581,6 @@ "updated_at": "2016-07-22T08:55:44.161Z", "template": false, "description": "", - "priority": null, "type": "ProjectLabel" } } @@ -2249,9 +2271,6 @@ } ] } - ], - "labels": [ - ], "milestones": [ { diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 6312b990a66..069ea960321 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -134,6 +134,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(GroupLabel.count).to eq(1) end + + it 'has label priorities' do + restored_project_json + + expect(GroupLabel.first.priorities).not_to be_empty + end end it 'has a project feature' do diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index 9a8ba61559b..c8bba553558 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -114,7 +114,13 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do it 'has project and group labels' do label_types = saved_project_json['issues'].first['label_links'].map { |link| link['label']['type']} - expect(label_types).to match(['ProjectLabel', 'GroupLabel']) + expect(label_types).to match_array(['ProjectLabel', 'GroupLabel']) + end + + it 'has priorities associated to labels' do + priorities = saved_project_json['issues'].first['label_links'].map { |link| link['label']['priorities']} + + expect(priorities.flatten).not_to be_empty end it 'saves the correct service type' do @@ -154,6 +160,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do group_label = create(:group_label, group: group) create(:label_link, label: project_label, target: issue) create(:label_link, label: group_label, target: issue) + create(:label_priority, label: group_label, priority: 1) milestone = create(:milestone, project: project) merge_request = create(:merge_request, source_project: project, milestone: milestone) commit_status = create(:commit_status, project: project) diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 26049914bac..feee0f025d8 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -60,7 +60,7 @@ LabelLink: - target_type - created_at - updated_at -Label: +ProjectLabel: - id - title - color @@ -331,3 +331,10 @@ AwardEmoji: - awardable_type - created_at - updated_at +LabelPriority: +- id +- project_id +- label_id +- priority +- created_at +- updated_at \ No newline at end of file -- cgit v1.2.1 From 4f6d1c1d70d744ff599ae9c51e1cbc3a3c23e13e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 19 Oct 2016 11:53:31 -0200 Subject: Rename Labels::CreateService to Labels::FindOrCreateService --- spec/services/labels/create_service_spec.rb | 51 ---------------------- .../services/labels/find_or_create_service_spec.rb | 51 ++++++++++++++++++++++ 2 files changed, 51 insertions(+), 51 deletions(-) delete mode 100644 spec/services/labels/create_service_spec.rb create mode 100644 spec/services/labels/find_or_create_service_spec.rb (limited to 'spec') diff --git a/spec/services/labels/create_service_spec.rb b/spec/services/labels/create_service_spec.rb deleted file mode 100644 index 1e4bc294b46..00000000000 --- a/spec/services/labels/create_service_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -require 'spec_helper' - -describe Labels::CreateService, services: true do - describe '#execute' do - let(:user) { create(:user) } - let(:group) { create(:group) } - let(:project) { create(:project, namespace: group) } - - let(:params) do - { - title: 'Security', - description: 'Security related stuff.', - color: '#FF0000' - } - end - - subject(:service) { described_class.new(user, project, params) } - - before do - project.team << [user, :developer] - end - - context 'when label does not exist at group level' do - it 'creates a new label at project level' do - expect { service.execute }.to change(project.labels, :count).by(1) - end - end - - context 'when label exists at group level' do - it 'returns the group label' do - group_label = create(:group_label, group: group, title: 'Security') - - expect(service.execute).to eq group_label - end - end - - context 'when label does not exist at group level' do - it 'creates a new label at project leve' do - expect { service.execute }.to change(project.labels, :count).by(1) - end - end - - context 'when label exists at project level' do - it 'returns the project label' do - project_label = create(:label, project: project, title: 'Security') - - expect(service.execute).to eq project_label - end - end - end -end diff --git a/spec/services/labels/find_or_create_service_spec.rb b/spec/services/labels/find_or_create_service_spec.rb new file mode 100644 index 00000000000..cbfc63de811 --- /dev/null +++ b/spec/services/labels/find_or_create_service_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe Labels::FindOrCreateService, services: true do + describe '#execute' do + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:project) { create(:project, namespace: group) } + + let(:params) do + { + title: 'Security', + description: 'Security related stuff.', + color: '#FF0000' + } + end + + subject(:service) { described_class.new(user, project, params) } + + before do + project.team << [user, :developer] + end + + context 'when label does not exist at group level' do + it 'creates a new label at project level' do + expect { service.execute }.to change(project.labels, :count).by(1) + end + end + + context 'when label exists at group level' do + it 'returns the group label' do + group_label = create(:group_label, group: group, title: 'Security') + + expect(service.execute).to eq group_label + end + end + + context 'when label does not exist at group level' do + it 'creates a new label at project leve' do + expect { service.execute }.to change(project.labels, :count).by(1) + end + end + + context 'when label exists at project level' do + it 'returns the project label' do + project_label = create(:label, project: project, title: 'Security') + + expect(service.execute).to eq project_label + end + end + end +end -- cgit v1.2.1 From 1d8b74fee34af0f13e69a3363417493746279488 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 19 Oct 2016 14:47:17 -0200 Subject: Avoid touch label links that does not belongs to project when moving it --- spec/services/labels/transfer_service_spec.rb | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/services/labels/transfer_service_spec.rb b/spec/services/labels/transfer_service_spec.rb index cb09c16698a..ddf3527dc0f 100644 --- a/spec/services/labels/transfer_service_spec.rb +++ b/spec/services/labels/transfer_service_spec.rb @@ -5,33 +5,38 @@ describe Labels::TransferService, services: true do let(:user) { create(:user) } let(:group_1) { create(:group) } let(:group_2) { create(:group) } - let(:project) { create(:project, namespace: group_2) } + let(:group_3) { create(:group) } + let(:project_1) { create(:project, namespace: group_2) } + let(:project_2) { create(:project, namespace: group_3) } let(:group_label_1) { create(:group_label, group: group_1, name: 'Group Label 1') } let(:group_label_2) { create(:group_label, group: group_1, name: 'Group Label 2') } let(:group_label_3) { create(:group_label, group: group_1, name: 'Group Label 3') } let(:group_label_4) { create(:group_label, group: group_2, name: 'Group Label 4') } - let(:project_label_1) { create(:label, project: project, name: 'Project Label 1') } + let(:group_label_5) { create(:group_label, group: group_3, name: 'Group Label 5') } + let(:project_label_1) { create(:label, project: project_1, name: 'Project Label 1') } - subject(:service) { described_class.new(user, group_1, project) } + subject(:service) { described_class.new(user, group_1, project_1) } before do - create(:labeled_issue, project: project, labels: [group_label_1]) - create(:labeled_issue, project: project, labels: [group_label_4]) - create(:labeled_issue, project: project, labels: [project_label_1]) - create(:labeled_merge_request, source_project: project, labels: [group_label_1, group_label_2]) + create(:labeled_issue, project: project_1, labels: [group_label_1]) + create(:labeled_issue, project: project_1, labels: [group_label_4]) + create(:labeled_issue, project: project_1, labels: [project_label_1]) + create(:labeled_issue, project: project_2, labels: [group_label_5]) + create(:labeled_merge_request, source_project: project_1, labels: [group_label_1, group_label_2]) + create(:labeled_merge_request, source_project: project_2, labels: [group_label_5]) end it 'recreates the missing group labels at project level' do - expect { service.execute }.to change(project.labels, :count).by(2) + expect { service.execute }.to change(project_1.labels, :count).by(2) end it 'recreates label priorities related to the missing group labels' do - create(:label_priority, project: project, label: group_label_1, priority: 1) + create(:label_priority, project: project_1, label: group_label_1, priority: 1) service.execute - new_project_label = project.labels.find_by(title: group_label_1.title) + new_project_label = project_1.labels.find_by(title: group_label_1.title) expect(new_project_label.id).not_to eq group_label_1.id expect(new_project_label.priorities).not_to be_empty end @@ -39,13 +44,13 @@ describe Labels::TransferService, services: true do it 'does not recreate missing group labels that are not applied to issues or merge requests' do service.execute - expect(project.labels.where(title: group_label_3.title)).to be_empty + expect(project_1.labels.where(title: group_label_3.title)).to be_empty end it 'does not recreate missing group labels that already exist in the project group' do service.execute - expect(project.labels.where(title: group_label_4.title)).to be_empty + expect(project_1.labels.where(title: group_label_4.title)).to be_empty end end end -- cgit v1.2.1 From 2fabd1a123e2bcbf8f372679cacd50fc1da11252 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 19 Oct 2016 22:14:57 +0300 Subject: Change the order of tested methods in project_members_controller_spec Signed-off-by: Dmitriy Zaporozhets --- .../projects/project_members_controller_spec.rb | 88 +++++++++++----------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index ea56bd72912..8519ebc1d5f 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -4,50 +4,6 @@ describe Projects::ProjectMembersController do let(:user) { create(:user) } let(:project) { create(:project, :public) } - describe 'POST apply_import' do - let(:another_project) { create(:project, :private) } - let(:member) { create(:user) } - - before do - project.team << [user, :master] - another_project.team << [member, :guest] - sign_in(user) - end - - shared_context 'import applied' do - before do - post(:apply_import, namespace_id: project.namespace, - project_id: project, - source_project_id: another_project.id) - end - end - - context 'when user can access source project members' do - before { another_project.team << [user, :guest] } - include_context 'import applied' - - it 'imports source project members' do - expect(project.team_members).to include member - expect(response).to set_flash.to 'Successfully imported' - expect(response).to redirect_to( - namespace_project_project_members_path(project.namespace, project) - ) - end - end - - context 'when user is not member of a source project' do - include_context 'import applied' - - it 'does not import team members' do - expect(project.team_members).not_to include member - end - - it 'responds with not found' do - expect(response.status).to eq 404 - end - end - end - describe 'GET index' do it 'renders index with 200 status code' do get :index, namespace_id: project.namespace, project_id: project @@ -228,4 +184,48 @@ describe Projects::ProjectMembersController do end end end + + describe 'POST apply_import' do + let(:another_project) { create(:project, :private) } + let(:member) { create(:user) } + + before do + project.team << [user, :master] + another_project.team << [member, :guest] + sign_in(user) + end + + shared_context 'import applied' do + before do + post(:apply_import, namespace_id: project.namespace, + project_id: project, + source_project_id: another_project.id) + end + end + + context 'when user can access source project members' do + before { another_project.team << [user, :guest] } + include_context 'import applied' + + it 'imports source project members' do + expect(project.team_members).to include member + expect(response).to set_flash.to 'Successfully imported' + expect(response).to redirect_to( + namespace_project_project_members_path(project.namespace, project) + ) + end + end + + context 'when user is not member of a source project' do + include_context 'import applied' + + it 'does not import team members' do + expect(project.team_members).not_to include member + end + + it 'responds with not found' do + expect(response.status).to eq 404 + end + end + end end -- cgit v1.2.1 From ed9838cd292ce78ae98079f513d0d1648b7f49f0 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 14 Oct 2016 19:38:41 -0300 Subject: Create project feature when project is created --- spec/models/project_spec.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index e6d98e25d0b..f4dda1ee558 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -67,6 +67,14 @@ describe Project, models: true do it { is_expected.to have_many(:notification_settings).dependent(:destroy) } it { is_expected.to have_many(:forks).through(:forked_project_links) } + context 'after create' do + it "creates project feature" do + project = FactoryGirl.build(:project) + + expect { project.save }.to change{ project.project_feature.present? }.from(false).to(true) + end + end + describe '#members & #requesters' do let(:project) { create(:project, :public) } let(:requester) { create(:user) } @@ -531,9 +539,9 @@ describe Project, models: true do end describe '#has_wiki?' do - let(:no_wiki_project) { build(:project, wiki_enabled: false, has_external_wiki: false) } - let(:wiki_enabled_project) { build(:project) } - let(:external_wiki_project) { build(:project, has_external_wiki: true) } + let(:no_wiki_project) { create(:project, wiki_access_level: ProjectFeature::DISABLED, has_external_wiki: false) } + let(:wiki_enabled_project) { create(:project) } + let(:external_wiki_project) { create(:project, has_external_wiki: true) } it 'returns true if project is wiki enabled or has external wiki' do expect(wiki_enabled_project).to have_wiki -- cgit v1.2.1 From 9124310f2871117acaac98781be84c9fc016e2ad Mon Sep 17 00:00:00 2001 From: Callum Dryden Date: Thu, 6 Oct 2016 15:19:27 +0000 Subject: Differentiate the expire from leave event At the moment we cannot see weather a user left a project due to their membership expiring of if they themselves opted to leave the project. This adds a new event type that allows us to make this differentiation. Note that is not really feasable to go back and reliably fix up the previous events. As a result the events for previous expire removals will remain the same however events of this nature going forward will be correctly represented. --- .../project_member_activity_index_spec.rb | 41 ++++++++++++++++++++++ spec/models/concerns/expirable_spec.rb | 31 ++++++++++++++++ spec/models/event_spec.rb | 27 ++++++++++++++ spec/models/members/project_member_spec.rb | 11 ++++++ spec/services/event_create_service_spec.rb | 19 ++++++++++ 5 files changed, 129 insertions(+) create mode 100644 spec/features/dashboard/project_member_activity_index_spec.rb create mode 100644 spec/models/concerns/expirable_spec.rb (limited to 'spec') diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb new file mode 100644 index 00000000000..ba77093a6d4 --- /dev/null +++ b/spec/features/dashboard/project_member_activity_index_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +feature 'Project member activity', feature: true, js: true do + include WaitForAjax + + let(:user) { create(:user) } + let(:project) { create(:empty_project, :public, name: 'x', namespace: user.namespace) } + + before do + project.team << [user, :master] + end + + def visit_activities_and_wait_with_event(event_type) + Event.create(project: project, author_id: user.id, action: event_type) + visit activity_namespace_project_path(project.namespace.path, project.path) + wait_for_ajax + end + + subject { page.find(".event-title").text } + + context 'when a user joins the project' do + before { visit_activities_and_wait_with_event(Event::JOINED) } + + it { is_expected.to eq("#{user.name} joined project") } + end + + context 'when a user leaves the project' do + before { visit_activities_and_wait_with_event(Event::LEFT) } + + it { is_expected.to eq("#{user.name} left project") } + end + + context 'when a users membership expires for the project' do + before { visit_activities_and_wait_with_event(Event::EXPIRED) } + + it "presents the correct message" do + message = "#{user.name} removed due to membership expiration from project" + is_expected.to eq(message) + end + end +end diff --git a/spec/models/concerns/expirable_spec.rb b/spec/models/concerns/expirable_spec.rb new file mode 100644 index 00000000000..f7b436f32e6 --- /dev/null +++ b/spec/models/concerns/expirable_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Expirable do + describe 'ProjectMember' do + let(:no_expire) { create(:project_member) } + let(:expire_later) { create(:project_member, expires_at: Time.current + 6.days) } + let(:expired) { create(:project_member, expires_at: Time.current - 6.days) } + + describe '.expired' do + it { expect(ProjectMember.expired).to match_array([expired]) } + end + + describe '#expired?' do + it { expect(no_expire.expired?).to eq(false) } + it { expect(expire_later.expired?).to eq(false) } + it { expect(expired.expired?).to eq(true) } + end + + describe '#expires?' do + it { expect(no_expire.expires?).to eq(false) } + it { expect(expire_later.expires?).to eq(true) } + it { expect(expired.expires?).to eq(true) } + end + + describe '#expires_soon?' do + it { expect(no_expire.expires_soon?).to eq(false) } + it { expect(expire_later.expires_soon?).to eq(true) } + it { expect(expired.expires_soon?).to eq(true) } + end + end +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 733b79079ed..aca49be2942 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -40,6 +40,33 @@ describe Event, models: true do end end + describe '#membership_changed?' do + context "created" do + subject { build(:event, action: Event::CREATED).membership_changed? } + it { is_expected.to be_falsey } + end + + context "updated" do + subject { build(:event, action: Event::UPDATED).membership_changed? } + it { is_expected.to be_falsey } + end + + context "expired" do + subject { build(:event, action: Event::EXPIRED).membership_changed? } + it { is_expected.to be_truthy } + end + + context "left" do + subject { build(:event, action: Event::LEFT).membership_changed? } + it { is_expected.to be_truthy } + end + + context "joined" do + subject { build(:event, action: Event::JOINED).membership_changed? } + it { is_expected.to be_truthy } + end + end + describe '#note?' do subject { Event.new(project: target.project, target: target) } diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb index d85a1c1e3b2..b2fe96e2e02 100644 --- a/spec/models/members/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -54,6 +54,17 @@ describe ProjectMember, models: true do master_todos end + it "creates an expired event when left due to expiry" do + expired = create(:project_member, project: project, expires_at: Time.now - 6.days) + expired.destroy + expect(Event.first.action).to eq(Event::EXPIRED) + end + + it "creates a left event when left due to leave" do + master.destroy + expect(Event.first.action).to eq(Event::LEFT) + end + it "destroys itself and delete associated todos" do expect(owner.user.todos.size).to eq(2) expect(master.user.todos.size).to eq(3) diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb index 16a9956fe7f..b7dc99ed887 100644 --- a/spec/services/event_create_service_spec.rb +++ b/spec/services/event_create_service_spec.rb @@ -110,4 +110,23 @@ describe EventCreateService, services: true do end end end + + describe 'Project' do + let(:user) { create :user } + let(:project) { create(:empty_project) } + + describe '#join_project' do + subject { service.join_project(project, user) } + + it { is_expected.to be_truthy } + it { expect { subject }.to change { Event.count }.from(0).to(1) } + end + + describe '#expired_leave_project' do + subject { service.expired_leave_project(project, user) } + + it { is_expected.to be_truthy } + it { expect { subject }.to change { Event.count }.from(0).to(1) } + end + end end -- cgit v1.2.1 From e6f515ecbed85b204e8f7bc9934b0bf208a0ea4c Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 19 Oct 2016 16:53:12 +0100 Subject: Revert "Add #closed_without_source_project?" This reverts commit 31c37c6c38258684fc92e0d91119c33872e39034. See #23341 --- spec/models/merge_request_spec.rb | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 6db5e7f7d80..ee003a9d18f 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1274,38 +1274,6 @@ describe MergeRequest, models: true do end end - describe '#closed_without_source_project?' do - let(:project) { create(:project) } - let(:user) { create(:user) } - let(:fork_project) { create(:project, forked_from_project: project, namespace: user.namespace) } - let(:destroy_service) { Projects::DestroyService.new(fork_project, user) } - - context 'when the merge request is closed' do - let(:closed_merge_request) do - create(:closed_merge_request, - source_project: fork_project, - target_project: project) - end - - it 'returns false if the source project exists' do - expect(closed_merge_request.closed_without_source_project?).to be_falsey - end - - it 'returns true if the source project does not exist' do - destroy_service.execute - closed_merge_request.reload - - expect(closed_merge_request.closed_without_source_project?).to be_truthy - end - end - - context 'when the merge request is open' do - it 'returns false' do - expect(subject.closed_without_source_project?).to be_falsey - end - end - end - describe '#reopenable?' do context 'when the merge request is closed' do it 'returns true' do -- cgit v1.2.1 From a4ef4244d4b9b54246f53bba5c02746542034da5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 20 Oct 2016 16:16:57 +0800 Subject: Preserve note_type and position for notes from emails Closes #23208 --- spec/fixtures/emails/commands_in_reply.eml | 2 -- spec/fixtures/emails/commands_only_reply.eml | 2 -- .../email/handler/create_note_handler_spec.rb | 24 ++++++++++++---------- 3 files changed, 13 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/fixtures/emails/commands_in_reply.eml b/spec/fixtures/emails/commands_in_reply.eml index 06bf60ab734..712f6f797b4 100644 --- a/spec/fixtures/emails/commands_in_reply.eml +++ b/spec/fixtures/emails/commands_in_reply.eml @@ -23,8 +23,6 @@ Cool! /close /todo -/due tomorrow - On Sun, Jun 9, 2013 at 1:39 PM, eviltrout via Discourse Meta wrote: diff --git a/spec/fixtures/emails/commands_only_reply.eml b/spec/fixtures/emails/commands_only_reply.eml index aed64224b06..2d2e2f94290 100644 --- a/spec/fixtures/emails/commands_only_reply.eml +++ b/spec/fixtures/emails/commands_only_reply.eml @@ -21,8 +21,6 @@ X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1 /close /todo -/due tomorrow - On Sun, Jun 9, 2013 at 1:39 PM, eviltrout via Discourse Meta wrote: diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb index 4909fed6b77..48660d1dd1b 100644 --- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb @@ -12,10 +12,13 @@ describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do let(:email_raw) { fixture_file('emails/valid_reply.eml') } let(:project) { create(:project, :public) } - let(:noteable) { create(:issue, project: project) } let(:user) { create(:user) } + let(:note) { create(:diff_note_on_merge_request, project: project) } + let(:noteable) { note.noteable } - let!(:sent_notification) { SentNotification.record(noteable, user.id, mail_key) } + let!(:sent_notification) do + SentNotification.record_note(note, user.id, mail_key) + end context "when the recipient address doesn't include a mail key" do let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub(mail_key, "") } @@ -82,7 +85,6 @@ describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do expect { receiver.execute }.to change { noteable.notes.count }.by(1) expect(noteable.reload).to be_closed - expect(noteable.due_date).to eq(Date.tomorrow) expect(TodoService.new.todo_exist?(noteable, user)).to be_truthy end end @@ -100,7 +102,6 @@ describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do expect { receiver.execute }.to change { noteable.notes.count }.by(1) expect(noteable.reload).to be_open - expect(noteable.due_date).to be_nil expect(TodoService.new.todo_exist?(noteable, user)).to be_falsy end end @@ -117,7 +118,6 @@ describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do expect { receiver.execute }.to change { noteable.notes.count }.by(2) expect(noteable.reload).to be_closed - expect(noteable.due_date).to eq(Date.tomorrow) expect(TodoService.new.todo_exist?(noteable, user)).to be_truthy end end @@ -138,10 +138,11 @@ describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do it "creates a comment" do expect { receiver.execute }.to change { noteable.notes.count }.by(1) - note = noteable.notes.last + new_note = noteable.notes.last - expect(note.author).to eq(sent_notification.recipient) - expect(note.note).to include("I could not disagree more.") + expect(new_note.author).to eq(sent_notification.recipient) + expect(new_note.position).to eq(note.position) + expect(new_note.note).to include("I could not disagree more.") end it "adds all attachments" do @@ -160,10 +161,11 @@ describe Gitlab::Email::Handler::CreateNoteHandler, lib: true do shared_examples 'an email that contains a mail key' do |header| it "fetches the mail key from the #{header} header and creates a comment" do expect { receiver.execute }.to change { noteable.notes.count }.by(1) - note = noteable.notes.last + new_note = noteable.notes.last - expect(note.author).to eq(sent_notification.recipient) - expect(note.note).to include('I could not disagree more.') + expect(new_note.author).to eq(sent_notification.recipient) + expect(new_note.position).to eq(note.position) + expect(new_note.note).to include('I could not disagree more.') end end -- cgit v1.2.1 From d9d0b81bc6117f9c01c28c1fab597f556b56f369 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 20 Oct 2016 12:10:27 +0200 Subject: Make label API spec independent of order --- spec/requests/api/labels_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 1da9988978b..867bc615b97 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -22,8 +22,7 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.size).to eq(2) - expect(json_response.first['name']).to eq(group_label.name) - expect(json_response.second['name']).to eq(label1.name) + expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, label1.name]) end end -- cgit v1.2.1 From 1cdad622aacf9ae7e7d61e575aaa77dddf7ae7b9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 20 Oct 2016 18:13:45 +0800 Subject: Should send to notification_email instead, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17146325 --- spec/models/project_services/pipeline_email_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb index 57baff3354f..4f56bceda44 100644 --- a/spec/models/project_services/pipeline_email_service_spec.rb +++ b/spec/models/project_services/pipeline_email_service_spec.rb @@ -58,7 +58,7 @@ describe PipelinesEmailService do end it 'sends email' do - should_only_email(double(email: recipient), kind: :bcc) + should_only_email(double(notification_email: recipient), kind: :bcc) end end -- cgit v1.2.1 From 64e2d884d6c8d822ae6e7d4d26af054396b74921 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 20 Oct 2016 12:15:29 +0200 Subject: Return conflict error in label API when title is taken by group label --- spec/requests/api/labels_spec.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 1da9988978b..840112299bc 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -83,7 +83,20 @@ describe API::API, api: true do expect(json_response['message']['title']).to eq(['is invalid']) end - it 'returns 409 if label already exists' do + it 'returns 409 if label already exists in group' do + group = create(:group) + group_label = create(:group_label, group: group) + project.update(group: group) + + post api("/projects/#{project.id}/labels", user), + name: group_label.name, + color: '#FFAABB' + + expect(response).to have_http_status(409) + expect(json_response['message']).to eq('Label already exists') + end + + it 'returns 409 if label already exists in project' do post api("/projects/#{project.id}/labels", user), name: 'label1', color: '#FFAABB' -- cgit v1.2.1 From 06564f9e049417087fa53cf8ec15c22ec65724d5 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 20 Oct 2016 12:47:32 +0200 Subject: Update gl_field_error tests for better input filtering. --- spec/javascripts/gl_field_errors_spec.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6 index 36feb2b2aa5..da9259edd78 100644 --- a/spec/javascripts/gl_field_errors_spec.js.es6 +++ b/spec/javascripts/gl_field_errors_spec.js.es6 @@ -11,12 +11,12 @@ this.fieldErrors = new global.GlFieldErrors($form); }); - it('should properly initialize the form', function() { + it('should select the correct input elements', function() { expect(this.$form).toBeDefined(); expect(this.$form.length).toBe(1); expect(this.fieldErrors).toBeDefined(); const inputs = this.fieldErrors.state.inputs; - expect(inputs.length).toBe(5); + expect(inputs.length).toBe(4); }); it('should ignore elements with custom error handling', function() { -- cgit v1.2.1 From 493367108eef14c8517c6d023ec46267c1e706cf Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Wed, 19 Oct 2016 14:30:17 +0200 Subject: Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method --- spec/models/issue_spec.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 3b8b743af2d..60d30eb7418 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -100,11 +100,17 @@ describe Issue, models: true do end it 'returns the merge request to close this issue' do - allow(mr).to receive(:closes_issue?).with(issue).and_return(true) + mr expect(issue.closed_by_merge_requests).to eq([mr]) end + it "returns an empty array when the merge request is closed already" do + closed_mr + + expect(issue.closed_by_merge_requests).to eq([]) + end + it "returns an empty array when the current issue is closed already" do expect(closed_issue.closed_by_merge_requests).to eq([]) end -- cgit v1.2.1 From bc31a489dd8c329cf011ac898498735809c319dd Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 20 Oct 2016 12:59:39 +0200 Subject: Restrict ProjectCacheWorker jobs to one per 15 min This ensures ProjectCacheWorker jobs for a given project are performed at most once per 15 minutes. This should reduce disk load a bit in cases where there are multiple pushes happening (which should schedule multiple ProjectCacheWorker jobs). --- spec/workers/project_cache_worker_spec.rb | 38 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index 5785a6a06ff..f5b60b90d11 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -6,21 +6,39 @@ describe ProjectCacheWorker do subject { described_class.new } describe '#perform' do - it 'updates project cache data' do - expect_any_instance_of(Repository).to receive(:size) - expect_any_instance_of(Repository).to receive(:commit_count) + context 'when an exclusive lease can be obtained' do + before do + allow(subject).to receive(:try_obtain_lease_for).with(project.id). + and_return(true) + end - expect_any_instance_of(Project).to receive(:update_repository_size) - expect_any_instance_of(Project).to receive(:update_commit_count) + it 'updates project cache data' do + expect_any_instance_of(Repository).to receive(:size) + expect_any_instance_of(Repository).to receive(:commit_count) - subject.perform(project.id) + expect_any_instance_of(Project).to receive(:update_repository_size) + expect_any_instance_of(Project).to receive(:update_commit_count) + + subject.perform(project.id) + end + + it 'handles missing repository data' do + expect_any_instance_of(Repository).to receive(:exists?).and_return(false) + expect_any_instance_of(Repository).not_to receive(:size) + + subject.perform(project.id) + end end - it 'handles missing repository data' do - expect_any_instance_of(Repository).to receive(:exists?).and_return(false) - expect_any_instance_of(Repository).not_to receive(:size) + context 'when an exclusive lease can not be obtained' do + it 'does nothing' do + allow(subject).to receive(:try_obtain_lease_for).with(project.id). + and_return(false) + + expect(subject).not_to receive(:update_caches) - subject.perform(project.id) + subject.perform(project.id) + end end end end -- cgit v1.2.1 From 374071321d0cfb7a161ec38e85e27e1d46ae7c9a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 19 Oct 2016 17:13:04 +0100 Subject: Fix the merge request view when source projects or branches are removed --- spec/features/merge_requests/created_from_fork_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'spec') diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb index a506624b30d..cfc1244429f 100644 --- a/spec/features/merge_requests/created_from_fork_spec.rb +++ b/spec/features/merge_requests/created_from_fork_spec.rb @@ -25,6 +25,20 @@ feature 'Merge request created from fork' do expect(page).to have_content 'Test merge request' end + context 'source project is deleted' do + background do + MergeRequests::MergeService.new(project, user).execute(merge_request) + fork_project.destroy! + end + + scenario 'user can access merge request' do + visit_merge_request(merge_request) + + expect(page).to have_content 'Test merge request' + expect(page).to have_content "(removed):#{merge_request.source_branch}" + end + end + context 'pipeline present in source project' do include WaitForAjax -- cgit v1.2.1 From 61536ed2cff454bb2e3db8b7ca9ee09cc407461f Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 19 Oct 2016 19:33:51 +0100 Subject: Rename forked_source_project_missing? to source_project_missing? --- spec/models/merge_request_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index ee003a9d18f..6e5137602aa 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1198,7 +1198,7 @@ describe MergeRequest, models: true do end end - describe "#forked_source_project_missing?" do + describe "#source_project_missing?" do let(:project) { create(:project) } let(:fork_project) { create(:project, forked_from_project: project) } let(:user) { create(:user) } @@ -1211,13 +1211,13 @@ describe MergeRequest, models: true do target_project: project) end - it { expect(merge_request.forked_source_project_missing?).to be_falsey } + it { expect(merge_request.source_project_missing?).to be_falsey } end context "when the source project is the same as the target project" do let(:merge_request) { create(:merge_request, source_project: project) } - it { expect(merge_request.forked_source_project_missing?).to be_falsey } + it { expect(merge_request.source_project_missing?).to be_falsey } end context "when the fork does not exist" do @@ -1231,7 +1231,7 @@ describe MergeRequest, models: true do unlink_project.execute merge_request.reload - expect(merge_request.forked_source_project_missing?).to be_truthy + expect(merge_request.source_project_missing?).to be_truthy end end end -- cgit v1.2.1 From c1212beaa495b5b0c3b805bb1b2a7bdc6d1a941b Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 19 Oct 2016 14:49:09 +0200 Subject: Use deployment IID when saving refs --- spec/controllers/projects/merge_requests_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index d6980471ea4..940d54f8686 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -913,7 +913,7 @@ describe Projects::MergeRequestsController do end describe 'GET ci_environments_status' do - context 'when the environment is from a forked project' do + context 'the environment is from a forked project' do let!(:forked) { create(:project) } let!(:environment) { create(:environment, project: forked) } let!(:deployment) { create(:deployment, environment: environment, sha: forked.commit.id, ref: 'master') } -- cgit v1.2.1 From b5d210c9d6d44fc664b006567b8f488e198ad04f Mon Sep 17 00:00:00 2001 From: Airat Shigapov Date: Thu, 15 Sep 2016 18:45:22 +0300 Subject: Render hipchat notification descriptions as HTML instead of raw markdown --- spec/models/project_services/hipchat_service_spec.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 26dd95bdfec..90066f01f6f 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -117,7 +117,7 @@ describe HipchatService, models: true do end context 'issue events' do - let(:issue) { create(:issue, title: 'Awesome issue', description: 'please fix') } + let(:issue) { create(:issue, title: 'Awesome issue', description: '**please** fix') } let(:issue_service) { Issues::CreateService.new(project, user) } let(:issues_sample_data) { issue_service.hook_data(issue, 'open') } @@ -135,12 +135,12 @@ describe HipchatService, models: true do "issue ##{obj_attr["iid"]} in " \ "#{project_name}: " \ "Awesome issue" \ - "
    please fix
    ") + "

    please fix

    \n
    ") end end context 'merge request events' do - let(:merge_request) { create(:merge_request, description: 'please fix', title: 'Awesome merge request', target_project: project, source_project: project) } + let(:merge_request) { create(:merge_request, description: '**please** fix', title: 'Awesome merge request', target_project: project, source_project: project) } let(:merge_service) { MergeRequests::CreateService.new(project, user) } let(:merge_sample_data) { merge_service.hook_data(merge_request, 'open') } @@ -159,7 +159,7 @@ describe HipchatService, models: true do "merge request !#{obj_attr["iid"]} in " \ "#{project_name}: " \ "Awesome merge request" \ - "
    please fix
    ") + "

    please fix

    \n
    ") end end @@ -190,7 +190,7 @@ describe HipchatService, models: true do "commit #{commit_id} in " \ "#{project_name}: " \ "#{title}" \ - "
    a comment on a commit
    ") + "

    a comment on a commit

    \n
    ") end end @@ -203,7 +203,7 @@ describe HipchatService, models: true do let(:merge_request_note) do create(:note_on_merge_request, noteable: merge_request, project: project, - note: "merge request note") + note: "merge request **note**") end it "calls Hipchat API for merge request comment events" do @@ -222,7 +222,7 @@ describe HipchatService, models: true do "merge request !#{merge_id} in " \ "#{project_name}: " \ "#{title}" \ - "
    merge request note
    ") + "

    merge request note

    \n
    ") end end @@ -230,7 +230,7 @@ describe HipchatService, models: true do let(:issue) { create(:issue, project: project) } let(:issue_note) do create(:note_on_issue, noteable: issue, project: project, - note: "issue note") + note: "issue **note**") end it "calls Hipchat API for issue comment events" do @@ -247,7 +247,7 @@ describe HipchatService, models: true do "issue ##{issue_id} in " \ "#{project_name}: " \ "#{title}" \ - "
    issue note
    ") + "

    issue note

    \n
    ") end end @@ -275,7 +275,7 @@ describe HipchatService, models: true do "snippet ##{snippet_id} in " \ "#{project_name}: " \ "#{title}" \ - "
    snippet note
    ") + "

    snippet note

    \n
    ") end end end -- cgit v1.2.1 From 32cf2e5f77c24c27782adc37d4635b06dfada060 Mon Sep 17 00:00:00 2001 From: David Eisner Date: Wed, 5 Oct 2016 13:38:08 +0100 Subject: Tests for markdown HipChat notifications --- spec/models/project_services/hipchat_service_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 90066f01f6f..1029b6d2459 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -135,7 +135,7 @@ describe HipchatService, models: true do "issue ##{obj_attr["iid"]} in " \ "#{project_name}: " \ "Awesome issue" \ - "

    please fix

    \n
    ") + "

    please fix

    ") end end @@ -159,7 +159,7 @@ describe HipchatService, models: true do "merge request !#{obj_attr["iid"]} in " \ "#{project_name}: " \ "Awesome merge request" \ - "

    please fix

    \n
    ") + "

    please fix

    ") end end @@ -190,7 +190,7 @@ describe HipchatService, models: true do "commit #{commit_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    a comment on a commit

    \n
    ") + "

    a comment on a commit

    ") end end @@ -222,7 +222,7 @@ describe HipchatService, models: true do "merge request !#{merge_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    merge request note

    \n
    ") + "

    merge request note

    ") end end @@ -247,7 +247,7 @@ describe HipchatService, models: true do "issue ##{issue_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    issue note

    \n
    ") + "

    issue note

    ") end end @@ -275,7 +275,7 @@ describe HipchatService, models: true do "snippet ##{snippet_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    snippet note

    \n
    ") + "

    snippet note

    ") end end end -- cgit v1.2.1 From 257d15a67007f7c8750ca6d00a7c13f8e8a9f974 Mon Sep 17 00:00:00 2001 From: Airat Shigapov Date: Wed, 19 Oct 2016 22:51:15 +0300 Subject: Return truncation for notification descriptions, fix minor bugs with rendering --- spec/models/project_services/hipchat_service_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb index 1029b6d2459..2da3a9cb09f 100644 --- a/spec/models/project_services/hipchat_service_spec.rb +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -135,7 +135,7 @@ describe HipchatService, models: true do "issue ##{obj_attr["iid"]} in " \ "#{project_name}: " \ "Awesome issue" \ - "

    please fix

    ") + "
    please fix
    ") end end @@ -159,7 +159,7 @@ describe HipchatService, models: true do "merge request !#{obj_attr["iid"]} in " \ "#{project_name}: " \ "Awesome merge request" \ - "

    please fix

    ") + "
    please fix
    ") end end @@ -190,7 +190,7 @@ describe HipchatService, models: true do "commit #{commit_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    a comment on a commit

    ") + "
    a comment on a commit
    ") end end @@ -222,7 +222,7 @@ describe HipchatService, models: true do "merge request !#{merge_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    merge request note

    ") + "
    merge request note
    ") end end @@ -247,7 +247,7 @@ describe HipchatService, models: true do "issue ##{issue_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    issue note

    ") + "
    issue note
    ") end end @@ -275,7 +275,7 @@ describe HipchatService, models: true do "snippet ##{snippet_id} in " \ "#{project_name}: " \ "#{title}" \ - "

    snippet note

    ") + "
    snippet note
    ") end end end -- cgit v1.2.1 From 2e411b5ea0faf733aa457ecc28064bb48f07deed Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Wed, 19 Oct 2016 15:35:38 +0200 Subject: Test GitLab project import for a user with only their default namespace. Refactor the spec file: - remove hardcoded record IDs - avoid top-level let if not used in all scenarios - prefer expect { ... }.to change { ... }.from(0).to(1) over checking that there are no records at the beginning of the test --- .../projects/import_export/import_file_spec.rb | 53 ++++++++++++---------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index f32834801a0..3015576f6f8 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -3,13 +3,8 @@ require 'spec_helper' feature 'Import/Export - project import integration test', feature: true, js: true do include Select2Helper - let(:admin) { create(:admin) } - let(:normal_user) { create(:user) } - let!(:namespace) { create(:namespace, name: "asd", owner: admin) } let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } let(:export_path) { "#{Dir::tmpdir}/import_file_spec" } - let(:project) { Project.last } - let(:project_hook) { Gitlab::Git::Hook.new('post-receive', project.repository.path) } background do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) @@ -19,41 +14,43 @@ feature 'Import/Export - project import integration test', feature: true, js: tr FileUtils.rm_rf(export_path, secure: true) end - context 'admin user' do + context 'when selecting the namespace' do + let(:user) { create(:admin) } + let!(:namespace) { create(:namespace, name: "asd", owner: user) } + before do - login_as(admin) + login_as(user) end scenario 'user imports an exported project successfully' do - expect(Project.all.count).to be_zero - visit new_project_path - select2('2', from: '#project_namespace_id') + select2(namespace.id, from: '#project_namespace_id') fill_in :project_path, with: 'test-project-path', visible: true click_link 'GitLab export' expect(page).to have_content('GitLab project export') - expect(URI.parse(current_url).query).to eq('namespace_id=2&path=test-project-path') + expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=test-project-path") attach_file('file', file) - click_on 'Import project' # import starts + expect { click_on 'Import project' }.to change { Project.count }.from(0).to(1) + project = Project.last expect(project).not_to be_nil expect(project.issues).not_to be_empty expect(project.merge_requests).not_to be_empty - expect(project_hook).to exist - expect(wiki_exists?).to be true + expect(project_hook_exists?(project)).to be true + expect(wiki_exists?(project)).to be true expect(project.import_status).to eq('finished') end scenario 'invalid project' do - project = create(:project, namespace_id: 2) + project = create(:project, namespace: namespace) visit new_project_path - select2('2', from: '#project_namespace_id') + select2(namespace.id, from: '#project_namespace_id') fill_in :project_path, with: project.name, visible: true click_link 'GitLab export' @@ -66,11 +63,11 @@ feature 'Import/Export - project import integration test', feature: true, js: tr end scenario 'project with no name' do - create(:project, namespace_id: 2) + create(:project, namespace: namespace) visit new_project_path - select2('2', from: '#project_namespace_id') + select2(namespace.id, from: '#project_namespace_id') # click on disabled element find(:link, 'GitLab export').trigger('click') @@ -81,24 +78,30 @@ feature 'Import/Export - project import integration test', feature: true, js: tr end end - context 'normal user' do + context 'when limited to the default user namespace' do + let(:user) { create(:user) } before do - login_as(normal_user) + login_as(user) end - scenario 'non-admin user is allowed to import a project' do - expect(Project.all.count).to be_zero - + scenario 'passes correct namespace ID in the URL' do visit new_project_path fill_in :project_path, with: 'test-project-path', visible: true - expect(page).to have_content('GitLab export') + click_link 'GitLab export' + + expect(page).to have_content('GitLab project export') + expect(URI.parse(current_url).query).to eq("namespace_id=#{user.namespace.id}&path=test-project-path") end end - def wiki_exists? + def wiki_exists?(project) wiki = ProjectWiki.new(project) File.exist?(wiki.repository.path_to_repo) && !wiki.repository.empty? end + + def project_hook_exists?(project) + Gitlab::Git::Hook.new('post-receive', project.repository.path).exists? + end end -- cgit v1.2.1 From 23e81bfde879dfd116cb70cb8034d0fce21fffb6 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Thu, 20 Oct 2016 16:40:24 +0200 Subject: Ignore external issues when bulk assigning issues to author of merge request. Fixes #23552 --- spec/services/merge_requests/assign_issues_service_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/services/merge_requests/assign_issues_service_spec.rb b/spec/services/merge_requests/assign_issues_service_spec.rb index 7aeb95a15ea..5034b6ef33f 100644 --- a/spec/services/merge_requests/assign_issues_service_spec.rb +++ b/spec/services/merge_requests/assign_issues_service_spec.rb @@ -46,4 +46,16 @@ describe MergeRequests::AssignIssuesService, services: true do it 'assigns these to the merge request owner' do expect { service.execute }.to change { issue.reload.assignee }.to(user) end + + it 'ignores external issues' do + external_issue = ExternalIssue.new('JIRA-123', project) + service = described_class.new( + project, + user, + merge_request: merge_request, + closes_issues: [external_issue] + ) + + expect(service.assignable_issues.count).to eq 0 + end end -- cgit v1.2.1 From 168197cd5a179c961301225626ac1a175f892782 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 18 Oct 2016 16:49:19 +0300 Subject: Fix project member access levels --- .../projects/project_members_controller_spec.rb | 36 ++++++++++++++++++++++ spec/requests/api/members_spec.rb | 11 +++++++ 2 files changed, 47 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 8519ebc1d5f..5e487241d07 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -228,4 +228,40 @@ describe Projects::ProjectMembersController do end end end + + describe 'POST create' do + let(:stranger) { create(:user) } + + context 'when creating owner' do + before do + project.team << [user, :master] + sign_in(user) + end + + it 'does not create a member' do + expect do + post :create, user_ids: stranger.id, + namespace_id: project.namespace, + access_level: Member::OWNER, + project_id: project + end.to change { project.members.count }.by(0) + end + end + + context 'when create master' do + before do + project.team << [user, :master] + sign_in(user) + end + + it 'creates a member' do + expect do + post :create, user_ids: stranger.id, + namespace_id: project.namespace, + access_level: Member::MASTER, + project_id: project + end.to change { project.members.count }.by(1) + end + end + end end diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index d22e0595788..493c0a893d1 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -328,4 +328,15 @@ describe API::Members, api: true do it_behaves_like 'DELETE /:sources/:id/members/:user_id', 'group' do let(:source) { group } end + + context 'Adding owner to project' do + it 'returns 403' do + expect do + post api("/projects/#{project.id}/members", master), + user_id: stranger.id, access_level: Member::OWNER + + expect(response).to have_http_status(422) + end.to change { project.members.count }.by(0) + end + end end -- cgit v1.2.1 From 6061c9fa3d942c4b1aa466ee8f5f8eb3ae48853e Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 21 Oct 2016 18:16:39 +0800 Subject: Send only to users have :read_build access, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6342#note_17193335 --- spec/workers/pipeline_notification_worker_spec.rb | 132 +++++++++++++--------- 1 file changed, 81 insertions(+), 51 deletions(-) (limited to 'spec') diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb index c334b2057a6..d487a719680 100644 --- a/spec/workers/pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -17,84 +17,114 @@ describe PipelineNotificationWorker do describe '#execute' do before do reset_delivered_emails! - pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] + pipeline.project.team << [pusher, Gitlab::Access::DEVELOPER] end - shared_examples 'sending emails' do - it 'sends emails' do - perform_enqueued_jobs do - subject.perform(pipeline.id) - end + context 'when watcher has developer access' do + before do + pipeline.project.team << [watcher, Gitlab::Access::DEVELOPER] + end - emails = ActionMailer::Base.deliveries - actual = emails.flat_map(&:bcc).sort - expected_receivers = [pusher, watcher].map(&:email).uniq.sort + shared_examples 'sending emails' do + it 'sends emails' do + perform_enqueued_jobs do + subject.perform(pipeline.id) + end - expect(actual).to eq(expected_receivers) - expect(emails.size).to eq(1) - expect(emails.last.subject).to include(email_subject) - end - end + emails = ActionMailer::Base.deliveries + actual = emails.flat_map(&:bcc).sort + expected_receivers = receivers.map(&:email).uniq.sort - context 'with success pipeline' do - let(:status) { 'success' } - let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } + expect(actual).to eq(expected_receivers) + expect(emails.size).to eq(1) + expect(emails.last.subject).to include(email_subject) + end + end - it_behaves_like 'sending emails' + context 'with success pipeline' do + let(:status) { 'success' } + let(:email_subject) { "Pipeline ##{pipeline.id} has succeeded" } + let(:receivers) { [pusher, watcher] } - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } + it_behaves_like 'sending emails' - context 'with success pipeline notification on' do + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } let(:watcher) { user } - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: true) + context 'with success pipeline notification on' do + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: true) + end + + it_behaves_like 'sending emails' end - it_behaves_like 'sending emails' - end + context 'with success pipeline notification off' do + let(:receivers) { [pusher] } + + before do + watcher.global_notification_setting. + update(level: 'custom', success_pipeline: false) + end - context 'with success pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', success_pipeline: false) + it_behaves_like 'sending emails' end + end + + context 'with failed pipeline' do + let(:status) { 'failed' } + let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } it_behaves_like 'sending emails' + + context 'with pipeline from someone else' do + let(:pusher) { create(:user) } + let(:watcher) { user } + + context 'with failed pipeline notification on' do + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) + end + + it_behaves_like 'sending emails' + end + + context 'with failed pipeline notification off' do + let(:receivers) { [pusher] } + + before do + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: false) + end + + it_behaves_like 'sending emails' + end + end end end end - context 'with failed pipeline' do + context 'when watcher has no read_build access' do let(:status) { 'failed' } let(:email_subject) { "Pipeline ##{pipeline.id} has failed" } + let(:watcher) { create(:user) } - it_behaves_like 'sending emails' + before do + pipeline.project.team << [watcher, Gitlab::Access::GUEST] - context 'with pipeline from someone else' do - let(:pusher) { create(:user) } - - context 'with failed pipeline notification on' do - let(:watcher) { user } - - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: true) - end + watcher.global_notification_setting. + update(level: 'custom', failed_pipeline: true) - it_behaves_like 'sending emails' + perform_enqueued_jobs do + subject.perform(pipeline.id) end + end - context 'with failed pipeline notification off' do - before do - watcher.global_notification_setting. - update(level: 'custom', failed_pipeline: false) - end - - it_behaves_like 'sending emails' - end + it 'does not send emails' do + should_only_email(pusher, kind: :bcc) end end end -- cgit v1.2.1 From 2c09d2a13d83494f195fda8620e322dff7738dc5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 21 Oct 2016 18:22:09 +0800 Subject: Test against notification email --- spec/support/email_helpers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/support/email_helpers.rb b/spec/support/email_helpers.rb index a946f10f71a..3e979f2f470 100644 --- a/spec/support/email_helpers.rb +++ b/spec/support/email_helpers.rb @@ -1,6 +1,6 @@ module EmailHelpers def sent_to_user?(user, recipients = email_recipients) - recipients.include?(user.email) + recipients.include?(user.notification_email) end def reset_delivered_emails! -- cgit v1.2.1 From c81ff152e08d58c13efbd50c40dd2e083ac65083 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Fri, 21 Oct 2016 13:53:38 +0200 Subject: Change "Group#web_url" to return "/groups/twitter" rather than "/twitter". Bring back the old behaviour which was changed by 6b90ccb9. Fixes #23527. --- spec/models/group_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'spec') diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index ac862055ebc..47f89f744cb 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -265,4 +265,10 @@ describe Group, models: true do members end + + describe '#web_url' do + it 'returns the canonical URL' do + expect(group.web_url).to include("groups/#{group.name}") + end + end end -- cgit v1.2.1 From b939529c2a2c724f1471ab3b0ec2a5dac10c913c Mon Sep 17 00:00:00 2001 From: Airat Shigapov Date: Fri, 21 Oct 2016 18:05:36 +0300 Subject: Fix wrong endpoint in api/users documentation, fix same typo in spec describe blocks --- spec/requests/api/users_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index f83f4d2c9b1..d48752473f3 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -846,7 +846,7 @@ describe API::API, api: true do end end - describe 'PUT /user/:id/block' do + describe 'PUT /users/:id/block' do before { admin } it 'blocks existing user' do put api("/users/#{user.id}/block", admin) @@ -873,7 +873,7 @@ describe API::API, api: true do end end - describe 'PUT /user/:id/unblock' do + describe 'PUT /users/:id/unblock' do let(:blocked_user) { create(:user, state: 'blocked') } before { admin } @@ -914,7 +914,7 @@ describe API::API, api: true do end end - describe 'GET /user/:id/events' do + describe 'GET /users/:id/events' do let(:user) { create(:user) } let(:project) { create(:empty_project) } let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) } -- cgit v1.2.1 From 97731760d7252acf8ee94c707c0e107492b1ef24 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 21 Oct 2016 18:13:41 +0200 Subject: Re-organize queues to use for Sidekiq Dumping too many jobs in the same queue (e.g. the "default" queue) is a dangerous setup. Jobs that take a long time to process can effectively block any other work from being performed given there are enough of these jobs. Furthermore it becomes harder to monitor the jobs as a single queue could contain jobs for different workers. In such a setup the only reliable way of getting counts per job is to iterate over all jobs in a queue, which is a rather time consuming process. By using separate queues for various workers we have better control over throughput, we can add weight to queues, and we can monitor queues better. Some workers still use the same queue whenever their work is related. For example, the various CI pipeline workers use the same "pipeline" queue. This commit includes a Rails migration that moves Sidekiq jobs from the old queues to the new ones. This migration also takes care of doing the inverse if ever needed. This does require downtime as otherwise new jobs could be scheduled in the old queues after this migration completes. This commit also includes an RSpec test that blacklists the use of the "default" queue and ensures cron workers use the "cronjob" queue. Fixes gitlab-org/gitlab-ce#23370 --- spec/workers/concerns/build_queue_spec.rb | 14 +++++++ spec/workers/concerns/cronjob_queue_spec.rb | 18 +++++++++ .../concerns/dedicated_sidekiq_queue_spec.rb | 20 ++++++++++ spec/workers/concerns/pipeline_queue_spec.rb | 14 +++++++ .../concerns/repository_check_queue_spec.rb | 18 +++++++++ spec/workers/every_sidekiq_worker_spec.rb | 44 ++++++++++++++++++++++ 6 files changed, 128 insertions(+) create mode 100644 spec/workers/concerns/build_queue_spec.rb create mode 100644 spec/workers/concerns/cronjob_queue_spec.rb create mode 100644 spec/workers/concerns/dedicated_sidekiq_queue_spec.rb create mode 100644 spec/workers/concerns/pipeline_queue_spec.rb create mode 100644 spec/workers/concerns/repository_check_queue_spec.rb create mode 100644 spec/workers/every_sidekiq_worker_spec.rb (limited to 'spec') diff --git a/spec/workers/concerns/build_queue_spec.rb b/spec/workers/concerns/build_queue_spec.rb new file mode 100644 index 00000000000..6bf955e0be2 --- /dev/null +++ b/spec/workers/concerns/build_queue_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe BuildQueue do + let(:worker) do + Class.new do + include Sidekiq::Worker + include BuildQueue + end + end + + it 'sets the queue name of a worker' do + expect(worker.sidekiq_options['queue'].to_s).to eq('build') + end +end diff --git a/spec/workers/concerns/cronjob_queue_spec.rb b/spec/workers/concerns/cronjob_queue_spec.rb new file mode 100644 index 00000000000..5d1336c21a6 --- /dev/null +++ b/spec/workers/concerns/cronjob_queue_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe CronjobQueue do + let(:worker) do + Class.new do + include Sidekiq::Worker + include CronjobQueue + end + end + + it 'sets the queue name of a worker' do + expect(worker.sidekiq_options['queue'].to_s).to eq('cronjob') + end + + it 'disables retrying of failed jobs' do + expect(worker.sidekiq_options['retry']).to eq(false) + end +end diff --git a/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb b/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb new file mode 100644 index 00000000000..512baec8b7e --- /dev/null +++ b/spec/workers/concerns/dedicated_sidekiq_queue_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe DedicatedSidekiqQueue do + let(:worker) do + Class.new do + def self.name + 'Foo::Bar::DummyWorker' + end + + include Sidekiq::Worker + include DedicatedSidekiqQueue + end + end + + describe 'queue names' do + it 'sets the queue name based on the class name' do + expect(worker.sidekiq_options['queue']).to eq('foo_bar_dummy') + end + end +end diff --git a/spec/workers/concerns/pipeline_queue_spec.rb b/spec/workers/concerns/pipeline_queue_spec.rb new file mode 100644 index 00000000000..40794d0e42a --- /dev/null +++ b/spec/workers/concerns/pipeline_queue_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe PipelineQueue do + let(:worker) do + Class.new do + include Sidekiq::Worker + include PipelineQueue + end + end + + it 'sets the queue name of a worker' do + expect(worker.sidekiq_options['queue'].to_s).to eq('pipeline') + end +end diff --git a/spec/workers/concerns/repository_check_queue_spec.rb b/spec/workers/concerns/repository_check_queue_spec.rb new file mode 100644 index 00000000000..8868e969829 --- /dev/null +++ b/spec/workers/concerns/repository_check_queue_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe RepositoryCheckQueue do + let(:worker) do + Class.new do + include Sidekiq::Worker + include RepositoryCheckQueue + end + end + + it 'sets the queue name of a worker' do + expect(worker.sidekiq_options['queue'].to_s).to eq('repository_check') + end + + it 'disables retrying of failed jobs' do + expect(worker.sidekiq_options['retry']).to eq(false) + end +end diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb new file mode 100644 index 00000000000..fc9adf47c1e --- /dev/null +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe 'Every Sidekiq worker' do + let(:workers) do + root = Rails.root.join('app', 'workers') + concerns = root.join('concerns').to_s + + workers = Dir[root.join('**', '*.rb')]. + reject { |path| path.start_with?(concerns) } + + workers.map do |path| + ns = Pathname.new(path).relative_path_from(root).to_s.gsub('.rb', '') + + ns.camelize.constantize + end + end + + it 'does not use the default queue' do + workers.each do |worker| + expect(worker.sidekiq_options['queue'].to_s).not_to eq('default') + end + end + + it 'uses the cronjob queue when the worker runs as a cronjob' do + cron_workers = Settings.cron_jobs. + map { |job_name, options| options['job_class'].constantize }. + to_set + + workers.each do |worker| + next unless cron_workers.include?(worker) + + expect(worker.sidekiq_options['queue'].to_s).to eq('cronjob') + end + end + + it 'defines the queue in the Sidekiq configuration file' do + config = YAML.load_file(Rails.root.join('config', 'sidekiq_queues.yml').to_s) + queue_names = config[:queues].map { |(queue, _)| queue }.to_set + + workers.each do |worker| + expect(queue_names).to include(worker.sidekiq_options['queue'].to_s) + end + end +end -- cgit v1.2.1 From f388fceb4cc64d67b95e45cdbe77c9907803d6f1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 22 Oct 2016 01:10:47 +0800 Subject: Make sure pusher has the read_build privilege --- spec/models/ci/pipeline_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index ab05150c97e..65e663be411 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -542,6 +542,8 @@ describe Ci::Pipeline, models: true do before do reset_delivered_emails! + project.team << [pipeline.user, Gitlab::Access::DEVELOPER] + perform_enqueued_jobs do pipeline.enqueue pipeline.run -- cgit v1.2.1 From 7664c76a165e4f151bec3e5f3a25b5eb1f962bb4 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 21 Oct 2016 21:40:18 +0100 Subject: Removed append logic Updated test --- spec/features/projects/issuable_templates_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index d886909ce85..2f377312ea5 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -77,7 +77,7 @@ feature 'issuable templates', feature: true, js: true do scenario 'user selects "bug" template' do select_template 'bug' wait_for_ajax - preview_template("#{prior_description}\n\n#{template_content}") + preview_template("#{template_content}") save_changes end end -- cgit v1.2.1 From 0890aeb61a5378ec3bb98511de236ee01eee8711 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 22 Oct 2016 01:59:40 -0700 Subject: Fix error in generating labels Attempting to generate default set of labels would result in an error: ArgumentError: wrong number of arguments (given 1, expected 0) Closes #23649 --- spec/controllers/projects/labels_controller_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 622ab154493..7ba4406c1f6 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -70,4 +70,19 @@ describe Projects::LabelsController do get :index, namespace_id: project.namespace.to_param, project_id: project.to_param end end + + describe 'POST #generate' do + let(:admin) { create(:admin) } + let(:project) { create(:empty_project) } + + before do + sign_in(admin) + end + + it 'creates labels' do + post :generate, namespace_id: project.namespace.to_param, project_id: project.to_param + + expect(response.code).to eq(302) + end + end end -- cgit v1.2.1 From e6968964870286af5ce6a1f7cf1152c057fd5c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Sat, 22 Oct 2016 13:46:23 +0200 Subject: Fix status code expectation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/controllers/projects/labels_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 7ba4406c1f6..41df63d445a 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -82,7 +82,7 @@ describe Projects::LabelsController do it 'creates labels' do post :generate, namespace_id: project.namespace.to_param, project_id: project.to_param - expect(response.code).to eq(302) + expect(response).to have_http_status(302) end end end -- cgit v1.2.1 From 204da00ea0dc52c6746b160fd698e07f55a7fc00 Mon Sep 17 00:00:00 2001 From: Jared Ready Date: Thu, 29 Sep 2016 20:18:46 -0500 Subject: Move spec/mailers/shared/notify.rb to spec/support --- spec/mailers/emails/builds_spec.rb | 1 - spec/mailers/emails/merge_requests_spec.rb | 1 - spec/mailers/emails/profile_spec.rb | 1 - spec/mailers/notify_spec.rb | 1 - spec/mailers/shared/notify.rb | 200 ----------------------------- spec/support/notify_shared_examples.rb | 200 +++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 204 deletions(-) delete mode 100644 spec/mailers/shared/notify.rb create mode 100644 spec/support/notify_shared_examples.rb (limited to 'spec') diff --git a/spec/mailers/emails/builds_spec.rb b/spec/mailers/emails/builds_spec.rb index 0df89938e97..d968096783c 100644 --- a/spec/mailers/emails/builds_spec.rb +++ b/spec/mailers/emails/builds_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' require 'email_spec' -require 'mailers/shared/notify' describe Notify do include EmailSpec::Matchers diff --git a/spec/mailers/emails/merge_requests_spec.rb b/spec/mailers/emails/merge_requests_spec.rb index 4d3811af254..e22858d1d8f 100644 --- a/spec/mailers/emails/merge_requests_spec.rb +++ b/spec/mailers/emails/merge_requests_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' require 'email_spec' -require 'mailers/shared/notify' describe Notify, "merge request notifications" do include EmailSpec::Matchers diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb index 781472d0c00..14bc062ef12 100644 --- a/spec/mailers/emails/profile_spec.rb +++ b/spec/mailers/emails/profile_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' require 'email_spec' -require 'mailers/shared/notify' describe Notify do include EmailSpec::Matchers diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index c8207e58e90..f5f3f58613d 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' require 'email_spec' -require 'mailers/shared/notify' describe Notify do include EmailSpec::Helpers diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb deleted file mode 100644 index 3956d05060b..00000000000 --- a/spec/mailers/shared/notify.rb +++ /dev/null @@ -1,200 +0,0 @@ -shared_context 'gitlab email notification' do - let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name } - let(:gitlab_sender) { Gitlab.config.gitlab.email_from } - let(:gitlab_sender_reply_to) { Gitlab.config.gitlab.email_reply_to } - let(:recipient) { create(:user, email: 'recipient@example.com') } - let(:project) { create(:project) } - let(:new_user_address) { 'newguy@example.com' } - - before do - ActionMailer::Base.deliveries.clear - email = recipient.emails.create(email: "notifications@example.com") - recipient.update_attribute(:notification_email, email.email) - stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}") - end -end - -shared_context 'reply-by-email is enabled with incoming address without %{key}' do - before do - stub_incoming_email_setting(enabled: true, address: "reply@#{Gitlab.config.gitlab.host}") - end -end - -shared_examples 'a multiple recipients email' do - it 'is sent to the given recipient' do - is_expected.to deliver_to recipient.notification_email - end -end - -shared_examples 'an email sent from GitLab' do - it 'is sent from GitLab' do - sender = subject.header[:from].addrs[0] - expect(sender.display_name).to eq(gitlab_sender_display_name) - expect(sender.address).to eq(gitlab_sender) - end - - it 'has a Reply-To address' do - reply_to = subject.header[:reply_to].addresses - expect(reply_to).to eq([gitlab_sender_reply_to]) - end - - context 'when custom suffix for email subject is set' do - before do - stub_config_setting(email_subject_suffix: 'A Nice Suffix') - end - - it 'ends the subject with the suffix' do - is_expected.to have_subject /\ \| A Nice Suffix$/ - end - end -end - -shared_examples 'an email that contains a header with author username' do - it 'has X-GitLab-Author header containing author\'s username' do - is_expected.to have_header 'X-GitLab-Author', user.username - end -end - -shared_examples 'an email with X-GitLab headers containing project details' do - it 'has X-GitLab-Project* headers' do - is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ - is_expected.to have_header 'X-GitLab-Project-Id', /#{project.id}/ - is_expected.to have_header 'X-GitLab-Project-Path', /#{project.path_with_namespace}/ - end -end - -shared_examples 'a new thread email with reply-by-email enabled' do - let(:regex) { /\A\Z/ } - - it 'has a Message-ID header' do - is_expected.to have_header 'Message-ID', "<#{model.class.model_name.singular_route_key}_#{model.id}@#{Gitlab.config.gitlab.host}>" - end - - it 'has a References header' do - is_expected.to have_header 'References', regex - end -end - -shared_examples 'a thread answer email with reply-by-email enabled' do - include_examples 'an email with X-GitLab headers containing project details' - let(:regex) { /\A<#{model.class.model_name.singular_route_key}_#{model.id}@#{Gitlab.config.gitlab.host}> \Z/ } - - it 'has a Message-ID header' do - is_expected.to have_header 'Message-ID', /\A<(.*)@#{Gitlab.config.gitlab.host}>\Z/ - end - - it 'has a In-Reply-To header' do - is_expected.to have_header 'In-Reply-To', "<#{model.class.model_name.singular_route_key}_#{model.id}@#{Gitlab.config.gitlab.host}>" - end - - it 'has a References header' do - is_expected.to have_header 'References', regex - end - - it 'has a subject that begins with Re: ' do - is_expected.to have_subject /^Re: / - end -end - -shared_examples 'an email starting a new thread with reply-by-email enabled' do - include_examples 'an email with X-GitLab headers containing project details' - include_examples 'a new thread email with reply-by-email enabled' - - context 'when reply-by-email is enabled with incoming address with %{key}' do - it 'has a Reply-To header' do - is_expected.to have_header 'Reply-To', /\Z/ - end - end - - context 'when reply-by-email is enabled with incoming address without %{key}' do - include_context 'reply-by-email is enabled with incoming address without %{key}' - include_examples 'a new thread email with reply-by-email enabled' - - it 'has a Reply-To header' do - is_expected.to have_header 'Reply-To', /\Z/ - end - end -end - -shared_examples 'an answer to an existing thread with reply-by-email enabled' do - include_examples 'an email with X-GitLab headers containing project details' - include_examples 'a thread answer email with reply-by-email enabled' - - context 'when reply-by-email is enabled with incoming address with %{key}' do - it 'has a Reply-To header' do - is_expected.to have_header 'Reply-To', /\Z/ - end - end - - context 'when reply-by-email is enabled with incoming address without %{key}' do - include_context 'reply-by-email is enabled with incoming address without %{key}' - include_examples 'a thread answer email with reply-by-email enabled' - - it 'has a Reply-To header' do - is_expected.to have_header 'Reply-To', /\Z/ - end - end -end - -shared_examples 'a new user email' do - it 'is sent to the new user' do - is_expected.to deliver_to new_user_address - end - - it 'has the correct subject' do - is_expected.to have_subject /^Account was created for you$/i - end - - it 'contains the new user\'s login name' do - is_expected.to have_body_text /#{new_user_address}/ - end -end - -shared_examples 'it should have Gmail Actions links' do - it { is_expected.to have_body_text '' + markdown = "[#{link_label}](#{issue.to_reference})" + result = described_class.to_html(markdown, project: project) + expect(result).not_to include(link_label) + end + + it 'escapes the data-original attribute on a reference' do + markdown = %Q{[">bad things](#{issue.to_reference})} + result = described_class.to_html(markdown, project: project) + expect(result).to include(%{data-original='\">bad things'}) + end + end +end diff --git a/spec/lib/banzai/redactor_spec.rb b/spec/lib/banzai/redactor_spec.rb index 254657a881d..6d2c141e18b 100644 --- a/spec/lib/banzai/redactor_spec.rb +++ b/spec/lib/banzai/redactor_spec.rb @@ -6,39 +6,60 @@ describe Banzai::Redactor do let(:redactor) { described_class.new(project, user) } describe '#redact' do - it 'redacts an Array of documents' do - doc1 = Nokogiri::HTML. - fragment('foo') - - doc2 = Nokogiri::HTML. - fragment('bar') - - expect(redactor).to receive(:nodes_visible_to_user).and_return([]) - - redacted_data = redactor.redact([doc1, doc2]) - - expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) - expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([0, 0]) - expect(doc1.to_html).to eq('foo') - expect(doc2.to_html).to eq('bar') + context 'when reference not visible to user' do + before do + expect(redactor).to receive(:nodes_visible_to_user).and_return([]) + end + + it 'redacts an array of documents' do + doc1 = Nokogiri::HTML. + fragment('foo') + + doc2 = Nokogiri::HTML. + fragment('bar') + + redacted_data = redactor.redact([doc1, doc2]) + + expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) + expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([0, 0]) + expect(doc1.to_html).to eq('foo') + expect(doc2.to_html).to eq('bar') + end + + it 'replaces redacted reference with inner HTML' do + doc = Nokogiri::HTML.fragment("foo") + redactor.redact([doc]) + expect(doc.to_html).to eq('foo') + end + + context 'when data-original attribute provided' do + let(:original_content) { 'foo' } + it 'replaces redacted reference with original content' do + doc = Nokogiri::HTML.fragment("bar") + redactor.redact([doc]) + expect(doc.to_html).to eq(original_content) + end + end end - it 'does not redact an Array of documents' do - doc1_html = 'foo' - doc1 = Nokogiri::HTML.fragment(doc1_html) + context 'when reference visible to user' do + it 'does not redact an array of documents' do + doc1_html = 'foo' + doc1 = Nokogiri::HTML.fragment(doc1_html) - doc2_html = 'bar' - doc2 = Nokogiri::HTML.fragment(doc2_html) + doc2_html = 'bar' + doc2 = Nokogiri::HTML.fragment(doc2_html) - nodes = redactor.document_nodes([doc1, doc2]).map { |x| x[:nodes] } - expect(redactor).to receive(:nodes_visible_to_user).and_return(nodes.flatten) + nodes = redactor.document_nodes([doc1, doc2]).map { |x| x[:nodes] } + expect(redactor).to receive(:nodes_visible_to_user).and_return(nodes.flatten) - redacted_data = redactor.redact([doc1, doc2]) + redacted_data = redactor.redact([doc1, doc2]) - expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) - expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([1, 1]) - expect(doc1.to_html).to eq(doc1_html) - expect(doc2.to_html).to eq(doc2_html) + expect(redacted_data.map { |data| data[:document] }).to eq([doc1, doc2]) + expect(redacted_data.map { |data| data[:visible_reference_count] }).to eq([1, 1]) + expect(doc1.to_html).to eq(doc1_html) + expect(doc2.to_html).to eq(doc2_html) + end end end diff --git a/spec/support/banzai/reference_filter_shared_examples.rb b/spec/support/banzai/reference_filter_shared_examples.rb new file mode 100644 index 00000000000..eb5da662ab5 --- /dev/null +++ b/spec/support/banzai/reference_filter_shared_examples.rb @@ -0,0 +1,13 @@ +# Specs for reference links containing HTML. +# +# Requires a reference: +# let(:reference) { '#42' } +shared_examples 'a reference containing an element node' do + let(:inner_html) { 'element node inside' } + let(:reference_with_element) { %{#{inner_html}} } + + it 'does not escape inner html' do + doc = reference_filter(reference_with_element) + expect(doc.children.first.inner_html).to eq(inner_html) + end +end -- cgit v1.2.1 From 3c2f40cd39cab63d6bf33e156123cc74aeb0b4a9 Mon Sep 17 00:00:00 2001 From: Alex Sanford Date: Thu, 6 Oct 2016 22:09:15 -0300 Subject: Add validation errors to Merge Request form If source branch or target branch doesn't exist in the project, display form validation errors. Previously, this caused a 500 error code. --- spec/features/merge_requests/create_new_mr_spec.rb | 8 ++++ spec/services/merge_requests/build_service_spec.rb | 49 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'spec') diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb index b963d1305b5..c68e1ea4af9 100644 --- a/spec/features/merge_requests/create_new_mr_spec.rb +++ b/spec/features/merge_requests/create_new_mr_spec.rb @@ -59,4 +59,12 @@ feature 'Create New Merge Request', feature: true, js: true do expect(page).to have_css('a.btn.active', text: 'Side-by-side') end end + + it 'does not allow non-existing branches' do + visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_branch: 'non-exist-target', source_branch: 'non-exist-source' }) + + expect(page).to have_content('The form contains the following errors') + expect(page).to have_content('Source branch "non-exist-source" does not exist') + expect(page).to have_content('Target branch "non-exist-target" does not exist') + end end diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index 3a3f07ddcb9..3f5df049ea2 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -25,6 +25,8 @@ describe MergeRequests::BuildService, services: true do before do allow(CompareService).to receive_message_chain(:new, :execute).and_return(compare) + allow(project).to receive(:commit).and_return(commit_1) + allow(project).to receive(:commit).and_return(commit_2) end describe 'execute' do @@ -193,5 +195,52 @@ describe MergeRequests::BuildService, services: true do end end end + + context 'source branch does not exist' do + before do + allow(project).to receive(:commit).with(source_branch).and_return(nil) + allow(project).to receive(:commit).with(target_branch).and_return(commit_1) + end + + it 'forbids the merge request from being created' do + expect(merge_request.can_be_created).to eq(false) + end + + it 'adds an error message to the merge request' do + expect(merge_request.errors).to contain_exactly('Source branch "feature-branch" does not exist') + end + end + + context 'target branch does not exist' do + before do + allow(project).to receive(:commit).with(source_branch).and_return(commit_1) + allow(project).to receive(:commit).with(target_branch).and_return(nil) + end + + it 'forbids the merge request from being created' do + expect(merge_request.can_be_created).to eq(false) + end + + it 'adds an error message to the merge request' do + expect(merge_request.errors).to contain_exactly('Target branch "master" does not exist') + end + end + + context 'both source and target branches do not exist' do + before do + allow(project).to receive(:commit).and_return(nil) + end + + it 'forbids the merge request from being created' do + expect(merge_request.can_be_created).to eq(false) + end + + it 'adds both error messages to the merge request' do + expect(merge_request.errors).to contain_exactly( + 'Source branch "feature-branch" does not exist', + 'Target branch "master" does not exist' + ) + end + end end end -- cgit v1.2.1 From c85c146aa2042710caddc6666ce8f9e07b2fe5ca Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sun, 23 Oct 2016 09:46:39 +0200 Subject: Add support for token attr in project hooks API The UI allows to define a token to validate payload on the target URL, this patch adds the feature to the API. --- spec/requests/api/project_hooks_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index cfcdcad74cd..53113c62996 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -36,6 +36,7 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response.first['pipeline_events']).to eq(true) expect(json_response.first['wiki_page_events']).to eq(true) expect(json_response.first['enable_ssl_verification']).to eq(true) + expect(json_response.first['token']).to eq('S3cr3t') end end @@ -62,6 +63,7 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response['pipeline_events']).to eq(hook.pipeline_events) expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events) expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification) + expect(json_response['token']).to eq(hook.token) end it "returns a 404 error if hook id is not available" do @@ -99,6 +101,7 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response['pipeline_events']).to eq(false) expect(json_response['wiki_page_events']).to eq(false) expect(json_response['enable_ssl_verification']).to eq(true) + expect(json_response['token']).to eq('S3cr3t') end it "returns a 400 error if url not given" do @@ -127,6 +130,7 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response['pipeline_events']).to eq(hook.pipeline_events) expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events) expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification) + expect(json_response['token']).to eq(hook.token) end it "returns 404 error if hook id not found" do -- cgit v1.2.1 From f77be11cb9caa62cdd4690a53c73b6d34e102148 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 1 Nov 2016 11:40:06 +0000 Subject: Ensure hook tokens are write-only in the API --- spec/requests/api/project_hooks_spec.rb | 36 +++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index 53113c62996..5f39329a1b8 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -36,7 +36,6 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response.first['pipeline_events']).to eq(true) expect(json_response.first['wiki_page_events']).to eq(true) expect(json_response.first['enable_ssl_verification']).to eq(true) - expect(json_response.first['token']).to eq('S3cr3t') end end @@ -63,7 +62,6 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response['pipeline_events']).to eq(hook.pipeline_events) expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events) expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification) - expect(json_response['token']).to eq(hook.token) end it "returns a 404 error if hook id is not available" do @@ -90,6 +88,7 @@ describe API::API, 'ProjectHooks', api: true do expect do post api("/projects/#{project.id}/hooks", user), url: "http://example.com", issues_events: true end.to change {project.hooks.count}.by(1) + expect(response).to have_http_status(201) expect(json_response['url']).to eq('http://example.com') expect(json_response['issues_events']).to eq(true) @@ -101,7 +100,24 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response['pipeline_events']).to eq(false) expect(json_response['wiki_page_events']).to eq(false) expect(json_response['enable_ssl_verification']).to eq(true) - expect(json_response['token']).to eq('S3cr3t') + expect(json_response).not_to include('token') + end + + it "adds the token without including it in the response" do + token = "secret token" + + expect do + post api("/projects/#{project.id}/hooks", user), url: "http://example.com", token: token + end.to change {project.hooks.count}.by(1) + + expect(response).to have_http_status(201) + expect(json_response["url"]).to eq("http://example.com") + expect(json_response).not_to include("token") + + hook = project.hooks.find(json_response["id"]) + + expect(hook.url).to eq("http://example.com") + expect(hook.token).to eq(token) end it "returns a 400 error if url not given" do @@ -130,7 +146,19 @@ describe API::API, 'ProjectHooks', api: true do expect(json_response['pipeline_events']).to eq(hook.pipeline_events) expect(json_response['wiki_page_events']).to eq(hook.wiki_page_events) expect(json_response['enable_ssl_verification']).to eq(hook.enable_ssl_verification) - expect(json_response['token']).to eq(hook.token) + end + + it "adds the token without including it in the response" do + token = "secret token" + + put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: "http://example.org", token: token + + expect(response).to have_http_status(200) + expect(json_response["url"]).to eq("http://example.org") + expect(json_response).not_to include("token") + + expect(hook.reload.url).to eq("http://example.org") + expect(hook.reload.token).to eq(token) end it "returns 404 error if hook id not found" do -- cgit v1.2.1 From a6ba358a8fe5a965a46ca07c8c0382348b2b8d8c Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 19 Oct 2016 15:25:37 +0300 Subject: Make specs a bit faster --- spec/features/admin/admin_runners_spec.rb | 27 ++++++++++++------- spec/features/commits_spec.rb | 8 +++--- spec/features/projects/builds_spec.rb | 38 ++++++++++++++++----------- spec/requests/api/merge_request_diffs_spec.rb | 32 +++++++++++----------- spec/requests/api/merge_requests_spec.rb | 16 +++++------ spec/requests/ci/api/builds_spec.rb | 25 +++++++++++------- spec/requests/ci/api/runners_spec.rb | 10 ++++--- 7 files changed, 90 insertions(+), 66 deletions(-) (limited to 'spec') diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 2f82fafc13a..d92c66b689d 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -7,15 +7,16 @@ describe "Admin Runners" do describe "Runners page" do before do - runner = FactoryGirl.create(:ci_runner) + runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now) pipeline = FactoryGirl.create(:ci_pipeline) FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id) visit admin_runners_path end - it { page.has_text? "Manage Runners" } - it { page.has_text? "To register a new runner" } - it { page.has_text? "Runners with last contact less than a minute ago: 1" } + it 'has all necessary texts' do + expect(page).to have_text "To register a new Runner" + expect(page).to have_text "Runners with last contact less than a minute ago: 1" + end describe 'search' do before do @@ -27,8 +28,10 @@ describe "Admin Runners" do search_form.click_button 'Search' end - it { expect(page).to have_content("runner-foo") } - it { expect(page).not_to have_content("runner-bar") } + it 'shows correct runner' do + expect(page).to have_content("runner-foo") + expect(page).not_to have_content("runner-bar") + end end end @@ -46,8 +49,10 @@ describe "Admin Runners" do end describe 'projects' do - it { expect(page).to have_content(@project1.name_with_namespace) } - it { expect(page).to have_content(@project2.name_with_namespace) } + it 'contains project names' do + expect(page).to have_content(@project1.name_with_namespace) + expect(page).to have_content(@project2.name_with_namespace) + end end describe 'search' do @@ -57,8 +62,10 @@ describe "Admin Runners" do search_form.click_button 'Search' end - it { expect(page).to have_content(@project1.name_with_namespace) } - it { expect(page).not_to have_content(@project2.name_with_namespace) } + it 'contains name of correct project' do + expect(page).to have_content(@project1.name_with_namespace) + expect(page).not_to have_content(@project2.name_with_namespace) + end end describe 'enable/create' do diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 5910803df51..338c53f08a6 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -64,9 +64,11 @@ describe 'Commits' do visit ci_status_path(pipeline) end - it { expect(page).to have_content pipeline.sha[0..7] } - it { expect(page).to have_content pipeline.git_commit_message } - it { expect(page).to have_content pipeline.git_author_name } + it 'shows pipeline`s data' do + expect(page).to have_content pipeline.sha[0..7] + expect(page).to have_content pipeline.git_commit_message + expect(page).to have_content pipeline.git_author_name + end end context 'Download artifacts' do diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index d1685f95503..23ea3857dd7 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -79,12 +79,14 @@ describe "Builds" do click_link "Cancel running" end - it { expect(page).to have_selector('.nav-links li.active', text: 'All') } - it { expect(page).to have_content 'canceled' } - it { expect(page).to have_content @build.short_sha } - it { expect(page).to have_content @build.ref } - it { expect(page).to have_content @build.name } - it { expect(page).not_to have_link 'Cancel running' } + it 'shows all necessary content' do + expect(page).to have_selector('.nav-links li.active', text: 'All') + expect(page).to have_content 'canceled' + expect(page).to have_content @build.short_sha + expect(page).to have_content @build.ref + expect(page).to have_content @build.name + expect(page).not_to have_link 'Cancel running' + end end describe "GET /:project/builds/:id" do @@ -93,10 +95,12 @@ describe "Builds" do visit namespace_project_build_path(@project.namespace, @project, @build) end - it { expect(page.status_code).to eq(200) } - it { expect(page).to have_content @commit.sha[0..7] } - it { expect(page).to have_content @commit.git_commit_message } - it { expect(page).to have_content @commit.git_author_name } + it 'shows commit`s data' do + expect(page.status_code).to eq(200) + expect(page).to have_content @commit.sha[0..7] + expect(page).to have_content @commit.git_commit_message + expect(page).to have_content @commit.git_author_name + end end context "Build from other project" do @@ -167,7 +171,7 @@ describe "Builds" do describe 'Variables' do before do - @trigger_request = create :ci_trigger_request_with_variables + @trigger_request = create :ci_trigger_request_with_variables @build = create :ci_build, pipeline: @commit, trigger_request: @trigger_request visit namespace_project_build_path(@project.namespace, @project, @build) end @@ -176,14 +180,14 @@ describe "Builds" do expect(page).to have_css('.reveal-variables') expect(page).not_to have_css('.js-build-variable') expect(page).not_to have_css('.js-build-value') - + click_button 'Reveal Variables' expect(page).not_to have_css('.reveal-variables') expect(page).to have_selector('.js-build-variable', text: 'TRIGGER_KEY_1') expect(page).to have_selector('.js-build-value', text: 'TRIGGER_VALUE_1') end - end + end end describe "POST /:project/builds/:id/cancel" do @@ -194,9 +198,11 @@ describe "Builds" do click_link "Cancel" end - it { expect(page.status_code).to eq(200) } - it { expect(page).to have_content 'canceled' } - it { expect(page).to have_content 'Retry' } + it 'loads the page and shows all needed controls' do + expect(page.status_code).to eq(200) + expect(page).to have_content 'canceled' + expect(page).to have_content 'Retry' + end end context "Build from other project" do diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb index 8f1e5ac9891..131c2d406ea 100644 --- a/spec/requests/api/merge_request_diffs_spec.rb +++ b/spec/requests/api/merge_request_diffs_spec.rb @@ -14,14 +14,14 @@ describe API::API, 'MergeRequestDiffs', api: true do end describe 'GET /projects/:id/merge_requests/:merge_request_id/versions' do - context 'valid merge request' do - before { get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions", user) } - let(:merge_request_diff) { merge_request.merge_request_diffs.first } - - it { expect(response.status).to eq 200 } - it { expect(json_response.size).to eq(merge_request.merge_request_diffs.size) } - it { expect(json_response.first['id']).to eq(merge_request_diff.id) } - it { expect(json_response.first['head_commit_sha']).to eq(merge_request_diff.head_commit_sha) } + it 'returns 200 for a valid merge request' do + get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions", user) + merge_request_diff = merge_request.merge_request_diffs.first + + expect(response.status).to eq 200 + expect(json_response.size).to eq(merge_request.merge_request_diffs.size) + expect(json_response.first['id']).to eq(merge_request_diff.id) + expect(json_response.first['head_commit_sha']).to eq(merge_request_diff.head_commit_sha) end it 'returns a 404 when merge_request_id not found' do @@ -31,14 +31,14 @@ describe API::API, 'MergeRequestDiffs', api: true do end describe 'GET /projects/:id/merge_requests/:merge_request_id/versions/:version_id' do - context 'valid merge request' do - before { get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions/#{merge_request_diff.id}", user) } - let(:merge_request_diff) { merge_request.merge_request_diffs.first } - - it { expect(response.status).to eq 200 } - it { expect(json_response['id']).to eq(merge_request_diff.id) } - it { expect(json_response['head_commit_sha']).to eq(merge_request_diff.head_commit_sha) } - it { expect(json_response['diffs'].size).to eq(merge_request_diff.diffs.size) } + it 'returns a 200 for a valid merge request' do + merge_request_diff = merge_request.merge_request_diffs.first + get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions/#{merge_request_diff.id}", user) + + expect(response.status).to eq 200 + expect(json_response['id']).to eq(merge_request_diff.id) + expect(json_response['head_commit_sha']).to eq(merge_request_diff.head_commit_sha) + expect(json_response['diffs'].size).to eq(merge_request_diff.diffs.size) end it 'returns a 404 when merge_request_id not found' do diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index b813ee967f8..bae4fa11ec2 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -186,14 +186,14 @@ describe API::API, api: true do end describe 'GET /projects/:id/merge_requests/:merge_request_id/commits' do - context 'valid merge request' do - before { get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/commits", user) } - let(:commit) { merge_request.commits.first } - - it { expect(response.status).to eq 200 } - it { expect(json_response.size).to eq(merge_request.commits.size) } - it { expect(json_response.first['id']).to eq(commit.id) } - it { expect(json_response.first['title']).to eq(commit.title) } + it 'returns a 200 when merge request is valid' do + get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/commits", user) + commit = merge_request.commits.first + + expect(response.status).to eq 200 + expect(json_response.size).to eq(merge_request.commits.size) + expect(json_response.first['id']).to eq(commit.id) + expect(json_response.first['title']).to eq(commit.title) end it 'returns a 404 when merge_request_id not found' do diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 7b7d62feb2c..6d49c42c215 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -220,26 +220,33 @@ describe Ci::API::API do end context 'when request is valid' do - it { expect(response.status).to eq 202 } + it 'gets correct response' do + expect(response.status).to eq 202 + expect(response.header).to have_key 'Range' + expect(response.header).to have_key 'Build-Status' + end + it { expect(build.reload.trace).to eq 'BUILD TRACE appended' } - it { expect(response.header).to have_key 'Range' } - it { expect(response.header).to have_key 'Build-Status' } end context 'when content-range start is too big' do let(:headers_with_range) { headers.merge({ 'Content-Range' => '15-20' }) } - it { expect(response.status).to eq 416 } - it { expect(response.header).to have_key 'Range' } - it { expect(response.header['Range']).to eq '0-11' } + it 'gets correct response' do + expect(response.status).to eq 416 + expect(response.header).to have_key 'Range' + expect(response.header['Range']).to eq '0-11' + end end context 'when content-range start is too small' do let(:headers_with_range) { headers.merge({ 'Content-Range' => '8-20' }) } - it { expect(response.status).to eq 416 } - it { expect(response.header).to have_key 'Range' } - it { expect(response.header['Range']).to eq '0-11' } + it 'gets correct response' do + expect(response.status).to eq 416 + expect(response.header).to have_key 'Range' + expect(response.header['Range']).to eq '0-11' + end end context 'when Content-Range header is missing' do diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb index 43596f07cb5..d6c26fd8a94 100644 --- a/spec/requests/ci/api/runners_spec.rb +++ b/spec/requests/ci/api/runners_spec.rb @@ -109,10 +109,12 @@ describe Ci::API::API do end describe "DELETE /runners/delete" do - let!(:runner) { FactoryGirl.create(:ci_runner) } - before { delete ci_api("/runners/delete"), token: runner.token } + it 'returns 200' do + runner = FactoryGirl.create(:ci_runner) + delete ci_api("/runners/delete"), token: runner.token - it { expect(response).to have_http_status 200 } - it { expect(Ci::Runner.count).to eq(0) } + expect(response).to have_http_status 200 + expect(Ci::Runner.count).to eq(0) + end end end -- cgit v1.2.1 From f4e31b820e0cebd0f4bd0fe5a5d6a7a3c903a969 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Fri, 28 Oct 2016 18:56:13 -0200 Subject: Fix project features default values --- spec/lib/gitlab/utils_spec.rb | 35 ++++++++++++++++++++++ .../project_features_compatibility_spec.rb | 14 +++++++++ spec/models/project_spec.rb | 6 ++-- spec/requests/api/api_helpers_spec.rb | 30 ------------------- spec/services/projects/create_service_spec.rb | 2 +- 5 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 spec/lib/gitlab/utils_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb new file mode 100644 index 00000000000..d5d87310874 --- /dev/null +++ b/spec/lib/gitlab/utils_spec.rb @@ -0,0 +1,35 @@ +describe Gitlab::Utils, lib: true do + def to_boolean(value) + described_class.to_boolean(value) + end + + describe '.to_boolean' do + it 'accepts booleans' do + expect(to_boolean(true)).to be(true) + expect(to_boolean(false)).to be(false) + end + + it 'converts a valid string to a boolean' do + expect(to_boolean(true)).to be(true) + expect(to_boolean('true')).to be(true) + expect(to_boolean('YeS')).to be(true) + expect(to_boolean('t')).to be(true) + expect(to_boolean('1')).to be(true) + expect(to_boolean('ON')).to be(true) + + expect(to_boolean('FaLse')).to be(false) + expect(to_boolean('F')).to be(false) + expect(to_boolean('NO')).to be(false) + expect(to_boolean('n')).to be(false) + expect(to_boolean('0')).to be(false) + expect(to_boolean('oFF')).to be(false) + end + + it 'converts an invalid string to nil' do + expect(to_boolean('fals')).to be_nil + expect(to_boolean('yeah')).to be_nil + expect(to_boolean('')).to be_nil + expect(to_boolean(nil)).to be_nil + end + end +end diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb index 5363aea4d22..9041690023f 100644 --- a/spec/models/concerns/project_features_compatibility_spec.rb +++ b/spec/models/concerns/project_features_compatibility_spec.rb @@ -22,4 +22,18 @@ describe ProjectFeaturesCompatibility do expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::DISABLED) end end + + it "converts fields from true to ProjectFeature::ENABLED" do + features.each do |feature| + project.update_attribute("#{feature}_enabled".to_sym, true) + expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::ENABLED) + end + end + + it "converts fields from false to ProjectFeature::DISABLED" do + features.each do |feature| + project.update_attribute("#{feature}_enabled".to_sym, false) + expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::DISABLED) + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index f4dda1ee558..aef277357cf 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -67,11 +67,11 @@ describe Project, models: true do it { is_expected.to have_many(:notification_settings).dependent(:destroy) } it { is_expected.to have_many(:forks).through(:forked_project_links) } - context 'after create' do - it "creates project feature" do + context 'after initialized' do + it "has a project_feature" do project = FactoryGirl.build(:project) - expect { project.save }.to change{ project.project_feature.present? }.from(false).to(true) + expect(project.project_feature.present?).to be_present end end diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index f7fe4c10873..01bb9e955e0 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -265,36 +265,6 @@ describe API::Helpers, api: true do end end - describe '.to_boolean' do - it 'accepts booleans' do - expect(to_boolean(true)).to be(true) - expect(to_boolean(false)).to be(false) - end - - it 'converts a valid string to a boolean' do - expect(to_boolean(true)).to be(true) - expect(to_boolean('true')).to be(true) - expect(to_boolean('YeS')).to be(true) - expect(to_boolean('t')).to be(true) - expect(to_boolean('1')).to be(true) - expect(to_boolean('ON')).to be(true) - - expect(to_boolean('FaLse')).to be(false) - expect(to_boolean('F')).to be(false) - expect(to_boolean('NO')).to be(false) - expect(to_boolean('n')).to be(false) - expect(to_boolean('0')).to be(false) - expect(to_boolean('oFF')).to be(false) - end - - it 'converts an invalid string to nil' do - expect(to_boolean('fals')).to be_nil - expect(to_boolean('yeah')).to be_nil - expect(to_boolean('')).to be_nil - expect(to_boolean(nil)).to be_nil - end - end - describe '.handle_api_exception' do before do allow_any_instance_of(self.class).to receive(:sentry_enabled?).and_return(true) diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 3ea1273abc3..876bfaf085c 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -69,7 +69,7 @@ describe Projects::CreateService, services: true do context 'wiki_enabled false does not create wiki repository directory' do before do - @opts.merge!( { project_feature_attributes: { wiki_access_level: ProjectFeature::DISABLED } }) + @opts.merge!(wiki_enabled: false) @project = create_project(@user, @opts) @path = ProjectWiki.new(@project, @user).send(:path_to_repo) end -- cgit v1.2.1 From f8530580100f56fe3bef5f3a73d3e543b038f98f Mon Sep 17 00:00:00 2001 From: Yar Date: Tue, 25 Oct 2016 20:14:58 +0300 Subject: Allow to search for user by secondary email address in the admin interface It is not possible to search for a user by his secondary email address in the Users search bar in the admin interface(/admin/users). A use-case could be that an admin wants to remove a specific secondary email address of an user, because it interferes with another user. Issue #23761 This commit adds ability to search not only by main email, but also by any secondary email in the admin interface. --- spec/models/user_spec.rb | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'spec') diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 10c39b90212..d1ed774a914 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -599,6 +599,80 @@ describe User, models: true do end end + describe '.search_with_secondary_emails' do + def search_with_secondary_emails(query) + described_class.search_with_secondary_emails(query) + end + + let!(:user) { create(:user) } + let!(:email) { create(:email) } + + it 'returns users with a matching name' do + expect(search_with_secondary_emails(user.name)).to eq([user]) + end + + it 'returns users with a partially matching name' do + expect(search_with_secondary_emails(user.name[0..2])).to eq([user]) + end + + it 'returns users with a matching name regardless of the casing' do + expect(search_with_secondary_emails(user.name.upcase)).to eq([user]) + end + + it 'returns users with a matching email' do + expect(search_with_secondary_emails(user.email)).to eq([user]) + end + + it 'returns users with a partially matching email' do + expect(search_with_secondary_emails(user.email[0..2])).to eq([user]) + end + + it 'returns users with a matching email regardless of the casing' do + expect(search_with_secondary_emails(user.email.upcase)).to eq([user]) + end + + it 'returns users with a matching username' do + expect(search_with_secondary_emails(user.username)).to eq([user]) + end + + it 'returns users with a partially matching username' do + expect(search_with_secondary_emails(user.username[0..2])).to eq([user]) + end + + it 'returns users with a matching username regardless of the casing' do + expect(search_with_secondary_emails(user.username.upcase)).to eq([user]) + end + + it 'returns users with a matching whole secondary email' do + expect(search_with_secondary_emails(email.email)).to eq([email.user]) + end + + it 'returns users with a matching part of secondary email' do + expect(search_with_secondary_emails(email.email[1..4])).to eq([email.user]) + end + + it 'return users with a matching part of secondary email regardless of case' do + expect(search_with_secondary_emails(email.email[1..4].upcase)).to eq([email.user]) + expect(search_with_secondary_emails(email.email[1..4].downcase)).to eq([email.user]) + expect(search_with_secondary_emails(email.email[1..4].capitalize)).to eq([email.user]) + end + + it 'returns multiple users with matching secondary emails' do + email1 = create(:email, email: '1_testemail@example.com') + email2 = create(:email, email: '2_testemail@example.com') + email3 = create(:email, email: 'other@email.com') + email3.user.update_attributes!(email: 'another@mail.com') + + expect( + search_with_secondary_emails('testemail@example.com').map(&:id) + ).to include(email1.user.id, email2.user.id) + + expect( + search_with_secondary_emails('testemail@example.com').map(&:id) + ).not_to include(email3.user.id) + end + end + describe 'by_username_or_id' do let(:user1) { create(:user, username: 'foo') } -- cgit v1.2.1 From 93bd3dd8a8f587dc860c72653364d853c27bc6fd Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 21 Oct 2016 13:49:09 +0200 Subject: Upgrade gl_field_errors to support more use cases. --- spec/javascripts/fixtures/gl_field_errors.html.haml | 2 +- spec/javascripts/gl_field_errors_spec.js.es6 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/fixtures/gl_field_errors.html.haml b/spec/javascripts/fixtures/gl_field_errors.html.haml index 2526e5e33a5..3026af8856d 100644 --- a/spec/javascripts/fixtures/gl_field_errors.html.haml +++ b/spec/javascripts/fixtures/gl_field_errors.html.haml @@ -10,6 +10,6 @@ .form-group %input.hidden{ type:'hidden' } .form-group - %input.custom.no-gl-field-errors{ type:'text' } Custom, do not validate + %input.custom.gl-field-error-ignore{ type:'text' } Custom, do not validate .form-group %input.submit{type: 'submit'} Submit diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6 index 4bdd72800ea..220e8c32447 100644 --- a/spec/javascripts/gl_field_errors_spec.js.es6 +++ b/spec/javascripts/gl_field_errors_spec.js.es6 @@ -21,7 +21,7 @@ }); it('should ignore elements with custom error handling', function() { - const customErrorFlag = 'no-gl-field-errors'; + const customErrorFlag = 'gl-field-error-ignore'; const customErrorElem = $(`.${customErrorFlag}`); expect(customErrorElem.length).toBe(1); -- cgit v1.2.1 From af5322e90b47e830e7713482854ddf6450a0d8c1 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Tue, 2 Aug 2016 22:46:43 -0600 Subject: Add Rake task to create/repair GitLab Shell hooks symlinks --- spec/rake_helper.rb | 19 +++++++++++++++++++ spec/support/rake_helpers.rb | 10 ++++++++++ spec/tasks/gitlab/shell_rake_spec.rb | 26 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 spec/rake_helper.rb create mode 100644 spec/support/rake_helpers.rb create mode 100644 spec/tasks/gitlab/shell_rake_spec.rb (limited to 'spec') diff --git a/spec/rake_helper.rb b/spec/rake_helper.rb new file mode 100644 index 00000000000..9b5b4bf9fea --- /dev/null +++ b/spec/rake_helper.rb @@ -0,0 +1,19 @@ +require 'spec_helper' +require 'rake' + +RSpec.configure do |config| + config.include RakeHelpers + + # Redirect stdout so specs don't have so much noise + config.before(:all) do + $stdout = StringIO.new + + Rake.application.rake_require 'tasks/gitlab/task_helpers' + Rake::Task.define_task :environment + end + + # Reset stdout + config.after(:all) do + $stdout = STDOUT + end +end diff --git a/spec/support/rake_helpers.rb b/spec/support/rake_helpers.rb new file mode 100644 index 00000000000..52d80c69835 --- /dev/null +++ b/spec/support/rake_helpers.rb @@ -0,0 +1,10 @@ +module RakeHelpers + def run_rake_task(task_name) + Rake::Task[task_name].reenable + Rake.application.invoke_task task_name + end + + def stub_warn_user_is_not_gitlab + allow_any_instance_of(Object).to receive(:warn_user_is_not_gitlab) + end +end diff --git a/spec/tasks/gitlab/shell_rake_spec.rb b/spec/tasks/gitlab/shell_rake_spec.rb new file mode 100644 index 00000000000..226d34fe2c9 --- /dev/null +++ b/spec/tasks/gitlab/shell_rake_spec.rb @@ -0,0 +1,26 @@ +require 'rake_helper' + +describe 'gitlab:shell rake tasks' do + before do + Rake.application.rake_require 'tasks/gitlab/shell' + + stub_warn_user_is_not_gitlab + end + + describe 'install task' do + it 'invokes create_hooks task' do + expect(Rake::Task['gitlab:shell:create_hooks']).to receive(:invoke) + + run_rake_task('gitlab:shell:install') + end + end + + describe 'create_hooks task' do + it 'calls gitlab-shell bin/create_hooks' do + expect_any_instance_of(Object).to receive(:system) + .with("#{Gitlab.config.gitlab_shell.path}/bin/create-hooks", *repository_storage_paths_args) + + run_rake_task('gitlab:shell:create_hooks') + end + end +end -- cgit v1.2.1 From d939fbed0953be5e19308ec7dc7832cfd1d38160 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Wed, 2 Nov 2016 11:35:21 +0100 Subject: Change show-gl-field-errors to gl-show-field-errors --- spec/javascripts/fixtures/gl_field_errors.html.haml | 2 +- spec/javascripts/gl_field_errors_spec.js.es6 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/fixtures/gl_field_errors.html.haml b/spec/javascripts/fixtures/gl_field_errors.html.haml index 3026af8856d..69445b61367 100644 --- a/spec/javascripts/fixtures/gl_field_errors.html.haml +++ b/spec/javascripts/fixtures/gl_field_errors.html.haml @@ -1,4 +1,4 @@ -%form.show-gl-field-errors{action: 'submit', method: 'post'} +%form.gl-show-field-errors{action: 'submit', method: 'post'} .form-group %input.required-text{required: true, type: 'text'} Text .form-group diff --git a/spec/javascripts/gl_field_errors_spec.js.es6 b/spec/javascripts/gl_field_errors_spec.js.es6 index 220e8c32447..0713e30e485 100644 --- a/spec/javascripts/gl_field_errors_spec.js.es6 +++ b/spec/javascripts/gl_field_errors_spec.js.es6 @@ -8,7 +8,7 @@ describe('GL Style Field Errors', function() { beforeEach(function() { fixture.load('gl_field_errors.html'); - const $form = this.$form = $('form.show-gl-field-errors'); + const $form = this.$form = $('form.gl-show-field-errors'); this.fieldErrors = new global.GlFieldErrors($form); }); -- cgit v1.2.1 From 57fd233a557158dbaa1a227f7c549fbe6a45e799 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Wed, 19 Oct 2016 14:08:30 +0000 Subject: Update docs and unexpose token --- spec/requests/api/system_hooks_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index cdf0874dbdc..55567941e08 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -30,7 +30,6 @@ describe API::API, api: true do it "returns an array of hooks" do get api("/hooks", admin) - byebug expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.first['url']).to eq(hook.url) -- cgit v1.2.1 From 37f229c7358a48c6a9af3481927e9e4faee17e3d Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 2 Nov 2016 13:24:24 +0100 Subject: Update docs and test description [ci skip] --- spec/requests/api/system_hooks_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index 55567941e08..f685a3685e6 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -48,6 +48,7 @@ describe API::API, api: true do it "responds with 400 if url not given" do post api("/hooks", admin) + expect(response).to have_http_status(400) end @@ -57,7 +58,7 @@ describe API::API, api: true do end.not_to change { SystemHook.count } end - it 'allows the events to be selected' do + it 'sets default values for events' do post api('/hooks', admin), url: 'http://mep.mep', enable_ssl_verification: true expect(response).to have_http_status(201) -- cgit v1.2.1 From 6419fe366a83314258f24d4ee2852a461b590c61 Mon Sep 17 00:00:00 2001 From: Brian Kintz Date: Thu, 1 Sep 2016 01:50:27 -0400 Subject: Use the server's base URL without relative URL part when creating links in JIRA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/models/project_services/jira_service_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index a9f637147d1..a3e9adae4e2 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +include Gitlab::Routing.url_helpers describe JiraService, models: true do describe "Associations" do @@ -66,6 +67,27 @@ describe JiraService, models: true do ).once end + it "references the GitLab commit/merge request" do + @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) + + expect(WebMock).to have_requested(:post, @comment_url).with( + body: /#{Gitlab.config.gitlab.url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/ + ).once + end + + it "references the GitLab commit/merge request (relative URL)" do + stub_config_setting(relative_url_root: '/gitlab') + stub_config_setting(url: Settings.send(:build_gitlab_url)) + + Project.default_url_options[:script_name] = "/gitlab" + + @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) + + expect(WebMock).to have_requested(:post, @comment_url).with( + body: /#{Gitlab.config.gitlab.url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/ + ).once + end + it "calls the api with jira_issue_transition_id" do @jira_service.jira_issue_transition_id = 'this-is-a-custom-id' @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) -- cgit v1.2.1 From acfe394018df50bfc08aa9e41265231747675646 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 28 Oct 2016 14:32:07 +0200 Subject: Add PoC for resource serializers --- spec/serializers/entity_request_spec.rb | 26 ++++++++++++++++++ spec/serializers/environment_serializer_spec.rb | 35 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 spec/serializers/entity_request_spec.rb create mode 100644 spec/serializers/environment_serializer_spec.rb (limited to 'spec') diff --git a/spec/serializers/entity_request_spec.rb b/spec/serializers/entity_request_spec.rb new file mode 100644 index 00000000000..1c220a7b95d --- /dev/null +++ b/spec/serializers/entity_request_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe EntityRequest do + subject do + described_class.new(user: 'user', project: 'some project') + end + + describe 'methods created' do + it 'defines accessible attributes' do + expect(subject.user).to eq 'user' + expect(subject.project).to eq 'some project' + end + + it 'raises error when attribute is not defined' do + expect { subject.some_method }.to raise_error NoMethodError + end + end + + describe '#merge!' do + before { subject.merge!(build: 'some build') } + + it 'appends parameters' do + expect(subject.build).to eq 'some build' + end + end +end diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb new file mode 100644 index 00000000000..3470863681c --- /dev/null +++ b/spec/serializers/environment_serializer_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe EnvironmentSerializer do + let(:serializer) do + described_class.new(path: 'some path').represent(resource) + end + + context 'when there is a single object provided' do + let(:resource) { create(:environment) } + + it 'shows json' do + puts serializer.to_json + end + + it 'it generates payload for single object' do + expect(parsed_json).to be_an_instance_of Hash + end + end + + context 'when there is a collection of objects provided' do + let(:resource) { create_list(:environment, 2) } + + it 'shows json' do + puts serializer.to_json + end + + it 'generates payload for collection' do + expect(parsed_json).to be_an_instance_of Array + end + end + + def parsed_json + JSON.parse(serializer.to_json) + end +end -- cgit v1.2.1 From f1e9c97d64b96bdd398616743ad048f8d147e26b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 2 Nov 2016 14:36:21 +0100 Subject: Use entity request object in environment entity --- spec/serializers/environment_serializer_spec.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 3470863681c..cd9486111f1 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -2,18 +2,21 @@ require 'spec_helper' describe EnvironmentSerializer do let(:serializer) do - described_class.new(path: 'some path').represent(resource) + described_class.new(path: 'some path', user: user) + .represent(resource) end + let(:user) { create(:user) } + context 'when there is a single object provided' do let(:resource) { create(:environment) } it 'shows json' do - puts serializer.to_json + puts serializer.as_json end it 'it generates payload for single object' do - expect(parsed_json).to be_an_instance_of Hash + expect(serializer.as_json).to be_an_instance_of Hash end end @@ -21,15 +24,11 @@ describe EnvironmentSerializer do let(:resource) { create_list(:environment, 2) } it 'shows json' do - puts serializer.to_json + puts serializer.as_json end it 'generates payload for collection' do - expect(parsed_json).to be_an_instance_of Array + expect(serializer.as_json).to be_an_instance_of Array end end - - def parsed_json - JSON.parse(serializer.to_json) - end end -- cgit v1.2.1 From 895673733a5712ee4b69c84195a1d717a72fc032 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 2 Nov 2016 22:15:20 +0000 Subject: Add a `--force` option to bin/changelog --- spec/bin/changelog_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/bin/changelog_spec.rb b/spec/bin/changelog_spec.rb index da167dc570f..8c8bc1b0f1c 100644 --- a/spec/bin/changelog_spec.rb +++ b/spec/bin/changelog_spec.rb @@ -10,6 +10,18 @@ describe 'bin/changelog' do expect(options.amend).to eq true end + it 'parses --force' do + options = described_class.parse(%w[foo --force bar]) + + expect(options.force).to eq true + end + + it 'parses -f' do + options = described_class.parse(%w[foo -f bar]) + + expect(options.force).to eq true + end + it 'parses --merge-request' do options = described_class.parse(%w[foo --merge-request 1234 bar]) -- cgit v1.2.1 From 573921cb9d0b139dec324fb1368feb1347b51624 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 12:54:10 +0100 Subject: Implement entities needed for environments folders --- spec/factories/deployments.rb | 4 ++-- spec/serializers/environment_serializer_spec.rb | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 6f24bf58d14..8c8e5dc54c2 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -1,9 +1,9 @@ FactoryGirl.define do factory :deployment, class: Deployment do - sha '97de212e80737a608d939f648d959671fb0a0142' + sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0' ref 'master' tag false - project nil + project environment factory: :environment diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index cd9486111f1..f7de6c450ab 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -2,17 +2,25 @@ require 'spec_helper' describe EnvironmentSerializer do let(:serializer) do - described_class.new(path: 'some path', user: user) + described_class + .new(user: user, project: project) .represent(resource) end let(:user) { create(:user) } context 'when there is a single object provided' do - let(:resource) { create(:environment) } + let(:deployment) do + create(:deployment, deployable: deployable, + user: user) + end + + let(:deployable) { create(:ci_build) } + let(:project) { deployment.project } + let(:resource) { deployment.environment } it 'shows json' do - puts serializer.as_json + pp serializer.as_json end it 'it generates payload for single object' do @@ -21,6 +29,7 @@ describe EnvironmentSerializer do end context 'when there is a collection of objects provided' do + let(:project) { create(:empty_project) } let(:resource) { create_list(:environment, 2) } it 'shows json' do -- cgit v1.2.1 From 7dd6485a0fd7fc264f86f389da3ab846c62e8724 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 13:42:22 +0100 Subject: Add manual actions for deployment serialization --- spec/serializers/environment_serializer_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'spec') diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index f7de6c450ab..2c94a076aba 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -10,6 +10,11 @@ describe EnvironmentSerializer do let(:user) { create(:user) } context 'when there is a single object provided' do + before do + create(:ci_build, :manual, name: 'manual1', + pipeline: deployable.pipeline) + end + let(:deployment) do create(:deployment, deployable: deployable, user: user) -- cgit v1.2.1 From c3dae798e16dee0b64bc8c9fd0e0e21b2502318e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 14:01:35 +0100 Subject: Extend tests for environments serializer --- spec/serializers/environment_serializer_spec.rb | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 2c94a076aba..81393beb416 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -24,21 +24,30 @@ describe EnvironmentSerializer do let(:project) { deployment.project } let(:resource) { deployment.environment } - it 'shows json' do - pp serializer.as_json - end - it 'it generates payload for single object' do expect(serializer.as_json).to be_an_instance_of Hash end + + it 'contains important elements of environment' do + expect(serializer.as_json) + .to include(:name, :external_url, :environment_url, :last_deployment) + end + + it 'contains relevant information about last deployment' do + last_deployment = serializer.as_json.fetch(:last_deployment) + + expect(last_deployment) + .to include(:ref, :user, :commit, :deployable, :manual_actions) + end end context 'when there is a collection of objects provided' do let(:project) { create(:empty_project) } let(:resource) { create_list(:environment, 2) } - it 'shows json' do - puts serializer.as_json + it 'contains important elements of environment' do + expect(serializer.as_json.first) + .to include(:last_deployment, :name, :external_url) end it 'generates payload for collection' do -- cgit v1.2.1 From a68e7e605aa684e88523f6e28f995c3b497945c6 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 14:22:19 +0100 Subject: Add basic tests for build entity used by serialzier --- spec/serializers/build_entity_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 spec/serializers/build_entity_spec.rb (limited to 'spec') diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb new file mode 100644 index 00000000000..b7acc2066ba --- /dev/null +++ b/spec/serializers/build_entity_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe BuildEntity do + subject do + described_class.new(build, request: double).as_json + end + + context 'when build is a regular job' do + let(:build) { create(:ci_build) } + + it 'contains url to build page and retry action' do + expect(subject).to include(:build_url, :retry_url) + expect(subject).not_to include(:play_url) + end + end + + context 'when build is a manual action' do + let(:build) { create(:ci_build, :manual) } + + it 'contains url to play action' do + expect(subject).to include(:play_url) + end + end +end -- cgit v1.2.1 From c493f285c0d113bc6a880e666e83572eaf8f9403 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 22:05:31 +0800 Subject: Try not to include anything globally! --- spec/models/project_services/jira_service_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index a3e9adae4e2..fd9abc09c57 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' -include Gitlab::Routing.url_helpers describe JiraService, models: true do + include Gitlab::Routing.url_helpers + describe "Associations" do it { is_expected.to belong_to :project } it { is_expected.to have_one :service_hook } -- cgit v1.2.1 From f203ca5c932cc24787e1c44c5801c15923cd04ab Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 3 Nov 2016 15:13:57 +0100 Subject: Fix specs related to deployments and environments --- spec/factories/deployments.rb | 4 ++-- spec/serializers/environment_serializer_spec.rb | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 8c8e5dc54c2..6f24bf58d14 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -1,9 +1,9 @@ FactoryGirl.define do factory :deployment, class: Deployment do - sha 'b83d6e391c22777fca1ed3012fce84f633d7fed0' + sha '97de212e80737a608d939f648d959671fb0a0142' ref 'master' tag false - project + project nil environment factory: :environment diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 81393beb416..32f144faf54 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -8,6 +8,7 @@ describe EnvironmentSerializer do end let(:user) { create(:user) } + let(:project) { create(:project) } context 'when there is a single object provided' do before do @@ -17,11 +18,12 @@ describe EnvironmentSerializer do let(:deployment) do create(:deployment, deployable: deployable, - user: user) + user: user, + project: project, + sha: project.commit.id) end let(:deployable) { create(:ci_build) } - let(:project) { deployment.project } let(:resource) { deployment.environment } it 'it generates payload for single object' do -- cgit v1.2.1 From 9bb25ee18f4baaadafd95ec92cfe39065d349c1d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 23:02:19 +0800 Subject: Use stubs instead of modifying global states --- spec/models/project_services/jira_service_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index fd9abc09c57..ee0e38bd373 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -80,7 +80,9 @@ describe JiraService, models: true do stub_config_setting(relative_url_root: '/gitlab') stub_config_setting(url: Settings.send(:build_gitlab_url)) - Project.default_url_options[:script_name] = "/gitlab" + allow(JiraService).to receive(:default_url_options) do + { script_name: '/gitlab' } + end @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) -- cgit v1.2.1 From cfb511ea692fedffbad5b6ee1a7638b1eb78a4d6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 27 Oct 2016 10:22:18 +0000 Subject: Merge branch 'fix/import-projectmember-security' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix Import/Export foreign key issue to do with project members Cleans-up any foreign keys in `ProjectMember` - same as we do with the rest of the models when importing. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23837 and https://gitlab.com/gitlab-org/gitlab-ce/issues/23739 See merge request !2020 Signed-off-by: Rémy Coutable --- spec/lib/gitlab/import_export/attribute_cleaner_spec.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb index b8e7932eb4a..63bab0f0d0d 100644 --- a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' describe Gitlab::ImportExport::AttributeCleaner, lib: true do + let(:relation_class){ double('relation_class').as_null_object } let(:unsafe_hash) do { + 'id' => 101, 'service_id' => 99, 'moved_to_id' => 99, 'namespace_id' => 99, @@ -27,8 +29,9 @@ describe Gitlab::ImportExport::AttributeCleaner, lib: true do end it 'removes unwanted attributes from the hash' do - described_class.clean!(relation_hash: unsafe_hash) + # allow(relation_class).to receive(:attribute_method?).and_return(true) + parsed_hash = described_class.clean(relation_hash: unsafe_hash, relation_class: relation_class) - expect(unsafe_hash).to eq(post_safe_hash) + expect(parsed_hash).to eq(post_safe_hash) end end -- cgit v1.2.1 From dc9b3db8b0e278399c5ce4ff9b0c5e388ecfe5b0 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 27 Oct 2016 15:10:19 +0000 Subject: Merge branch 'fix/import-export-symlink-vulnerability' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix symlink vulnerability in Import/Export Replaces https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/2018 made by @james Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23822 See merge request !2022 Signed-off-by: Rémy Coutable --- .../lib/gitlab/import_export/file_importer_spec.rb | 42 ++++++++++++++++++++++ .../import_export/project_tree_restorer_spec.rb | 14 ++++++++ .../gitlab/import_export/version_checker_spec.rb | 16 ++++++++- spec/support/import_export/common_util.rb | 10 ++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 spec/lib/gitlab/import_export/file_importer_spec.rb create mode 100644 spec/support/import_export/common_util.rb (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb new file mode 100644 index 00000000000..a88ddd17aca --- /dev/null +++ b/spec/lib/gitlab/import_export/file_importer_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe Gitlab::ImportExport::FileImporter, lib: true do + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: 'test') } + let(:export_path) { "#{Dir::tmpdir}/file_importer_spec" } + let(:valid_file) { "#{shared.export_path}/valid.json" } + let(:symlink_file) { "#{shared.export_path}/invalid.json" } + let(:subfolder_symlink_file) { "#{shared.export_path}/subfolder/invalid.json" } + + before do + stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0) + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) + allow_any_instance_of(Gitlab::ImportExport::CommandLineUtil).to receive(:untar_zxf).and_return(true) + + setup_files + + described_class.import(archive_file: '', shared: shared) + end + + after do + FileUtils.rm_rf(export_path) + end + + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end + + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end + + def setup_files + FileUtils.mkdir_p("#{shared.export_path}/subfolder/") + FileUtils.touch(valid_file) + FileUtils.ln_s(valid_file, symlink_file) + FileUtils.ln_s(valid_file, subfolder_symlink_file) + end +end diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 069ea960321..3038ab53ad8 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +include ImportExport::CommonUtil describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do describe 'restore project tree' do @@ -175,6 +176,19 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do expect(MergeRequest.find_by_title('MR2').source_project_id).to eq(-1) end end + + context 'project.json file access check' do + it 'does not read a symlink' do + Dir.mktmpdir do |tmpdir| + setup_symlink(tmpdir, 'project.json') + allow(shared).to receive(:export_path).and_call_original + + restored_project_json + + expect(shared.errors.first).not_to include('test') + end + end + end end end end diff --git a/spec/lib/gitlab/import_export/version_checker_spec.rb b/spec/lib/gitlab/import_export/version_checker_spec.rb index c680e712b59..2405ac5abfe 100644 --- a/spec/lib/gitlab/import_export/version_checker_spec.rb +++ b/spec/lib/gitlab/import_export/version_checker_spec.rb @@ -1,8 +1,10 @@ require 'spec_helper' +include ImportExport::CommonUtil describe Gitlab::ImportExport::VersionChecker, services: true do + let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: '') } + describe 'bundle a project Git repo' do - let(:shared) { Gitlab::ImportExport::Shared.new(relative_path: '') } let(:version) { Gitlab::ImportExport.version } before do @@ -27,4 +29,16 @@ describe Gitlab::ImportExport::VersionChecker, services: true do end end end + + describe 'version file access check' do + it 'does not read a symlink' do + Dir.mktmpdir do |tmpdir| + setup_symlink(tmpdir, 'VERSION') + + described_class.check!(shared: shared) + + expect(shared.errors.first).not_to include('test') + end + end + end end diff --git a/spec/support/import_export/common_util.rb b/spec/support/import_export/common_util.rb new file mode 100644 index 00000000000..2542a59bb00 --- /dev/null +++ b/spec/support/import_export/common_util.rb @@ -0,0 +1,10 @@ +module ImportExport + module CommonUtil + def setup_symlink(tmpdir, symlink_name) + allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(tmpdir) + + File.open("#{tmpdir}/test", 'w') { |file| file.write("test") } + FileUtils.ln_s("#{tmpdir}/test", "#{tmpdir}/#{symlink_name}") + end + end +end -- cgit v1.2.1 From 1ae557c106e94c20742d0788dc7eb604603faa08 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Nov 2016 23:39:37 +0800 Subject: Merge status_for and status, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7034#note_17742297 --- spec/models/commit_spec.rb | 70 ++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'spec') diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 468e198e9ea..203fb6596a6 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -210,49 +210,51 @@ eos end describe '#status' do - shared_examples 'giving the status from pipeline' do - it do - expect(commit.status).to eq(Ci::Pipeline.status) + context 'without arguments for compound status' do + shared_examples 'giving the status from pipeline' do + it do + expect(commit.status).to eq(Ci::Pipeline.status) + end end - end - context 'with pipelines' do - let!(:pipeline) do - create(:ci_empty_pipeline, project: project, sha: commit.sha) - end + context 'with pipelines' do + let!(:pipeline) do + create(:ci_empty_pipeline, project: project, sha: commit.sha) + end - it_behaves_like 'giving the status from pipeline' - end + it_behaves_like 'giving the status from pipeline' + end - context 'without pipelines' do - it_behaves_like 'giving the status from pipeline' + context 'without pipelines' do + it_behaves_like 'giving the status from pipeline' + end end - end - describe '#status_for' do - let!(:pipeline_from_master) do - create(:ci_empty_pipeline, - project: project, - sha: commit.sha, - ref: 'master', - status: 'failed') - end + context 'when a particular ref is specified' do + let!(:pipeline_from_master) do + create(:ci_empty_pipeline, + project: project, + sha: commit.sha, + ref: 'master', + status: 'failed') + end - let!(:pipeline_from_fix) do - create(:ci_empty_pipeline, - project: project, - sha: commit.sha, - ref: 'fix', - status: 'success') - end + let!(:pipeline_from_fix) do + create(:ci_empty_pipeline, + project: project, + sha: commit.sha, + ref: 'fix', + status: 'success') + end - it 'gives pipelines from a particular branch' do - expect(commit.status_for('master')).to eq(pipeline_from_master.status) - expect(commit.status_for('fix')).to eq(pipeline_from_fix.status) - end + it 'gives pipelines from a particular branch' do + expect(commit.status('master')).to eq(pipeline_from_master.status) + expect(commit.status('fix')).to eq(pipeline_from_fix.status) + end - it 'gives compound status if ref is nil' do - expect(commit.status_for(nil)).to eq(commit.status) + it 'gives compound status if ref is nil' do + expect(commit.status(nil)).to eq(commit.status) + end end end -- cgit v1.2.1 From f3c3d8e63ba078e55c0ce516e19ec11cea429e43 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Nov 2016 00:00:03 +0800 Subject: There's no such method --- spec/models/commit_spec.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'spec') diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 203fb6596a6..e3bb3482d67 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -205,10 +205,6 @@ eos end end - describe '#ci_commits' do - # TODO: kamil - end - describe '#status' do context 'without arguments for compound status' do shared_examples 'giving the status from pipeline' do -- cgit v1.2.1 From d84eb9abd6e851cfe86d4dc64e0ceff9aa9acbc0 Mon Sep 17 00:00:00 2001 From: Lucas Deschamps Date: Thu, 3 Nov 2016 11:29:37 +0100 Subject: Issues atom feed url reflect filters on dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/atom/dashboard_issues_spec.rb | 11 ++++++++++ spec/features/atom/issues_spec.rb | 29 +++++++++++++++++++++++- spec/features/dashboard_issues_spec.rb | 20 +++++++++++++++-- spec/features/issues/filter_issues_spec.rb | 34 +++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb index 4dd9548cfc5..21ee6cedbae 100644 --- a/spec/features/atom/dashboard_issues_spec.rb +++ b/spec/features/atom/dashboard_issues_spec.rb @@ -19,6 +19,17 @@ describe "Dashboard Issues Feed", feature: true do expect(body).to have_selector('title', text: "#{user.name} issues") end + it "renders atom feed with url parameters" do + visit issues_dashboard_path(:atom, private_token: user.private_token, state: 'opened', assignee_id: user.id) + + link = find('link[type="application/atom+xml"]') + params = CGI::parse(URI.parse(link[:href]).query) + + expect(params).to include('private_token' => [user.private_token]) + expect(params).to include('state' => ['opened']) + expect(params).to include('assignee_id' => [user.id.to_s]) + end + context "issue with basic fields" do let!(:issue2) { create(:issue, author: user, assignee: user, project: project2, description: 'test desc') } diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb index 09c140868fb..863412d18eb 100644 --- a/spec/features/atom/issues_spec.rb +++ b/spec/features/atom/issues_spec.rb @@ -3,10 +3,14 @@ require 'spec_helper' describe 'Issues Feed', feature: true do describe 'GET /issues' do let!(:user) { create(:user) } + let!(:group) { create(:group) } let!(:project) { create(:project) } let!(:issue) { create(:issue, author: user, project: project) } - before { project.team << [user, :developer] } + before do + project.team << [user, :developer] + group.add_developer(user) + end context 'when authenticated' do it 'renders atom feed' do @@ -33,5 +37,28 @@ describe 'Issues Feed', feature: true do expect(body).to have_selector('entry summary', text: issue.title) end end + + it "renders atom feed with url parameters for project issues" do + visit namespace_project_issues_path(project.namespace, project, + :atom, private_token: user.private_token, state: 'opened', assignee_id: user.id) + + link = find('link[type="application/atom+xml"]') + params = CGI::parse(URI.parse(link[:href]).query) + + expect(params).to include('private_token' => [user.private_token]) + expect(params).to include('state' => ['opened']) + expect(params).to include('assignee_id' => [user.id.to_s]) + end + + it "renders atom feed with url parameters for group issues" do + visit issues_group_path(group, :atom, private_token: user.private_token, state: 'opened', assignee_id: user.id) + + link = find('link[type="application/atom+xml"]') + params = CGI::parse(URI.parse(link[:href]).query) + + expect(params).to include('private_token' => [user.private_token]) + expect(params).to include('state' => ['opened']) + expect(params).to include('assignee_id' => [user.id.to_s]) + end end end diff --git a/spec/features/dashboard_issues_spec.rb b/spec/features/dashboard_issues_spec.rb index 9b54b5301e5..b898f9bc64f 100644 --- a/spec/features/dashboard_issues_spec.rb +++ b/spec/features/dashboard_issues_spec.rb @@ -44,6 +44,22 @@ describe "Dashboard Issues filtering", feature: true, js: true do expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1) expect(page).to have_selector('.issue', count: 1) end + + it 'updates atom feed link' do + visit_issues(milestone_title: '', assignee_id: user.id) + + link = find('.nav-controls a', text: 'Subscribe') + params = CGI::parse(URI.parse(link[:href]).query) + auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) + auto_discovery_params = CGI::parse(URI.parse(auto_discovery_link[:href]).query) + + expect(params).to include('private_token' => [user.private_token]) + expect(params).to include('milestone_title' => ['']) + expect(params).to include('assignee_id' => [user.id.to_s]) + expect(auto_discovery_params).to include('private_token' => [user.private_token]) + expect(auto_discovery_params).to include('milestone_title' => ['']) + expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) + end end def show_milestone_dropdown @@ -51,7 +67,7 @@ describe "Dashboard Issues filtering", feature: true, js: true do expect(page).to have_selector('.dropdown-content', visible: true) end - def visit_issues - visit issues_dashboard_path + def visit_issues(*args) + visit issues_dashboard_path(*args) end end diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 78208aed46d..2798db92f0f 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -4,6 +4,7 @@ describe 'Filter issues', feature: true do include WaitForAjax let!(:project) { create(:project) } + let!(:group) { create(:group) } let!(:user) { create(:user)} let!(:milestone) { create(:milestone, project: project) } let!(:label) { create(:label, project: project) } @@ -11,6 +12,7 @@ describe 'Filter issues', feature: true do before do project.team << [user, :master] + group.add_developer(user) login_as(user) create(:issue, project: project) end @@ -347,4 +349,36 @@ describe 'Filter issues', feature: true do end end end + + it 'updates atom feed link for project issues' do + visit namespace_project_issues_path(project.namespace, project, milestone_title: '', assignee_id: user.id) + + link = find('.nav-controls a', text: 'Subscribe') + params = CGI::parse(URI.parse(link[:href]).query) + auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) + auto_discovery_params = CGI::parse(URI.parse(auto_discovery_link[:href]).query) + + expect(params).to include('private_token' => [user.private_token]) + expect(params).to include('milestone_title' => ['']) + expect(params).to include('assignee_id' => [user.id.to_s]) + expect(auto_discovery_params).to include('private_token' => [user.private_token]) + expect(auto_discovery_params).to include('milestone_title' => ['']) + expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) + end + + it 'updates atom feed link for group issues' do + visit issues_group_path(group, milestone_title: '', assignee_id: user.id) + + link = find('.nav-controls a', text: 'Subscribe') + params = CGI::parse(URI.parse(link[:href]).query) + auto_discovery_link = find('link[type="application/atom+xml"]', visible: false) + auto_discovery_params = CGI::parse(URI.parse(auto_discovery_link[:href]).query) + + expect(params).to include('private_token' => [user.private_token]) + expect(params).to include('milestone_title' => ['']) + expect(params).to include('assignee_id' => [user.id.to_s]) + expect(auto_discovery_params).to include('private_token' => [user.private_token]) + expect(auto_discovery_params).to include('milestone_title' => ['']) + expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s]) + end end -- cgit v1.2.1 From 46689162a3902ab294341b5860f16947ed030170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 3 Nov 2016 15:15:03 +0100 Subject: Ensure merge request's "remove branch" accessors return booleans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/merge_requests/edit_mr_spec.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/merge_requests/edit_mr_spec.rb b/spec/features/merge_requests/edit_mr_spec.rb index c77e719c5df..c46bd8d449f 100644 --- a/spec/features/merge_requests/edit_mr_spec.rb +++ b/spec/features/merge_requests/edit_mr_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Edit Merge Request', feature: true do let(:user) { create(:user) } let(:project) { create(:project, :public) } - let(:merge_request) { create(:merge_request, :with_diffs, source_project: project) } + let(:merge_request) { create(:merge_request, :simple, source_project: project) } before do project.team << [user, :master] @@ -28,5 +28,17 @@ feature 'Edit Merge Request', feature: true do expect(page).to have_content 'Someone edited the merge request the same time you did' end + + it 'allows to unselect "Remove source branch"' do + merge_request.update(merge_params: { 'force_remove_source_branch' => '1' }) + expect(merge_request.merge_params['force_remove_source_branch']).to be_truthy + + visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + uncheck 'Remove source branch when merge request is accepted' + + click_button 'Save changes' + + expect(page).to have_content 'Remove source branch' + end end end -- cgit v1.2.1 From 813fd6f67531a0a9f9d072f18315d2ed43526de4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 2 Nov 2016 22:21:12 +0000 Subject: DRY up the specs for bin/changelog --- spec/bin/changelog_spec.rb | 56 +++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) (limited to 'spec') diff --git a/spec/bin/changelog_spec.rb b/spec/bin/changelog_spec.rb index 8c8bc1b0f1c..7f4298db59f 100644 --- a/spec/bin/changelog_spec.rb +++ b/spec/bin/changelog_spec.rb @@ -10,54 +10,38 @@ describe 'bin/changelog' do expect(options.amend).to eq true end - it 'parses --force' do - options = described_class.parse(%w[foo --force bar]) + it 'parses --force and -f' do + %w[--force -f].each do |flag| + options = described_class.parse(%W[foo #{flag} bar]) - expect(options.force).to eq true + expect(options.force).to eq true + end end - it 'parses -f' do - options = described_class.parse(%w[foo -f bar]) + it 'parses --merge-request and -m' do + %w[--merge-request -m].each do |flag| + options = described_class.parse(%W[foo #{flag} 1234 bar]) - expect(options.force).to eq true + expect(options.merge_request).to eq 1234 + end end - it 'parses --merge-request' do - options = described_class.parse(%w[foo --merge-request 1234 bar]) + it 'parses --dry-run and -n' do + %w[--dry-run -n].each do |flag| + options = described_class.parse(%W[foo #{flag} bar]) - expect(options.merge_request).to eq 1234 + expect(options.dry_run).to eq true + end end - it 'parses -m' do - options = described_class.parse(%w[foo -m 4321 bar]) - - expect(options.merge_request).to eq 4321 - end - - it 'parses --dry-run' do - options = described_class.parse(%w[foo --dry-run bar]) - - expect(options.dry_run).to eq true - end - - it 'parses -n' do - options = described_class.parse(%w[foo -n bar]) - - expect(options.dry_run).to eq true - end - - it 'parses --git-username' do + it 'parses --git-username and -u' do allow(described_class).to receive(:git_user_name).and_return('Jane Doe') - options = described_class.parse(%w[foo --git-username bar]) - - expect(options.author).to eq 'Jane Doe' - end - it 'parses -u' do - allow(described_class).to receive(:git_user_name).and_return('John Smith') - options = described_class.parse(%w[foo -u bar]) + %w[--git-username -u].each do |flag| + options = described_class.parse(%W[foo #{flag} bar]) - expect(options.author).to eq 'John Smith' + expect(options.author).to eq 'Jane Doe' + end end it 'parses -h' do -- cgit v1.2.1 From 055e2ac293d7c79450dcd398a36d7f2382989822 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Thu, 3 Nov 2016 16:13:35 -0500 Subject: Move jquery.timeago to vendor directory --- spec/javascripts/merge_request_widget_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 1e2072f370a..49dfeab61d8 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,6 +1,6 @@ /* eslint-disable */ /*= require merge_request_widget */ -/*= require lib/utils/jquery.timeago.js */ +/*= require jquery.timeago.js */ (function() { describe('MergeRequestWidget', function() { -- cgit v1.2.1 From c1388d0efb79b755c06b9db19fc4ad47af7cf0a3 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 3 Nov 2016 14:12:20 +0000 Subject: Allow multiple repository storage shards to be enabled, and automatically round-robin between them --- spec/models/application_setting_spec.rb | 56 ++++++++++++++++++++++++++++++--- spec/models/project_spec.rb | 15 +++++---- spec/requests/api/settings_spec.rb | 1 + 3 files changed, 62 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index cc215d252f9..2b76e056f3c 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -41,14 +41,62 @@ describe ApplicationSetting, models: true do subject { setting } end - context 'repository storages inclussion' do + # Upgraded databases will have this sort of content + context 'repository_storages is a String, not an Array' do + before { setting.__send__(:raw_write_attribute, :repository_storages, 'default') } + + it { expect(setting.repository_storages_before_type_cast).to eq('default') } + it { expect(setting.repository_storages).to eq(['default']) } + end + + context 'repository storages' do before do - storages = { 'custom' => 'tmp/tests/custom_repositories' } + storages = { + 'custom1' => 'tmp/tests/custom_repositories_1', + 'custom2' => 'tmp/tests/custom_repositories_2', + 'custom3' => 'tmp/tests/custom_repositories_3', + + } allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) end - it { is_expected.to allow_value('custom').for(:repository_storage) } - it { is_expected.not_to allow_value('alternative').for(:repository_storage) } + describe 'inclusion' do + it { is_expected.to allow_value('custom1').for(:repository_storages) } + it { is_expected.to allow_value(['custom2', 'custom3']).for(:repository_storages) } + it { is_expected.not_to allow_value('alternative').for(:repository_storages) } + it { is_expected.not_to allow_value(['alternative', 'custom1']).for(:repository_storages) } + end + + describe 'presence' do + it { is_expected.not_to allow_value([]).for(:repository_storages) } + it { is_expected.not_to allow_value("").for(:repository_storages) } + it { is_expected.not_to allow_value(nil).for(:repository_storages) } + end + + describe '.pick_repository_storage' do + it 'uses Array#sample to pick a random storage' do + array = double('array', sample: 'random') + expect(setting).to receive(:repository_storages).and_return(array) + + expect(setting.pick_repository_storage).to eq('random') + end + + describe '#repository_storage' do + it 'returns the first storage' do + setting.repository_storages = ['good', 'bad'] + + expect(setting.repository_storage).to eq('good') + end + end + + describe '#repository_storage=' do + it 'overwrites repository_storages' do + setting.repository_storage = 'overwritten' + + expect(setting.repository_storages).to eq(['overwritten']) + end + end + end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index aef277357cf..0245897938c 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -837,16 +837,19 @@ describe Project, models: true do context 'repository storage by default' do let(:project) { create(:empty_project) } - subject { project.repository_storage } - before do - storages = { 'alternative_storage' => '/some/path' } + storages = { + 'default' => 'tmp/tests/repositories', + 'picked' => 'tmp/tests/repositories', + } allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) - stub_application_setting(repository_storage: 'alternative_storage') - allow_any_instance_of(Project).to receive(:ensure_dir_exist).and_return(true) end - it { is_expected.to eq('alternative_storage') } + it 'picks storage from ApplicationSetting' do + expect_any_instance_of(ApplicationSetting).to receive(:pick_repository_storage).and_return('picked') + + expect(project.repository_storage).to eq('picked') + end end context 'shared runners by default' do diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index f4903d8e0be..096a8ebab70 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -33,6 +33,7 @@ describe API::API, 'Settings', api: true do expect(json_response['default_projects_limit']).to eq(3) expect(json_response['signin_enabled']).to be_falsey expect(json_response['repository_storage']).to eq('custom') + expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['koding_enabled']).to be_truthy expect(json_response['koding_url']).to eq('http://koding.example.com') end -- cgit v1.2.1 From bea83d2579ca3b8ca48802f5c114cea60bce396e Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Thu, 27 Oct 2016 10:47:14 +0900 Subject: Remove an extra leading space from diff content --- spec/helpers/diff_helper_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 9c7c79f57c6..837e7afa7e8 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -61,7 +61,7 @@ describe DiffHelper do describe '#diff_line_content' do it 'returns non breaking space when line is empty' do - expect(diff_line_content(nil)).to eq('  ') + expect(diff_line_content(nil)).to eq(' ') end it 'returns the line itself' do -- cgit v1.2.1 From 27528d4490804c4bf5e16f44d12f9825cf7c6cef Mon Sep 17 00:00:00 2001 From: the-undefined Date: Thu, 3 Nov 2016 06:34:52 +0000 Subject: Move spinach public snippet feature to rspec spec - Add rspec feature for public snippets - Remove spinach test for public snippets --- spec/features/snippets/public_snippets_spec.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 spec/features/snippets/public_snippets_spec.rb (limited to 'spec') diff --git a/spec/features/snippets/public_snippets_spec.rb b/spec/features/snippets/public_snippets_spec.rb new file mode 100644 index 00000000000..34300ccb940 --- /dev/null +++ b/spec/features/snippets/public_snippets_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +feature 'Public Snippets', feature: true do + scenario 'Unauthenticated user should see public snippets' do + public_snippet = create(:personal_snippet, :public) + + visit snippet_path(public_snippet) + + expect(page).to have_content(public_snippet.content) + end + + scenario 'Unauthenticated user should see raw public snippets' do + public_snippet = create(:personal_snippet, :public) + + visit raw_snippet_path(public_snippet) + + expect(page).to have_content(public_snippet.content) + end +end -- cgit v1.2.1 From a2c1178c21796933916bb44b3d6b8e4d11d89d7f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 10:16:30 +0100 Subject: Expose commit author if author exists --- spec/serializers/environment_serializer_spec.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 32f144faf54..37bc086826c 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -7,6 +7,7 @@ describe EnvironmentSerializer do .represent(resource) end + let(:json) { serializer.as_json } let(:user) { create(:user) } let(:project) { create(:project) } @@ -27,16 +28,16 @@ describe EnvironmentSerializer do let(:resource) { deployment.environment } it 'it generates payload for single object' do - expect(serializer.as_json).to be_an_instance_of Hash + expect(json).to be_an_instance_of Hash end it 'contains important elements of environment' do - expect(serializer.as_json) + expect(json) .to include(:name, :external_url, :environment_url, :last_deployment) end it 'contains relevant information about last deployment' do - last_deployment = serializer.as_json.fetch(:last_deployment) + last_deployment = json.fetch(:last_deployment) expect(last_deployment) .to include(:ref, :user, :commit, :deployable, :manual_actions) @@ -48,12 +49,12 @@ describe EnvironmentSerializer do let(:resource) { create_list(:environment, 2) } it 'contains important elements of environment' do - expect(serializer.as_json.first) + expect(json.first) .to include(:last_deployment, :name, :external_url) end it 'generates payload for collection' do - expect(serializer.as_json).to be_an_instance_of Array + expect(json).to be_an_instance_of Array end end end -- cgit v1.2.1 From c315332b8a90d26197ad93a6e982888aa575e2d4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 10:19:29 +0100 Subject: Refine build entity tests a little --- spec/serializers/build_entity_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index b7acc2066ba..2282b560d7f 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -1,10 +1,12 @@ require 'spec_helper' describe BuildEntity do - subject do - described_class.new(build, request: double).as_json + let(:entity) do + described_class.new(build, request: double) end + subject { entity.as_json } + context 'when build is a regular job' do let(:build) { create(:ci_build) } -- cgit v1.2.1 From 7108e2e75362aec227765820e116e3d7bc1ac08d Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 4 Nov 2016 09:29:52 +0000 Subject: Fix new branch button spec 1. We can create the note directly on the issue, rather than attaching it after creation. 2. We need to update the MergeRequestClosesIssues relation to ensure that the issue know that it's closed by the MR. 3. We should also check that the unavailable button is displayed - not just that the available button is displayed. --- spec/features/issues/new_branch_button_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/new_branch_button_spec.rb b/spec/features/issues/new_branch_button_spec.rb index fb0c4704285..755f4eb1b0b 100644 --- a/spec/features/issues/new_branch_button_spec.rb +++ b/spec/features/issues/new_branch_button_spec.rb @@ -18,8 +18,8 @@ feature 'Start new branch from an issue', feature: true do end context "when there is a referenced merge request" do - let(:note) do - create(:note, :on_issue, :system, project: project, + let!(:note) do + create(:note, :on_issue, :system, project: project, noteable: issue, note: "Mentioned in !#{referenced_mr.iid}") end let(:referenced_mr) do @@ -28,12 +28,13 @@ feature 'Start new branch from an issue', feature: true do end before do - issue.notes << note + referenced_mr.cache_merge_request_closes_issues!(user) visit namespace_project_issue_path(project.namespace, project, issue) end it "hides the new branch button", js: true do + expect(page).to have_css('#new-branch .unavailable') expect(page).not_to have_css('#new-branch .available') expect(page).to have_content /1 Related Merge Request/ end -- cgit v1.2.1 From 277712cc670684ed6df162f810f860215da2a7ee Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 7 Oct 2016 16:18:42 +0100 Subject: Creates new list from a new label Closes #23026 --- spec/features/boards/boards_spec.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index a92075fec8f..6cb8753e8fc 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -380,6 +380,25 @@ describe 'Issue Boards', feature: true, js: true do wait_for_board_cards(1, 5) end + + it 'creates new list from a new label' do + click_button 'Create new list' + + wait_for_ajax + + click_link 'Create new label' + + fill_in('new_label_name', with: 'Testing New Label') + + first('.suggest-colors a').click + + click_button 'Create' + + wait_for_ajax + wait_for_vue_resource + + expect(page).to have_selector('.board', count: 5) + end end end -- cgit v1.2.1 From dcd70453a46f9fbf178382b49ff2b9af1937b982 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 1 Nov 2016 17:08:04 +0200 Subject: Fix: Guest sees some repository details and gets 404 --- spec/features/projects/features_visibility_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index e796ee570b7..09aa6758b5c 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -183,4 +183,19 @@ describe 'Edit Project Settings', feature: true do end end end + + # Regression spec for https://gitlab.com/gitlab-org/gitlab-ce/issues/24056 + describe 'project statistic visibility' do + let!(:project) { create(:project, :private) } + + before do + project.team << [member, :guest] + login_as(member) + visit namespace_project_path(project.namespace, project) + end + + it "does not show project statistic for guest" do + expect(page).not_to have_selector('.project-stats') + end + end end -- cgit v1.2.1 From b7dff1b072204c8c2ad480301b3139e4823c41f4 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 3 Nov 2016 12:22:56 +0200 Subject: Fix: Todos Filter Shows All Users --- spec/features/todos/todos_filtering_spec.rb | 53 ++++++++++++++++++++++++----- spec/models/user_spec.rb | 14 ++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/features/todos/todos_filtering_spec.rb b/spec/features/todos/todos_filtering_spec.rb index b9e66243d84..d1f2bc78884 100644 --- a/spec/features/todos/todos_filtering_spec.rb +++ b/spec/features/todos/todos_filtering_spec.rb @@ -36,17 +36,54 @@ describe 'Dashboard > User filters todos', feature: true, js: true do expect(page).not_to have_content project_2.name_with_namespace end - it 'filters by author' do - click_button 'Author' - within '.dropdown-menu-author' do - fill_in 'Search authors', with: user_1.name - click_link user_1.name + context "Author filter" do + it 'filters by author' do + click_button 'Author' + + within '.dropdown-menu-author' do + fill_in 'Search authors', with: user_1.name + click_link user_1.name + end + + wait_for_ajax + + expect(find('.todos-list')).to have_content user_1.name + expect(find('.todos-list')).not_to have_content user_2.name end - wait_for_ajax + it "shows only authors of existing todos" do + click_button 'Author' + + within '.dropdown-menu-author' do + # It should contain two users + "Any Author" + expect(page).to have_selector('.dropdown-menu-user-link', count: 3) + expect(page).to have_content(user_1.name) + expect(page).to have_content(user_2.name) + end + end - expect(find('.todos-list')).to have_content user_1.name - expect(find('.todos-list')).not_to have_content user_2.name + it "shows only authors of existing done todos" do + user_3 = create :user + user_4 = create :user + create(:todo, user: user_1, author: user_3, project: project_1, target: issue, action: 1, state: :done) + create(:todo, user: user_1, author: user_4, project: project_2, target: merge_request, action: 2, state: :done) + + project_1.team << [user_3, :developer] + project_2.team << [user_4, :developer] + + visit dashboard_todos_path(state: 'done') + + click_button 'Author' + + within '.dropdown-menu-author' do + # It should contain two users + "Any Author" + expect(page).to have_selector('.dropdown-menu-user-link', count: 3) + expect(page).to have_content(user_3.name) + expect(page).to have_content(user_4.name) + expect(page).not_to have_content(user_1.name) + expect(page).not_to have_content(user_2.name) + end + end end it 'filters by type' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d1ed774a914..ba47479a2e1 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -256,6 +256,20 @@ describe User, models: true do expect(users_without_two_factor).not_to include(user_with_2fa.id) end end + + describe '.todo_authors' do + it 'filters users' do + create :user + user_2 = create :user + user_3 = create :user + current_user = create :user + create(:todo, user: current_user, author: user_2, state: :done) + create(:todo, user: current_user, author: user_3, state: :pending) + + expect(User.todo_authors(current_user.id, 'pending')).to eq [user_3] + expect(User.todo_authors(current_user.id, 'done')).to eq [user_2] + end + end end describe "Respond to" do -- cgit v1.2.1 From 3968b07d7ea1fd2ca07e427a487ea94ca0c6081d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 13:08:58 +0100 Subject: Add tests for serialization entities, add user entity --- spec/serializers/build_entity_spec.rb | 5 ++++ spec/serializers/commit_entity_spec.rb | 44 ++++++++++++++++++++++++++++++++++ spec/serializers/user_entity_spec.rb | 23 ++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 spec/serializers/commit_entity_spec.rb create mode 100644 spec/serializers/user_entity_spec.rb (limited to 'spec') diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index 2282b560d7f..2734f5bedca 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -14,6 +14,11 @@ describe BuildEntity do expect(subject).to include(:build_url, :retry_url) expect(subject).not_to include(:play_url) end + + it 'does not contain sensitive information' do + expect(subject).not_to include(/token/) + expect(subject).not_to include(/variables/) + end end context 'when build is a manual action' do diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb new file mode 100644 index 00000000000..628e35c9a28 --- /dev/null +++ b/spec/serializers/commit_entity_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe CommitEntity do + let(:entity) do + described_class.new(commit, request: request) + end + + let(:request) { double('request') } + let(:project) { create(:project) } + let(:commit) { project.commit } + + subject { entity.as_json } + + before do + allow(request).to receive(:project).and_return(project) + end + + context 'when commit author is a user' do + before do + create(:user, email: commit.author_email) + end + + it 'contains information about user' do + expect(subject.fetch(:author)).not_to be_nil + end + end + + context 'when commit author is not a user' do + it 'does not contain author details' do + expect(subject.fetch(:author)).to be_nil + end + end + + it 'contains commit URL' do + expect(subject).to include(:commit_url) + end + + it 'needs to receive project in the request' do + expect(request).to receive(:project) + .and_return(project) + + subject + end +end diff --git a/spec/serializers/user_entity_spec.rb b/spec/serializers/user_entity_spec.rb new file mode 100644 index 00000000000..c5d11cbcf5e --- /dev/null +++ b/spec/serializers/user_entity_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe UserEntity do + let(:entity) { described_class.new(user) } + let(:user) { create(:user) } + subject { entity.as_json } + + it 'exposes user name and login' do + expect(subject).to include(:username, :name) + end + + it 'does not expose passwords' do + expect(subject).not_to include(/password/) + end + + it 'does not expose tokens' do + expect(subject).not_to include(/token/) + end + + it 'does not expose 2FA OTPs' do + expect(subject).not_to include(/otp/) + end +end -- cgit v1.2.1 From e49fb264e6cb5eff44330d69d34b5f74ef262659 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 13:23:06 +0100 Subject: Add tests for deployment and environment entitites --- spec/serializers/deployment_entity_spec.rb | 20 ++++++++++++++++++++ spec/serializers/environment_entity_spec.rb | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 spec/serializers/deployment_entity_spec.rb create mode 100644 spec/serializers/environment_entity_spec.rb (limited to 'spec') diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb new file mode 100644 index 00000000000..51b6de91571 --- /dev/null +++ b/spec/serializers/deployment_entity_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe DeploymentEntity do + let(:entity) do + described_class.new(deployment, request: double) + end + + let(:deployment) { create(:deployment) } + + subject { entity.as_json } + + it 'exposes internal deployment id' do + expect(subject).to include(:iid) + end + + it 'exposes nested information about branch' do + expect(subject[:ref][:name]).to eq 'master' + expect(subject[:ref][:ref_url]).not_to be_empty + end +end diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb new file mode 100644 index 00000000000..4ca8c299147 --- /dev/null +++ b/spec/serializers/environment_entity_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe EnvironmentEntity do + let(:entity) do + described_class.new(environment, request: double) + end + + let(:environment) { create(:environment) } + subject { entity.as_json } + + it 'exposes latest deployment' do + expect(subject).to include(:last_deployment) + end + + it 'exposes core elements of environment' do + expect(subject).to include(:id, :name, :state, :environment_url) + end +end -- cgit v1.2.1 From 6bcc52a53678ca68001189c801497862d3f6e758 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 27 Oct 2016 14:59:52 +0200 Subject: Refine Git garbage collection --- spec/lib/gitlab/backend/shell_spec.rb | 1 - spec/lib/gitlab/exclusive_lease_spec.rb | 27 ++++- spec/models/application_setting_spec.rb | 18 +++ .../services/projects/housekeeping_service_spec.rb | 28 ++++- spec/workers/git_garbage_collect_worker_spec.rb | 122 +++++++++++++++++++-- 5 files changed, 178 insertions(+), 18 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index f826d0d1b04..4b08a02ec73 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -14,7 +14,6 @@ describe Gitlab::Shell, lib: true do it { is_expected.to respond_to :add_repository } it { is_expected.to respond_to :remove_repository } it { is_expected.to respond_to :fork_repository } - it { is_expected.to respond_to :gc } it { is_expected.to respond_to :add_namespace } it { is_expected.to respond_to :rm_namespace } it { is_expected.to respond_to :mv_namespace } diff --git a/spec/lib/gitlab/exclusive_lease_spec.rb b/spec/lib/gitlab/exclusive_lease_spec.rb index 6b3bd08b978..a366d68a146 100644 --- a/spec/lib/gitlab/exclusive_lease_spec.rb +++ b/spec/lib/gitlab/exclusive_lease_spec.rb @@ -5,32 +5,47 @@ describe Gitlab::ExclusiveLease, type: :redis do describe '#try_obtain' do it 'cannot obtain twice before the lease has expired' do - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600) - expect(lease.try_obtain).to eq(true) + lease = described_class.new(unique_key, timeout: 3600) + expect(lease.try_obtain).to be_present expect(lease.try_obtain).to eq(false) end it 'can obtain after the lease has expired' do timeout = 1 - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: timeout) + lease = described_class.new(unique_key, timeout: timeout) lease.try_obtain # start the lease sleep(2 * timeout) # lease should have expired now - expect(lease.try_obtain).to eq(true) + expect(lease.try_obtain).to be_present end end describe '#exists?' do it 'returns true for an existing lease' do - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600) + lease = described_class.new(unique_key, timeout: 3600) lease.try_obtain expect(lease.exists?).to eq(true) end it 'returns false for a lease that does not exist' do - lease = Gitlab::ExclusiveLease.new(unique_key, timeout: 3600) + lease = described_class.new(unique_key, timeout: 3600) expect(lease.exists?).to eq(false) end end + + describe '.cancel' do + it 'can cancel a lease' do + uuid = new_lease(unique_key) + expect(uuid).to be_present + expect(new_lease(unique_key)).to eq(false) + + described_class.cancel(unique_key, uuid) + expect(new_lease(unique_key)).to be_present + end + + def new_lease(key) + described_class.new(key, timeout: 3600).try_obtain + end + end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 2b76e056f3c..b950fcdd81a 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -98,6 +98,24 @@ describe ApplicationSetting, models: true do end end end + + context 'housekeeping settings' do + it { is_expected.not_to allow_value(0).for(:housekeeping_incremental_repack_period) } + + it 'wants the full repack period to be longer than the incremental repack period' do + subject.housekeeping_incremental_repack_period = 2 + subject.housekeeping_full_repack_period = 1 + + expect(subject).not_to be_valid + end + + it 'wants the gc period to be longer than the full repack period' do + subject.housekeeping_full_repack_period = 2 + subject.housekeeping_gc_period = 1 + + expect(subject).not_to be_valid + end + end end context 'restricted signup domains' do diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb index cf90b33dfb4..57a5aa5cedc 100644 --- a/spec/services/projects/housekeeping_service_spec.rb +++ b/spec/services/projects/housekeeping_service_spec.rb @@ -14,8 +14,10 @@ describe Projects::HousekeepingService do describe '#execute' do it 'enqueues a sidekiq job' do - expect(subject).to receive(:try_obtain_lease).and_return(true) - expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id) + expect(subject).to receive(:try_obtain_lease).and_return(:the_uuid) + expect(subject).to receive(:lease_key).and_return(:the_lease_key) + expect(subject).to receive(:task).and_return(:the_task) + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :the_task, :the_lease_key, :the_uuid) subject.execute expect(project.reload.pushes_since_gc).to eq(0) @@ -58,4 +60,26 @@ describe Projects::HousekeepingService do end.to change { project.pushes_since_gc }.from(0).to(1) end end + + it 'uses all three kinds of housekeeping we offer' do + allow(subject).to receive(:try_obtain_lease).and_return(:the_uuid) + allow(subject).to receive(:lease_key).and_return(:the_lease_key) + + # At push 200 + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :gc, :the_lease_key, :the_uuid). + exactly(1).times + # At push 50, 100, 150 + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :full_repack, :the_lease_key, :the_uuid). + exactly(3).times + # At push 10, 20, ... (except those above) + expect(GitGarbageCollectWorker).to receive(:perform_async).with(project.id, :incremental_repack, :the_lease_key, :the_uuid). + exactly(16).times + + 201.times do + subject.increment! + subject.execute if subject.needed? + end + + expect(project.pushes_since_gc).to eq(1) + end end diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index c9f5aae0815..ae258bde26d 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -1,3 +1,6 @@ +require 'digest' +require 'fileutils' + require 'spec_helper' describe GitGarbageCollectWorker do @@ -6,16 +9,12 @@ describe GitGarbageCollectWorker do subject { GitGarbageCollectWorker.new } - before do - allow(subject).to receive(:gitlab_shell).and_return(shell) - end - describe "#perform" do - it "runs `git gc`" do - expect(shell).to receive(:gc).with( - project.repository_storage_path, - project.path_with_namespace). - and_return(true) + it "flushes ref caches when the task is 'gc'" do + expect(subject).to receive(:command).with(:gc).and_return([:the, :command]) + expect(Gitlab::Popen).to receive(:popen). + with([:the, :command], project.repository.path_to_repo).and_return(["", 0]) + expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original expect_any_instance_of(Repository).to receive(:branch_names).and_call_original expect_any_instance_of(Repository).to receive(:branch_count).and_call_original @@ -23,5 +22,110 @@ describe GitGarbageCollectWorker do subject.perform(project.id) end + + shared_examples 'gc tasks' do + before { allow(subject).to receive(:bitmaps_enabled?).and_return(bitmaps_enabled) } + + it 'incremental repack adds a new packfile' do + create_objects(project) + before_packs = packs(project) + + expect(before_packs.count).to be >= 1 + + subject.perform(project.id, 'incremental_repack') + after_packs = packs(project) + + # Exactly one new pack should have been created + expect(after_packs.count).to eq(before_packs.count + 1) + + # Previously existing packs are still around + expect(before_packs & after_packs).to eq(before_packs) + end + + it 'full repack consolidates into 1 packfile' do + create_objects(project) + subject.perform(project.id, 'incremental_repack') + before_packs = packs(project) + + expect(before_packs.count).to be >= 2 + + subject.perform(project.id, 'full_repack') + after_packs = packs(project) + + expect(after_packs.count).to eq(1) + + # Previously existing packs should be gone now + expect(after_packs - before_packs).to eq(after_packs) + + expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled) + end + + it 'gc consolidates into 1 packfile and updates packed-refs' do + create_objects(project) + before_packs = packs(project) + before_packed_refs = packed_refs(project) + + expect(before_packs.count).to be >= 1 + + subject.perform(project.id, 'gc') + after_packed_refs = packed_refs(project) + after_packs = packs(project) + + expect(after_packs.count).to eq(1) + + # Previously existing packs should be gone now + expect(after_packs - before_packs).to eq(after_packs) + + # The packed-refs file should have been updated during 'git gc' + expect(before_packed_refs).not_to eq(after_packed_refs) + + expect(File.exist?(bitmap_path(after_packs.first))).to eq(bitmaps_enabled) + end + end + + context 'with bitmaps enabled' do + let(:bitmaps_enabled) { true } + + include_examples 'gc tasks' + end + + context 'with bitmaps disabled' do + let(:bitmaps_enabled) { false } + + include_examples 'gc tasks' + end + end + + # Create a new commit on a random new branch + def create_objects(project) + rugged = project.repository.rugged + old_commit = rugged.branches.first.target + new_commit_sha = Rugged::Commit.create( + rugged, + message: "hello world #{SecureRandom.hex(6)}", + author: Gitlab::Git::committer_hash(email: 'foo@bar', name: 'baz'), + committer: Gitlab::Git::committer_hash(email: 'foo@bar', name: 'baz'), + tree: old_commit.tree, + parents: [old_commit], + ) + project.repository.update_ref!( + "refs/heads/#{SecureRandom.hex(6)}", + new_commit_sha, + Gitlab::Git::BLANK_SHA + ) + end + + def packs(project) + Dir["#{project.repository.path_to_repo}/objects/pack/*.pack"] + end + + def packed_refs(project) + path = "#{project.repository.path_to_repo}/packed-refs" + FileUtils.touch(path) + File.read(path) + end + + def bitmap_path(pack) + pack.sub(/\.pack\z/, '.bitmap') end end -- cgit v1.2.1 From c5eca4a632d3be058a0094d269fb0aac88e130d5 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 4 Nov 2016 14:34:10 +0100 Subject: Remove unused 'require' --- spec/workers/git_garbage_collect_worker_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index ae258bde26d..e471a68a49a 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -1,4 +1,3 @@ -require 'digest' require 'fileutils' require 'spec_helper' -- cgit v1.2.1 From 1db9f826c16053e32a1d234bf40b2ca399779cdf Mon Sep 17 00:00:00 2001 From: Rodolfo Santos Date: Fri, 16 Sep 2016 08:02:42 -0300 Subject: Add setting to only allow merge requests to be merged when all discussions are resolved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../projects/merge_requests_controller_spec.rb | 26 ++++++++++ spec/factories/merge_requests.rb | 5 ++ ...eck_if_mergeable_with_unresolved_discussions.rb | 53 ++++++++++++++++++++ spec/models/merge_request_spec.rb | 58 +++++++++++++++++++++- spec/requests/api/projects_spec.rb | 36 +++++++++++++- 5 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 940d54f8686..79820e9a435 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -297,6 +297,32 @@ describe Projects::MergeRequestsController do end end end + + context 'when project project has unresolved discussion' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, allowed) + end + + context "when the only_allow_merge_if_all_discussions_are_resolved? is true" do + let(:allowed) { true } + + it 'returns :failed' do + merge_with_sha + + expect(assigns(:status)).to eq(:failed) + end + end + + context "when the only_allow_merge_if_all_discussions_are_resolved? is false" do + let(:allowed) { false } + + it 'returns :failed' do + merge_with_sha + + expect(assigns(:status)).to eq(:success) + end + end + end end end diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index f780e01253c..37eb49c94df 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -68,6 +68,11 @@ FactoryGirl.define do factory :closed_merge_request, traits: [:closed] factory :reopened_merge_request, traits: [:reopened] factory :merge_request_with_diffs, traits: [:with_diffs] + factory :merge_request_with_diff_notes do + after(:create) do |mr| + create(:diff_note_on_merge_request, noteable: mr, project: mr.source_project) + end + end factory :labeled_merge_request do transient do diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb new file mode 100644 index 00000000000..100ddda0167 --- /dev/null +++ b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +feature 'Check if mergeable with unresolved discussions', js: true, feature: true do + let!(:user) { create(:user) } + let!(:project) { create(:project, :public, only_allow_merge_if_all_discussions_are_resolved: allowed) } + let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user, title: "Bug NS-04" ) } + + before do + login_as user + project.team << [user, :master] + end + + context 'when only_allow_merge_if_all_discussions_are_resolved is false' do + let(:allowed) { false } + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'when only_allow_merge_if_all_discussions_are_resolved is true' do + let(:allowed) { true } + + context "when discussions are resolved" do + + before do + merge_request.discussions.each { |d| d.resolve!(user) } + end + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context "when discussions are unresolved" do + + it 'does not allow to merge' do + visit_merge_request(merge_request) + + expect(page).not_to have_button 'Accept Merge Request' + expect(page).to have_content('This merge request has unresolved discussions') + end + end + end + + def visit_merge_request(merge_request) + visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + end +end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 1067ff7bb4d..f3d0373e6d7 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -837,6 +837,17 @@ describe MergeRequest, models: true do expect(subject.mergeable_state?).to be_falsey end end + + context "when project settings restrict to merge only when all the discussions are resolved" do + before do + project.only_allow_merge_if_all_discussions_are_resolved = true + allow(subject).to receive(:mergeable_discussions_state?) { false } + end + + it 'returns false' do + expect(subject.mergeable_state?).to be_falsey + end + end end end @@ -887,7 +898,52 @@ describe MergeRequest, models: true do end end - describe '#environments' do + describe '#mergeable_discussions_state?' do + let!(:user) { create(:user) } + let!(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: allowed) } + + subject { create(:merge_request_with_diff_notes, source_project: project) } + + context 'when is true' do + let(:allowed) { true } + + context 'when discussions are resolved' do + before do + subject.discussions.each { |d| d.resolve!(user) } + end + + it 'returns true' do + expect(subject.mergeable_discussions_state?).to be_truthy + end + end + + context 'when discussions are unresolved' do + before do + subject.discussions.map(&:unresolve!) + end + + it 'returns false' do + expect(subject.mergeable_discussions_state?).to be_falsey + end + end + end + + context 'when is false' do + let(:allowed) { false } + + context 'when discussions are unresolved' do + before do + subject.discussions.map(&:unresolve!) + end + + it 'returns true' do + expect(subject.mergeable_discussions_state?).to be_truthy + end + end + end + end + + describe "#environments" do let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 973928d007a..3c8f0ac531a 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -256,7 +256,8 @@ describe API::API, api: true do merge_requests_enabled: false, wiki_enabled: false, only_allow_merge_if_build_succeeds: false, - request_access_enabled: true + request_access_enabled: true, + only_allow_merge_if_all_discussions_are_resolved: false }) post api('/projects', user), project @@ -327,6 +328,22 @@ describe API::API, api: true do expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy end + it 'sets a project as allowing merge even if discussions are unresolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false }) + + post api('/projects', user), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey + end + + it 'sets a project as allowing merge only if all discussions are resolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true }) + + post api('/projects', user), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy + end + context 'when a visibility level is restricted' do before do @project = attributes_for(:project, { public: true }) @@ -448,6 +465,22 @@ describe API::API, api: true do post api("/projects/user/#{user.id}", admin), project expect(json_response['only_allow_merge_if_build_succeeds']).to be_truthy end + + it 'sets a project as allowing merge even if discussions are unresolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false }) + + post api("/projects/user/#{user.id}", admin), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey + end + + it 'sets a project as allowing merge only if all discussions are resolved' do + project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true }) + + post api("/projects/user/#{user.id}", admin), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_truthy + end end describe "POST /projects/:id/uploads" do @@ -509,6 +542,7 @@ describe API::API, api: true do expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name) expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access) expect(json_response['only_allow_merge_if_build_succeeds']).to eq(project.only_allow_merge_if_build_succeeds) + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to eq(project.only_allow_merge_if_all_discussions_are_resolved) end it 'returns a project by path name' do -- cgit v1.2.1 From 3f029144607428aa21e81d1d4b40544b835f3d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 26 Oct 2016 19:19:17 +0200 Subject: Complete and improve specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../projects/merge_requests_controller_spec.rb | 68 +++++++++++++++++----- ...eck_if_mergeable_with_unresolved_discussions.rb | 50 ++++++++++------ spec/models/merge_request_spec.rb | 39 +++++-------- 3 files changed, 103 insertions(+), 54 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 79820e9a435..49127aecc63 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -298,28 +298,68 @@ describe Projects::MergeRequestsController do end end - context 'when project project has unresolved discussion' do - before do - project.update_column(:only_allow_merge_if_all_discussions_are_resolved, allowed) - end + describe 'only_allow_merge_if_all_discussions_are_resolved? setting' do + let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } + + context 'when enabled' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, true) + end + + context 'with unresolved discussion' do + before do + expect(merge_request).not_to be_discussions_resolved + end + + it 'returns :failed' do + merge_with_sha + + expect(assigns(:status)).to eq(:failed) + end + end - context "when the only_allow_merge_if_all_discussions_are_resolved? is true" do - let(:allowed) { true } + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + expect(merge_request).to be_discussions_resolved + end - it 'returns :failed' do - merge_with_sha + it 'returns :success' do + merge_with_sha - expect(assigns(:status)).to eq(:failed) + expect(assigns(:status)).to eq(:success) + end end end - context "when the only_allow_merge_if_all_discussions_are_resolved? is false" do - let(:allowed) { false } + context 'when disabled' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, false) + end + + context 'with unresolved discussion' do + before do + expect(merge_request).not_to be_discussions_resolved + end + + it 'returns :success' do + merge_with_sha - it 'returns :failed' do - merge_with_sha + expect(assigns(:status)).to eq(:success) + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + expect(merge_request).to be_discussions_resolved + end + + it 'returns :success' do + merge_with_sha - expect(assigns(:status)).to eq(:success) + expect(assigns(:status)).to eq(:success) + end end end end diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb index 100ddda0167..7f11db3c417 100644 --- a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb +++ b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb @@ -1,30 +1,30 @@ require 'spec_helper' feature 'Check if mergeable with unresolved discussions', js: true, feature: true do - let!(:user) { create(:user) } - let!(:project) { create(:project, :public, only_allow_merge_if_all_discussions_are_resolved: allowed) } - let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user, title: "Bug NS-04" ) } + let(:user) { create(:user) } + let(:project) { create(:project) } + let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } before do login_as user project.team << [user, :master] end - context 'when only_allow_merge_if_all_discussions_are_resolved is false' do - let(:allowed) { false } - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' + context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, true) end - end - context 'when only_allow_merge_if_all_discussions_are_resolved is true' do - let(:allowed) { true } + context 'with unresolved discussions' do + it 'does not allow to merge' do + visit_merge_request(merge_request) - context "when discussions are resolved" do + expect(page).not_to have_button 'Accept Merge Request' + expect(page).to have_content('This merge request has unresolved discussions') + end + end + context 'with all discussions resolved' do before do merge_request.discussions.each { |d| d.resolve!(user) } end @@ -35,14 +35,30 @@ feature 'Check if mergeable with unresolved discussions', js: true, feature: tru expect(page).to have_button 'Accept Merge Request' end end + end - context "when discussions are unresolved" do + context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, false) + end + context 'with unresolved discussions' do it 'does not allow to merge' do visit_merge_request(merge_request) - expect(page).not_to have_button 'Accept Merge Request' - expect(page).to have_content('This merge request has unresolved discussions') + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + end + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' end end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index f3d0373e6d7..fb032a89d50 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -825,11 +825,8 @@ describe MergeRequest, models: true do end context 'when failed' do - before { allow(subject).to receive(:broken?) { false } } - - context 'when project settings restrict to merge only if build succeeds and build failed' do + context 'when #mergeable_ci_state? is false' do before do - project.only_allow_merge_if_build_succeeds = true allow(subject).to receive(:mergeable_ci_state?) { false } end @@ -838,9 +835,8 @@ describe MergeRequest, models: true do end end - context "when project settings restrict to merge only when all the discussions are resolved" do + context 'when #mergeable_discussions_state? is false' do before do - project.only_allow_merge_if_all_discussions_are_resolved = true allow(subject).to receive(:mergeable_discussions_state?) { false } end @@ -899,45 +895,42 @@ describe MergeRequest, models: true do end describe '#mergeable_discussions_state?' do - let!(:user) { create(:user) } - let!(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: allowed) } - - subject { create(:merge_request_with_diff_notes, source_project: project) } + let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project) } - context 'when is true' do - let(:allowed) { true } + context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do + let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: true) } - context 'when discussions are resolved' do + context 'with all discussions resolved' do before do - subject.discussions.each { |d| d.resolve!(user) } + merge_request.discussions.each { |d| d.resolve!(merge_request.author) } end it 'returns true' do - expect(subject.mergeable_discussions_state?).to be_truthy + expect(merge_request.mergeable_discussions_state?).to be_truthy end end - context 'when discussions are unresolved' do + context 'with unresolved discussions' do before do - subject.discussions.map(&:unresolve!) + merge_request.discussions.each(&:unresolve!) end it 'returns false' do - expect(subject.mergeable_discussions_state?).to be_falsey + expect(merge_request.mergeable_discussions_state?).to be_falsey end end end - context 'when is false' do - let(:allowed) { false } + context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do + let(:project) { create(:project, only_allow_merge_if_all_discussions_are_resolved: false) } - context 'when discussions are unresolved' do + context 'with unresolved discussions' do before do - subject.discussions.map(&:unresolve!) + merge_request.discussions.each(&:unresolve!) end it 'returns true' do - expect(subject.mergeable_discussions_state?).to be_truthy + expect(merge_request.mergeable_discussions_state?).to be_truthy end end end -- cgit v1.2.1 From b0a4635be395f0ce14e15e1671d7acfc2360d1ba Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 4 Nov 2016 15:00:39 +0100 Subject: Simplify implementation of entity serializers --- spec/serializers/entity_request_spec.rb | 8 -------- 1 file changed, 8 deletions(-) (limited to 'spec') diff --git a/spec/serializers/entity_request_spec.rb b/spec/serializers/entity_request_spec.rb index 1c220a7b95d..86654adfd54 100644 --- a/spec/serializers/entity_request_spec.rb +++ b/spec/serializers/entity_request_spec.rb @@ -15,12 +15,4 @@ describe EntityRequest do expect { subject.some_method }.to raise_error NoMethodError end end - - describe '#merge!' do - before { subject.merge!(build: 'some build') } - - it 'appends parameters' do - expect(subject.build).to eq 'some build' - end - end end -- cgit v1.2.1 From 8c2143a0a7330768211b8a03a6693ac823679339 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 27 Oct 2016 19:20:47 -0200 Subject: Allow to test JIRA service when project does not have repository --- spec/models/project_services/jira_service_spec.rb | 56 +++++++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index ee0e38bd373..05ee4a08391 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -33,6 +33,41 @@ describe JiraService, models: true do end end + describe '#can_test?' do + let(:jira_service) { described_class.new } + + it 'returns false if username is blank' do + allow(jira_service).to receive_messages( + url: 'http://jira.example.com', + username: '', + password: '12345678' + ) + + expect(jira_service.can_test?).to be_falsy + end + + it 'returns false if password is blank' do + allow(jira_service).to receive_messages( + url: 'http://jira.example.com', + username: 'tester', + password: '' + ) + + expect(jira_service.can_test?).to be_falsy + end + + it 'returns true if password and username are present' do + jira_service = described_class.new + allow(jira_service).to receive_messages( + url: 'http://jira.example.com', + username: 'tester', + password: '12345678' + ) + + expect(jira_service.can_test?).to be_truthy + end + end + describe "Execute" do let(:user) { create(:user) } let(:project) { create(:project) } @@ -46,16 +81,19 @@ describe JiraService, models: true do service_hook: true, url: 'http://jira.example.com', username: 'gitlab_jira_username', - password: 'gitlab_jira_password' + password: 'gitlab_jira_password', + project_key: 'GitLabProject' ) @jira_service.save - project_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123' - @transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions' - @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment' + project_issues_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123' + @project_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/project/GitLabProject' + @transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions' + @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment' - WebMock.stub_request(:get, project_url) + WebMock.stub_request(:get, @project_url) + WebMock.stub_request(:get, project_issues_url) WebMock.stub_request(:post, @transitions_url) WebMock.stub_request(:post, @comment_url) end @@ -99,6 +137,14 @@ describe JiraService, models: true do body: /this-is-a-custom-id/ ).once end + + context "when testing" do + it "tries to get jira project" do + @jira_service.execute(nil) + + expect(WebMock).to have_requested(:get, @project_url) + end + end end describe "Stored password invalidation" do -- cgit v1.2.1 From 2ad630fb51da9eacfb8716a4615e250efd44e0a7 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 21 Sep 2016 11:34:16 -0500 Subject: Fix deselecting calendar days on contribution graph --- spec/features/calendar_spec.rb | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'spec') diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index 7fa0c95cae2..3e0b6364e0d 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -52,6 +52,10 @@ feature 'Contributions Calendar', js: true, feature: true do Event.create(push_params) end + def get_first_cell_content + find('.user-calendar-activities').text + end + before do login_as :user visit @user.username @@ -62,6 +66,43 @@ feature 'Contributions Calendar', js: true, feature: true do expect(page).to have_css('.js-contrib-calendar') end + describe 'select calendar day', js: true do + let(:cells) { page.all('.user-contrib-cell') } + let(:first_cell_content_before) { get_first_cell_content } + + before do + cells[0].click + wait_for_ajax + first_cell_content_before + end + + it 'displays calendar day activities', js: true do + expect(get_first_cell_content).not_to eq('') + end + + describe 'select another calendar day', js: true do + before do + cells[1].click + wait_for_ajax + end + + it 'displays different calendar day activities', js: true do + expect(get_first_cell_content).not_to eq(first_cell_content_before) + end + end + + describe 'deselect calendar day', js: true do + before do + cells[0].click + wait_for_ajax + end + + it 'hides calendar day activities', js: true do + expect(get_first_cell_content).to eq('') + end + end + end + describe '1 calendar activity' do before do Issues::CreateService.new(contributed_project, @user, issue_params).execute -- cgit v1.2.1 From dd45c5e11eb2b315d89779abf6103e2531e1cc08 Mon Sep 17 00:00:00 2001 From: Jared Deckard Date: Tue, 20 Sep 2016 10:50:32 -0500 Subject: Add javascript unit tests for Build Move comments to the correct location Remove array extension usage Move build options to fixture to match view --- spec/javascripts/build_spec.js.es6 | 174 ++++++++++++++++++++++++++++++ spec/javascripts/fixtures/build.html.haml | 57 ++++++++++ 2 files changed, 231 insertions(+) create mode 100644 spec/javascripts/build_spec.js.es6 create mode 100644 spec/javascripts/fixtures/build.html.haml (limited to 'spec') diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 new file mode 100644 index 00000000000..44485c7745c --- /dev/null +++ b/spec/javascripts/build_spec.js.es6 @@ -0,0 +1,174 @@ +/* eslint-disable */ +//= require build +//= require breakpoints +//= require jquery.nicescroll +//= require turbolinks + +(() => { + describe('Build', () => { + fixture.preload('build.html'); + + beforeEach(function() { + fixture.load('build.html'); + spyOn($, 'ajax'); + }); + + describe('constructor', () => { + beforeEach(function() { + jasmine.clock().install(); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + describe('setup', function() { + beforeEach(function() { + this.build = new Build(); + }); + + it('copies build options', function() { + expect(this.build.pageUrl).toBe('http://example.com/root/test-build/builds/2'); + expect(this.build.buildUrl).toBe('http://example.com/root/test-build/builds/2.json'); + expect(this.build.buildStatus).toBe('passed'); + expect(this.build.buildStage).toBe('test'); + expect(this.build.state).toBe('buildstate'); + }); + + it('only shows the jobs matching the current stage', function() { + expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false); + expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true); + expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); + }); + + it('selects the current stage in the build dropdown menu', function() { + expect($('.stage-selection').text()).toBe('test'); + }); + + it('updates the jobs when the build dropdown changes', function() { + $('.stage-item:contains("build")').click(); + + expect($('.stage-selection').text()).toBe('build'); + expect($('.build-job[data-stage="build"]').is(':visible')).toBe(true); + expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false); + expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); + }); + }); + + describe('initial build trace', function() { + beforeEach(function() { + new Build(); + }); + + it('displays the initial build trace', function() { + expect($.ajax.calls.count()).toBe(1); + const [{url, dataType, success, context}] = $.ajax.calls.argsFor(0); + expect(url).toBe('http://example.com/root/test-build/builds/2.json'); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, {trace_html: 'Example', status: 'running'}); + + expect($('#build-trace .js-build-output').text()).toMatch(/Example/); + }); + + it('removes the spinner', function() { + const [{success, context}] = $.ajax.calls.argsFor(0); + success.call(context, {trace_html: 'Example', status: 'success'}); + + expect($('.js-build-refresh').length).toBe(0); + }); + }); + + describe('running build', function() { + beforeEach(function() { + $('.js-build-options').data('buildStatus', 'running'); + this.build = new Build(); + spyOn(this.build, 'location') + .and.returnValue('http://example.com/root/test-build/builds/2'); + }); + + it('updates the build trace on an interval', function() { + jasmine.clock().tick(4001); + + expect($.ajax.calls.count()).toBe(2); + let [{url, dataType, success, context}] = $.ajax.calls.argsFor(1); + expect(url).toBe( + 'http://example.com/root/test-build/builds/2/trace.json?state=buildstate' + ); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, { + html: 'Update', + status: 'running', + state: 'newstate', + append: true + }); + + expect($('#build-trace .js-build-output').text()).toMatch(/Update/); + expect(this.build.state).toBe('newstate'); + + jasmine.clock().tick(4001); + + expect($.ajax.calls.count()).toBe(3); + [{url, dataType, success, context}] = $.ajax.calls.argsFor(2); + expect(url).toBe( + 'http://example.com/root/test-build/builds/2/trace.json?state=newstate' + ); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, { + html: 'More', + status: 'running', + state: 'finalstate', + append: true + }); + + expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); + expect(this.build.state).toBe('finalstate'); + }); + + it('replaces the entire build trace', function() { + jasmine.clock().tick(4001); + let [{success, context}] = $.ajax.calls.argsFor(1); + success.call(context, { + html: 'Update', + status: 'running', + append: true + }); + + expect($('#build-trace .js-build-output').text()).toMatch(/Update/); + + jasmine.clock().tick(4001); + [{success, context}] = $.ajax.calls.argsFor(2); + success.call(context, { + html: 'Different', + status: 'running', + append: false + }); + + expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); + expect($('#build-trace .js-build-output').text()).toMatch(/Different/); + }); + + it('reloads the page when the build is done', function() { + spyOn(Turbolinks, 'visit'); + + jasmine.clock().tick(4001); + let [{success, context}] = $.ajax.calls.argsFor(1); + success.call(context, { + html: 'Final', + status: 'passed', + append: true + }); + + expect(Turbolinks.visit).toHaveBeenCalledWith( + 'http://example.com/root/test-build/builds/2' + ); + }); + }); + }); + }); +})(); diff --git a/spec/javascripts/fixtures/build.html.haml b/spec/javascripts/fixtures/build.html.haml new file mode 100644 index 00000000000..a2bc81c6be7 --- /dev/null +++ b/spec/javascripts/fixtures/build.html.haml @@ -0,0 +1,57 @@ +.build-page + .prepend-top-default + .autoscroll-container + %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll + #js-build-scroll.scroll-controls + %a.btn{href: '#build-trace'} + %i.fa.fa-angle-up + %a.btn{href: '#down-build-trace'} + %i.fa.fa-angle-down + %pre.build-trace#build-trace + %code.bash.js-build-output + %i.fa.fa-refresh.fa-spin.js-build-refresh + +%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar + .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default + Build + %strong #1 + %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } + %i.fa.fa-angle-double-right + .blocks-container + .dropdown.build-dropdown + .title Stage + %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'} + %span.stage-selection More + %i.fa.fa-caret-down + %ul.dropdown-menu + %li + %a.stage-item build + %li + %a.stage-item test + %li + %a.stage-item deploy + .builds-container + .build-job{data: {stage: 'build'}} + %a{href: 'http://example.com/root/test-build/builds/1'} + %i.fa.fa-check + %i.fa.fa-check-circle-o + %span + Setup + .build-job{data: {stage: 'test'}} + %a{href: 'http://example.com/root/test-build/builds/2'} + %i.fa.fa-check + %i.fa.fa-check-circle-o + %span + Tests + .build-job{data: {stage: 'deploy'}} + %a{href: 'http://example.com/root/test-build/builds/3'} + %i.fa.fa-check + %i.fa.fa-check-circle-o + %span + Deploy + +.js-build-options{ data: { page_url: 'http://example.com/root/test-build/builds/2', + build_url: 'http://example.com/root/test-build/builds/2.json', + build_status: 'passed', + build_stage: 'test', + state1: 'buildstate' }} -- cgit v1.2.1 From e517da3ff07b09d680d11c98b8298d02a4b105eb Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 28 Oct 2016 14:38:10 +0100 Subject: Created wait_for_turbolinks and added test for refs dropdown selection with special chars --- spec/features/projects/ref_switcher_spec.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/projects/ref_switcher_spec.rb b/spec/features/projects/ref_switcher_spec.rb index b3ba40b35af..472491188c9 100644 --- a/spec/features/projects/ref_switcher_spec.rb +++ b/spec/features/projects/ref_switcher_spec.rb @@ -22,8 +22,20 @@ feature 'Ref switcher', feature: true, js: true do input.native.send_keys :down input.native.send_keys :down input.native.send_keys :enter + end + + expect(page).to have_title 'expand-collapse-files' + end + + it "user selects ref with special characters" do + click_button 'master' + wait_for_ajax - expect(page).to have_content 'expand-collapse-files' + page.within '.project-refs-form' do + page.fill_in 'Search branches and tags', with: "'test'" + click_link "'test'" end + + expect(page).to have_title "'test'" end end -- cgit v1.2.1 From 4f377364ad2b073e59e8edde86f270c80cdb317a Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Mon, 31 Oct 2016 14:56:55 +0000 Subject: Added new .eslintrc for jasmine tests and corrected build_spec --- spec/javascripts/.eslintrc | 11 +++++++ spec/javascripts/build_spec.js.es6 | 65 +++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 32 deletions(-) create mode 100644 spec/javascripts/.eslintrc (limited to 'spec') diff --git a/spec/javascripts/.eslintrc b/spec/javascripts/.eslintrc new file mode 100644 index 00000000000..90388929612 --- /dev/null +++ b/spec/javascripts/.eslintrc @@ -0,0 +1,11 @@ +{ + "plugins": ["jasmine"], + "env": { + "jasmine": true + }, + "extends": "plugin:jasmine/recommended", + "rules": { + "prefer-arrow-callback": 0, + "func-names": 0 + } +} diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index 44485c7745c..370944b6a8c 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -1,4 +1,5 @@ -/* eslint-disable */ +/* global Build */ +/* eslint-disable no-new */ //= require build //= require breakpoints //= require jquery.nicescroll @@ -8,13 +9,13 @@ describe('Build', () => { fixture.preload('build.html'); - beforeEach(function() { + beforeEach(function () { fixture.load('build.html'); spyOn($, 'ajax'); }); describe('constructor', () => { - beforeEach(function() { + beforeEach(function () { jasmine.clock().install(); }); @@ -22,12 +23,12 @@ jasmine.clock().uninstall(); }); - describe('setup', function() { - beforeEach(function() { + describe('setup', function () { + beforeEach(function () { this.build = new Build(); }); - it('copies build options', function() { + it('copies build options', function () { expect(this.build.pageUrl).toBe('http://example.com/root/test-build/builds/2'); expect(this.build.buildUrl).toBe('http://example.com/root/test-build/builds/2.json'); expect(this.build.buildStatus).toBe('passed'); @@ -35,17 +36,17 @@ expect(this.build.state).toBe('buildstate'); }); - it('only shows the jobs matching the current stage', function() { + it('only shows the jobs matching the current stage', function () { expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false); expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true); expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); }); - it('selects the current stage in the build dropdown menu', function() { + it('selects the current stage in the build dropdown menu', function () { expect($('.stage-selection').text()).toBe('test'); }); - it('updates the jobs when the build dropdown changes', function() { + it('updates the jobs when the build dropdown changes', function () { $('.stage-item:contains("build")').click(); expect($('.stage-selection').text()).toBe('build'); @@ -55,44 +56,44 @@ }); }); - describe('initial build trace', function() { - beforeEach(function() { + describe('initial build trace', function () { + beforeEach(function () { new Build(); }); - it('displays the initial build trace', function() { + it('displays the initial build trace', function () { expect($.ajax.calls.count()).toBe(1); - const [{url, dataType, success, context}] = $.ajax.calls.argsFor(0); + const [{ url, dataType, success, context }] = $.ajax.calls.argsFor(0); expect(url).toBe('http://example.com/root/test-build/builds/2.json'); expect(dataType).toBe('json'); expect(success).toEqual(jasmine.any(Function)); - success.call(context, {trace_html: 'Example', status: 'running'}); + success.call(context, { trace_html: 'Example', status: 'running' }); expect($('#build-trace .js-build-output').text()).toMatch(/Example/); }); - it('removes the spinner', function() { - const [{success, context}] = $.ajax.calls.argsFor(0); - success.call(context, {trace_html: 'Example', status: 'success'}); + it('removes the spinner', function () { + const [{ success, context }] = $.ajax.calls.argsFor(0); + success.call(context, { trace_html: 'Example', status: 'success' }); expect($('.js-build-refresh').length).toBe(0); }); }); - describe('running build', function() { - beforeEach(function() { + describe('running build', function () { + beforeEach(function () { $('.js-build-options').data('buildStatus', 'running'); this.build = new Build(); spyOn(this.build, 'location') .and.returnValue('http://example.com/root/test-build/builds/2'); }); - it('updates the build trace on an interval', function() { + it('updates the build trace on an interval', function () { jasmine.clock().tick(4001); expect($.ajax.calls.count()).toBe(2); - let [{url, dataType, success, context}] = $.ajax.calls.argsFor(1); + let [{ url, dataType, success, context }] = $.ajax.calls.argsFor(1); expect(url).toBe( 'http://example.com/root/test-build/builds/2/trace.json?state=buildstate' ); @@ -103,7 +104,7 @@ html: 'Update', status: 'running', state: 'newstate', - append: true + append: true, }); expect($('#build-trace .js-build-output').text()).toMatch(/Update/); @@ -112,7 +113,7 @@ jasmine.clock().tick(4001); expect($.ajax.calls.count()).toBe(3); - [{url, dataType, success, context}] = $.ajax.calls.argsFor(2); + [{ url, dataType, success, context }] = $.ajax.calls.argsFor(2); expect(url).toBe( 'http://example.com/root/test-build/builds/2/trace.json?state=newstate' ); @@ -123,45 +124,45 @@ html: 'More', status: 'running', state: 'finalstate', - append: true + append: true, }); expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); expect(this.build.state).toBe('finalstate'); }); - it('replaces the entire build trace', function() { + it('replaces the entire build trace', function () { jasmine.clock().tick(4001); - let [{success, context}] = $.ajax.calls.argsFor(1); + let [{ success, context }] = $.ajax.calls.argsFor(1); success.call(context, { html: 'Update', status: 'running', - append: true + append: true, }); expect($('#build-trace .js-build-output').text()).toMatch(/Update/); jasmine.clock().tick(4001); - [{success, context}] = $.ajax.calls.argsFor(2); + [{ success, context }] = $.ajax.calls.argsFor(2); success.call(context, { html: 'Different', status: 'running', - append: false + append: false, }); expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Different/); }); - it('reloads the page when the build is done', function() { + it('reloads the page when the build is done', function () { spyOn(Turbolinks, 'visit'); jasmine.clock().tick(4001); - let [{success, context}] = $.ajax.calls.argsFor(1); + const [{ success, context }] = $.ajax.calls.argsFor(1); success.call(context, { html: 'Final', status: 'passed', - append: true + append: true, }); expect(Turbolinks.visit).toHaveBeenCalledWith( -- cgit v1.2.1 From 80a2e3a9c89a34df06eb2996fd5bdbaa6223f98c Mon Sep 17 00:00:00 2001 From: the-undefined Date: Wed, 2 Nov 2016 06:47:12 +0000 Subject: Add missing security specs for raw snippet access Each project visibility type (Public, Internal, Private) has an access feature spec to catch security regressions. This commit adds relevent tests for the raw snippet path in each of these project access specs. Refacotrings: - Use an empty project factory for access specs --- .../project/snippet/internal_access_spec.rb | 78 ++++++++++---- .../project/snippet/private_access_spec.rb | 16 ++- .../security/project/snippet/public_access_spec.rb | 116 ++++++++++++++------- 3 files changed, 151 insertions(+), 59 deletions(-) (limited to 'spec') diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb index db53a9cec97..49deacc5c74 100644 --- a/spec/features/security/project/snippet/internal_access_spec.rb +++ b/spec/features/security/project/snippet/internal_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Internal Project Snippets Access", feature: true do include AccessMatchers - let(:project) { create(:project, :internal) } + let(:project) { create(:empty_project, :internal) } let(:owner) { project.owner } let(:master) { create(:user) } @@ -48,31 +48,63 @@ describe "Internal Project Snippets Access", feature: true do it { is_expected.to be_denied_for :visitor } end - describe "GET /:project_path/snippets/:id for an internal snippet" do - subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + describe "GET /:project_path/snippets/:id" do + context "for an internal snippet" do + subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end - describe "GET /:project_path/snippets/:id for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + describe "GET /:project_path/snippets/:id/raw" do + context "for an internal snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end end diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb index d23d645c8e5..a1bfc076d99 100644 --- a/spec/features/security/project/snippet/private_access_spec.rb +++ b/spec/features/security/project/snippet/private_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Private Project Snippets Access", feature: true do include AccessMatchers - let(:project) { create(:project, :private) } + let(:project) { create(:empty_project, :private) } let(:owner) { project.owner } let(:master) { create(:user) } @@ -60,4 +60,18 @@ describe "Private Project Snippets Access", feature: true do it { is_expected.to be_denied_for :external } it { is_expected.to be_denied_for :visitor } end + + describe "GET /:project_path/snippets/:id/raw for a private snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb index e3665b6116a..30bcd87ef04 100644 --- a/spec/features/security/project/snippet/public_access_spec.rb +++ b/spec/features/security/project/snippet/public_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Public Project Snippets Access", feature: true do include AccessMatchers - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public) } let(:owner) { project.owner } let(:master) { create(:user) } @@ -49,45 +49,91 @@ describe "Public Project Snippets Access", feature: true do it { is_expected.to be_denied_for :visitor } end - describe "GET /:project_path/snippets/:id for a public snippet" do - subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } + describe "GET /:project_path/snippets/:id" do + context "for a public snippet" do + subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } - end + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :external } + it { is_expected.to be_allowed_for :visitor } + end - describe "GET /:project_path/snippets/:id for an internal snippet" do - subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + context "for an internal snippet" do + subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end - describe "GET /:project_path/snippets/:id for a private snippet" do - subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + describe "GET /:project_path/snippets/:id/raw" do + context "for a public snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, public_snippet) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :external } + it { is_expected.to be_allowed_for :visitor } + end + + context "for an internal snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, internal_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end + + context "for a private snippet" do + subject { raw_namespace_project_snippet_path(project.namespace, project, private_snippet) } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for developer } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :external } + it { is_expected.to be_denied_for :visitor } + end end end -- cgit v1.2.1 From c16d5bcd48bb03f0eb145da4be9460cca87d1f91 Mon Sep 17 00:00:00 2001 From: winniehell Date: Sat, 5 Nov 2016 11:53:23 +0100 Subject: Move Ajax interceptor into describe block (!7304) --- spec/javascripts/boards/boards_store_spec.js.es6 | 215 ++++++++++++----------- spec/javascripts/boards/list_spec.js.es6 | 5 + spec/javascripts/boards/mock_data.js.es6 | 4 +- 3 files changed, 116 insertions(+), 108 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js.es6 index 6208c2386b0..b84dfc8197b 100644 --- a/spec/javascripts/boards/boards_store_spec.js.es6 +++ b/spec/javascripts/boards/boards_store_spec.js.es6 @@ -13,8 +13,9 @@ //= require boards/stores/boards_store //= require ./mock_data -(() => { +describe('Store', () => { beforeEach(() => { + Vue.http.interceptors.push(boardsMockInterceptor); gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); @@ -24,145 +25,147 @@ }); }); - describe('Store', () => { - it('starts with a blank state', () => { - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); - }); + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor); + }); - describe('lists', () => { - it('creates new list without persisting to DB', () => { - gl.issueBoards.BoardsStore.addList(listObj); + it('starts with a blank state', () => { + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); + }); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - }); + describe('lists', () => { + it('creates new list without persisting to DB', () => { + gl.issueBoards.BoardsStore.addList(listObj); - it('finds list by ID', () => { - gl.issueBoards.BoardsStore.addList(listObj); - const list = gl.issueBoards.BoardsStore.findList('id', 1); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + }); - expect(list.id).toBe(1); - }); + it('finds list by ID', () => { + gl.issueBoards.BoardsStore.addList(listObj); + const list = gl.issueBoards.BoardsStore.findList('id', 1); - it('finds list by type', () => { - gl.issueBoards.BoardsStore.addList(listObj); - const list = gl.issueBoards.BoardsStore.findList('type', 'label'); + expect(list.id).toBe(1); + }); - expect(list).toBeDefined(); - }); + it('finds list by type', () => { + gl.issueBoards.BoardsStore.addList(listObj); + const list = gl.issueBoards.BoardsStore.findList('type', 'label'); - it('finds list limited by type', () => { - gl.issueBoards.BoardsStore.addList({ - id: 1, - position: 0, - title: 'Test', - list_type: 'backlog' - }); - const list = gl.issueBoards.BoardsStore.findList('id', 1, 'backlog'); + expect(list).toBeDefined(); + }); - expect(list).toBeDefined(); + it('finds list limited by type', () => { + gl.issueBoards.BoardsStore.addList({ + id: 1, + position: 0, + title: 'Test', + list_type: 'backlog' }); + const list = gl.issueBoards.BoardsStore.findList('id', 1, 'backlog'); - it('gets issue when new list added', (done) => { - gl.issueBoards.BoardsStore.addList(listObj); - const list = gl.issueBoards.BoardsStore.findList('id', 1); + expect(list).toBeDefined(); + }); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + it('gets issue when new list added', (done) => { + gl.issueBoards.BoardsStore.addList(listObj); + const list = gl.issueBoards.BoardsStore.findList('id', 1); - setTimeout(() => { - expect(list.issues.length).toBe(1); - expect(list.issues[0].id).toBe(1); - done(); - }, 0); - }); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - it('persists new list', (done) => { - gl.issueBoards.BoardsStore.new({ - title: 'Test', - type: 'label', - label: { - id: 1, - title: 'Testing', - color: 'red', - description: 'testing;' - } - }); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - - setTimeout(() => { - const list = gl.issueBoards.BoardsStore.findList('id', 1); - expect(list).toBeDefined(); - expect(list.id).toBe(1); - expect(list.position).toBe(0); - done(); - }, 0); - }); + setTimeout(() => { + expect(list.issues.length).toBe(1); + expect(list.issues[0].id).toBe(1); + done(); + }, 0); + }); - it('check for blank state adding', () => { - expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); + it('persists new list', (done) => { + gl.issueBoards.BoardsStore.new({ + title: 'Test', + type: 'label', + label: { + id: 1, + title: 'Testing', + color: 'red', + description: 'testing;' + } }); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - it('check for blank state not adding', () => { - gl.issueBoards.BoardsStore.addList(listObj); - expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false); - }); + setTimeout(() => { + const list = gl.issueBoards.BoardsStore.findList('id', 1); + expect(list).toBeDefined(); + expect(list.id).toBe(1); + expect(list.position).toBe(0); + done(); + }, 0); + }); - it('check for blank state adding when backlog & done list exist', () => { - gl.issueBoards.BoardsStore.addList({ - list_type: 'backlog' - }); - gl.issueBoards.BoardsStore.addList({ - list_type: 'done' - }); + it('check for blank state adding', () => { + expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); + }); + + it('check for blank state not adding', () => { + gl.issueBoards.BoardsStore.addList(listObj); + expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false); + }); - expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); + it('check for blank state adding when backlog & done list exist', () => { + gl.issueBoards.BoardsStore.addList({ + list_type: 'backlog' }); + gl.issueBoards.BoardsStore.addList({ + list_type: 'done' + }); + + expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true); + }); - it('adds the blank state', () => { - gl.issueBoards.BoardsStore.addBlankState(); + it('adds the blank state', () => { + gl.issueBoards.BoardsStore.addBlankState(); - const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank'); - expect(list).toBeDefined(); - }); + const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank'); + expect(list).toBeDefined(); + }); - it('removes list from state', () => { - gl.issueBoards.BoardsStore.addList(listObj); + it('removes list from state', () => { + gl.issueBoards.BoardsStore.addList(listObj); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1); - gl.issueBoards.BoardsStore.removeList(1, 'label'); + gl.issueBoards.BoardsStore.removeList(1, 'label'); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); - }); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0); + }); - it('moves the position of lists', () => { - const listOne = gl.issueBoards.BoardsStore.addList(listObj), - listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); + it('moves the position of lists', () => { + const listOne = gl.issueBoards.BoardsStore.addList(listObj), + listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); - gl.issueBoards.BoardsStore.moveList(listOne, ['2', '1']); + gl.issueBoards.BoardsStore.moveList(listOne, ['2', '1']); - expect(listOne.position).toBe(1); - }); + expect(listOne.position).toBe(1); + }); - it('moves an issue from one list to another', (done) => { - const listOne = gl.issueBoards.BoardsStore.addList(listObj), - listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); + it('moves an issue from one list to another', (done) => { + const listOne = gl.issueBoards.BoardsStore.addList(listObj), + listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate); - expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); + expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); - setTimeout(() => { - expect(listOne.issues.length).toBe(1); - expect(listTwo.issues.length).toBe(1); + setTimeout(() => { + expect(listOne.issues.length).toBe(1); + expect(listTwo.issues.length).toBe(1); - gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1)); + gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1)); - expect(listOne.issues.length).toBe(0); - expect(listTwo.issues.length).toBe(1); + expect(listOne.issues.length).toBe(0); + expect(listTwo.issues.length).toBe(1); - done(); - }, 0); - }); + done(); + }, 0); }); }); -})(); +}); diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6 index 1a0427fdd90..dfbcbe3a7c1 100644 --- a/spec/javascripts/boards/list_spec.js.es6 +++ b/spec/javascripts/boards/list_spec.js.es6 @@ -17,12 +17,17 @@ describe('List model', () => { let list; beforeEach(() => { + Vue.http.interceptors.push(boardsMockInterceptor); gl.boardService = new BoardService('/test/issue-boards/board', '1'); gl.issueBoards.BoardsStore.create(); list = new List(listObj); }); + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, boardsMockInterceptor); + }); + it('gets issues when created', (done) => { setTimeout(() => { expect(list.issues.length).toBe(1); diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6 index 80d05e8a1a3..fcb3d8f17d8 100644 --- a/spec/javascripts/boards/mock_data.js.es6 +++ b/spec/javascripts/boards/mock_data.js.es6 @@ -48,10 +48,10 @@ const BoardsMockData = { } }; -Vue.http.interceptors.push((request, next) => { +const boardsMockInterceptor = (request, next) => { const body = BoardsMockData[request.method][request.url]; next(request.respondWith(JSON.stringify(body), { status: 200 })); -}); +}; -- cgit v1.2.1 From a09079219fcb2cd7dc7e343446ea499792344df6 Mon Sep 17 00:00:00 2001 From: winniehell Date: Sat, 5 Nov 2016 12:41:36 +0100 Subject: Remove logging to console in diff_comments_store_spec --- spec/javascripts/diff_comments_store_spec.js.es6 | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/diff_comments_store_spec.js.es6 b/spec/javascripts/diff_comments_store_spec.js.es6 index 5d817802602..9b2845af608 100644 --- a/spec/javascripts/diff_comments_store_spec.js.es6 +++ b/spec/javascripts/diff_comments_store_spec.js.es6 @@ -92,7 +92,6 @@ it('is unresolved with 2 notes', () => { const discussion = CommentsStore.state['a']; createDiscussion(2, false); - console.log(discussion.isResolved()); expect(discussion.isResolved()).toBe(false); }); -- cgit v1.2.1 From 685072f5889f60e9ced0511fd72ce0d3d6be6230 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Sat, 5 Nov 2016 14:59:08 +0100 Subject: simplify url generation --- spec/models/project_services/jira_service_spec.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 05ee4a08391..ed5abcf7fc0 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -69,6 +69,7 @@ describe JiraService, models: true do end describe "Execute" do + let(:custom_base_url) { 'http://custom_url' } let(:user) { create(:user) } let(:project) { create(:project) } let(:merge_request) { create(:merge_request) } @@ -107,10 +108,12 @@ describe JiraService, models: true do end it "references the GitLab commit/merge request" do - @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) + stub_config_setting(base_url: custom_base_url) + stub_config_setting(url: custom_base_url) + @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) expect(WebMock).to have_requested(:post, @comment_url).with( - body: /#{Gitlab.config.gitlab.url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/ + body: /#{custom_base_url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/ ).once end -- cgit v1.2.1 From b9176afbc887b2bac4e07fdad65f3560cc3ceedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sun, 6 Nov 2016 20:27:58 +0200 Subject: update existing test --- spec/lib/gitlab/identifier_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/identifier_spec.rb b/spec/lib/gitlab/identifier_spec.rb index 47d6f1007d1..f42c4453dd1 100644 --- a/spec/lib/gitlab/identifier_spec.rb +++ b/spec/lib/gitlab/identifier_spec.rb @@ -65,7 +65,7 @@ describe Gitlab::Identifier do commit = double(:commit, author_email: user.email) expect(project).to receive(:commit).with('123').twice.and_return(commit) - expect(User).to receive(:find_by).once.and_call_original + expect(User).to receive(:find_by_any_email).once.and_call_original 2.times do expect(identifier.identify_using_commit(project, '123')).to eq(user) -- cgit v1.2.1 From 76c237460a801050e68def5ff54c15e4e74b38a8 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 29 Sep 2016 16:33:38 +0200 Subject: Ability to update labels priority via API --- spec/requests/api/labels_spec.rb | 88 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index f702dfaaf53..7e532912d08 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -6,6 +6,7 @@ describe API::API, api: true do let(:user) { create(:user) } let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } let!(:label1) { create(:label, title: 'label1', project: project) } + let!(:priority_label) { create(:label, title: 'bug', project: project, priority: 3) } before do project.team << [user, :master] @@ -21,8 +22,16 @@ describe API::API, api: true do expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.size).to eq(2) - expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, label1.name]) + expect(json_response.size).to eq(3) + expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) + expect(json_response.last['name']).to eq(label1.name) + expect(json_response.last['color']).to be_present + expect(json_response.last['description']).to be_nil + expect(json_response.last['open_issues_count']).to eq(0) + expect(json_response.last['closed_issues_count']).to eq(0) + expect(json_response.last['open_merge_requests_count']).to eq(0) + expect(json_response.last['priority']).to be_nil + expect(json_response.last['subscribed']).to be_falsey end end @@ -31,21 +40,39 @@ describe API::API, api: true do post api("/projects/#{project.id}/labels", user), name: 'Foo', color: '#FFAABB', - description: 'test' + description: 'test', + priority: 2 + expect(response).to have_http_status(201) expect(json_response['name']).to eq('Foo') expect(json_response['color']).to eq('#FFAABB') expect(json_response['description']).to eq('test') + expect(json_response['priority']).to eq(2) end it 'returns created label when only required params' do post api("/projects/#{project.id}/labels", user), name: 'Foo & Bar', color: '#FFAABB' + expect(response.status).to eq(201) expect(json_response['name']).to eq('Foo & Bar') expect(json_response['color']).to eq('#FFAABB') expect(json_response['description']).to be_nil + expect(json_response['priority']).to be_nil + end + + it 'creates a prioritized label' do + post api("/projects/#{project.id}/labels", user), + name: 'Foo & Bar', + color: '#FFAABB', + priority: 3 + + expect(response.status).to eq(201) + expect(json_response['name']).to eq('Foo & Bar') + expect(json_response['color']).to eq('#FFAABB') + expect(json_response['description']).to be_nil + expect(json_response['priority']).to eq(3) end it 'returns a 400 bad request if name not given' do @@ -95,6 +122,15 @@ describe API::API, api: true do expect(json_response['message']).to eq('Label already exists') end + it 'returns 400 for invalid priority' do + post api("/projects/#{project.id}/labels", user), + name: 'Foo', + color: '#FFAAFFFF', + priority: 'foo' + + expect(response).to have_http_status(400) + end + it 'returns 409 if label already exists in project' do post api("/projects/#{project.id}/labels", user), name: 'label1', @@ -155,11 +191,43 @@ describe API::API, api: true do it 'returns 200 if description is changed' do put api("/projects/#{project.id}/labels", user), - name: 'label1', + name: 'bug', description: 'test' + expect(response).to have_http_status(200) - expect(json_response['name']).to eq(label1.name) + expect(json_response['name']).to eq(priority_label.name) expect(json_response['description']).to eq('test') + expect(json_response['priority']).to eq(3) + end + + it 'returns 200 if priority is changed' do + put api("/projects/#{project.id}/labels", user), + name: 'bug', + priority: 10 + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(priority_label.name) + expect(json_response['priority']).to eq(10) + end + + it 'returns 200 if a priority is added' do + put api("/projects/#{project.id}/labels", user), + name: 'label1', + priority: 3 + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(label1.name) + expect(json_response['priority']).to eq(3) + end + + it 'returns 200 if the priority is removed' do + put api("/projects/#{project.id}/labels", user), + name: priority_label.name, + priority: nil + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(priority_label.name) + expect(json_response['priority']).to be_nil end it 'returns 404 if label does not exist' do @@ -178,7 +246,7 @@ describe API::API, api: true do it 'returns 400 if no new parameters given' do put api("/projects/#{project.id}/labels", user), name: 'label1' expect(response).to have_http_status(400) - expect(json_response['error']).to eq('new_name, color, description are missing, '\ + expect(json_response['error']).to eq('new_name, color, description, priority are missing, '\ 'at least one parameter must be provided') end @@ -206,6 +274,14 @@ describe API::API, api: true do expect(response).to have_http_status(400) expect(json_response['message']['color']).to eq(['must be a valid color code']) end + + it 'returns 400 for invalid priority' do + post api("/projects/#{project.id}/labels", user), + name: 'Foo', + priority: 'foo' + + expect(response).to have_http_status(400) + end end describe "POST /projects/:id/labels/:label_id/subscription" do -- cgit v1.2.1 From 29668aec46f0c7479bf974e6d27ace866c800940 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 4 Nov 2016 04:47:39 +0000 Subject: Use `git update-ref --stdin -z` to speed up TestEnv.set_repo_refs Previously, we were calling `git update-ref ` about 30 times per test using `create(:project)` or similar. --- spec/support/test_env.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index c79975d8667..778e665500d 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -204,20 +204,18 @@ module TestEnv end def set_repo_refs(repo_path, branch_sha) + instructions = branch_sha.map {|branch, sha| "update refs/heads/#{branch}\x00#{sha}\x00" }.join("\x00") << "\x00" + update_refs = %W(#{Gitlab.config.git.bin_path} update-ref --stdin -z) + reset = proc do + IO.popen(update_refs, "w") {|io| io.write(instructions) } + $?.success? + end + Dir.chdir(repo_path) do - branch_sha.each do |branch, sha| - # Try to reset without fetching to avoid using the network. - reset = %W(#{Gitlab.config.git.bin_path} update-ref refs/heads/#{branch} #{sha}) - unless system(*reset) - if system(*%W(#{Gitlab.config.git.bin_path} fetch origin)) - unless system(*reset) - raise 'The fetched test seed '\ - 'does not contain the required revision.' - end - else - raise 'Could not fetch test seed repository.' - end - end + # Try to reset without fetching to avoid using the network. + unless reset.call + raise 'Could not fetch test seed repository.' unless system(*%W(#{Gitlab.config.git.bin_path} fetch origin)) + raise 'The fetched test seed does not contain the required revision.' unless reset.call end end end -- cgit v1.2.1 From 3c957c006633d2df44f0d23a3131294f9b657d2b Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 13 Oct 2016 17:53:01 +0200 Subject: Added tests for IssuePolicy --- spec/policies/issue_policy_spec.rb | 119 +++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 spec/policies/issue_policy_spec.rb (limited to 'spec') diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb new file mode 100644 index 00000000000..7591bfd1471 --- /dev/null +++ b/spec/policies/issue_policy_spec.rb @@ -0,0 +1,119 @@ +require 'spec_helper' + +describe IssuePolicy, models: true do + let(:user) { create(:user) } + + describe '#rules' do + context 'using a regular issue' do + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project) } + let(:policies) { described_class.abilities(user, issue).to_set } + + context 'with a regular user' do + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + + context 'with a user that is a project reporter' do + before do + project.team << [user, :reporter] + end + + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'includes the admin_issue permission' do + expect(policies).to include(:admin_issue) + end + + it 'includes the update_issue permission' do + expect(policies).to include(:update_issue) + end + end + + context 'with a user that is a project guest' do + before do + project.team << [user, :guest] + end + + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + end + + context 'using a confidential issue' do + let(:issue) { create(:issue, :confidential) } + + context 'with a regular user' do + let(:policies) { described_class.abilities(user, issue).to_set } + + it 'does not include the read_issue permission' do + expect(policies).not_to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + + context 'with a user that is a project member' do + let(:policies) { described_class.abilities(user, issue).to_set } + + before do + issue.project.team << [user, :reporter] + end + + it 'includes the read_issue permission' do + expect(policies).to include(:read_issue) + end + + it 'includes the admin_issue permission' do + expect(policies).to include(:admin_issue) + end + + it 'includes the update_issue permission' do + expect(policies).to include(:update_issue) + end + end + + context 'without a user' do + let(:policies) { described_class.abilities(nil, issue).to_set } + + it 'does not include the read_issue permission' do + expect(policies).not_to include(:read_issue) + end + + it 'does not include the admin_issue permission' do + expect(policies).not_to include(:admin_issue) + end + + it 'does not include the update_issue permission' do + expect(policies).not_to include(:update_issue) + end + end + end + end +end -- cgit v1.2.1 From 467b346f0684053081d7e762df1a2b5df5888543 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 13 Oct 2016 17:53:47 +0200 Subject: Add User#projects_with_reporter_access_limited_to This method can be used to retrieve a list of projects for a user that said user has reporter access to. This list is then be reduced down to a specific set of projects. This allows you to reduce a list of projects to a list of projects you have reporter access to in an efficient manner. --- spec/models/user_spec.rb | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'spec') diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ba47479a2e1..3b152e15b61 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1205,4 +1205,40 @@ describe User, models: true do expect(user.viewable_starred_projects).not_to include(private_project) end end + + describe '#projects_with_reporter_access_limited_to' do + let(:project1) { create(:project) } + let(:project2) { create(:project) } + let(:user) { create(:user) } + + before do + project1.team << [user, :reporter] + project2.team << [user, :guest] + end + + it 'returns the projects when using a single project ID' do + projects = user.projects_with_reporter_access_limited_to(project1.id) + + expect(projects).to eq([project1]) + end + + it 'returns the projects when using an Array of project IDs' do + projects = user.projects_with_reporter_access_limited_to([project1.id]) + + expect(projects).to eq([project1]) + end + + it 'returns the projects when using an ActiveRecord relation' do + projects = user. + projects_with_reporter_access_limited_to(Project.select(:id)) + + expect(projects).to eq([project1]) + end + + it 'does not return projects you do not have reporter access to' do + projects = user.projects_with_reporter_access_limited_to(project2.id) + + expect(projects).to be_empty + end + end end -- cgit v1.2.1 From 24261f2dbd50583ac997c3f53f78104a96fa2cd3 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 11 Oct 2016 17:37:19 +0200 Subject: Add the method ExternalIssue#project_id This method returns the project's ID, making ExternalIssue slightly more compatible with Issue (which also defines the "project_id" method). --- spec/models/external_issue_spec.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/external_issue_spec.rb b/spec/models/external_issue_spec.rb index ebba6e14578..2debe1289a3 100644 --- a/spec/models/external_issue_spec.rb +++ b/spec/models/external_issue_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe ExternalIssue, models: true do - let(:project) { double('project', to_reference: 'namespace1/project1') } + let(:project) { double('project', id: 1, to_reference: 'namespace1/project1') } let(:issue) { described_class.new('EXT-1234', project) } describe 'modules' do @@ -36,4 +36,10 @@ describe ExternalIssue, models: true do end end end + + describe '#project_id' do + it 'returns the ID of the project' do + expect(issue.project_id).to eq(project.id) + end + end end -- cgit v1.2.1 From 89bb29b247b57e3b4ba053a5fd17f2087ac4414f Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 11 Oct 2016 17:31:19 +0200 Subject: Flush Housekeeping data from Redis specs These specs use raw Redis objects which can not use the memory based caching mechanism used for tests. As such we have to explicitly flush the data from Redis before/after each spec to ensure no data lingers on. --- spec/services/git_push_service_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'spec') diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 45bc44ba172..1c7a3d04b09 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -538,9 +538,16 @@ describe GitPushService, services: true do let(:housekeeping) { Projects::HousekeepingService.new(project) } before do + # Flush any raw Redis data stored by the housekeeping code. + Gitlab::Redis.with { |conn| conn.flushall } + allow(Projects::HousekeepingService).to receive(:new).and_return(housekeeping) end + after do + Gitlab::Redis.with { |conn| conn.flushall } + end + it 'does not perform housekeeping when not needed' do expect(housekeeping).not_to receive(:execute) -- cgit v1.2.1 From f694f94c491452a50035c2ff43c8ba595c0e73aa Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 12 Oct 2016 14:01:34 +0200 Subject: Added IssueCollection This class can be used to reduce a list of issues down to a subset based on user permissions. This class operates in such a way that it can reduce issues using as few queries as possible, if any at all. --- spec/models/concerns/issuable_spec.rb | 21 +++++++++++++ spec/models/issue_collection_spec.rb | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 spec/models/issue_collection_spec.rb (limited to 'spec') diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index a59d30687f6..a9603074c32 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -341,4 +341,25 @@ describe Issue, "Issuable" do expect(Issue.with_label([bug.title, enhancement.title])).to match_array([issue2]) end end + + describe '#assignee_or_author?' do + let(:user) { build(:user, id: 1) } + let(:issue) { build(:issue) } + + it 'returns true for a user that is assigned to an issue' do + issue.assignee = user + + expect(issue.assignee_or_author?(user)).to eq(true) + end + + it 'returns true for a user that is the author of an issue' do + issue.author = user + + expect(issue.assignee_or_author?(user)).to eq(true) + end + + it 'returns false for a user that is not the assignee or author' do + expect(issue.assignee_or_author?(user)).to eq(false) + end + end end diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb new file mode 100644 index 00000000000..d9ab397c302 --- /dev/null +++ b/spec/models/issue_collection_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe IssueCollection do + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:issue1) { create(:issue, project: project) } + let(:issue2) { create(:issue, project: project) } + let(:collection) { described_class.new([issue1, issue2]) } + + describe '#collection' do + it 'returns the issues in the same order as the input Array' do + expect(collection.collection).to eq([issue1, issue2]) + end + end + + describe '#updatable_by_user' do + context 'using an admin user' do + it 'returns all issues' do + user = create(:admin) + + expect(collection.updatable_by_user(user)).to eq([issue1, issue2]) + end + end + + context 'using a user that has no access to the project' do + it 'returns no issues when the user is not an assignee or author' do + expect(collection.updatable_by_user(user)).to be_empty + end + + it 'returns the issues the user is assigned to' do + issue1.assignee = user + + expect(collection.updatable_by_user(user)).to eq([issue1]) + end + + it 'returns the issues for which the user is the author' do + issue1.author = user + + expect(collection.updatable_by_user(user)).to eq([issue1]) + end + end + + context 'using a user that has reporter access to the project' do + it 'returns the issues of the project' do + project.team << [user, :reporter] + + expect(collection.updatable_by_user(user)).to eq([issue1, issue2]) + end + end + + context 'using a user that is the owner of a project' do + it 'returns the issues of the project' do + expect(collection.updatable_by_user(project.namespace.owner)). + to eq([issue1, issue2]) + end + end + end +end -- cgit v1.2.1 From 509910b89f636f95d2d5a9cd3f38ce8f7f4f47a6 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 7 Oct 2016 15:20:57 +0200 Subject: Process commits in a separate worker This moves the code used for processing commits from GitPushService to its own Sidekiq worker: ProcessCommitWorker. Using a Sidekiq worker allows us to process multiple commits in parallel. This in turn will lead to issues being closed faster and cross references being created faster. Furthermore by isolating this code into a separate class it's easier to test and maintain the code. The new worker also ensures it can efficiently check which issues can be closed, without having to run numerous SQL queries for every issue. --- spec/models/issue_collection_spec.rb | 9 +++ spec/services/git_push_service_spec.rb | 9 +++ spec/services/issues/close_service_spec.rb | 49 ++++++++----- spec/workers/process_commit_worker_spec.rb | 109 +++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 16 deletions(-) create mode 100644 spec/workers/process_commit_worker_spec.rb (limited to 'spec') diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb index d9ab397c302..d742c814680 100644 --- a/spec/models/issue_collection_spec.rb +++ b/spec/models/issue_collection_spec.rb @@ -55,4 +55,13 @@ describe IssueCollection do end end end + + describe '#visible_to' do + it 'is an alias for updatable_by_user' do + updatable_by_user = described_class.instance_method(:updatable_by_user) + visible_to = described_class.instance_method(:visible_to) + + expect(visible_to).to eq(updatable_by_user) + end + end end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 1c7a3d04b09..cea7e6429f9 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -302,6 +302,9 @@ describe GitPushService, services: true do author_email: commit_author.email ) + allow_any_instance_of(ProcessCommitWorker).to receive(:find_commit). + and_return(commit) + allow(project.repository).to receive(:commits_between).and_return([commit]) end @@ -357,6 +360,9 @@ describe GitPushService, services: true do committed_date: commit_time ) + allow_any_instance_of(ProcessCommitWorker).to receive(:find_commit). + and_return(commit) + allow(project.repository).to receive(:commits_between).and_return([commit]) end @@ -393,6 +399,9 @@ describe GitPushService, services: true do allow(project.repository).to receive(:commits_between). and_return([closing_commit]) + allow_any_instance_of(ProcessCommitWorker).to receive(:find_commit). + and_return(closing_commit) + project.team << [commit_author, :master] end diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index 5dfb33f4b28..4465f22a001 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -15,10 +15,39 @@ describe Issues::CloseService, services: true do end describe '#execute' do + let(:service) { described_class.new(project, user) } + + it 'checks if the user is authorized to update the issue' do + expect(service).to receive(:can?).with(user, :update_issue, issue). + and_call_original + + service.execute(issue) + end + + it 'does not close the issue when the user is not authorized to do so' do + allow(service).to receive(:can?).with(user, :update_issue, issue). + and_return(false) + + expect(service).not_to receive(:close_issue) + expect(service.execute(issue)).to eq(issue) + end + + it 'closes the issue when the user is authorized to do so' do + allow(service).to receive(:can?).with(user, :update_issue, issue). + and_return(true) + + expect(service).to receive(:close_issue). + with(issue, commit: nil, notifications: true, system_note: true) + + service.execute(issue) + end + end + + describe '#close_issue' do context "valid params" do before do perform_enqueued_jobs do - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end end @@ -41,24 +70,12 @@ describe Issues::CloseService, services: true do end end - context 'current user is not authorized to close issue' do - before do - perform_enqueued_jobs do - described_class.new(project, guest).execute(issue) - end - end - - it 'does not close the issue' do - expect(issue).to be_open - end - end - context 'when issue is not confidential' do it 'executes issue hooks' do expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :issue_hooks) expect(project).to receive(:execute_services).with(an_instance_of(Hash), :issue_hooks) - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end end @@ -69,14 +86,14 @@ describe Issues::CloseService, services: true do expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :confidential_issue_hooks) expect(project).to receive(:execute_services).with(an_instance_of(Hash), :confidential_issue_hooks) - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end end context 'external issue tracker' do before do allow(project).to receive(:default_issues_tracker?).and_return(false) - described_class.new(project, user).execute(issue) + described_class.new(project, user).close_issue(issue) end it { expect(issue).to be_valid } diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb new file mode 100644 index 00000000000..3e4fee42240 --- /dev/null +++ b/spec/workers/process_commit_worker_spec.rb @@ -0,0 +1,109 @@ +require 'spec_helper' + +describe ProcessCommitWorker do + let(:worker) { described_class.new } + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:issue) { create(:issue, project: project, author: user) } + let(:commit) { project.commit } + + describe '#perform' do + it 'does not process the commit when the project does not exist' do + expect(worker).not_to receive(:close_issues) + + worker.perform(-1, user.id, commit.id) + end + + it 'does not process the commit when the user does not exist' do + expect(worker).not_to receive(:close_issues) + + worker.perform(project.id, -1, commit.id) + end + + it 'does not process the commit when the commit no longer exists' do + expect(worker).not_to receive(:close_issues) + + worker.perform(project.id, user.id, 'this-should-does-not-exist') + end + + it 'processes the commit message' do + expect(worker).to receive(:process_commit_message).and_call_original + + worker.perform(project.id, user.id, commit.id) + end + + it 'updates the issue metrics' do + expect(worker).to receive(:update_issue_metrics).and_call_original + + worker.perform(project.id, user.id, commit.id) + end + end + + describe '#process_commit_message' do + context 'when pushing to the default branch' do + it 'closes issues that should be closed per the commit message' do + allow(commit).to receive(:safe_message). + and_return("Closes #{issue.to_reference}") + + expect(worker).to receive(:close_issues). + with(project, user, user, commit, [issue]) + + worker.process_commit_message(project, commit, user, user, true) + end + end + + context 'when pushing to a non-default branch' do + it 'does not close any issues' do + allow(commit).to receive(:safe_message). + and_return("Closes #{issue.to_reference}") + + expect(worker).not_to receive(:close_issues) + + worker.process_commit_message(project, commit, user, user, false) + end + end + + it 'creates cross references' do + expect(commit).to receive(:create_cross_references!) + + worker.process_commit_message(project, commit, user, user) + end + end + + describe '#close_issues' do + context 'when the user can update the issues' do + it 'closes the issues' do + worker.close_issues(project, user, user, commit, [issue]) + + issue.reload + + expect(issue.closed?).to eq(true) + end + end + + context 'when the user can not update the issues' do + it 'does not close the issues' do + other_user = create(:user) + + worker.close_issues(project, other_user, other_user, commit, [issue]) + + issue.reload + + expect(issue.closed?).to eq(false) + end + end + end + + describe '#update_issue_metrics' do + it 'updates any existing issue metrics' do + allow(commit).to receive(:safe_message). + and_return("Closes #{issue.to_reference}") + + worker.update_issue_metrics(commit, user) + + metric = Issue::Metrics.first + + expect(metric.first_mentioned_in_commit_at).to eq(commit.committed_date) + end + end +end -- cgit v1.2.1 From d76416f5e8697341c1c32b0bf19101501300349d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 7 Nov 2016 13:33:33 +0100 Subject: Evade some exceptions when using invalid references --- spec/models/repository_spec.rb | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 04b7d19d414..f35de604c7a 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -113,6 +113,26 @@ describe Repository, models: true do end end + describe '#ref_exists?' do + context 'when ref exists' do + it 'returns true' do + expect(repository.ref_exists?('refs/heads/master')).to be true + end + end + + context 'when ref does not exist' do + it 'returns false' do + expect(repository.ref_exists?('refs/heads/non-existent')).to be false + end + end + + context 'when ref format is incorrect' do + it 'returns false' do + expect(repository.ref_exists?('refs/heads/invalid:master')).to be false + end + end + end + describe '#last_commit_for_path' do subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id } @@ -197,6 +217,35 @@ describe Repository, models: true do end end + describe '#commit' do + context 'when ref exists' do + it 'returns commit object' do + expect(repository.commit('master')) + .to be_an_instance_of Commit + end + end + + context 'when ref does not exist' do + it 'returns nil' do + expect(repository.commit('non-existent-ref')).to be_nil + end + end + + context 'when ref is not valid' do + context 'when preceding tree element exists' do + it 'returns nil' do + expect(repository.commit('master:ref')).to be_nil + end + end + + context 'when preceding tree element does not exist' do + it 'returns nil' do + expect(repository.commit('non-existent:ref')).to be_nil + end + end + end + end + describe "#commit_dir" do it "commits a change that creates a new directory" do expect do -- cgit v1.2.1 From 82e551bdac7f2792e1d6aceb1b0b674dbd3dda81 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 7 Nov 2016 15:16:04 +0200 Subject: Refactor routing constraints Signed-off-by: Dmitriy Zaporozhets --- spec/lib/constraints/constrainer_helper_spec.rb | 20 +++++++++++++ spec/lib/constraints/group_url_constrainer_spec.rb | 17 ++++++++--- .../constraints/namespace_url_constrainer_spec.rb | 35 ---------------------- spec/lib/constraints/user_url_constrainer_spec.rb | 12 ++++++-- 4 files changed, 42 insertions(+), 42 deletions(-) create mode 100644 spec/lib/constraints/constrainer_helper_spec.rb delete mode 100644 spec/lib/constraints/namespace_url_constrainer_spec.rb (limited to 'spec') diff --git a/spec/lib/constraints/constrainer_helper_spec.rb b/spec/lib/constraints/constrainer_helper_spec.rb new file mode 100644 index 00000000000..27c8d72aefc --- /dev/null +++ b/spec/lib/constraints/constrainer_helper_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe ConstrainerHelper, lib: true do + include ConstrainerHelper + + describe '#extract_resource_path' do + it { expect(extract_resource_path('/gitlab/')).to eq('gitlab') } + it { expect(extract_resource_path('///gitlab//')).to eq('gitlab') } + it { expect(extract_resource_path('/gitlab.atom')).to eq('gitlab') } + + context 'relative url' do + before do + allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' } + end + + it { expect(extract_resource_path('/gitlab/foo')).to eq('foo') } + it { expect(extract_resource_path('/foo/bar')).to eq('foo/bar') } + end + end +end diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index f0b75a664f2..be69a36c2b6 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -1,10 +1,19 @@ require 'spec_helper' describe GroupUrlConstrainer, lib: true do - let!(:username) { create(:group, path: 'gitlab-org') } + let!(:group) { create(:group, path: 'gitlab') } - describe '#find_resource' do - it { expect(!!subject.find_resource('gitlab-org')).to be_truthy } - it { expect(!!subject.find_resource('gitlab-com')).to be_falsey } + describe '#matches?' do + context 'root group' do + it { expect(subject.matches?(request '/gitlab')).to be_truthy } + it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } + it { expect(subject.matches?(request '/gitlab/edit')).to be_falsey } + it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } + it { expect(subject.matches?(request '/.gitlab')).to be_falsey } + end + end + + def request(path) + OpenStruct.new(path: path) end end diff --git a/spec/lib/constraints/namespace_url_constrainer_spec.rb b/spec/lib/constraints/namespace_url_constrainer_spec.rb deleted file mode 100644 index 7814711fe27..00000000000 --- a/spec/lib/constraints/namespace_url_constrainer_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' - -describe NamespaceUrlConstrainer, lib: true do - let!(:group) { create(:group, path: 'gitlab') } - - describe '#matches?' do - context 'existing namespace' do - it { expect(subject.matches?(request '/gitlab')).to be_truthy } - it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } - it { expect(subject.matches?(request '/gitlab/')).to be_truthy } - it { expect(subject.matches?(request '//gitlab/')).to be_truthy } - end - - context 'non-existing namespace' do - it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } - it { expect(subject.matches?(request '/gitlab.ce')).to be_falsey } - it { expect(subject.matches?(request '/g/gitlab')).to be_falsey } - it { expect(subject.matches?(request '/.gitlab')).to be_falsey } - end - - context 'relative url' do - before do - allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' } - end - - it { expect(subject.matches?(request '/gitlab/gitlab')).to be_truthy } - it { expect(subject.matches?(request '/gitlab/gitlab-ce')).to be_falsey } - it { expect(subject.matches?(request '/gitlab/')).to be_falsey } - end - end - - def request(path) - OpenStruct.new(path: path) - end -end diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index 4b26692672f..d7b7d5664ff 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -3,8 +3,14 @@ require 'spec_helper' describe UserUrlConstrainer, lib: true do let!(:username) { create(:user, username: 'dz') } - describe '#find_resource' do - it { expect(!!subject.find_resource('dz')).to be_truthy } - it { expect(!!subject.find_resource('john')).to be_falsey } + describe '#matches?' do + it { expect(subject.matches?(request '/dz')).to be_truthy } + it { expect(subject.matches?(request '/dz.atom')).to be_truthy } + it { expect(subject.matches?(request '/dz/projects')).to be_falsey } + it { expect(subject.matches?(request '/gitlab')).to be_falsey } + end + + def request(path) + OpenStruct.new(path: path) end end -- cgit v1.2.1 From 63f0b099744834424e6fef78c694beda9d8b16fe Mon Sep 17 00:00:00 2001 From: Rares Sfirlogea Date: Fri, 4 Nov 2016 12:52:38 +0100 Subject: Expose Label id to API [e44da1c] Add Label API expected keys to tests [ac929c8] Update Label API documentation --- spec/requests/api/labels_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 7e532912d08..2ff90b6deac 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -17,12 +17,18 @@ describe API::API, api: true do group = create(:group) group_label = create(:group_label, group: group) project.update(group: group) + expected_keys = [ + 'id', 'name', 'color', 'description', + 'open_issues_count', 'closed_issues_count', 'open_merge_requests_count', + 'subscribed', 'priority' + ] get api("/projects/#{project.id}/labels", user) expect(response).to have_http_status(200) expect(json_response).to be_an Array expect(json_response.size).to eq(3) + expect(json_response.first.keys).to match_array expected_keys expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) expect(json_response.last['name']).to eq(label1.name) expect(json_response.last['color']).to be_present -- cgit v1.2.1 From 591e18364a82fc8a9a906310e37566c05ad4f4ab Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 3 Nov 2016 13:01:23 +0200 Subject: Add tests for project#index routing Signed-off-by: Dmitriy Zaporozhets --- spec/controllers/projects_controller_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 8eefa284ba0..a302d1c57f4 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -7,6 +7,26 @@ describe ProjectsController do let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + describe 'GET index' do + context 'as a user' do + it 'redirects to root page' do + sign_in(user) + + get :index + + expect(response).to redirect_to(root_path) + end + end + + context 'as a guest' do + it 'redirects to Explore page' do + get :index + + expect(response).to redirect_to(explore_root_path) + end + end + end + describe "GET show" do context "user not project member" do before { sign_in(user) } -- cgit v1.2.1 From e6e4147880e831cdc6cc9ef31774297222f654c3 Mon Sep 17 00:00:00 2001 From: Lisanne Fellinger Date: Thu, 27 Oct 2016 22:08:20 +0200 Subject: Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Relocated git_blame spec and fixed styling issue Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Relocated git_blame spec and fixed styling issue Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Rewritten spinach git_blame tests to rspec feature tests Fixing rubocop violations Relocated git_blame spec and fixed styling issue --- spec/features/projects/files/browse_files_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 spec/features/projects/files/browse_files_spec.rb (limited to 'spec') diff --git a/spec/features/projects/files/browse_files_spec.rb b/spec/features/projects/files/browse_files_spec.rb new file mode 100644 index 00000000000..69295e450d0 --- /dev/null +++ b/spec/features/projects/files/browse_files_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +feature 'user checks git blame', feature: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + login_with(user) + visit namespace_project_tree_path(project.namespace, project, project.default_branch) + end + + scenario "can see blame of '.gitignore'" do + click_link ".gitignore" + click_link 'Blame' + + expect(page).to have_content "*.rb" + expect(page).to have_content "Dmitriy Zaporozhets" + expect(page).to have_content "Initial commit" + end +end -- cgit v1.2.1 From 16b0723a7ce709437084c12647e59b3a73479ddf Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Tue, 30 Aug 2016 21:44:30 +0100 Subject: Use the Gitlab Workhorse HTTP header in the admin dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/helpers/components_helper_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 spec/helpers/components_helper_spec.rb (limited to 'spec') diff --git a/spec/helpers/components_helper_spec.rb b/spec/helpers/components_helper_spec.rb new file mode 100644 index 00000000000..94a59193be8 --- /dev/null +++ b/spec/helpers/components_helper_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe ComponentsHelper do + describe '#gitlab_workhorse_version' do + context 'without a Gitlab-Workhorse header' do + it 'shows the version from Gitlab::Workhorse.version' do + expect(helper.gitlab_workhorse_version).to eq Gitlab::Workhorse.version + end + end + + context 'with a Gitlab-Workhorse header' do + before do + helper.request.headers['Gitlab-Workhorse'] = '42.42.0-rc3' + end + + it 'shows the actual GitLab Workhorse version currently in use' do + expect(helper.gitlab_workhorse_version).to eq '42.42.0' + end + end + end +end -- cgit v1.2.1 From 9d51421346178c9189ffb47189f51d573ab42822 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 19 Aug 2016 18:33:46 -0500 Subject: Use separate email-friendly token for incoming email and let incoming email token be reset --- spec/features/projects/issues/issues_spec.rb | 0 spec/fixtures/emails/wrong_authentication_token.eml | 18 ------------------ spec/fixtures/emails/wrong_incoming_email_token.eml | 18 ++++++++++++++++++ .../gitlab/email/handler/create_issue_handler_spec.rb | 6 +++--- 4 files changed, 21 insertions(+), 21 deletions(-) create mode 100644 spec/features/projects/issues/issues_spec.rb delete mode 100644 spec/fixtures/emails/wrong_authentication_token.eml create mode 100644 spec/fixtures/emails/wrong_incoming_email_token.eml (limited to 'spec') diff --git a/spec/features/projects/issues/issues_spec.rb b/spec/features/projects/issues/issues_spec.rb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spec/fixtures/emails/wrong_authentication_token.eml b/spec/fixtures/emails/wrong_authentication_token.eml deleted file mode 100644 index 0994c2f7775..00000000000 --- a/spec/fixtures/emails/wrong_authentication_token.eml +++ /dev/null @@ -1,18 +0,0 @@ -Return-Path: -Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400 -Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Thu, 13 Jun 2013 17:03:50 -0400 -Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for ; Thu, 13 Jun 2013 14:03:48 -0700 -Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700 -Date: Thu, 13 Jun 2013 17:03:48 -0400 -From: Jake the Dog -To: incoming+gitlabhq/gitlabhq+bad_token@appmail.adventuretime.ooo -Message-ID: -Subject: New Issue by email -Mime-Version: 1.0 -Content-Type: text/plain; - charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -X-Sieve: CMU Sieve 2.2 -X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu, - 13 Jun 2013 14:03:48 -0700 (PDT) -X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1 diff --git a/spec/fixtures/emails/wrong_incoming_email_token.eml b/spec/fixtures/emails/wrong_incoming_email_token.eml new file mode 100644 index 00000000000..0994c2f7775 --- /dev/null +++ b/spec/fixtures/emails/wrong_incoming_email_token.eml @@ -0,0 +1,18 @@ +Return-Path: +Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400 +Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Thu, 13 Jun 2013 17:03:50 -0400 +Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for ; Thu, 13 Jun 2013 14:03:48 -0700 +Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700 +Date: Thu, 13 Jun 2013 17:03:48 -0400 +From: Jake the Dog +To: incoming+gitlabhq/gitlabhq+bad_token@appmail.adventuretime.ooo +Message-ID: +Subject: New Issue by email +Mime-Version: 1.0 +Content-Type: text/plain; + charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +X-Sieve: CMU Sieve 2.2 +X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu, + 13 Jun 2013 14:03:48 -0700 (PDT) +X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1 diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb index a5cc7b02936..939189a3bc0 100644 --- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb @@ -18,7 +18,7 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do create( :user, email: 'jake@adventuretime.ooo', - authentication_token: 'auth_token' + incoming_email_token: 'auth_token' ) end @@ -60,8 +60,8 @@ xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do end end - context "when we can't find the authentication_token" do - let(:email_raw) { fixture_file("emails/wrong_authentication_token.eml") } + context "when we can't find the incoming_email_token" do + let(:email_raw) { fixture_file("emails/wrong_incoming_email_token.eml") } it "raises an UserNotFoundError" do expect { receiver.execute }.to raise_error(Gitlab::Email::UserNotFoundError) -- cgit v1.2.1 From 011e561bfa227f3ecbafe5b1ffd51700c680a15f Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Tue, 18 Oct 2016 19:03:31 +0100 Subject: implements reset incoming email token on issues modal and account page, reactivates all tests and writes more tests for it --- spec/controllers/projects_controller_spec.rb | 27 ++++++++++++++++++++ spec/features/issues_spec.rb | 23 ++++++++++++++++- spec/features/profile_spec.rb | 29 ++++++++++++++++++++++ spec/features/projects/issues/issues_spec.rb | 0 .../email/handler/create_issue_handler_spec.rb | 2 +- spec/models/project_spec.rb | 5 ++-- 6 files changed, 81 insertions(+), 5 deletions(-) delete mode 100644 spec/features/projects/issues/issues_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 8eefa284ba0..ca6bf17005c 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -264,6 +264,33 @@ describe ProjectsController do end end + describe 'PUT #new_issue_address' do + subject do + put :new_issue_address, + namespace_id: project.namespace.to_param, + id: project.to_param + user.reload + end + + before do + sign_in(user) + project.team << [user, :developer] + allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) + end + + it 'has http status 200' do + expect(response).to have_http_status(200) + end + + it 'changes the user incoming email token' do + expect { subject }.to change { user.incoming_email_token } + end + + it 'changes projects new issue address' do + expect { subject }.to change { project.new_issue_address(user) } + end + end + describe "POST #toggle_star" do it "toggles star if user is signed in" do sign_in(user) diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index b504329656f..cdd02a8c8e3 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' describe 'Issues', feature: true do include IssueHelpers include SortingHelper + include WaitForAjax let(:project) { create(:project) } @@ -368,6 +369,26 @@ describe 'Issues', feature: true do end end + describe 'when I want to reset my incoming email token' do + let(:project1) { create(:project, namespace: @user.namespace) } + + before do + allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) + project1.team << [@user, :master] + visit namespace_project_issues_path(@user.namespace, project1) + end + + it 'changes incoming email address token', js: true do + find('.issue-email-modal-btn').click + previous_token = find('input#issue_email').value + + find('.incoming-email-token-reset').click + wait_for_ajax + + expect(find('input#issue_email').value).not_to eq(previous_token) + end + end + describe 'update labels from issue#show', js: true do let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } let!(:label) { create(:label, project: project) } @@ -553,7 +574,7 @@ describe 'Issues', feature: true do end end - xdescribe 'new issue by email' do + describe 'new issue by email' do shared_examples 'show the email in the modal' do before do stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index c3d8c349ca4..7a562b5e03d 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -32,4 +32,33 @@ describe 'Profile account page', feature: true do expect(current_path).to eq(profile_account_path) end end + + describe 'when I reset private token' do + before do + visit profile_account_path + end + + it 'resets private token' do + previous_token = find("#private-token").value + + click_link('Reset private token') + + expect(find('#private-token').value).not_to eq(previous_token) + end + end + + describe 'when I reset incoming email token' do + before do + allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) + visit profile_account_path + end + + it 'resets incoming email token' do + previous_token = find('#incoming-email-token').value + + click_link('Reset incoming email token') + + expect(find('#incoming-email-token').value).not_to eq(previous_token) + end + end end diff --git a/spec/features/projects/issues/issues_spec.rb b/spec/features/projects/issues/issues_spec.rb deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb index 939189a3bc0..cb3651e3845 100644 --- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require_relative '../email_shared_blocks' -xdescribe Gitlab::Email::Handler::CreateIssueHandler, lib: true do +describe Gitlab::Email::Handler::CreateIssueHandler, lib: true do include_context :email_shared_context it_behaves_like :email_shared_examples diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0245897938c..0810d06b50f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -295,7 +295,7 @@ describe Project, models: true do end end - xdescribe "#new_issue_address" do + describe "#new_issue_address" do let(:project) { create(:empty_project, path: "somewhere") } let(:user) { create(:user) } @@ -305,8 +305,7 @@ describe Project, models: true do end it 'returns the address to create a new issue' do - token = user.authentication_token - address = "p+#{project.namespace.path}/#{project.path}+#{token}@gl.ab" + address = "p+#{project.path_with_namespace}+#{user.incoming_email_token}@gl.ab" expect(project.new_issue_address(user)).to eq(address) end -- cgit v1.2.1 From fa1ac47ef167e55d79a69d69596012fe5ac99d20 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 8 Sep 2016 13:57:24 -0500 Subject: Replace jQuery.timeago with timeago.js --- spec/helpers/application_helper_spec.rb | 24 +++--------------------- spec/javascripts/merge_request_widget_spec.js | 2 +- 2 files changed, 4 insertions(+), 22 deletions(-) (limited to 'spec') diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 73f5470cf35..c706e418d26 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -218,42 +218,24 @@ describe ApplicationHelper do end it 'includes a default js-timeago class' do - expect(element.attr('class')).to eq 'js-timeago js-timeago-pending' + expect(element.attr('class')).to eq 'js-timeago' end it 'accepts a custom html_class' do expect(element(html_class: 'custom_class').attr('class')). - to eq 'js-timeago custom_class js-timeago-pending' + to eq 'js-timeago custom_class' end it 'accepts a custom tooltip placement' do expect(element(placement: 'bottom').attr('data-placement')).to eq 'bottom' end - it 're-initializes timeago Javascript' do - el = element.next_element - - expect(el.name).to eq 'script' - expect(el.text).to include "$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()" - end - - it 'allows the script tag to be excluded' do - expect(element(skip_js: true)).not_to include 'script' - end - it 'converts to Time' do expect { helper.time_ago_with_tooltip(Date.today) }.not_to raise_error end - it 'add class for the short format and includes inline script' do + it 'add class for the short format' do timeago_element = element(short_format: 'short') - expect(timeago_element.attr('class')).to eq 'js-short-timeago js-timeago-pending' - script_element = timeago_element.next_element - expect(script_element.name).to eq 'script' - end - - it 'add class for the short format and does not include inline script' do - timeago_element = element(short_format: 'short', skip_js: true) expect(timeago_element.attr('class')).to eq 'js-short-timeago' expect(timeago_element.next_element).to eq nil end diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 49dfeab61d8..91f19aca719 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,6 +1,6 @@ /* eslint-disable */ /*= require merge_request_widget */ -/*= require jquery.timeago.js */ +/*= require lib/utils/timeago.js */ (function() { describe('MergeRequestWidget', function() { -- cgit v1.2.1 From 903431e8895ba196edc7ce67d46279d0d06cba1d Mon Sep 17 00:00:00 2001 From: the-undefined Date: Mon, 7 Nov 2016 08:01:27 +0000 Subject: Move 'Explore Snippets' Spinach feature to Rspec This commit moves the `snippets/discover.feature` Spinach test to a Rspec feature, as part of deprecating the Spinach test suite. The original feature was called 'Discover Snippets', but the UI no longer reflects this wording. The new Rspec feature is called 'Explore Snippets' to reflect UI/Controller/View naming in use. - Remove Spinach discover snippets feature and steps - Add Rspec feature test --- spec/features/snippets/explore_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 spec/features/snippets/explore_spec.rb (limited to 'spec') diff --git a/spec/features/snippets/explore_spec.rb b/spec/features/snippets/explore_spec.rb new file mode 100644 index 00000000000..10a4597e467 --- /dev/null +++ b/spec/features/snippets/explore_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +feature 'Explore Snippets', feature: true do + scenario 'User should see snippets that are not private' do + public_snippet = create(:personal_snippet, :public) + internal_snippet = create(:personal_snippet, :internal) + private_snippet = create(:personal_snippet, :private) + + login_as create(:user) + visit explore_snippets_path + + expect(page).to have_content(public_snippet.title) + expect(page).to have_content(internal_snippet.title) + expect(page).not_to have_content(private_snippet.title) + end +end -- cgit v1.2.1 From 659ef54605e37ba750486f25957ec367264dffd4 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 8 Nov 2016 10:05:19 +0100 Subject: API: Return 400 when creating a systemhook fails --- spec/requests/api/system_hooks_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index f685a3685e6..6c9df21f598 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -52,6 +52,12 @@ describe API::API, api: true do expect(response).to have_http_status(400) end + it "responds with 400 if url is invalid" do + post api("/hooks", admin), url: 'hp://mep.mep' + + expect(response).to have_http_status(400) + end + it "does not create new hook without url" do expect do post api("/hooks", admin) -- cgit v1.2.1 From c2e2cde910008e148c0af49ee6135be0b3d7f7d9 Mon Sep 17 00:00:00 2001 From: Borja Aparicio Date: Tue, 25 Oct 2016 14:54:18 +0200 Subject: Added API spec test for projects/owned endpoint --- spec/requests/api/projects_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 3c8f0ac531a..d6e9fd2c4b2 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -175,6 +175,30 @@ describe API::API, api: true do end end + describe 'GET /projects/owned' do + before do + project3 + project4 + end + + context 'when unauthenticated' do + it 'returns authentication error' do + get api('/projects/owned') + expect(response).to have_http_status(401) + end + end + + context 'when authenticated as project owner' do + it 'returns an array of projects the user owns' do + get api('/projects/owned', user4) + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq(project4.name) + expect(json_response.first['owner']['username']).to eq(user4.username) + end + end + end + describe 'GET /projects/visible' do let(:public_project) { create(:project, :public) } -- cgit v1.2.1 From 4f2c4411615a7c870fd1fa54525079f7ea97d6e5 Mon Sep 17 00:00:00 2001 From: Borja Aparicio Date: Tue, 25 Oct 2016 15:22:12 +0200 Subject: Added API endpoint groups/owned --- spec/requests/api/groups_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 7b47bf5afc1..b29a13b1d8b 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -68,6 +68,24 @@ describe API::API, api: true do end end + describe 'GET /groups/owned' do + context 'when unauthenticated' do + it 'returns authentication error' do + get api('/groups/owned') + expect(response).to have_http_status(401) + end + end + + context 'when authenticated as group owner' do + it 'returns an array of groups the user owns' do + get api('/groups/owned', user2) + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq(group2.name) + end + end + end + describe "GET /groups/:id" do context "when authenticated as user" do it "returns one of user1's groups" do -- cgit v1.2.1 From ebc44befdc773b39a171d38dc13c38cd6630828a Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 7 Nov 2016 20:36:58 +0200 Subject: Fix broken commits search --- spec/features/global_search_spec.rb | 28 ++++++++++++++++++++++++++++ spec/features/search_spec.rb | 26 ++++++++++++++++++++++++++ spec/spec_helper.rb | 1 + spec/support/search_helpers.rb | 5 +++++ 4 files changed, 60 insertions(+) create mode 100644 spec/features/global_search_spec.rb create mode 100644 spec/support/search_helpers.rb (limited to 'spec') diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb new file mode 100644 index 00000000000..f6409e00f22 --- /dev/null +++ b/spec/features/global_search_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +feature 'Global search', feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + before do + project.team << [user, :master] + login_with(user) + end + + describe 'I search through the issues and I see pagination' do + before do + allow_any_instance_of(Gitlab::SearchResults).to receive(:per_page).and_return(1) + create_list(:issue, 2, project: project, title: 'initial') + end + + it "has a pagination" do + visit dashboard_projects_path + + fill_in "search", with: "initial" + click_button "Go" + + select_filter("Issues") + expect(page).to have_selector('.gl-pagination .page', count: 2) + end + end +end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index 1806200c82c..caecd027aaa 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -100,6 +100,32 @@ describe "Search", feature: true do expect(page).to have_link(snippet.title) end + + it 'finds a commit' do + visit namespace_project_path(project.namespace, project) + + page.within '.search' do + fill_in 'search', with: 'add' + click_button 'Go' + end + + click_link "Commits" + + expect(page).to have_selector('.commit-row-description') + end + + it 'finds a code' do + visit namespace_project_path(project.namespace, project) + + page.within '.search' do + fill_in 'search', with: 'def' + click_button 'Go' + end + + click_link "Code" + + expect(page).to have_selector('.file-content .code') + end end describe 'Right header search field', feature: true do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b2ca856f89f..73cf4c9a24c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -29,6 +29,7 @@ RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include Warden::Test::Helpers, type: :request config.include LoginHelpers, type: :feature + config.include SearchHelpers, type: :feature config.include StubConfiguration config.include EmailHelpers config.include TestEnv diff --git a/spec/support/search_helpers.rb b/spec/support/search_helpers.rb new file mode 100644 index 00000000000..abbbb636d66 --- /dev/null +++ b/spec/support/search_helpers.rb @@ -0,0 +1,5 @@ +module SearchHelpers + def select_filter(name) + find(:xpath, "//ul[contains(@class, 'search-filter')]//a[contains(.,'#{name}')]").click + end +end -- cgit v1.2.1 From 869696bca3d8ff72e2dbaa96744eb7a7d560f0cf Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 8 Nov 2016 14:21:19 +0200 Subject: Faster search --- spec/models/repository_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 04b7d19d414..12989d4db53 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -362,6 +362,19 @@ describe Repository, models: true do expect(results.first).not_to start_with('fatal:') end + it 'properly handles when query is not present' do + results = repository.search_files('', 'master') + + expect(results).to match_array([]) + end + + it 'properly handles query when repo is empty' do + repository = create(:empty_project).repository + results = repository.search_files('test', 'master') + + expect(results).to match_array([]) + end + describe 'result' do subject { results.first } -- cgit v1.2.1 From 08d21fe89927fa9ebd3695fde047a17d27893dbf Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 8 Nov 2016 14:32:42 +0200 Subject: Add small improvements to constrainers and specs Signed-off-by: Dmitriy Zaporozhets --- spec/lib/constraints/group_url_constrainer_spec.rb | 2 +- spec/lib/constraints/user_url_constrainer_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index be69a36c2b6..42299b17c2b 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -14,6 +14,6 @@ describe GroupUrlConstrainer, lib: true do end def request(path) - OpenStruct.new(path: path) + double(:request, path: path) end end diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index d7b7d5664ff..b3f8530c609 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -11,6 +11,6 @@ describe UserUrlConstrainer, lib: true do end def request(path) - OpenStruct.new(path: path) + double(:request, path: path) end end -- cgit v1.2.1 From 04a8372cdfff501fe67c17612a0b5e098f7d56c9 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 8 Nov 2016 14:20:58 +0100 Subject: Add environment teardown service --- spec/services/ci/stop_environment_service_spec.rb | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 spec/services/ci/stop_environment_service_spec.rb (limited to 'spec') diff --git a/spec/services/ci/stop_environment_service_spec.rb b/spec/services/ci/stop_environment_service_spec.rb new file mode 100644 index 00000000000..40b2a028f67 --- /dev/null +++ b/spec/services/ci/stop_environment_service_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Ci::StopEnvironmentService, services: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + + let(:service) { described_class.new(project, user) } + + describe '#execute' do + context 'when environment exists' do + let(:environment) { create(:environment, project: project) } + let(:deployable) { create(:ci_build) } + + let(:stop_build) do + create(:ci_build, :manual, name: 'environment/teardown', + pipeline: deployable.pipeline) + end + + before do + create(:deployment, environment: environment, + deployable: deployable, + on_stop: stop_build.name, + user: user, + project: project, + sha: project.commit.id) + end + + it 'stops environment' do + expect_any_instance_of(Environment).to receive(:stop!) + + service.execute('master') + end + end + end +end -- cgit v1.2.1 From 5395f92e7ca93a907cdb2507b2ba2073863bc83a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 8 Nov 2016 15:54:17 +0200 Subject: Fix routing spec for group controller Signed-off-by: Dmitriy Zaporozhets --- spec/routing/routing_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index c18a2d55e43..61dca5d5a62 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -266,13 +266,13 @@ describe "Groups", "routing" do end it "also display group#show on the short path" do - allow(Group).to receive(:find_by_path).and_return(true) + allow(Group).to receive(:find_by).and_return(true) expect(get('/1')).to route_to('groups#show', id: '1') end it "also display group#show with dot in the path" do - allow(Group).to receive(:find_by_path).and_return(true) + allow(Group).to receive(:find_by).and_return(true) expect(get('/group.with.dot')).to route_to('groups#show', id: 'group.with.dot') end -- cgit v1.2.1 From a0aaf93fe591215a7fc29a52ff6cbd38604c8dcb Mon Sep 17 00:00:00 2001 From: Yatish Mehta Date: Tue, 25 Oct 2016 14:08:53 -0700 Subject: Add query param to filter users on 'external' & 'blocked' type on API --- spec/requests/api/users_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index ae8639d78d5..34d1f557e4b 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -48,6 +48,17 @@ describe API::API, api: true do end['username']).to eq(username) end + it "returns an array of blocked users" do + ldap_blocked_user + create(:user, state: 'blocked') + + get api("/users?blocked=true", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response).to all(include('state' => /(blocked|ldap_blocked)/)) + end + it "returns one user" do get api("/users?username=#{omniauth_user.username}", user) expect(response).to have_http_status(200) @@ -69,6 +80,16 @@ describe API::API, api: true do expect(json_response.first.keys).to include 'last_sign_in_at' expect(json_response.first.keys).to include 'confirmed_at' end + + it "returns an array of external users" do + create(:user, external: true) + + get api("/users?external=true", admin) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response).to all(include('external' => true)) + end end end -- cgit v1.2.1 From dc307830571aaca1ff20b409d7075eee83f21fb9 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Thu, 29 Sep 2016 14:08:27 -0500 Subject: Introduce better credential and error checking to `rake gitlab:ldap:check` It was previously possible for invalid credential errors to go unnoticed in this task. Users would believe everything was configured correctly and then sign in would fail with 'invalid credentials'. This adds a specific bind check, plus catches errors connecting to the server. Also, specs :) --- spec/lib/gitlab/ldap/config_spec.rb | 39 ++++++++++++++++++++++++--- spec/tasks/gitlab/check_rake_spec.rb | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 spec/tasks/gitlab/check_rake_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/ldap/config_spec.rb b/spec/lib/gitlab/ldap/config_spec.rb index 835853a83a4..f5ebe703083 100644 --- a/spec/lib/gitlab/ldap/config_spec.rb +++ b/spec/lib/gitlab/ldap/config_spec.rb @@ -1,20 +1,51 @@ require 'spec_helper' describe Gitlab::LDAP::Config, lib: true do - let(:config) { Gitlab::LDAP::Config.new provider } - let(:provider) { 'ldapmain' } + include LdapHelpers + + let(:config) { Gitlab::LDAP::Config.new('ldapmain') } describe '#initalize' do it 'requires a provider' do expect{ Gitlab::LDAP::Config.new }.to raise_error ArgumentError end - it "works" do + it 'works' do expect(config).to be_a described_class end - it "raises an error if a unknow provider is used" do + it 'raises an error if a unknown provider is used' do expect{ Gitlab::LDAP::Config.new 'unknown' }.to raise_error(RuntimeError) end end + + describe '#has_auth?' do + it 'is true when password is set' do + stub_ldap_config( + options: { + 'bind_dn' => 'uid=admin,dc=example,dc=com', + 'password' => 'super_secret' + } + ) + + expect(config.has_auth?).to be_truthy + end + + it 'is true when bind_dn is set and password is empty' do + stub_ldap_config( + options: { + 'bind_dn' => 'uid=admin,dc=example,dc=com', + 'password' => '' + } + ) + + expect(config.has_auth?).to be_truthy + end + + it 'is false when password and bind_dn are not set' do + stub_ldap_config(options: { 'bind_dn' => nil, 'password' => nil }) + + expect(config.has_auth?).to be_falsey + end + end end diff --git a/spec/tasks/gitlab/check_rake_spec.rb b/spec/tasks/gitlab/check_rake_spec.rb new file mode 100644 index 00000000000..538ff952bf4 --- /dev/null +++ b/spec/tasks/gitlab/check_rake_spec.rb @@ -0,0 +1,51 @@ +require 'rake_helper' + +describe 'gitlab:ldap:check rake task' do + include LdapHelpers + + before do + Rake.application.rake_require 'tasks/gitlab/check' + + stub_warn_user_is_not_gitlab + end + + context 'when LDAP is not enabled' do + it 'does not attempt to bind or search for users' do + expect(Gitlab::LDAP::Config).not_to receive(:providers) + expect(Gitlab::LDAP::Adapter).not_to receive(:open) + + run_rake_task('gitlab:ldap:check') + end + end + + context 'when LDAP is enabled' do + let(:ldap) { double(:ldap) } + let(:adapter) { ldap_adapter('ldapmain', ldap) } + + before do + allow(Gitlab::LDAP::Config) + .to receive_messages( + enabled?: true, + providers: ['ldapmain'] + ) + allow(Gitlab::LDAP::Adapter).to receive(:open).and_yield(adapter) + allow(adapter).to receive(:users).and_return([]) + end + + it 'attempts to bind using credentials' do + stub_ldap_config(has_auth?: true) + + expect(ldap).to receive(:bind) + + run_rake_task('gitlab:ldap:check') + end + + it 'searches for 100 LDAP users' do + stub_ldap_config(uid: 'uid') + + expect(adapter).to receive(:users).with('uid', '*', 100) + + run_rake_task('gitlab:ldap:check') + end + end +end -- cgit v1.2.1 From f7ef7bea11012bef6d373ce3b3c43fac08b047fd Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 9 Nov 2016 09:42:09 +0100 Subject: Add environment factory review app trait --- spec/factories/deployments.rb | 3 ++- spec/factories/environments.rb | 23 +++++++++++++++++++++++ spec/services/ci/stop_environment_service_spec.rb | 15 +-------------- 3 files changed, 26 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb index 6f24bf58d14..29ad1af9fd9 100644 --- a/spec/factories/deployments.rb +++ b/spec/factories/deployments.rb @@ -3,8 +3,9 @@ FactoryGirl.define do sha '97de212e80737a608d939f648d959671fb0a0142' ref 'master' tag false + user project nil - + deployable factory: :ci_build environment factory: :environment after(:build) do |deployment, evaluator| diff --git a/spec/factories/environments.rb b/spec/factories/environments.rb index 846cccfc7fa..bb6558a403f 100644 --- a/spec/factories/environments.rb +++ b/spec/factories/environments.rb @@ -4,5 +4,28 @@ FactoryGirl.define do project factory: :empty_project sequence(:external_url) { |n| "https://env#{n}.example.gitlab.com" } + + trait :with_review_app do |environment| + project + + # At this point `review app` is an ephemeral concept related to + # deployments being deployed for given environment. There is no + # first-class `review app` available so we need to create set of + # interconnected objects to simulate a review app. + # + after(:create) do |environment| + deployment = create(:deployment, + environment: environment, + project: environment.project, + sha: environment.project.commit.id) + + teardown_build = create(:ci_build, :manual, + name: "#{deployment.environment.name}:teardown", + pipeline: deployment.deployable.pipeline) + + deployment.update_column(:on_stop, teardown_build.name) + environment.update_attribute(:deployments, [deployment]) + end + end end end diff --git a/spec/services/ci/stop_environment_service_spec.rb b/spec/services/ci/stop_environment_service_spec.rb index 40b2a028f67..05e9e2d84cf 100644 --- a/spec/services/ci/stop_environment_service_spec.rb +++ b/spec/services/ci/stop_environment_service_spec.rb @@ -8,21 +8,8 @@ describe Ci::StopEnvironmentService, services: true do describe '#execute' do context 'when environment exists' do - let(:environment) { create(:environment, project: project) } - let(:deployable) { create(:ci_build) } - - let(:stop_build) do - create(:ci_build, :manual, name: 'environment/teardown', - pipeline: deployable.pipeline) - end - before do - create(:deployment, environment: environment, - deployable: deployable, - on_stop: stop_build.name, - user: user, - project: project, - sha: project.commit.id) + create(:environment, :with_review_app, project: project) end it 'stops environment' do -- cgit v1.2.1 From 79d94b167999544086db235602a9213a2d37831e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 26 Oct 2016 17:34:06 +0000 Subject: Merge branch '22481-honour-issue-visibility-for-groups' into 'security' Honour issue and merge request visibility in their respective finders This MR fixes a security issue with the IssuesFinder and MergeRequestFinder where they would return items the user did not have permission to see. This was most visible on the issue and merge requests page for a group containing projects that had set their issues or merge requests to "private". Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/22481 See merge request !2000 --- spec/features/groups/issues_spec.rb | 8 ++++ spec/features/groups/merge_requests_spec.rb | 8 ++++ spec/models/concerns/issuable_spec.rb | 5 ++ ..._features_apply_to_issuables_shared_examples.rb | 56 ++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 spec/features/groups/issues_spec.rb create mode 100644 spec/features/groups/merge_requests_spec.rb create mode 100644 spec/support/project_features_apply_to_issuables_shared_examples.rb (limited to 'spec') diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb new file mode 100644 index 00000000000..476eca17a9d --- /dev/null +++ b/spec/features/groups/issues_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +feature 'Group issues page', feature: true do + let(:path) { issues_group_path(group) } + let(:issuable) { create(:issue, project: project, title: "this is my created issuable")} + + include_examples 'project features apply to issuables', Issue +end diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb new file mode 100644 index 00000000000..a2791b57544 --- /dev/null +++ b/spec/features/groups/merge_requests_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +feature 'Group merge requests page', feature: true do + let(:path) { merge_requests_group_path(group) } + let(:issuable) { create(:merge_request, source_project: project, target_project: project, title: "this is my created issuable")} + + include_examples 'project features apply to issuables', MergeRequest +end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index a9603074c32..6e987967ca5 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -97,6 +97,11 @@ describe Issue, "Issuable" do end end + describe '.to_ability_name' do + it { expect(Issue.to_ability_name).to eq("issue") } + it { expect(MergeRequest.to_ability_name).to eq("merge_request") } + end + describe "#today?" do it "returns true when created today" do # Avoid timezone differences and just return exactly what we want diff --git a/spec/support/project_features_apply_to_issuables_shared_examples.rb b/spec/support/project_features_apply_to_issuables_shared_examples.rb new file mode 100644 index 00000000000..4621d17549b --- /dev/null +++ b/spec/support/project_features_apply_to_issuables_shared_examples.rb @@ -0,0 +1,56 @@ +shared_examples 'project features apply to issuables' do |klass| + let(:described_class) { klass } + + let(:group) { create(:group) } + let(:user_in_group) { create(:group_member, :developer, user: create(:user), group: group ).user } + let(:user_outside_group) { create(:user) } + + let(:project) { create(:empty_project, :public, project_args) } + + def project_args + feature = "#{described_class.model_name.plural}_access_level".to_sym + + args = { group: group } + args[feature] = access_level + + args + end + + before do + _ = issuable + login_as(user) + visit path + end + + context 'public access level' do + let(:access_level) { ProjectFeature::ENABLED } + + context 'group member' do + let(:user) { user_in_group } + + it { expect(page).to have_content(issuable.title) } + end + + context 'non-member' do + let(:user) { user_outside_group } + + it { expect(page).to have_content(issuable.title) } + end + end + + context 'private access level' do + let(:access_level) { ProjectFeature::PRIVATE } + + context 'group member' do + let(:user) { user_in_group } + + it { expect(page).to have_content(issuable.title) } + end + + context 'non-member' do + let(:user) { user_outside_group } + + it { expect(page).not_to have_content(issuable.title) } + end + end +end -- cgit v1.2.1 From bf061d0aff091a73611037b811cea2d3380962f4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 1 Nov 2016 20:18:51 +0000 Subject: Merge branch 'issue_23548_dev' into 'master' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit disable markdown in comments when referencing disabled features fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23548 This MR prevents the following references when tool is disabled: - issues - snippets - commits - when repo is disabled - commit range - when repo is disabled - milestones This MR does not prevent references to repository files, since they are just markdown links and don't leak information. See merge request !2011 Signed-off-by: Rémy Coutable --- spec/features/issues/new_branch_button_spec.rb | 1 + spec/lib/banzai/filter/redactor_filter_spec.rb | 42 ++++++---- .../banzai/reference_parser/base_parser_spec.rb | 35 +------- .../banzai/reference_parser/commit_parser_spec.rb | 8 ++ .../reference_parser/commit_range_parser_spec.rb | 8 ++ .../reference_parser/external_issue_parser_spec.rb | 8 ++ .../banzai/reference_parser/issue_parser_spec.rb | 10 ++- .../banzai/reference_parser/label_parser_spec.rb | 8 ++ .../reference_parser/merge_request_parser_spec.rb | 13 +++ .../reference_parser/milestone_parser_spec.rb | 8 ++ .../banzai/reference_parser/snippet_parser_spec.rb | 8 ++ .../banzai/reference_parser/user_parser_spec.rb | 2 + spec/lib/gitlab/closing_issue_extractor_spec.rb | 3 +- spec/lib/gitlab/gfm/reference_rewriter_spec.rb | 2 +- spec/lib/gitlab/reference_extractor_spec.rb | 3 +- spec/models/issue_spec.rb | 96 +++++++++++++--------- spec/support/cycle_analytics_helpers.rb | 3 +- spec/support/reference_parser_shared_examples.rb | 43 ++++++++++ 18 files changed, 204 insertions(+), 97 deletions(-) create mode 100644 spec/support/reference_parser_shared_examples.rb (limited to 'spec') diff --git a/spec/features/issues/new_branch_button_spec.rb b/spec/features/issues/new_branch_button_spec.rb index 755f4eb1b0b..ab901e74617 100644 --- a/spec/features/issues/new_branch_button_spec.rb +++ b/spec/features/issues/new_branch_button_spec.rb @@ -22,6 +22,7 @@ feature 'Start new branch from an issue', feature: true do create(:note, :on_issue, :system, project: project, noteable: issue, note: "Mentioned in !#{referenced_mr.iid}") end + let(:referenced_mr) do create(:merge_request, :simple, source_project: project, target_project: project, description: "Fixes ##{issue.iid}", author: user) diff --git a/spec/lib/banzai/filter/redactor_filter_spec.rb b/spec/lib/banzai/filter/redactor_filter_spec.rb index f181125156b..0140a91c7ba 100644 --- a/spec/lib/banzai/filter/redactor_filter_spec.rb +++ b/spec/lib/banzai/filter/redactor_filter_spec.rb @@ -28,31 +28,39 @@ describe Banzai::Filter::RedactorFilter, lib: true do and_return(parser_class) end - it 'removes unpermitted Project references' do - user = create(:user) - project = create(:empty_project) + context 'valid projects' do + before { allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(true) } - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user) + it 'allows permitted Project references' do + user = create(:user) + project = create(:empty_project) + project.team << [user, :master] + + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user) - expect(doc.css('a').length).to eq 0 + expect(doc.css('a').length).to eq 1 + end end - it 'allows permitted Project references' do - user = create(:user) - project = create(:empty_project) - project.team << [user, :master] + context 'invalid projects' do + before { allow_any_instance_of(Banzai::ReferenceParser::BaseParser).to receive(:can_read_reference?).and_return(false) } - link = reference_link(project: project.id, reference_type: 'test') - doc = filter(link, current_user: user) + it 'removes unpermitted references' do + user = create(:user) + project = create(:empty_project) - expect(doc.css('a').length).to eq 1 - end + link = reference_link(project: project.id, reference_type: 'test') + doc = filter(link, current_user: user) - it 'handles invalid Project references' do - link = reference_link(project: 12345, reference_type: 'test') + expect(doc.css('a').length).to eq 0 + end + + it 'handles invalid references' do + link = reference_link(project: 12345, reference_type: 'test') - expect { filter(link) }.not_to raise_error + expect { filter(link) }.not_to raise_error + end end end diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb index 9095d2b1345..aa127f0179d 100644 --- a/spec/lib/banzai/reference_parser/base_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb @@ -27,41 +27,12 @@ describe Banzai::ReferenceParser::BaseParser, lib: true do let(:link) { empty_html_link } context 'when the link has a data-project attribute' do - it 'returns the nodes if the attribute value equals the current project ID' do + it 'checks if user can read the resource' do link['data-project'] = project.id.to_s - expect(Ability).not_to receive(:allowed?) - expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) - end - - it 'returns the nodes if the user can read the project' do - other_project = create(:empty_project, :public) - - link['data-project'] = other_project.id.to_s - - expect(Ability).to receive(:allowed?). - with(user, :read_project, other_project). - and_return(true) - - expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) - end - - it 'returns an empty Array when the attribute value is empty' do - link['data-project'] = '' - - expect(subject.nodes_visible_to_user(user, [link])).to eq([]) - end - - it 'returns an empty Array when the user can not read the project' do - other_project = create(:empty_project, :public) - - link['data-project'] = other_project.id.to_s - - expect(Ability).to receive(:allowed?). - with(user, :read_project, other_project). - and_return(false) + expect(subject).to receive(:can_read_reference?).with(user, project) - expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + subject.nodes_visible_to_user(user, [link]) end end diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb index 0b76d29fce0..412ffa77c36 100644 --- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb @@ -8,6 +8,14 @@ describe Banzai::ReferenceParser::CommitParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-commit'] = 123 } + + it_behaves_like "referenced feature visibility", "repository" + end + end + describe '#referenced_by' do context 'when the link has a data-project attribute' do before do diff --git a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb index ba982f38542..96e55b0997a 100644 --- a/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/commit_range_parser_spec.rb @@ -8,6 +8,14 @@ describe Banzai::ReferenceParser::CommitRangeParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-commit-range'] = '123..456' } + + it_behaves_like "referenced feature visibility", "repository" + end + end + describe '#referenced_by' do context 'when the link has a data-project attribute' do before do diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb index a6ef8394fe7..50a5d1a19ba 100644 --- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb @@ -8,6 +8,14 @@ describe Banzai::ReferenceParser::ExternalIssueParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-external-issue'] = 123 } + + it_behaves_like "referenced feature visibility", "issues" + end + end + describe '#referenced_by' do context 'when the link has a data-project attribute' do before do diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb index 85cfe728b6a..6873b7b85f9 100644 --- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb @@ -4,10 +4,10 @@ describe Banzai::ReferenceParser::IssueParser, lib: true do include ReferenceParserHelpers let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - let(:issue) { create(:issue, project: project) } - subject { described_class.new(project, user) } - let(:link) { empty_html_link } + let(:user) { create(:user) } + let(:issue) { create(:issue, project: project) } + let(:link) { empty_html_link } + subject { described_class.new(project, user) } describe '#nodes_visible_to_user' do context 'when the link has a data-issue attribute' do @@ -15,6 +15,8 @@ describe Banzai::ReferenceParser::IssueParser, lib: true do link['data-issue'] = issue.id.to_s end + it_behaves_like "referenced feature visibility", "issues" + it 'returns the nodes when the user can read the issue' do expect(Ability).to receive(:issues_readable_by_user). with([issue], user). diff --git a/spec/lib/banzai/reference_parser/label_parser_spec.rb b/spec/lib/banzai/reference_parser/label_parser_spec.rb index 77fda47f0e7..8c540d35ddd 100644 --- a/spec/lib/banzai/reference_parser/label_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/label_parser_spec.rb @@ -9,6 +9,14 @@ describe Banzai::ReferenceParser::LabelParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-label'] = label.id.to_s } + + it_behaves_like "referenced feature visibility", "issues", "merge_requests" + end + end + describe '#referenced_by' do describe 'when the link has a data-label attribute' do context 'using an existing label ID' do diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb index cf89ad598ea..cb69ca16800 100644 --- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb @@ -8,6 +8,19 @@ describe Banzai::ReferenceParser::MergeRequestParser, lib: true do subject { described_class.new(merge_request.target_project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + let(:project) { merge_request.target_project } + + before do + project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + link['data-merge-request'] = merge_request.id.to_s + end + + it_behaves_like "referenced feature visibility", "merge_requests" + end + end + describe '#referenced_by' do describe 'when the link has a data-merge-request attribute' do context 'using an existing merge request ID' do diff --git a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb index 6aa45a22cc4..2d4d589ae34 100644 --- a/spec/lib/banzai/reference_parser/milestone_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/milestone_parser_spec.rb @@ -9,6 +9,14 @@ describe Banzai::ReferenceParser::MilestoneParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-milestone'] = milestone.id.to_s } + + it_behaves_like "referenced feature visibility", "issues", "merge_requests" + end + end + describe '#referenced_by' do describe 'when the link has a data-milestone attribute' do context 'using an existing milestone ID' do diff --git a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb index 59127b7c5d1..d217a775802 100644 --- a/spec/lib/banzai/reference_parser/snippet_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/snippet_parser_spec.rb @@ -9,6 +9,14 @@ describe Banzai::ReferenceParser::SnippetParser, lib: true do subject { described_class.new(project, user) } let(:link) { empty_html_link } + describe '#nodes_visible_to_user' do + context 'when the link has a data-issue attribute' do + before { link['data-snippet'] = snippet.id.to_s } + + it_behaves_like "referenced feature visibility", "snippets" + end + end + describe '#referenced_by' do describe 'when the link has a data-snippet attribute' do context 'using an existing snippet ID' do diff --git a/spec/lib/banzai/reference_parser/user_parser_spec.rb b/spec/lib/banzai/reference_parser/user_parser_spec.rb index 4e7f82a6e09..fafc2cec546 100644 --- a/spec/lib/banzai/reference_parser/user_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/user_parser_spec.rb @@ -103,6 +103,8 @@ describe Banzai::ReferenceParser::UserParser, lib: true do it 'returns the nodes if the attribute value equals the current project ID' do link['data-project'] = project.id.to_s + # Ensure that we dont call for Ability.allowed? + # When project_id in the node is equal to current project ID expect(Ability).not_to receive(:allowed?) expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) diff --git a/spec/lib/gitlab/closing_issue_extractor_spec.rb b/spec/lib/gitlab/closing_issue_extractor_spec.rb index de3f64249a2..1bbaca0739a 100644 --- a/spec/lib/gitlab/closing_issue_extractor_spec.rb +++ b/spec/lib/gitlab/closing_issue_extractor_spec.rb @@ -257,8 +257,9 @@ describe Gitlab::ClosingIssueExtractor, lib: true do context 'with an external issue tracker reference' do it 'extracts the referenced issue' do jira_project = create(:jira_project, name: 'JIRA_EXT1') + jira_project.team << [jira_project.creator, :master] jira_issue = ExternalIssue.new("#{jira_project.name}-1", project: jira_project) - closing_issue_extractor = described_class.new jira_project + closing_issue_extractor = described_class.new(jira_project, jira_project.creator) message = "Resolve #{jira_issue.to_reference}" expect(closing_issue_extractor.closed_by_message(message)).to eq([jira_issue]) diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index f045463c1cb..6b3dfebd85d 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::Gfm::ReferenceRewriter do let(:new_project) { create(:project, name: 'new') } let(:user) { create(:user) } - before { old_project.team << [user, :guest] } + before { old_project.team << [user, :reporter] } describe '#rewrite' do subject do diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index 7b4ccc83915..bf0ab9635fd 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Gitlab::ReferenceExtractor, lib: true do let(:project) { create(:project) } + before { project.team << [project.creator, :developer] } + subject { Gitlab::ReferenceExtractor.new(project, project.creator) } it 'accesses valid user objects' do @@ -42,7 +44,6 @@ describe Gitlab::ReferenceExtractor, lib: true do end it 'accesses valid issue objects' do - project.team << [project.creator, :developer] @i0 = create(:issue, project: project) @i1 = create(:issue, project: project) diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 60d30eb7418..300425767ed 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -22,7 +22,7 @@ describe Issue, models: true do it { is_expected.to have_db_index(:deleted_at) } end - describe 'visible_to_user' do + describe '.visible_to_user' do let(:user) { create(:user) } let(:authorized_user) { create(:user) } let(:project) { create(:project, namespace: authorized_user.namespace) } @@ -102,17 +102,17 @@ describe Issue, models: true do it 'returns the merge request to close this issue' do mr - expect(issue.closed_by_merge_requests).to eq([mr]) + expect(issue.closed_by_merge_requests(mr.author)).to eq([mr]) end it "returns an empty array when the merge request is closed already" do closed_mr - expect(issue.closed_by_merge_requests).to eq([]) + expect(issue.closed_by_merge_requests(closed_mr.author)).to eq([]) end it "returns an empty array when the current issue is closed already" do - expect(closed_issue.closed_by_merge_requests).to eq([]) + expect(closed_issue.closed_by_merge_requests(closed_issue.author)).to eq([]) end end @@ -218,7 +218,7 @@ describe Issue, models: true do source_project: subject.project, source_branch: "#{subject.iid}-branch" }) merge_request.create_cross_references!(user) - expect(subject.referenced_merge_requests).not_to be_empty + expect(subject.referenced_merge_requests(user)).not_to be_empty expect(subject.related_branches(user)).to eq([subject.to_branch_name]) end @@ -314,6 +314,22 @@ describe Issue, models: true do end describe '#visible_to_user?' do + context 'without a user' do + let(:issue) { build(:issue) } + + it 'returns true when the issue is publicly visible' do + expect(issue).to receive(:publicly_visible?).and_return(true) + + expect(issue.visible_to_user?).to eq(true) + end + + it 'returns false when the issue is not publicly visible' do + expect(issue).to receive(:publicly_visible?).and_return(false) + + expect(issue.visible_to_user?).to eq(false) + end + end + context 'with a user' do let(:user) { build(:user) } let(:issue) { build(:issue) } @@ -329,26 +345,24 @@ describe Issue, models: true do expect(issue.visible_to_user?(user)).to eq(false) end - end - context 'without a user' do - let(:issue) { build(:issue) } + it 'returns false when feature is disabled' do + expect(issue).not_to receive(:readable_by?) - it 'returns true when the issue is publicly visible' do - expect(issue).to receive(:publicly_visible?).and_return(true) + issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) - expect(issue.visible_to_user?).to eq(true) + expect(issue.visible_to_user?(user)).to eq(false) end - it 'returns false when the issue is not publicly visible' do - expect(issue).to receive(:publicly_visible?).and_return(false) + it 'returns false when restricted for members' do + expect(issue).not_to receive(:readable_by?) - expect(issue.visible_to_user?).to eq(false) + issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::PRIVATE) + + expect(issue.visible_to_user?(user)).to eq(false) end end - end - describe '#readable_by?' do describe 'with a regular user that is not a team member' do let(:user) { create(:user) } @@ -358,13 +372,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns false for a confidential issue' do issue = build(:issue, project: project, confidential: true) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end end @@ -375,13 +389,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end end @@ -393,13 +407,13 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end end end @@ -410,26 +424,28 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(false) end context 'when the user is the project owner' do + before { project.team << [user, :master] } + it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end end @@ -447,13 +463,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end @@ -467,13 +483,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end @@ -487,13 +503,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end end @@ -505,13 +521,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end it 'returns true for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).to be_readable_by(user) + expect(issue.visible_to_user?(user)).to eq(true) end end end @@ -523,13 +539,13 @@ describe Issue, models: true do it 'returns true for a regular issue' do issue = build(:issue, project: project) - expect(issue).to be_publicly_visible + expect(issue).to be_truthy end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end end @@ -539,13 +555,13 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end end @@ -555,13 +571,13 @@ describe Issue, models: true do it 'returns false for a regular issue' do issue = build(:issue, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end it 'returns false for a confidential issue' do issue = build(:issue, :confidential, project: project) - expect(issue).not_to be_publicly_visible + expect(issue).not_to be_falsy end end end diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb index 62a5b46d47b..75c95d70951 100644 --- a/spec/support/cycle_analytics_helpers.rb +++ b/spec/support/cycle_analytics_helpers.rb @@ -49,7 +49,8 @@ module CycleAnalyticsHelpers end def merge_merge_requests_closing_issue(issue) - merge_requests = issue.closed_by_merge_requests + merge_requests = issue.closed_by_merge_requests(user) + merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) } end diff --git a/spec/support/reference_parser_shared_examples.rb b/spec/support/reference_parser_shared_examples.rb new file mode 100644 index 00000000000..8eb74635a60 --- /dev/null +++ b/spec/support/reference_parser_shared_examples.rb @@ -0,0 +1,43 @@ +RSpec.shared_examples "referenced feature visibility" do |*related_features| + let(:feature_fields) do + related_features.map { |feature| (feature + "_access_level").to_sym } + end + + before { link['data-project'] = project.id.to_s } + + context "when feature is disabled" do + it "does not create reference" do + set_features_fields_to(ProjectFeature::DISABLED) + expect(subject.nodes_visible_to_user(user, [link])).to eq([]) + end + end + + context "when feature is enabled only for team members" do + before { set_features_fields_to(ProjectFeature::PRIVATE) } + + it "does not create reference for non member" do + non_member = create(:user) + + expect(subject.nodes_visible_to_user(non_member, [link])).to eq([]) + end + + it "creates reference for member" do + project.team << [user, :developer] + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + + context "when feature is enabled" do + # The project is public + it "creates reference" do + set_features_fields_to(ProjectFeature::ENABLED) + + expect(subject.nodes_visible_to_user(user, [link])).to eq([link]) + end + end + + def set_features_fields_to(visibility_level) + feature_fields.each { |field| project.project_feature.update_attribute(field, visibility_level) } + end +end -- cgit v1.2.1 From a14ee68fe4815d2906ece670bcc333303fd3c816 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 7 Nov 2016 16:27:35 +0000 Subject: Merge branch 'markdown-xss-fix-option-2.1' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix for HackerOne XSS vulnerability in markdown This is an updated blacklist patch to fix https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/2007. No text is removed. Dangerous schemes/protocols and invalid URIs are left intact but not linked. Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/23153 See merge request !2015 Signed-off-by: Rémy Coutable --- spec/lib/banzai/filter/autolink_filter_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'spec') diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb index dca7f997570..a6d2ea11fcc 100644 --- a/spec/lib/banzai/filter/autolink_filter_spec.rb +++ b/spec/lib/banzai/filter/autolink_filter_spec.rb @@ -99,6 +99,28 @@ describe Banzai::Filter::AutolinkFilter, lib: true do expect(doc.at_css('a')['href']).to eq link end + it 'autolinks rdar' do + link = 'rdar://localhost.com/blah' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'does not autolink javascript' do + link = 'javascript://alert(document.cookie);' + doc = filter("See #{link}") + + expect(doc.at_css('a')).to be_nil + end + + it 'does not autolink bad URLs' do + link = 'foo://23423:::asdf' + doc = filter("See #{link}") + + expect(doc.to_s).to eq("See #{link}") + end + it 'does not include trailing punctuation' do doc = filter("See #{link}.") expect(doc.at_css('a').text).to eq link -- cgit v1.2.1 From b0bf92140f469db90ef378fd42a6f65eee1d4633 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 2 Nov 2016 21:50:44 +0000 Subject: Merge branch 'fix-unathorized-cloning' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure external users are not able to clone disabled repositories. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/23788 See merge request !2017 Signed-off-by: Rémy Coutable --- spec/factories/projects.rb | 10 ++++--- spec/lib/gitlab/git_access_spec.rb | 25 ++++++++++++++++++ spec/lib/gitlab/git_access_wiki_spec.rb | 2 +- spec/models/guest_spec.rb | 47 +++++++++++++++++++++++++++++++++ spec/requests/git_http_spec.rb | 32 ++++++++++++++++++++++ 5 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 spec/models/guest_spec.rb (limited to 'spec') diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index dd4a86b1e31..bfd88a254f1 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -49,13 +49,17 @@ FactoryGirl.define do end after(:create) do |project, evaluator| + # Builds and MRs can't have higher visibility level than repository access level. + builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min + merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min + project.project_feature. - update_attributes( + update_attributes!( wiki_access_level: evaluator.wiki_access_level, - builds_access_level: evaluator.builds_access_level, + builds_access_level: builds_access_level, snippets_access_level: evaluator.snippets_access_level, issues_access_level: evaluator.issues_access_level, - merge_requests_access_level: evaluator.merge_requests_access_level, + merge_requests_access_level: merge_requests_access_level, repository_access_level: evaluator.repository_access_level ) end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 62aa212f1f6..f1d0a190002 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -66,6 +66,7 @@ describe Gitlab::GitAccess, lib: true do context 'pull code' do it { expect(subject.allowed?).to be_falsey } + it { expect(subject.message).to match(/You are not allowed to download code/) } end end @@ -77,6 +78,7 @@ describe Gitlab::GitAccess, lib: true do context 'pull code' do it { expect(subject.allowed?).to be_falsey } + it { expect(subject.message).to match(/Your account has been blocked/) } end end @@ -84,6 +86,29 @@ describe Gitlab::GitAccess, lib: true do context 'pull code' do it { expect(subject.allowed?).to be_falsey } end + + context 'when project is public' do + let(:public_project) { create(:project, :public) } + let(:guest_access) { Gitlab::GitAccess.new(nil, public_project, 'web', authentication_abilities: []) } + subject { guest_access.check('git-upload-pack', '_any') } + + context 'when repository is enabled' do + it 'give access to download code' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::ENABLED) + + expect(subject.allowed?).to be_truthy + end + end + + context 'when repository is disabled' do + it 'does not give access to download code' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED) + + expect(subject.allowed?).to be_falsey + expect(subject.message).to match(/You are not allowed to download code/) + end + end + end end describe 'deploy key permissions' do diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 576cda595bb..576aa5c366f 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -18,7 +18,7 @@ describe Gitlab::GitAccessWiki, lib: true do project.team << [user, :developer] end - subject { access.push_access_check(changes) } + subject { access.check('git-receive-pack', changes) } it { expect(subject.allowed?).to be_truthy } end diff --git a/spec/models/guest_spec.rb b/spec/models/guest_spec.rb new file mode 100644 index 00000000000..d79f929f7a1 --- /dev/null +++ b/spec/models/guest_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Guest, lib: true do + let(:public_project) { create(:project, :public) } + let(:private_project) { create(:project, :private) } + let(:internal_project) { create(:project, :internal) } + + describe '.can_pull?' do + context 'when project is private' do + it 'does not allow to pull the repo' do + expect(Guest.can?(:download_code, private_project)).to eq(false) + end + end + + context 'when project is internal' do + it 'does not allow to pull the repo' do + expect(Guest.can?(:download_code, internal_project)).to eq(false) + end + end + + context 'when project is public' do + context 'when repository is disabled' do + it 'does not allow to pull the repo' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED) + + expect(Guest.can?(:download_code, public_project)).to eq(false) + end + end + + context 'when repository is accessible only by team members' do + it 'does not allow to pull the repo' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::PRIVATE) + + expect(Guest.can?(:download_code, public_project)).to eq(false) + end + end + + context 'when repository is enabled' do + it 'allows to pull the repo' do + public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::ENABLED) + + expect(Guest.can?(:download_code, public_project)).to eq(true) + end + end + end + end +end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 27f0fd22ae6..f1728d61def 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -115,6 +115,38 @@ describe 'Git HTTP requests', lib: true do end.to raise_error(JWT::DecodeError) end end + + context 'when the repo is public' do + context 'but the repo is disabled' do + it 'does not allow to clone the repo' do + project = create(:project, :public, repository_access_level: ProjectFeature::DISABLED) + + download("#{project.path_with_namespace}.git", {}) do |response| + expect(response).to have_http_status(:unauthorized) + end + end + end + + context 'but the repo is enabled' do + it 'allows to clone the repo' do + project = create(:project, :public, repository_access_level: ProjectFeature::ENABLED) + + download("#{project.path_with_namespace}.git", {}) do |response| + expect(response).to have_http_status(:ok) + end + end + end + + context 'but only project members are allowed' do + it 'does not allow to clone the repo' do + project = create(:project, :public, repository_access_level: ProjectFeature::PRIVATE) + + download("#{project.path_with_namespace}.git", {}) do |response| + expect(response).to have_http_status(:unauthorized) + end + end + end + end end context "when the project is private" do -- cgit v1.2.1 From b0088b527eacd16773a85ad8f88e49de7c646cf1 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 4 Nov 2016 14:15:43 +0000 Subject: Merge branch '23403-fix-events-for-private-project-features' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Respect project visibility settings in the contributions calendar This MR fixes a number of bugs relating to access controls and date selection of events for the contributions calendar Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/23403 See merge request !2019 Signed-off-by: Rémy Coutable --- spec/lib/gitlab/contributions_calendar_spec.rb | 104 +++++++++++++++++++++++++ spec/models/event_spec.rb | 5 +- 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 spec/lib/gitlab/contributions_calendar_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb new file mode 100644 index 00000000000..01b2a55b63c --- /dev/null +++ b/spec/lib/gitlab/contributions_calendar_spec.rb @@ -0,0 +1,104 @@ +require 'spec_helper' + +describe Gitlab::ContributionsCalendar do + let(:contributor) { create(:user) } + let(:user) { create(:user) } + + let(:private_project) do + create(:empty_project, :private) do |project| + create(:project_member, user: contributor, project: project) + end + end + + let(:public_project) do + create(:empty_project, :public) do |project| + create(:project_member, user: contributor, project: project) + end + end + + let(:feature_project) do + create(:empty_project, :public, issues_access_level: ProjectFeature::PRIVATE) do |project| + create(:project_member, user: contributor, project: project).project + end + end + + let(:today) { Time.now.to_date } + let(:last_week) { today - 7.days } + let(:last_year) { today - 1.year } + + before do + travel_to today + end + + after do + travel_back + end + + def calendar(current_user = nil) + described_class.new(contributor, current_user) + end + + def create_event(project, day) + @targets ||= {} + @targets[project] ||= create(:issue, project: project, author: contributor) + + Event.create!( + project: project, + action: Event::CREATED, + target: @targets[project], + author: contributor, + created_at: day, + ) + end + + describe '#activity_dates' do + it "returns a hash of date => count" do + create_event(public_project, last_week) + create_event(public_project, last_week) + create_event(public_project, today) + + expect(calendar.activity_dates).to eq(last_week => 2, today => 1) + end + + it "only shows private events to authorized users" do + create_event(private_project, today) + create_event(feature_project, today) + + expect(calendar.activity_dates[today]).to eq(0) + expect(calendar(user).activity_dates[today]).to eq(0) + expect(calendar(contributor).activity_dates[today]).to eq(2) + end + end + + describe '#events_by_date' do + it "returns all events for a given date" do + e1 = create_event(public_project, today) + e2 = create_event(public_project, today) + create_event(public_project, last_week) + + expect(calendar.events_by_date(today)).to contain_exactly(e1, e2) + end + + it "only shows private events to authorized users" do + e1 = create_event(public_project, today) + e2 = create_event(private_project, today) + e3 = create_event(feature_project, today) + create_event(public_project, last_week) + + expect(calendar.events_by_date(today)).to contain_exactly(e1) + expect(calendar(contributor).events_by_date(today)).to contain_exactly(e1, e2, e3) + end + end + + describe '#starting_year' do + it "should be the start of last year" do + expect(calendar.starting_year).to eq(last_year.year) + end + end + + describe '#starting_month' do + it "should be the start of this month" do + expect(calendar.starting_month).to eq(today.month) + end + end +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index aca49be2942..29a3af68a9b 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -27,13 +27,14 @@ describe Event, models: true do end describe "Push event" do - let(:project) { create(:project) } + let(:project) { create(:project, :private) } let(:user) { project.owner } let(:event) { create_event(project, user) } it do expect(event.push?).to be_truthy - expect(event.visible_to_user?).to be_truthy + expect(event.visible_to_user?(user)).to be_truthy + expect(event.visible_to_user?(nil)).to be_falsey expect(event.tag?).to be_falsey expect(event.branch_name).to eq("master") expect(event.author).to eq(user) -- cgit v1.2.1 From 32042ef56adfa24ce5952c6f3b7dc97dea5fd2d4 Mon Sep 17 00:00:00 2001 From: Alejandro Rodriguez Date: Tue, 8 Nov 2016 18:37:15 +0000 Subject: Merge branch 'unauthenticated-container-registry-access' into 'security' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore unauthenticated access to public container registries Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/24284 See merge request !2025 Signed-off-by: Rémy Coutable --- spec/requests/jwt_controller_spec.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index f0ef155bd7b..a3e7844b2f3 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -20,7 +20,7 @@ describe JwtController do end end - context 'when using authorized request' do + context 'when using authenticated request' do context 'using CI token' do let(:build) { create(:ci_build, :running) } let(:project) { build.project } @@ -65,7 +65,7 @@ describe JwtController do let(:access_token) { create(:personal_access_token, user: user) } let(:headers) { { authorization: credentials(user.username, access_token.token) } } - it 'rejects the authorization attempt' do + it 'accepts the authorization attempt' do expect(response).to have_http_status(200) end end @@ -81,6 +81,20 @@ describe JwtController do end end + context 'when using unauthenticated request' do + it 'accepts the authorization attempt' do + get '/jwt/auth', parameters + + expect(response).to have_http_status(200) + end + + it 'allows read access' do + expect(service).to receive(:execute).with(authentication_abilities: Gitlab::Auth.read_authentication_abilities) + + get '/jwt/auth', parameters + end + end + context 'unknown service' do subject! { get '/jwt/auth', service: 'unknown' } -- cgit v1.2.1 From ae8a461d875b29d7492230df1a3ca419707e154d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 9 Nov 2016 13:16:21 +0100 Subject: Fix environment feature specs after changes in factory --- spec/features/environments_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index b565586ee14..10ca835e6ca 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -152,7 +152,9 @@ feature 'Environments', feature: true do end context 'with deployments' do - given(:deployment) { create(:deployment, environment: environment) } + given(:deployment) do + create(:deployment, environment: environment, deployable: nil) + end scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) -- cgit v1.2.1 From 45bd5391d7f20715ae4de7a4a5cd9233ab598c28 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 9 Nov 2016 13:31:33 +0100 Subject: Extend tests for service that stops environment --- spec/services/ci/stop_environment_service_spec.rb | 50 ++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/ci/stop_environment_service_spec.rb b/spec/services/ci/stop_environment_service_spec.rb index 05e9e2d84cf..047f9b0b2ca 100644 --- a/spec/services/ci/stop_environment_service_spec.rb +++ b/spec/services/ci/stop_environment_service_spec.rb @@ -7,7 +7,7 @@ describe Ci::StopEnvironmentService, services: true do let(:service) { described_class.new(project, user) } describe '#execute' do - context 'when environment exists' do + context 'when environment with review app exists' do before do create(:environment, :with_review_app, project: project) end @@ -17,6 +17,54 @@ describe Ci::StopEnvironmentService, services: true do service.execute('master') end + + context 'when specified branch does not exist' do + it 'does not stop environment' do + expect_any_instance_of(Environment).not_to receive(:stop!) + + service.execute('non/existent/branch') + end + end + + context 'when no branch not specified' do + it 'does not stop environment' do + expect_any_instance_of(Environment).not_to receive(:stop!) + + service.execute(nil) + end + end + + context 'when environment is not stoppable' do + before do + allow_any_instance_of(Environment) + .to receive(:stoppable?).and_return(false) + end + + it 'does not stop environment' do + expect_any_instance_of(Environment).not_to receive(:stop!) + + service.execute('master') + end + end + end + + context 'when there is no environment associated with review app' do + before do + create(:environment, project: project) + end + + it 'does not stop environment' do + expect_any_instance_of(Environment).not_to receive(:stop!) + + service.execute('master') + end + end + + context 'when environment does not exist' do + it 'does not raise error' do + expect { service.execute('master') } + .not_to raise_error + end end end end -- cgit v1.2.1 From 5328e3b1276d8eef15b6636a1d5b1c7a57d31ea6 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 9 Nov 2016 14:46:36 +0100 Subject: Make commit an optional arg for environments search --- spec/models/project_spec.rb | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0810d06b50f..d835eac34c2 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1646,15 +1646,18 @@ describe Project, models: true do end it 'returns environment when with_tags is set' do - expect(project.environments_for('master', project.commit, with_tags: true)).to contain_exactly(environment) + expect(project.environments_for('master', commit: project.commit, with_tags: true)) + .to contain_exactly(environment) end it 'does not return environment when no with_tags is set' do - expect(project.environments_for('master', project.commit)).to be_empty + expect(project.environments_for('master', commit: project.commit)) + .to be_empty end it 'does not return environment when commit is not part of deployment' do - expect(project.environments_for('master', project.commit('feature'))).to be_empty + expect(project.environments_for('master', commit: project.commit('feature'))) + .to be_empty end end @@ -1664,15 +1667,23 @@ describe Project, models: true do end it 'returns environment when ref is set' do - expect(project.environments_for('master', project.commit)).to contain_exactly(environment) + expect(project.environments_for('master', commit: project.commit)) + .to contain_exactly(environment) end it 'does not environment when ref is different' do - expect(project.environments_for('feature', project.commit)).to be_empty + expect(project.environments_for('feature', commit: project.commit)) + .to be_empty end it 'does not return environment when commit is not part of deployment' do - expect(project.environments_for('master', project.commit('feature'))).to be_empty + expect(project.environments_for('master', commit: project.commit('feature'))) + .to be_empty + end + + it 'returns environment when commit constraint is not set' do + expect(project.environments_for('master')) + .to contain_exactly(environment) end end end -- cgit v1.2.1 From 4a7fcc2af6eba65dff48b25c81d5925311fa933d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 9 Nov 2016 15:29:19 +0100 Subject: Stop environments for branch after branch removal --- spec/models/repository_spec.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 04b7d19d414..6d65f6ead12 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1182,7 +1182,18 @@ describe Repository, models: true do it 'flushes the visible content cache' do expect(repository).to receive(:expire_has_visible_content_cache) - repository.after_remove_branch + repository.after_remove_branch(user, 'master') + end + + context 'when there is environment with review app available for branch' do + before do + create(:environment, :with_review_app, project: project) + end + + it 'stops environment' do + expect_any_instance_of(Environment).to receive(:stop!) + repository.after_remove_branch(user, 'master') + end end end -- cgit v1.2.1 From 603ebe55f0232f16b5f1db95d2962a4cf5cdcc1b Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 9 Nov 2016 17:36:35 +0100 Subject: Grapify the session API --- spec/requests/api/session_spec.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb index acad1365ace..e3f22b4c578 100644 --- a/spec/requests/api/session_spec.rb +++ b/spec/requests/api/session_spec.rb @@ -67,22 +67,24 @@ describe API::API, api: true do end context "when empty password" do - it "returns authentication error" do + it "returns authentication error with email" do post api("/session"), email: user.email - expect(response).to have_http_status(401) - expect(json_response['email']).to be_nil - expect(json_response['private_token']).to be_nil + expect(response).to have_http_status(400) + end + + it "returns authentication error with username" do + post api("/session"), email: user.username + + expect(response).to have_http_status(400) end end context "when empty name" do it "returns authentication error" do post api("/session"), password: user.password - expect(response).to have_http_status(401) - expect(json_response['email']).to be_nil - expect(json_response['private_token']).to be_nil + expect(response).to have_http_status(400) end end end -- cgit v1.2.1 From 1a5a3be84080808554568a8c61a80cc6f3f536ed Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 8 Nov 2016 16:29:55 -0600 Subject: First pass at tests --- spec/views/projects/builds/show.html.haml_spec.rb | 50 +++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'spec') diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index da43622d3f9..0e702d80bd3 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -17,6 +17,56 @@ describe 'projects/builds/show' do allow(view).to receive(:can?).and_return(true) end + describe 'environment info in build view' do + context 'build with latest deployment' do + let(:build) { create(:ci_build, :success, environment: 'staging') } + let(:environment) { create(:environment, name: 'staging') } + let!(:deployment) { create(:deployment, deployable: build) } + + it 'shows deployment message' do + expect(rendered).to have_css('.environment-information', text: 'This build is the most recent deployment') + end + end + + context 'build with outdated deployment' do + let(:build) { create(:ci_build, :success, environment: 'staging', pipeline: pipeline) } + let(:environment) { create(:environment, name: 'staging', project: project) } + let!(:deployment) { create(:deployment, environment: environment, deployable: build) } + let!(:newer_deployment) { create(:deployment, environment: environment, deployable: build) } + + before do + assign(:build, build) + assign(:project, project) + + allow(view).to receive(:can?).and_return(true) + render + end + + it 'shows deployment message' do + expect(rendered).to have_css('.environment-information', text: "This build is an out-of-date deployment to #{environment.name}. View the most recent deployment #1") + end + end + + context 'build failed to deploy' do + let(:build) { create(:ci_build, :failed, environment: 'staging') } + let!(:environment) { create(:environment, name: 'staging') } + end + + context 'build will deploy' do + let(:build) { create(:ci_build, :running, environment: 'staging') } + let!(:environment) { create(:environment, name: 'staging') } + end + + context 'build that failed to deploy and environment has not been created' do + let(:build) { create(:ci_build, :failed, environment: 'staging') } + end + + context 'build that will deploy and environment has not been created' do + let(:build) { create(:ci_build, :running, environment: 'staging') } + let!(:environment) { create(:environment, name: 'staging') } + end + end + context 'when build is running' do before do build.run! -- cgit v1.2.1 From d7ba85c7496fb24625f3ebf3e78af42ec23e842e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 9 Nov 2016 19:40:25 +0100 Subject: Refine specs for build show page with environments --- spec/spec_helper.rb | 7 +-- spec/views/projects/builds/show.html.haml_spec.rb | 55 ++++++++++++++--------- 2 files changed, 39 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 73cf4c9a24c..bead1a006d1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,10 +26,11 @@ RSpec.configure do |config| config.verbose_retry = true config.display_try_failure_messages = true - config.include Devise::Test::ControllerHelpers, type: :controller + config.include Devise::Test::ControllerHelpers, type: :controller + config.include Devise::Test::ControllerHelpers, type: :view config.include Warden::Test::Helpers, type: :request - config.include LoginHelpers, type: :feature - config.include SearchHelpers, type: :feature + config.include LoginHelpers, type: :feature + config.include SearchHelpers, type: :feature config.include StubConfiguration config.include EmailHelpers config.include TestEnv diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index 0e702d80bd3..98b68e730e6 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -1,14 +1,12 @@ require 'spec_helper' -describe 'projects/builds/show' do - include Devise::Test::ControllerHelpers - +describe 'projects/builds/show', :view do let(:project) { create(:project) } + let(:build) { create(:ci_build, pipeline: pipeline) } + let(:pipeline) do - create(:ci_pipeline, project: project, - sha: project.commit.id) + create(:ci_pipeline, project: project, sha: project.commit.id) end - let(:build) { create(:ci_build, pipeline: pipeline) } before do assign(:build, build) @@ -19,31 +17,48 @@ describe 'projects/builds/show' do describe 'environment info in build view' do context 'build with latest deployment' do - let(:build) { create(:ci_build, :success, environment: 'staging') } - let(:environment) { create(:environment, name: 'staging') } - let!(:deployment) { create(:deployment, deployable: build) } + let(:build) do + create(:ci_build, :success, environment: 'staging') + end + + before do + create(:environment, name: 'staging') + create(:deployment, deployable: build) + end it 'shows deployment message' do - expect(rendered).to have_css('.environment-information', text: 'This build is the most recent deployment') + expected_text = 'This build is the most recent deployment' + + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) end end context 'build with outdated deployment' do - let(:build) { create(:ci_build, :success, environment: 'staging', pipeline: pipeline) } - let(:environment) { create(:environment, name: 'staging', project: project) } - let!(:deployment) { create(:deployment, environment: environment, deployable: build) } - let!(:newer_deployment) { create(:deployment, environment: environment, deployable: build) } + let(:build) do + create(:ci_build, :success, environment: 'staging', pipeline: pipeline) + end - before do - assign(:build, build) - assign(:project, project) + let(:environment) do + create(:environment, name: 'staging', project: project) + end - allow(view).to receive(:can?).and_return(true) - render + let!(:first_deployment) do + create(:deployment, environment: environment, deployable: build) + end + + let!(:second_deployment) do + create(:deployment, environment: environment, deployable: build) end it 'shows deployment message' do - expect(rendered).to have_css('.environment-information', text: "This build is an out-of-date deployment to #{environment.name}. View the most recent deployment #1") + expected_text = 'This build is an out-of-date deployment ' \ + "to staging. View the most recent deployment ##{first_deployment.id}" + render + + expect(rendered).to have_css('.environment-information', text: expected_text) end end -- cgit v1.2.1 From bf39c4bcdf64b656323a07e2f26079148f3a43c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 9 Nov 2016 19:21:52 +0100 Subject: Remove order-dependent expectation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/models/group_label_spec.rb | 2 +- spec/requests/api/labels_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb index 85eb889225b..2369658bf78 100644 --- a/spec/models/group_label_spec.rb +++ b/spec/models/group_label_spec.rb @@ -18,7 +18,7 @@ describe GroupLabel, models: true do end describe '#to_reference' do - let(:label) { create(:group_label) } + let(:label) { create(:group_label, title: 'feature') } context 'using id' do it 'returns a String reference to the object' do diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 2ff90b6deac..5d84976c9c3 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -15,7 +15,7 @@ describe API::API, api: true do describe 'GET /projects/:id/labels' do it 'returns all available labels to the project' do group = create(:group) - group_label = create(:group_label, group: group) + group_label = create(:group_label, title: 'feature', group: group) project.update(group: group) expected_keys = [ 'id', 'name', 'color', 'description', -- cgit v1.2.1 From 1afab9eb79c87f32c7b899e58bc9a0ea8a113594 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Wed, 21 Sep 2016 16:15:12 +0200 Subject: Add button to delete all merged branches It adds a button to the branches page that the user can use to delete all the branches that are already merged. This can be used to clean up all the branches that were forgotten to delete while merging MRs. Fixes #21076. --- .../projects/branches_controller_spec.rb | 58 ++++++++++++++++++++-- spec/requests/api/branches_spec.rb | 16 ++++++ .../delete_merged_branches_service_spec.rb | 54 ++++++++++++++++++++ spec/workers/delete_merged_branches_worker_spec.rb | 19 +++++++ 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 spec/services/delete_merged_branches_service_spec.rb create mode 100644 spec/workers/delete_merged_branches_worker_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 644de308c64..f7cf006efd6 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' describe Projects::BranchesController do - let(:project) { create(:project) } - let(:user) { create(:user) } + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:developer) { create(:user) } before do - sign_in(user) - project.team << [user, :master] + project.team << [user, :developer] allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) @@ -19,6 +19,8 @@ describe Projects::BranchesController do context "on creation of a new branch" do before do + sign_in(user) + post :create, namespace_id: project.namespace.to_param, project_id: project.to_param, @@ -68,6 +70,10 @@ describe Projects::BranchesController do let(:branch) { "1-feature-branch" } let!(:issue) { create(:issue, project: project) } + before do + sign_in(user) + end + it 'redirects' do post :create, namespace_id: project.namespace.to_param, @@ -94,6 +100,10 @@ describe Projects::BranchesController do describe "POST destroy with HTML format" do render_views + before do + sign_in(user) + end + it 'returns 303' do post :destroy, format: :html, @@ -109,6 +119,8 @@ describe Projects::BranchesController do render_views before do + sign_in(user) + post :destroy, format: :js, id: branch, @@ -139,4 +151,42 @@ describe Projects::BranchesController do it { expect(response).to have_http_status(404) } end end + + describe "DELETE destroy_all_merged" do + def destroy_all_merged + delete :destroy_all_merged, + namespace_id: project.namespace.to_param, + project_id: project.to_param + end + + context 'when user is allowed to push' do + before do + sign_in(user) + end + + it 'redirects to branches' do + destroy_all_merged + + expect(response).to redirect_to namespace_project_branches_path(project.namespace, project) + end + + it 'starts worker to delete merged branches' do + expect_any_instance_of(DeleteMergedBranchesService).to receive(:async_execute) + + destroy_all_merged + end + end + + context 'when user is not allowed to push' do + before do + sign_in(developer) + end + + it 'responds with status 404' do + destroy_all_merged + + expect(response).to have_http_status(404) + end + end + end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index 1711096f4bd..8f605757186 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -299,4 +299,20 @@ describe API::API, api: true do expect(json_response['message']).to eq('Cannot remove HEAD branch') end end + + describe "DELETE /projects/:id/repository/merged_branches" do + before do + allow_any_instance_of(Repository).to receive(:rm_branch).and_return(true) + end + + it 'returns 200' do + delete api("/projects/#{project.id}/repository/merged_branches", user) + expect(response).to have_http_status(200) + end + + it 'returns a 403 error if guest' do + delete api("/projects/#{project.id}/repository/merged_branches", user2) + expect(response).to have_http_status(403) + end + end end diff --git a/spec/services/delete_merged_branches_service_spec.rb b/spec/services/delete_merged_branches_service_spec.rb new file mode 100644 index 00000000000..181488e89c7 --- /dev/null +++ b/spec/services/delete_merged_branches_service_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe DeleteMergedBranchesService, services: true do + subject(:service) { described_class.new(project, project.owner) } + + let(:project) { create(:project) } + + context '#execute' do + context 'unprotected branches' do + before do + service.execute + end + + it 'deletes a branch that was merged' do + expect(project.repository.branch_names).not_to include('improve/awesome') + end + + it 'keeps branch that is unmerged' do + expect(project.repository.branch_names).to include('feature') + end + + it 'keeps "master"' do + expect(project.repository.branch_names).to include('master') + end + end + + context 'protected branches' do + before do + create(:protected_branch, name: 'improve/awesome', project: project) + service.execute + end + + it 'keeps protected branch' do + expect(project.repository.branch_names).to include('improve/awesome') + end + end + + context 'user without rights' do + let(:user) { create(:user) } + + it 'cannot execute' do + expect { described_class.new(project, user).execute }.to raise_error(Gitlab::Access::AccessDeniedError) + end + end + end + + context '#async_execute' do + it 'calls DeleteMergedBranchesWorker async' do + expect(DeleteMergedBranchesWorker).to receive(:perform_async) + + service.async_execute + end + end +end diff --git a/spec/workers/delete_merged_branches_worker_spec.rb b/spec/workers/delete_merged_branches_worker_spec.rb new file mode 100644 index 00000000000..d9497bd486c --- /dev/null +++ b/spec/workers/delete_merged_branches_worker_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe DeleteMergedBranchesWorker do + subject(:worker) { described_class.new } + + let(:project) { create(:project) } + + describe "#perform" do + it "calls DeleteMergedBranchesService" do + expect_any_instance_of(DeleteMergedBranchesService).to receive(:execute).and_return(true) + + worker.perform(project.id, project.owner.id) + end + + it "returns false when project was not found" do + expect(worker.perform('unknown', project.owner.id)).to be_falsy + end + end +end -- cgit v1.2.1 From 2b8292cd49dbc68b02f46f865b7115191bf2de07 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Wed, 9 Nov 2016 15:30:58 -0600 Subject: Finish specs for environment info --- spec/views/projects/builds/show.html.haml_spec.rb | 68 ++++++++++++++++++++--- 1 file changed, 60 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index 98b68e730e6..fa4d66bb6cb 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -28,7 +28,6 @@ describe 'projects/builds/show', :view do it 'shows deployment message' do expected_text = 'This build is the most recent deployment' - render expect(rendered).to have_css( @@ -63,22 +62,75 @@ describe 'projects/builds/show', :view do end context 'build failed to deploy' do - let(:build) { create(:ci_build, :failed, environment: 'staging') } - let!(:environment) { create(:environment, name: 'staging') } + let(:build) do + create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'The deployment of this build to staging did not complete.' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end end context 'build will deploy' do - let(:build) { create(:ci_build, :running, environment: 'staging') } - let!(:environment) { create(:environment, name: 'staging') } + let(:build) do + create(:ci_build, :running, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'This build is creating a deployment to staging' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end end context 'build that failed to deploy and environment has not been created' do - let(:build) { create(:ci_build, :failed, environment: 'staging') } + let(:build) do + create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'The deployment of this build to staging did not complete' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end end context 'build that will deploy and environment has not been created' do - let(:build) { create(:ci_build, :running, environment: 'staging') } - let!(:environment) { create(:environment, name: 'staging') } + let(:build) do + create(:ci_build, :running, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'This build is creating a deployment to staging' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end end end -- cgit v1.2.1 From d81d67bae44f189adddd1f4fb489a44e274e21b5 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Tue, 8 Nov 2016 12:48:28 -0800 Subject: 19205 Redesign group page header to match new navigation --- spec/features/groups_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 13bfe90302c..4b19886274e 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -80,7 +80,7 @@ feature 'Group', feature: true do visit path - expect(page).to have_css('.description > p > strong') + expect(page).to have_css('.group-home-desc > p > strong') end it 'passes through html-pipeline' do @@ -88,7 +88,7 @@ feature 'Group', feature: true do visit path - expect(page).to have_css('.description > p > img') + expect(page).to have_css('.group-home-desc > p > img') end it 'sanitizes unwanted tags' do @@ -96,7 +96,7 @@ feature 'Group', feature: true do visit path - expect(page).not_to have_css('.description h1') + expect(page).not_to have_css('.group-home-desc h1') end it 'permits `rel` attribute on links' do @@ -104,7 +104,7 @@ feature 'Group', feature: true do visit path - expect(page).to have_css('.description a[rel]') + expect(page).to have_css('.group-home-desc a[rel]') end end end -- cgit v1.2.1 From 3378642504a0644411797f7d843bcb411c85582f Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 9 Nov 2016 16:29:07 +0100 Subject: Grapify runners API --- spec/requests/api/runners_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb index f46f016135e..99414270be6 100644 --- a/spec/requests/api/runners_spec.rb +++ b/spec/requests/api/runners_spec.rb @@ -226,7 +226,7 @@ describe API::Runners, api: true do context 'authorized user' do context 'when runner is shared' do it 'does not update runner' do - put api("/runners/#{shared_runner.id}", user) + put api("/runners/#{shared_runner.id}", user), description: 'test' expect(response).to have_http_status(403) end @@ -234,7 +234,7 @@ describe API::Runners, api: true do context 'when runner is not shared' do it 'does not update runner without access to it' do - put api("/runners/#{specific_runner.id}", user2) + put api("/runners/#{specific_runner.id}", user2), description: 'test' expect(response).to have_http_status(403) end -- cgit v1.2.1 From f27e972e84b488fb96202772872379113f72c789 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 9 Nov 2016 15:14:02 +0100 Subject: Grapify milestones API --- spec/requests/api/milestones_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index dd192bea432..62327f64e50 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -123,6 +123,15 @@ describe API::API, api: true do expect(json_response['title']).to eq('updated title') end + it 'removes a due date if nil is passed' do + milestone.update!(due_date: "2016-08-05") + + put api("/projects/#{project.id}/milestones/#{milestone.id}", user), due_date: nil + + expect(response).to have_http_status(200) + expect(json_response['due_date']).to be_nil + end + it 'returns a 404 error if milestone id not found' do put api("/projects/#{project.id}/milestones/1234", user), title: 'updated title' -- cgit v1.2.1 From 2965883e60ce215343bc8d2e160f0a889baa02ac Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Wed, 9 Nov 2016 16:47:39 +0100 Subject: Grapify token API --- spec/requests/api/triggers_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb index 82bba1ce8a4..8ba2eccf66c 100644 --- a/spec/requests/api/triggers_spec.rb +++ b/spec/requests/api/triggers_spec.rb @@ -68,7 +68,7 @@ describe API::API do it 'validates variables to be a hash' do post api("/projects/#{project.id}/trigger/builds"), options.merge(variables: 'value', ref: 'master') expect(response).to have_http_status(400) - expect(json_response['message']).to eq('variables needs to be a hash') + expect(json_response['error']).to eq('variables is invalid') end it 'validates variables needs to be a map of key-valued strings' do -- cgit v1.2.1 From 948b4828ce75b56ddc71ac08c5e3a8a08b405fcc Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 9 Nov 2016 09:17:14 +0000 Subject: Issue board spec fixes --- spec/features/boards/new_issue_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index 760a8967123..a03cd6fbf2d 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -46,7 +46,7 @@ describe 'Issue Boards new issue', feature: true, js: true do click_button 'Cancel' - expect(page).to have_selector('.board-new-issue-form', visible: false) + expect(page).not_to have_selector('.board-new-issue-form') end end -- cgit v1.2.1 From c095b04b9a4c215318504a3633e8960719102f29 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 10 Nov 2016 08:02:03 +0000 Subject: Fixed tests for issue boards & diff note resolving --- spec/features/merge_requests/diff_notes_resolve_spec.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/diff_notes_resolve_spec.rb b/spec/features/merge_requests/diff_notes_resolve_spec.rb index 5e6d8467217..d5e3d8e7eff 100644 --- a/spec/features/merge_requests/diff_notes_resolve_spec.rb +++ b/spec/features/merge_requests/diff_notes_resolve_spec.rb @@ -69,8 +69,6 @@ feature 'Diff notes resolve', feature: true, js: true do page.within '.diff-content .note' do expect(page).to have_selector('.line-resolve-btn.is-active') - - expect(find('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}") end page.within '.line-resolve-all-container' do -- cgit v1.2.1 From d1f0b2f4339a7a46679ceb361982448229013c13 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 3 Nov 2016 11:47:15 -0200 Subject: Fix project Visibility level selector not using default values --- spec/features/projects/new_project_spec.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 spec/features/projects/new_project_spec.rb (limited to 'spec') diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb new file mode 100644 index 00000000000..abfc46601fb --- /dev/null +++ b/spec/features/projects/new_project_spec.rb @@ -0,0 +1,19 @@ +require "spec_helper" + +feature "New project", feature: true do + context "Visibility level selector" do + let(:user) { create(:admin) } + + before { login_as(user) } + + Gitlab::VisibilityLevel.options.each do |key, level| + it "sets selector to #{key}" do + stub_application_setting(default_project_visibility: level) + + visit new_project_path + + expect(find_field("project_visibility_level_#{level}")).to be_checked + end + end + end +end -- cgit v1.2.1 From 3fa265d19547669c60788e38e389fa12bb119235 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Thu, 10 Nov 2016 18:24:12 +0100 Subject: Fix expanding a collapsed diff when converting a symlink to a regular file In this case comparing old_path and new_path is not enough because there are two entires that match. --- spec/features/expand_collapse_diffs_spec.rb | 14 ++++++++++++++ spec/support/test_env.rb | 1 + 2 files changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb index 6c938bdead8..3934c936f20 100644 --- a/spec/features/expand_collapse_diffs_spec.rb +++ b/spec/features/expand_collapse_diffs_spec.rb @@ -182,6 +182,20 @@ feature 'Expand and collapse diffs', js: true, feature: true do end end end + + context 'expanding a diff when symlink was converted to a regular file' do + let(:branch) { 'symlink-expand-diff' } + + it 'shows the content of the regular file' do + expect(page).to have_content('This diff is collapsed') + expect(page).to have_no_content('No longer a symlink') + + find('.click-to-expand').click + wait_for_ajax + + expect(page).to have_content('No longer a symlink') + end + end end context 'visiting a commit without collapsed diffs' do diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 778e665500d..103f7542286 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -23,6 +23,7 @@ module TestEnv 'binary-encoding' => '7b1cf43', 'gitattributes' => '5a62481', 'expand-collapse-diffs' => '4842455', + 'symlink-expand-diff' => '81e6355', 'expand-collapse-files' => '025db92', 'expand-collapse-lines' => '238e82d', 'video' => '8879059', -- cgit v1.2.1 From 208530494e5d2c5c62a3e1c24489aae0e4935e3a Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 8 Nov 2016 16:31:37 -0600 Subject: Refactored initializer code to its own class and added tests --- spec/lib/gitlab/sidekiq_throttler_spec.rb | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 spec/lib/gitlab/sidekiq_throttler_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/sidekiq_throttler_spec.rb b/spec/lib/gitlab/sidekiq_throttler_spec.rb new file mode 100644 index 00000000000..ac4a64c0f43 --- /dev/null +++ b/spec/lib/gitlab/sidekiq_throttler_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Gitlab::SidekiqThrottler do + before do + Sidekiq.options[:concurrency] = 35 + + stub_application_setting( + sidekiq_throttling_enabled: true, + sidekiq_throttling_factor: 0.1, + sidekiq_throttling_queues: %w[build project_cache] + ) + end + + describe '#set_limit' do + it 'returns the correct limit' do + expect(Gitlab::SidekiqThrottler.send(:set_limit)).to eq 4 + end + end + + describe '#execute!' do + it 'sets limits on the selected queues' do + Gitlab::SidekiqThrottler.execute! + + expect(Sidekiq::Queue['build'].limit).to eq 4 + expect(Sidekiq::Queue['project_cache'].limit).to eq 4 + end + + it 'does not set limits on other queues' do + Gitlab::SidekiqThrottler.execute! + + expect(Sidekiq::Queue['merge'].limit).to be_nil + end + end +end -- cgit v1.2.1 From 3cff3a2e5b87c40927eb02a8884c84260ca30c2a Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Wed, 19 Oct 2016 09:50:34 -0500 Subject: Omniauth auto link LDAP user falls back to find by DN when user cannot be found by uid --- spec/lib/gitlab/o_auth/user_spec.rb | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/o_auth/user_spec.rb b/spec/lib/gitlab/o_auth/user_spec.rb index 78c669e8fa5..fc9e1cb430a 100644 --- a/spec/lib/gitlab/o_auth/user_spec.rb +++ b/spec/lib/gitlab/o_auth/user_spec.rb @@ -137,11 +137,12 @@ describe Gitlab::OAuth::User, lib: true do allow(ldap_user).to receive(:username) { uid } allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] } allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' } - allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user) end context "and no account for the LDAP user" do it "creates a user with dual LDAP and omniauth identities" do + allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user) + oauth_user.save expect(gl_user).to be_valid @@ -159,6 +160,8 @@ describe Gitlab::OAuth::User, lib: true do context "and LDAP user has an account already" do let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') } it "adds the omniauth identity to the LDAP account" do + allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user) + oauth_user.save expect(gl_user).to be_valid @@ -172,6 +175,24 @@ describe Gitlab::OAuth::User, lib: true do ]) end end + + context 'when an LDAP person is not found by uid' do + it 'tries to find an LDAP person by DN and adds the omniauth identity to the user' do + allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(nil) + allow(Gitlab::LDAP::Person).to receive(:find_by_dn).and_return(ldap_user) + + oauth_user.save + + identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } } + expect(identities_as_hash) + .to match_array( + [ + { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' }, + { provider: 'twitter', extern_uid: uid } + ] + ) + end + end end context "and no corresponding LDAP person" do -- cgit v1.2.1 From d55fb906e43430ec265f48928f609892681cccd9 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Thu, 10 Nov 2016 09:00:23 -0600 Subject: add tests for build row templates --- .../views/projects/builds/_build.html.haml_spec.rb | 28 ++++++++++++++++++++++ .../_generic_commit_status.html.haml_spec.rb | 28 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 spec/views/projects/builds/_build.html.haml_spec.rb create mode 100644 spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb (limited to 'spec') diff --git a/spec/views/projects/builds/_build.html.haml_spec.rb b/spec/views/projects/builds/_build.html.haml_spec.rb new file mode 100644 index 00000000000..e141a117731 --- /dev/null +++ b/spec/views/projects/builds/_build.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe 'projects/ci/builds/_build' do + include Devise::Test::ControllerHelpers + + let(:project) { create(:project) } + let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) } + let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'rspec 0:2', status: :pending) } + + before do + controller.prepend_view_path('app/views/projects') + allow(view).to receive(:can?).and_return(true) + end + + it 'won\'t include a column with a link to its pipeline by default' do + render partial: 'projects/ci/builds/build', locals: { build: build } + + expect(rendered).not_to have_link('#1337') + expect(rendered).not_to have_text('#1337 by API') + end + + it 'can include a column with a link to its pipeline' do + render partial: 'projects/ci/builds/build', locals: { build: build, pipeline_link: true } + + expect(rendered).to have_link('#1337') + expect(rendered).to have_text('#1337 by API') + end +end diff --git a/spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb b/spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb new file mode 100644 index 00000000000..49b20e5b36b --- /dev/null +++ b/spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe 'projects/generic_commit_statuses/_generic_commit_status.html.haml' do + include Devise::Test::ControllerHelpers + + let(:project) { create(:project) } + let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) } + let(:generic_commit_status) { create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3) } + + before do + controller.prepend_view_path('app/views/projects') + allow(view).to receive(:can?).and_return(true) + end + + it 'won\'t include a column with a link to its pipeline by default' do + render partial: 'projects/generic_commit_statuses/generic_commit_status', locals: { generic_commit_status: generic_commit_status } + + expect(rendered).not_to have_link('#1337') + expect(rendered).not_to have_text('#1337 by API') + end + + it 'can include a column with a link to its pipeline' do + render partial: 'projects/generic_commit_statuses/generic_commit_status', locals: { generic_commit_status: generic_commit_status, pipeline_link: true } + + expect(rendered).to have_link('#1337') + expect(rendered).to have_text('#1337 by API') + end +end -- cgit v1.2.1 From be3d74e096f6b5cb46b5d2440c16383633f1fc06 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 11 Nov 2016 10:16:03 +0100 Subject: Do not call environments service in repository model --- spec/models/repository_spec.rb | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 6d65f6ead12..04b7d19d414 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1182,18 +1182,7 @@ describe Repository, models: true do it 'flushes the visible content cache' do expect(repository).to receive(:expire_has_visible_content_cache) - repository.after_remove_branch(user, 'master') - end - - context 'when there is environment with review app available for branch' do - before do - create(:environment, :with_review_app, project: project) - end - - it 'stops environment' do - expect_any_instance_of(Environment).to receive(:stop!) - repository.after_remove_branch(user, 'master') - end + repository.after_remove_branch end end -- cgit v1.2.1 From d211011698016bd4f04bc32e7450d6df470ea0c2 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 11 Nov 2016 12:51:50 +0000 Subject: Make access request specs explicitly enable or disable access requests as required --- .../groups/group_members_controller_spec.rb | 2 +- .../projects/project_members_controller_spec.rb | 2 +- spec/factories/groups.rb | 4 +++ spec/factories/projects.rb | 4 +++ .../members/owner_manages_access_requests_spec.rb | 2 +- .../groups/members/user_requests_access_spec.rb | 2 +- ...uester_cannot_request_access_to_project_spec.rb | 4 +-- .../members/master_manages_access_requests_spec.rb | 2 +- .../projects/members/user_requests_access_spec.rb | 2 +- spec/finders/access_requests_finder_spec.rb | 15 +++++++---- spec/helpers/members_helper_spec.rb | 8 +++--- spec/mailers/notify_spec.rb | 15 +++++++---- spec/models/concerns/access_requestable_spec.rb | 8 +++--- spec/models/group_spec.rb | 2 +- spec/models/member_spec.rb | 4 +-- spec/models/project_spec.rb | 2 +- spec/models/project_team_spec.rb | 8 +++--- spec/models/user_spec.rb | 4 +-- spec/requests/api/access_requests_spec.rb | 22 +++++++-------- spec/requests/api/members_spec.rb | 20 +++++++------- .../members/approve_access_request_service_spec.rb | 4 +-- spec/services/members/destroy_service_spec.rb | 1 + .../members/request_access_service_spec.rb | 31 ++++++++++------------ 23 files changed, 92 insertions(+), 76 deletions(-) (limited to 'spec') diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index c7db84dd5f9..60db0192dfd 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Groups::GroupMembersController do let(:user) { create(:user) } - let(:group) { create(:group, :public) } + let(:group) { create(:group, :public, :access_requestable) } describe 'GET index' do it 'renders index with 200 status code' do diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 2a7523c6512..b52137fbe7e 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') describe Projects::ProjectMembersController do let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } describe 'GET index' do it 'renders index with 200 status code' do diff --git a/spec/factories/groups.rb b/spec/factories/groups.rb index 2d47a6f6c4c..ebd3595ea64 100644 --- a/spec/factories/groups.rb +++ b/spec/factories/groups.rb @@ -15,5 +15,9 @@ FactoryGirl.define do trait :private do visibility_level Gitlab::VisibilityLevel::PRIVATE end + + trait :access_requestable do + request_access_enabled true + end end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index bfd88a254f1..1166498ddff 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -24,6 +24,10 @@ FactoryGirl.define do visibility_level Gitlab::VisibilityLevel::PRIVATE end + trait :access_requestable do + request_access_enabled true + end + trait :empty_repo do after(:create) do |project| project.create_repository diff --git a/spec/features/groups/members/owner_manages_access_requests_spec.rb b/spec/features/groups/members/owner_manages_access_requests_spec.rb index d811b05b0c3..dbe150823ba 100644 --- a/spec/features/groups/members/owner_manages_access_requests_spec.rb +++ b/spec/features/groups/members/owner_manages_access_requests_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Groups > Members > Owner manages access requests', feature: true do let(:user) { create(:user) } let(:owner) { create(:user) } - let(:group) { create(:group, :public) } + let(:group) { create(:group, :public, :access_requestable) } background do group.request_access(user) diff --git a/spec/features/groups/members/user_requests_access_spec.rb b/spec/features/groups/members/user_requests_access_spec.rb index b3baa2ab57c..d8c9c487996 100644 --- a/spec/features/groups/members/user_requests_access_spec.rb +++ b/spec/features/groups/members/user_requests_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Groups > Members > User requests access', feature: true do let(:user) { create(:user) } let(:owner) { create(:user) } - let(:group) { create(:group, :public) } + let(:group) { create(:group, :public, :access_requestable) } let!(:project) { create(:project, :private, namespace: group) } background do diff --git a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb index c4ed92d2780..4973e0aee85 100644 --- a/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb +++ b/spec/features/projects/members/group_requester_cannot_request_access_to_project_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' feature 'Projects > Members > Group requester cannot request access to project', feature: true do let(:user) { create(:user) } let(:owner) { create(:user) } - let(:group) { create(:group, :public) } - let(:project) { create(:project, :public, namespace: group) } + let(:group) { create(:group, :public, :access_requestable) } + let(:project) { create(:project, :public, :access_requestable, namespace: group) } background do group.add_owner(owner) diff --git a/spec/features/projects/members/master_manages_access_requests_spec.rb b/spec/features/projects/members/master_manages_access_requests_spec.rb index d15376931c3..143390b71cd 100644 --- a/spec/features/projects/members/master_manages_access_requests_spec.rb +++ b/spec/features/projects/members/master_manages_access_requests_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Projects > Members > Master manages access requests', feature: true do let(:user) { create(:user) } let(:master) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } background do project.request_access(user) diff --git a/spec/features/projects/members/user_requests_access_spec.rb b/spec/features/projects/members/user_requests_access_spec.rb index 56ede8eb5be..97c42bd7f01 100644 --- a/spec/features/projects/members/user_requests_access_spec.rb +++ b/spec/features/projects/members/user_requests_access_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Projects > Members > User requests access', feature: true do let(:user) { create(:user) } let(:master) { create(:user) } - let(:project) { create(:project, :public) } + let(:project) { create(:project, :public, :access_requestable) } background do project.team << [master, :master] diff --git a/spec/finders/access_requests_finder_spec.rb b/spec/finders/access_requests_finder_spec.rb index 8cfea9659cb..c7278e971ae 100644 --- a/spec/finders/access_requests_finder_spec.rb +++ b/spec/finders/access_requests_finder_spec.rb @@ -3,12 +3,17 @@ require 'spec_helper' describe AccessRequestsFinder, services: true do let(:user) { create(:user) } let(:access_requester) { create(:user) } - let(:project) { create(:project, :public) } - let(:group) { create(:group, :public) } - before do - project.request_access(access_requester) - group.request_access(access_requester) + let(:project) do + create(:empty_project, :public, :access_requestable) do |project| + project.request_access(access_requester) + end + end + + let(:group) do + create(:group, :public, :access_requestable) do |group| + group.request_access(access_requester) + end end shared_examples 'a finder returning access requesters' do |method_name| diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb index 6703d88e357..ffca1c94da1 100644 --- a/spec/helpers/members_helper_spec.rb +++ b/spec/helpers/members_helper_spec.rb @@ -11,11 +11,11 @@ describe MembersHelper do describe '#remove_member_message' do let(:requester) { build(:user) } - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:project_member) { build(:project_member, project: project) } let(:project_member_invite) { build(:project_member, project: project).tap { |m| m.generate_invite_token! } } let(:project_member_request) { project.request_access(requester) } - let(:group) { create(:group) } + let(:group) { create(:group, :access_requestable) } let(:group_member) { build(:group_member, group: group) } let(:group_member_invite) { build(:group_member, group: group).tap { |m| m.generate_invite_token! } } let(:group_member_request) { group.request_access(requester) } @@ -32,10 +32,10 @@ describe MembersHelper do describe '#remove_member_title' do let(:requester) { build(:user) } - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:project_member) { build(:project_member, project: project) } let(:project_member_request) { project.request_access(requester) } - let(:group) { create(:group) } + let(:group) { create(:group, :access_requestable) } let(:group_member) { build(:group_member, group: group) } let(:group_member_request) { group.request_access(requester) } diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index f5f3f58613d..932a5dc4862 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -401,7 +401,12 @@ describe Notify do describe 'project access requested' do context 'for a project in a user namespace' do - let(:project) { create(:project, :public).tap { |p| p.team << [p.owner, :master, p.owner] } } + let(:project) do + create(:empty_project, :public, :access_requestable) do |project| + project.team << [project.owner, :master, project.owner] + end + end + let(:user) { create(:user) } let(:project_member) do project.request_access(user) @@ -428,7 +433,7 @@ describe Notify do context 'for a project in a group' do let(:group_owner) { create(:user) } let(:group) { create(:group).tap { |g| g.add_owner(group_owner) } } - let(:project) { create(:project, :public, namespace: group) } + let(:project) { create(:empty_project, :public, :access_requestable, namespace: group) } let(:user) { create(:user) } let(:project_member) do project.request_access(user) @@ -454,7 +459,7 @@ describe Notify do end describe 'project access denied' do - let(:project) { create(:project) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:user) { create(:user) } let(:project_member) do project.request_access(user) @@ -474,7 +479,7 @@ describe Notify do end describe 'project access changed' do - let(:project) { create(:project) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:user) { create(:user) } let(:project_member) { create(:project_member, project: project, user: user) } subject { Notify.member_access_granted_email('project', project_member.id) } @@ -685,7 +690,7 @@ describe Notify do context 'for a group' do describe 'group access requested' do - let(:group) { create(:group) } + let(:group) { create(:group, :public, :access_requestable) } let(:user) { create(:user) } let(:group_member) do group.request_access(user) diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb index 96eee0e8bdd..4829ef17a20 100644 --- a/spec/models/concerns/access_requestable_spec.rb +++ b/spec/models/concerns/access_requestable_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe AccessRequestable do describe 'Group' do describe '#request_access' do - let(:group) { create(:group, :public) } + let(:group) { create(:group, :public, :access_requestable) } let(:user) { create(:user) } it { expect(group.request_access(user)).to be_a(GroupMember) } @@ -11,7 +11,7 @@ describe AccessRequestable do end describe '#access_requested?' do - let(:group) { create(:group, :public) } + let(:group) { create(:group, :public, :access_requestable) } let(:user) { create(:user) } before { group.request_access(user) } @@ -22,14 +22,14 @@ describe AccessRequestable do describe 'Project' do describe '#request_access' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:user) { create(:user) } it { expect(project.request_access(user)).to be_a(ProjectMember) } end describe '#access_requested?' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:user) { create(:user) } before { project.request_access(user) } diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 47f89f744cb..1613a586a2c 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Group, models: true do - let!(:group) { create(:group) } + let!(:group) { create(:group, :access_requestable) } describe 'associations' do it { is_expected.to have_many :projects } diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 485121701af..12419d6fd5a 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -57,7 +57,7 @@ describe Member, models: true do describe 'Scopes & finders' do before do - project = create(:empty_project, :public) + project = create(:empty_project, :public, :access_requestable) group = create(:group) @owner_user = create(:user).tap { |u| group.add_owner(u) } @owner = group.members.find_by(user_id: @owner_user.id) @@ -174,7 +174,7 @@ describe Member, models: true do describe '.add_user' do %w[project group].each do |source_type| context "when source is a #{source_type}" do - let!(:source) { create(source_type, :public) } + let!(:source) { create(source_type, :public, :access_requestable) } let!(:user) { create(:user) } let!(:admin) { create(:admin) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0810d06b50f..3a0c3ec21cd 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -76,7 +76,7 @@ describe Project, models: true do end describe '#members & #requesters' do - let(:project) { create(:project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:requester) { create(:user) } let(:developer) { create(:user) } before do diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index e0f2dadf189..12228425579 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -137,7 +137,7 @@ describe ProjectTeam, models: true do describe '#find_member' do context 'personal project' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } let(:requester) { create(:user) } before do @@ -155,7 +155,7 @@ describe ProjectTeam, models: true do end context 'group project' do - let(:group) { create(:group) } + let(:group) { create(:group, :access_requestable) } let(:project) { create(:empty_project, group: group) } let(:requester) { create(:user) } @@ -200,7 +200,7 @@ describe ProjectTeam, models: true do let(:requester) { create(:user) } context 'personal project' do - let(:project) { create(:empty_project, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } context 'when project is not shared with group' do before do @@ -243,7 +243,7 @@ describe ProjectTeam, models: true do end context 'group project' do - let(:group) { create(:group) } + let(:group) { create(:group, :access_requestable) } let(:project) { create(:empty_project, group: group) } before do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 3b152e15b61..54b23b02003 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -37,7 +37,7 @@ describe User, models: true do describe '#group_members' do it 'does not include group memberships for which user is a requester' do user = create(:user) - group = create(:group, :public) + group = create(:group, :public, :access_requestable) group.request_access(user) expect(user.group_members).to be_empty @@ -47,7 +47,7 @@ describe User, models: true do describe '#project_members' do it 'does not include project memberships for which user is a requester' do user = create(:user) - project = create(:project, :public) + project = create(:project, :public, :access_requestable) project.request_access(user) expect(user.project_members).to be_empty diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb index b467890a403..1a771b3c87a 100644 --- a/spec/requests/api/access_requests_spec.rb +++ b/spec/requests/api/access_requests_spec.rb @@ -9,19 +9,19 @@ describe API::AccessRequests, api: true do let(:stranger) { create(:user) } let(:project) do - project = create(:project, :public, creator_id: master.id, namespace: master.namespace) - project.team << [developer, :developer] - project.team << [master, :master] - project.request_access(access_requester) - project + create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| + project.team << [developer, :developer] + project.team << [master, :master] + project.request_access(access_requester) + end end let(:group) do - group = create(:group, :public) - group.add_developer(developer) - group.add_owner(master) - group.request_access(access_requester) - group + create(:group, :public, :access_requestable) do |group| + group.add_developer(developer) + group.add_owner(master) + group.request_access(access_requester) + end end shared_examples 'GET /:sources/:id/access_requests' do |source_type| @@ -89,7 +89,7 @@ describe API::AccessRequests, api: true do context 'when authenticated as a stranger' do context "when access request is disabled for the #{source_type}" do before do - source.update(request_access_enabled: false) + source.update_attributes(request_access_enabled: false) end it 'returns 403' do diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index 493c0a893d1..2c94c86ccfa 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -9,19 +9,19 @@ describe API::Members, api: true do let(:stranger) { create(:user) } let(:project) do - project = create(:project, :public, creator_id: master.id, namespace: master.namespace) - project.team << [developer, :developer] - project.team << [master, :master] - project.request_access(access_requester) - project + create(:project, :public, :access_requestable, creator_id: master.id, namespace: master.namespace) do |project| + project.team << [developer, :developer] + project.team << [master, :master] + project.request_access(access_requester) + end end let!(:group) do - group = create(:group, :public) - group.add_developer(developer) - group.add_owner(master) - group.request_access(access_requester) - group + create(:group, :public, :access_requestable) do |group| + group.add_developer(developer) + group.add_owner(master) + group.request_access(access_requester) + end end shared_examples 'GET /:sources/:id/members' do |source_type| diff --git a/spec/services/members/approve_access_request_service_spec.rb b/spec/services/members/approve_access_request_service_spec.rb index 7b090343a3e..7d5a66801db 100644 --- a/spec/services/members/approve_access_request_service_spec.rb +++ b/spec/services/members/approve_access_request_service_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe Members::ApproveAccessRequestService, services: true do let(:user) { create(:user) } let(:access_requester) { create(:user) } - let(:project) { create(:project, :public) } - let(:group) { create(:group, :public) } + let(:project) { create(:empty_project, :public, :access_requestable) } + let(:group) { create(:group, :public, :access_requestable) } let(:opts) { {} } shared_examples 'a service raising ActiveRecord::RecordNotFound' do diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb index 9995f3488af..574df6e0f42 100644 --- a/spec/services/members/destroy_service_spec.rb +++ b/spec/services/members/destroy_service_spec.rb @@ -26,6 +26,7 @@ describe Members::DestroyService, services: true do context 'when the given member is an access requester' do before do source.members.find_by(user_id: member_user).destroy + source.update_attributes(request_access_enabled: true) source.request_access(member_user) end let(:access_requester) { source.requesters.find_by(user_id: member_user) } diff --git a/spec/services/members/request_access_service_spec.rb b/spec/services/members/request_access_service_spec.rb index 0d2d5f03199..853c125dadb 100644 --- a/spec/services/members/request_access_service_spec.rb +++ b/spec/services/members/request_access_service_spec.rb @@ -2,8 +2,6 @@ require 'spec_helper' describe Members::RequestAccessService, services: true do let(:user) { create(:user) } - let(:project) { create(:project, :private) } - let(:group) { create(:group, :private) } shared_examples 'a service raising Gitlab::Access::AccessDeniedError' do it 'raises Gitlab::Access::AccessDeniedError' do @@ -31,27 +29,26 @@ describe Members::RequestAccessService, services: true do end context 'when current user cannot request access to the project' do - it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do - let(:source) { project } + %i[project group].each do |source_type| + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { create(source_type, :private) } + end end + end - it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do - let(:source) { group } + context 'when access requests are disabled' do + %i[project group].each do |source_type| + it_behaves_like 'a service raising Gitlab::Access::AccessDeniedError' do + let(:source) { create(source_type, :public) } + end end end context 'when current user can request access to the project' do - before do - project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) - group.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) - end - - it_behaves_like 'a service creating a access request' do - let(:source) { project } - end - - it_behaves_like 'a service creating a access request' do - let(:source) { group } + %i[project group].each do |source_type| + it_behaves_like 'a service creating a access request' do + let(:source) { create(source_type, :public, :access_requestable) } + end end end end -- cgit v1.2.1 From e840749b84ceb226e46ebdfb489c735e3370cff7 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Thu, 10 Nov 2016 11:36:52 -0600 Subject: Refactored Sidekiq Throttler and updated documentation --- spec/lib/gitlab/sidekiq_throttler_spec.rb | 6 ------ 1 file changed, 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/sidekiq_throttler_spec.rb b/spec/lib/gitlab/sidekiq_throttler_spec.rb index ac4a64c0f43..ff32e0e699d 100644 --- a/spec/lib/gitlab/sidekiq_throttler_spec.rb +++ b/spec/lib/gitlab/sidekiq_throttler_spec.rb @@ -11,12 +11,6 @@ describe Gitlab::SidekiqThrottler do ) end - describe '#set_limit' do - it 'returns the correct limit' do - expect(Gitlab::SidekiqThrottler.send(:set_limit)).to eq 4 - end - end - describe '#execute!' do it 'sets limits on the selected queues' do Gitlab::SidekiqThrottler.execute! -- cgit v1.2.1 From 317c3883477c1af3db96fdbd7caeed46ceb67d72 Mon Sep 17 00:00:00 2001 From: Alex Sanford Date: Thu, 10 Nov 2016 20:04:28 -0400 Subject: Ensure labels are loaded on "show" methods of MR Previously, they were only being loaded on the actual `show` action, but not the actions representing the tabs (commits, builds, etc). --- .../projects/merge_requests_controller_spec.rb | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 49127aecc63..1d0750d1719 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -39,6 +39,17 @@ describe Projects::MergeRequestsController do end end + shared_examples "loads labels" do |action| + it "loads labels into the @labels variable" do + get action, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: merge_request.iid, + format: 'html' + expect(assigns(:labels)).not_to be_nil + end + end + describe "GET show" do shared_examples "export merge as" do |format| it "does generally work" do @@ -51,6 +62,8 @@ describe Projects::MergeRequestsController do expect(response).to be_success end + it_behaves_like "loads labels", :show + it "generates it" do expect_any_instance_of(MergeRequest).to receive(:"to_#{format}") @@ -406,6 +419,8 @@ describe Projects::MergeRequestsController do get :diffs, params.merge(extra_params) end + it_behaves_like "loads labels", :diffs + context 'with default params' do context 'as html' do before { go(format: 'html') } @@ -612,6 +627,8 @@ describe Projects::MergeRequestsController do format: format end + it_behaves_like "loads labels", :commits + context 'as html' do it 'renders the show template' do go @@ -630,6 +647,14 @@ describe Projects::MergeRequestsController do end end + describe 'GET builds' do + it_behaves_like "loads labels", :builds + end + + describe 'GET pipelines' do + it_behaves_like "loads labels", :pipelines + end + describe 'GET conflicts' do let(:json_response) { JSON.parse(response.body) } -- cgit v1.2.1 From 591f10f6bd8d92e083fbc3c691c874e62144ba25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Fri, 11 Nov 2016 14:23:08 -0300 Subject: Update 8.14-rc1 migrations to minimize downtime and deploy time See https://gitlab.com/gitlab-org/gitlab-ce/issues/24386 --- spec/requests/api/projects_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index d6e9fd2c4b2..f020d471422 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -360,6 +360,14 @@ describe API::API, api: true do expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey end + it 'sets a project as allowing merge if only_allow_merge_if_all_discussions_are_resolved is nil' do + project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: nil) + + post api('/projects', user), project + + expect(json_response['only_allow_merge_if_all_discussions_are_resolved']).to be_falsey + end + it 'sets a project as allowing merge only if all discussions are resolved' do project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true }) -- cgit v1.2.1 From 0803a350b09d2c80a7ff1c2d1e17712989b7a0c2 Mon Sep 17 00:00:00 2001 From: Josep Llaneras Date: Wed, 12 Oct 2016 01:22:09 +0200 Subject: Issue #13823: random message when all Todos are Done --- spec/features/todos/todos_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb index 3ae83ac082d..88eabea7e3a 100644 --- a/spec/features/todos/todos_spec.rb +++ b/spec/features/todos/todos_spec.rb @@ -44,7 +44,7 @@ describe 'Dashboard Todos', feature: true do end it 'shows "All done" message' do - expect(page).to have_content("Good job! Looks like you don't have any todos left.") + expect(page).to have_selector('.todos-all-done', count: 1) end end @@ -64,7 +64,7 @@ describe 'Dashboard Todos', feature: true do end it 'shows "All done" message' do - expect(page).to have_content("Good job! Looks like you don't have any todos left.") + expect(page).to have_selector('.todos-all-done', count: 1) end end end @@ -152,7 +152,7 @@ describe 'Dashboard Todos', feature: true do within('.todos-pending-count') { expect(page).to have_content '0' } expect(page).to have_content 'To do 0' expect(page).to have_content 'Done 0' - expect(page).to have_content "Good job! Looks like you don't have any todos left." + expect(page).to have_selector('.todos-all-done', count: 1) end end end -- cgit v1.2.1 From c50b98da723dab9a35ddb2cde0258d141cf92495 Mon Sep 17 00:00:00 2001 From: Drew Blessing Date: Fri, 11 Nov 2016 14:44:08 -0600 Subject: Centralize LDAP config/filter logic Centralize all LDAP config logic in `GitLab::LDAP::Config`. Previously, some logic was in the Devise initializer and it was not honoring the `user_filter`. If a user outside the configured `user_filter` signed in, an account would be created but they would then be denied access. Now that logic is centralized, the filter is honored and users outside the filter are never created. --- spec/lib/gitlab/ldap/config_spec.rb | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/ldap/config_spec.rb b/spec/lib/gitlab/ldap/config_spec.rb index f5ebe703083..1a6803e01c3 100644 --- a/spec/lib/gitlab/ldap/config_spec.rb +++ b/spec/lib/gitlab/ldap/config_spec.rb @@ -19,6 +19,87 @@ describe Gitlab::LDAP::Config, lib: true do end end + describe '#adapter_options' do + it 'constructs basic options' do + stub_ldap_config( + options: { + 'host' => 'ldap.example.com', + 'port' => 386, + 'method' => 'plain' + } + ) + + expect(config.adapter_options).to eq( + host: 'ldap.example.com', + port: 386, + encryption: nil + ) + end + + it 'includes authentication options when auth is configured' do + stub_ldap_config( + options: { + 'host' => 'ldap.example.com', + 'port' => 686, + 'method' => 'ssl', + 'bind_dn' => 'uid=admin,dc=example,dc=com', + 'password' => 'super_secret' + } + ) + + expect(config.adapter_options).to eq( + host: 'ldap.example.com', + port: 686, + encryption: :simple_tls, + auth: { + method: :simple, + username: 'uid=admin,dc=example,dc=com', + password: 'super_secret' + } + ) + end + end + + describe '#omniauth_options' do + it 'constructs basic options' do + stub_ldap_config( + options: { + 'host' => 'ldap.example.com', + 'port' => 386, + 'base' => 'ou=users,dc=example,dc=com', + 'method' => 'plain', + 'uid' => 'uid' + } + ) + + expect(config.omniauth_options).to include( + host: 'ldap.example.com', + port: 386, + base: 'ou=users,dc=example,dc=com', + method: 'plain', + filter: '(uid=%{username})' + ) + expect(config.omniauth_options.keys).not_to include(:bind_dn, :password) + end + + it 'includes authentication options when auth is configured' do + stub_ldap_config( + options: { + 'uid' => 'sAMAccountName', + 'user_filter' => '(memberOf=cn=group1,ou=groups,dc=example,dc=com)', + 'bind_dn' => 'uid=admin,dc=example,dc=com', + 'password' => 'super_secret' + } + ) + + expect(config.omniauth_options).to include( + filter: '(&(sAMAccountName=%{username})(memberOf=cn=group1,ou=groups,dc=example,dc=com))', + bind_dn: 'uid=admin,dc=example,dc=com', + password: 'super_secret' + ) + end + end + describe '#has_auth?' do it 'is true when password is set' do stub_ldap_config( -- cgit v1.2.1 From 0527ea09920d49bb9e1574e7a61958ba70dbe24e Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Tue, 8 Nov 2016 17:43:19 +0000 Subject: adds guard clause for readme model method and initializes a new view with proper stylesheets --- spec/helpers/preferences_helper_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'spec') diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb index 2f9291afc3f..3830fe26158 100644 --- a/spec/helpers/preferences_helper_spec.rb +++ b/spec/helpers/preferences_helper_spec.rb @@ -85,4 +85,25 @@ describe PreferencesHelper do and_return(double('user', messages)) end end + + describe 'default_project_view' do + let(:project) { create(:project) } + + context 'user not signed in' do + before do + stub_user + @repository = project.repository + end + + it 'returns readme view if repository is not empty' do + expect(helper.default_project_view).to eq('readme') + end + + it 'returns activity if repository is empty' do + expect(@repository).to receive(:head_commit).and_return(nil) + + expect(helper.default_project_view).to eq('activity') + end + end + end end -- cgit v1.2.1 From 062c9a08c44f2e178476cace0ebd8a55aa27e866 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Fri, 11 Nov 2016 22:57:23 +0000 Subject: change empty project view to annonymous user from activity to empty partial --- spec/helpers/preferences_helper_spec.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb index 3830fe26158..2bd4eace89f 100644 --- a/spec/helpers/preferences_helper_spec.rb +++ b/spec/helpers/preferences_helper_spec.rb @@ -90,19 +90,16 @@ describe PreferencesHelper do let(:project) { create(:project) } context 'user not signed in' do - before do - stub_user - @repository = project.repository - end + before { stub_user } it 'returns readme view if repository is not empty' do expect(helper.default_project_view).to eq('readme') end it 'returns activity if repository is empty' do - expect(@repository).to receive(:head_commit).and_return(nil) + expect(project).to receive(:empty_repo?).and_return(true) - expect(helper.default_project_view).to eq('activity') + expect(helper.default_project_view).to eq('empty') end end end -- cgit v1.2.1 From d48d879ef5e0b1517c43bef27f584655535259c8 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 13 Oct 2016 12:26:44 -0300 Subject: Does not raise error when Note not found when processing NewNoteWorker - Also remove unnecessary param --- spec/services/notes/create_service_spec.rb | 37 +++++++++++++++++++--- spec/workers/new_note_worker_spec.rb | 49 ++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 spec/workers/new_note_worker_spec.rb (limited to 'spec') diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index 93885c84dc3..25804696d2e 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -14,12 +14,41 @@ describe Notes::CreateService, services: true do end context "valid params" do - before do - @note = Notes::CreateService.new(project, user, opts).execute + it 'returns a valid note' do + note = Notes::CreateService.new(project, user, opts).execute + + expect(note).to be_valid + end + + it 'returns a persisted note' do + note = Notes::CreateService.new(project, user, opts).execute + + expect(note).to be_persisted + end + + it 'note has valid content' do + note = Notes::CreateService.new(project, user, opts).execute + + expect(note.note).to eq(opts[:note]) end - it { expect(@note).to be_valid } - it { expect(@note.note).to eq(opts[:note]) } + it 'TodoService#new_note is called' do + note = build(:note) + allow(project).to receive_message_chain(:notes, :new).with(opts) { note } + + expect_any_instance_of(TodoService).to receive(:new_note).with(note, user) + + Notes::CreateService.new(project, user, opts).execute + end + + it 'enqueues NewNoteWorker' do + note = build(:note, id: 999) + allow(project).to receive_message_chain(:notes, :new).with(opts) { note } + + expect(NewNoteWorker).to receive(:perform_async).with(note.id) + + Notes::CreateService.new(project, user, opts).execute + end end describe 'note with commands' do diff --git a/spec/workers/new_note_worker_spec.rb b/spec/workers/new_note_worker_spec.rb new file mode 100644 index 00000000000..8fdbb35afd0 --- /dev/null +++ b/spec/workers/new_note_worker_spec.rb @@ -0,0 +1,49 @@ +require "spec_helper" + +describe NewNoteWorker do + context 'when Note found' do + let(:note) { create(:note) } + + it "calls NotificationService#new_note" do + expect_any_instance_of(NotificationService).to receive(:new_note).with(note) + + described_class.new.perform(note.id) + end + + it "calls Notes::PostProcessService#execute" do + notes_post_process_service = double(Notes::PostProcessService) + allow(Notes::PostProcessService).to receive(:new).with(note) { notes_post_process_service } + + expect(notes_post_process_service).to receive(:execute) + + described_class.new.perform(note.id) + end + end + + context 'when Note not found' do + let(:unexistent_note_id) { 999 } + + it 'logs NewNoteWorker process skipping' do + expect(Rails.logger).to receive(:error). + with("NewNoteWorker: couldn't find note with ID=999, skipping job") + + described_class.new.perform(unexistent_note_id) + end + + it 'does not raise errors' do + expect { described_class.new.perform(unexistent_note_id) }.not_to raise_error + end + + it "does not call NotificationService#new_note" do + expect_any_instance_of(NotificationService).not_to receive(:new_note) + + described_class.new.perform(unexistent_note_id) + end + + it "does not call Notes::PostProcessService#execute" do + expect_any_instance_of(Notes::PostProcessService).not_to receive(:execute) + + described_class.new.perform(unexistent_note_id) + end + end +end -- cgit v1.2.1 From af941732ed92ad44a7568964e2a9191d0c72164c Mon Sep 17 00:00:00 2001 From: Vincent Composieux Date: Fri, 11 Nov 2016 12:27:23 +0100 Subject: Added ability to put emojis into repository name Added ability to put emojis into repository name --- spec/features/projects/project_settings_spec.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb index 3de25d7af7d..bf60cca4ea4 100644 --- a/spec/features/projects/project_settings_spec.rb +++ b/spec/features/projects/project_settings_spec.rb @@ -18,7 +18,7 @@ describe 'Edit Project Settings', feature: true do click_button 'Save changes' expect(page).to have_field 'project_name_edit', with: 'foo&bar' - expect(page).to have_content "Name can contain only letters, digits, '_', '.', dash and space. It must start with letter, digit or '_'." + expect(page).to have_content "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'." expect(page).to have_button 'Save changes' end end @@ -34,8 +34,21 @@ describe 'Edit Project Settings', feature: true do expect(page).to have_field 'Project name', with: 'foo&bar' expect(page).to have_field 'Path', with: 'foo&bar' - expect(page).to have_content "Name can contain only letters, digits, '_', '.', dash and space. It must start with letter, digit or '_'." + expect(page).to have_content "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'." expect(page).to have_content "Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'" end end + + describe 'Rename repository name with emojis' do + it 'shows error for invalid project name' do + visit edit_namespace_project_path(project.namespace, project) + + fill_in 'Project name', with: '🚀 foo bar ☁️' + + click_button 'Rename project' + + expect(page).to have_field 'Project name', with: '🚀 foo bar ☁️' + expect(page).not_to have_content "Name can contain only letters, digits, emojis '_', '.', dash and space. It must start with letter, digit, emoji or '_'." + end + end end -- cgit v1.2.1 From 5c966f70fb218d6f4de0f888733604293f36c33e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rebeca=20M=C3=A9ndez?= Date: Mon, 29 Aug 2016 17:23:40 +0200 Subject: Issue #4270: Recursive option for files through API --- spec/requests/api/repositories_spec.rb | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index c4dc2d9006a..38c8ad34f9d 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -18,6 +18,7 @@ describe API::API, api: true do it "returns project commits" do get api("/projects/#{project.id}/repository/tree", user) + expect(response).to have_http_status(200) expect(json_response).to be_an Array @@ -43,6 +44,40 @@ describe API::API, api: true do end end + + describe 'GET /projects/:id/repository/tree?recursive=1' do + context 'authorized user' do + before { project.team << [user2, :reporter] } + + it 'should return recursive project paths tree' do + get api("/projects/#{project.id}/repository/tree?recursive=1", user) + + expect(response.status).to eq(200) + + expect(json_response).to be_an Array + expect(json_response[4]['name']).to eq('html') + expect(json_response[4]['path']).to eq('files/html') + expect(json_response[4]['type']).to eq('tree') + expect(json_response[4]['mode']).to eq('040000') + end + + it 'returns a 404 for unknown ref' do + get api("/projects/#{project.id}/repository/tree?ref_name=foo&recursive=1", user) + expect(response).to have_http_status(404) + + expect(json_response).to be_an Object + json_response['message'] == '404 Tree Not Found' + end + end + + context "unauthorized user" do + it "does not return project commits" do + get api("/projects/#{project.id}/repository/tree?recursive=1") + expect(response).to have_http_status(401) + end + end + end + describe "GET /projects/:id/repository/blobs/:sha" do it "gets the raw file contents" do get api("/projects/#{project.id}/repository/blobs/master?filepath=README.md", user) -- cgit v1.2.1 From b99282804d682251928f932812068513f4061abb Mon Sep 17 00:00:00 2001 From: Fu Xu Date: Thu, 10 Nov 2016 13:57:46 +0800 Subject: fix error links in help page --- spec/controllers/help_controller_spec.rb | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'spec') diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb index 33c75e7584f..6fc6ea95e13 100644 --- a/spec/controllers/help_controller_spec.rb +++ b/spec/controllers/help_controller_spec.rb @@ -7,6 +7,40 @@ describe HelpController do sign_in(user) end + describe 'GET #index' do + context 'when url prefixed without /help/' do + it 'has correct url prefix' do + stub_readme("[API](api/README.md)") + get :index + expect(assigns[:help_index]).to eq '[API](/help/api/README.md)' + end + end + + context 'when url prefixed with help/' do + it 'will be an absolute path' do + stub_readme("[API](help/api/README.md)") + get :index + expect(assigns[:help_index]).to eq '[API](/help/api/README.md)' + end + end + + context 'when url prefixed with help' do + it 'will be an absolute path' do + stub_readme("[API](helpful_hints/README.md)") + get :index + expect(assigns[:help_index]).to eq '[API](/help/helpful_hints/README.md)' + end + end + + context 'when url prefixed with /help/' do + it 'will not be changed' do + stub_readme("[API](/help/api/README.md)") + get :index + expect(assigns[:help_index]).to eq '[API](/help/api/README.md)' + end + end + end + describe 'GET #show' do context 'for Markdown formats' do context 'when requested file exists' do @@ -72,4 +106,8 @@ describe HelpController do end end end + + def stub_readme(content) + allow(File).to receive(:read).and_return(content) + end end -- cgit v1.2.1 From d04961a2353c31eb80fe4431f01065a6f65b214a Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Sat, 12 Nov 2016 18:22:39 +0100 Subject: add blank line --- spec/models/project_services/jira_service_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index ed5abcf7fc0..af58d041260 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -112,6 +112,7 @@ describe JiraService, models: true do stub_config_setting(url: custom_base_url) @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) + expect(WebMock).to have_requested(:post, @comment_url).with( body: /#{custom_base_url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/ ).once -- cgit v1.2.1 From 7cc9d0f3b12a4eb2d5809558a88b3a6e989c47d9 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Sat, 12 Nov 2016 18:29:28 +0100 Subject: stub not needed --- spec/models/project_services/jira_service_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index af58d041260..2a87a411e9d 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -109,7 +109,6 @@ describe JiraService, models: true do it "references the GitLab commit/merge request" do stub_config_setting(base_url: custom_base_url) - stub_config_setting(url: custom_base_url) @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) -- cgit v1.2.1 From f080cb53160d7354fde017aabb834ab7d80bf574 Mon Sep 17 00:00:00 2001 From: Earth Date: Sun, 13 Nov 2016 02:59:43 +0300 Subject: Add a unit test for redirecting to sign-in page when user is not logged in and user visits the new fork page --- spec/controllers/projects/forks_controller_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index ac3469cb8a9..11ae425a76e 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -67,4 +67,19 @@ describe Projects::ForksController do end end end + + describe 'GET new' do + context 'when user is not logged in' do + + it 'redirects to the sign-in page' do + sign_out(user) + + get :new, + namespace_id: project.namespace.to_param, + project_id: project.to_param + + expect(response).to redirect_to(root_path + 'users/sign_in') + end + end + end end -- cgit v1.2.1 From 2c55d8167b32cb997a1f579df26ff52535455545 Mon Sep 17 00:00:00 2001 From: Earth Date: Sun, 13 Nov 2016 03:05:26 +0300 Subject: Replace tabs with spaces --- spec/controllers/projects/forks_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index 11ae425a76e..2bce652f4c5 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -75,7 +75,7 @@ describe Projects::ForksController do sign_out(user) get :new, - namespace_id: project.namespace.to_param, + namespace_id: project.namespace.to_param, project_id: project.to_param expect(response).to redirect_to(root_path + 'users/sign_in') -- cgit v1.2.1 From 37cad72970c1e75f9c63425bba780d7bfe554b95 Mon Sep 17 00:00:00 2001 From: Cagdas Gerede Date: Sun, 13 Nov 2016 03:12:35 +0300 Subject: Move sign_out out of it into before --- spec/controllers/projects/forks_controller_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index 2bce652f4c5..d29404e4a11 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -70,10 +70,9 @@ describe Projects::ForksController do describe 'GET new' do context 'when user is not logged in' do + before { sign_out(user) } it 'redirects to the sign-in page' do - sign_out(user) - get :new, namespace_id: project.namespace.to_param, project_id: project.to_param -- cgit v1.2.1 From c70146839009397b3a1a9ab9bd1108db3cb70c04 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 14 Nov 2016 10:31:45 +0100 Subject: Improve naming convention in ci configuration module --- spec/lib/gitlab/ci/config/entry/artifacts_spec.rb | 45 ++++ .../gitlab/ci/config/entry/attributable_spec.rb | 43 +++ spec/lib/gitlab/ci/config/entry/boolean_spec.rb | 34 +++ spec/lib/gitlab/ci/config/entry/cache_spec.rb | 60 +++++ spec/lib/gitlab/ci/config/entry/commands_spec.rb | 49 ++++ .../gitlab/ci/config/entry/configurable_spec.rb | 67 +++++ .../lib/gitlab/ci/config/entry/environment_spec.rb | 217 +++++++++++++++ spec/lib/gitlab/ci/config/entry/factory_spec.rb | 87 ++++++ spec/lib/gitlab/ci/config/entry/global_spec.rb | 299 +++++++++++++++++++++ spec/lib/gitlab/ci/config/entry/hidden_spec.rb | 47 ++++ spec/lib/gitlab/ci/config/entry/image_spec.rb | 46 ++++ spec/lib/gitlab/ci/config/entry/job_spec.rb | 140 ++++++++++ spec/lib/gitlab/ci/config/entry/jobs_spec.rb | 89 ++++++ spec/lib/gitlab/ci/config/entry/key_spec.rb | 34 +++ spec/lib/gitlab/ci/config/entry/paths_spec.rb | 34 +++ spec/lib/gitlab/ci/config/entry/script_spec.rb | 46 ++++ spec/lib/gitlab/ci/config/entry/services_spec.rb | 40 +++ spec/lib/gitlab/ci/config/entry/stage_spec.rb | 38 +++ spec/lib/gitlab/ci/config/entry/stages_spec.rb | 46 ++++ spec/lib/gitlab/ci/config/entry/trigger_spec.rb | 56 ++++ spec/lib/gitlab/ci/config/entry/undefined_spec.rb | 41 +++ .../lib/gitlab/ci/config/entry/unspecified_spec.rb | 32 +++ .../lib/gitlab/ci/config/entry/validatable_spec.rb | 54 ++++ spec/lib/gitlab/ci/config/entry/validator_spec.rb | 55 ++++ spec/lib/gitlab/ci/config/entry/variables_spec.rb | 48 ++++ spec/lib/gitlab/ci/config/node/artifacts_spec.rb | 45 ---- .../lib/gitlab/ci/config/node/attributable_spec.rb | 43 --- spec/lib/gitlab/ci/config/node/boolean_spec.rb | 34 --- spec/lib/gitlab/ci/config/node/cache_spec.rb | 60 ----- spec/lib/gitlab/ci/config/node/commands_spec.rb | 49 ---- .../lib/gitlab/ci/config/node/configurable_spec.rb | 67 ----- spec/lib/gitlab/ci/config/node/environment_spec.rb | 217 --------------- spec/lib/gitlab/ci/config/node/factory_spec.rb | 87 ------ spec/lib/gitlab/ci/config/node/global_spec.rb | 299 --------------------- spec/lib/gitlab/ci/config/node/hidden_spec.rb | 47 ---- spec/lib/gitlab/ci/config/node/image_spec.rb | 46 ---- spec/lib/gitlab/ci/config/node/job_spec.rb | 140 ---------- spec/lib/gitlab/ci/config/node/jobs_spec.rb | 89 ------ spec/lib/gitlab/ci/config/node/key_spec.rb | 34 --- spec/lib/gitlab/ci/config/node/paths_spec.rb | 34 --- spec/lib/gitlab/ci/config/node/script_spec.rb | 46 ---- spec/lib/gitlab/ci/config/node/services_spec.rb | 40 --- spec/lib/gitlab/ci/config/node/stage_spec.rb | 38 --- spec/lib/gitlab/ci/config/node/stages_spec.rb | 46 ---- spec/lib/gitlab/ci/config/node/trigger_spec.rb | 56 ---- spec/lib/gitlab/ci/config/node/undefined_spec.rb | 41 --- spec/lib/gitlab/ci/config/node/unspecified_spec.rb | 32 --- spec/lib/gitlab/ci/config/node/validatable_spec.rb | 54 ---- spec/lib/gitlab/ci/config/node/validator_spec.rb | 55 ---- spec/lib/gitlab/ci/config/node/variables_spec.rb | 48 ---- 50 files changed, 1747 insertions(+), 1747 deletions(-) create mode 100644 spec/lib/gitlab/ci/config/entry/artifacts_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/attributable_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/boolean_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/cache_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/commands_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/configurable_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/environment_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/factory_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/global_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/hidden_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/image_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/job_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/jobs_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/key_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/paths_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/script_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/services_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/stage_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/stages_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/trigger_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/undefined_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/unspecified_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/validatable_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/validator_spec.rb create mode 100644 spec/lib/gitlab/ci/config/entry/variables_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/artifacts_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/attributable_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/boolean_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/cache_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/commands_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/configurable_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/environment_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/factory_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/global_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/hidden_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/image_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/job_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/jobs_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/key_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/paths_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/script_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/services_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/stage_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/stages_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/trigger_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/undefined_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/unspecified_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/validatable_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/validator_spec.rb delete mode 100644 spec/lib/gitlab/ci/config/node/variables_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb new file mode 100644 index 00000000000..5c31423fdee --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Artifacts do + let(:entry) { described_class.new(config) } + + describe 'validation' do + context 'when entry config value is correct' do + let(:config) { { paths: %w[public/] } } + + describe '#value' do + it 'returns artifacs configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'when value of attribute is invalid' do + let(:config) { { name: 10 } } + + it 'reports error' do + expect(entry.errors) + .to include 'artifacts name should be a string' + end + end + + context 'when there is an unknown key present' do + let(:config) { { test: 100 } } + + it 'reports error' do + expect(entry.errors) + .to include 'artifacts config contains unknown keys: test' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/attributable_spec.rb b/spec/lib/gitlab/ci/config/entry/attributable_spec.rb new file mode 100644 index 00000000000..fde03c51e2c --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/attributable_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Attributable do + let(:node) { Class.new } + let(:instance) { node.new } + + before do + node.include(described_class) + + node.class_eval do + attributes :name, :test + end + end + + context 'config is a hash' do + before do + allow(instance) + .to receive(:config) + .and_return({ name: 'some name', test: 'some test' }) + end + + it 'returns the value of config' do + expect(instance.name).to eq 'some name' + expect(instance.test).to eq 'some test' + end + + it 'returns no method error for unknown attributes' do + expect { instance.unknown }.to raise_error(NoMethodError) + end + end + + context 'config is not a hash' do + before do + allow(instance) + .to receive(:config) + .and_return('some test') + end + + it 'returns nil' do + expect(instance.test).to be_nil + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/boolean_spec.rb b/spec/lib/gitlab/ci/config/entry/boolean_spec.rb new file mode 100644 index 00000000000..5f067cad93c --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/boolean_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Boolean do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is valid' do + let(:config) { false } + + describe '#value' do + it 'returns key value' do + expect(entry.value).to eq false + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not valid' do + let(:config) { ['incorrect'] } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'boolean config should be a boolean value' + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/cache_spec.rb b/spec/lib/gitlab/ci/config/entry/cache_spec.rb new file mode 100644 index 00000000000..70a327c5183 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/cache_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Cache do + let(:entry) { described_class.new(config) } + + describe 'validations' do + before { entry.compose! } + + context 'when entry config value is correct' do + let(:config) do + { key: 'some key', + untracked: true, + paths: ['some/path/'] } + end + + describe '#value' do + it 'returns hash value' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'when is not a hash' do + let(:config) { 'ls' } + + it 'reports errors with config value' do + expect(entry.errors) + .to include 'cache config should be a hash' + end + end + + context 'when descendants are invalid' do + let(:config) { { key: 1 } } + + it 'reports error with descendants' do + expect(entry.errors) + .to include 'key config should be a string or symbol' + end + end + + context 'when there is an unknown key present' do + let(:config) { { invalid: true } } + + it 'reports error with descendants' do + expect(entry.errors) + .to include 'cache config contains unknown keys: invalid' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/commands_spec.rb b/spec/lib/gitlab/ci/config/entry/commands_spec.rb new file mode 100644 index 00000000000..b8b0825a1c7 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/commands_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Commands do + let(:entry) { described_class.new(config) } + + context 'when entry config value is an array' do + let(:config) { ['ls', 'pwd'] } + + describe '#value' do + it 'returns array of strings' do + expect(entry.value).to eq config + end + end + + describe '#errors' do + it 'does not append errors' do + expect(entry.errors).to be_empty + end + end + end + + context 'when entry config value is a string' do + let(:config) { 'ls' } + + describe '#value' do + it 'returns array with single element' do + expect(entry.value).to eq ['ls'] + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not valid' do + let(:config) { 1 } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'commands config should be a ' \ + 'string or an array of strings' + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb new file mode 100644 index 00000000000..aff70ab6751 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Configurable do + let(:entry) { Class.new } + + before do + entry.include(described_class) + end + + describe 'validations' do + let(:validator) { entry.validator.new(instance) } + + before do + entry.class_eval do + attr_reader :config + + def initialize(config) + @config = config + end + end + + validator.validate + end + + context 'when entry validator is invalid' do + let(:instance) { entry.new('ls') } + + it 'returns invalid validator' do + expect(validator).to be_invalid + end + end + + context 'when entry instance is valid' do + let(:instance) { entry.new(key: 'value') } + + it 'returns valid validator' do + expect(validator).to be_valid + end + end + end + + describe 'configured nodes' do + before do + entry.class_eval do + node :object, Object, description: 'test object' + end + end + + describe '.nodes' do + it 'has valid nodes' do + expect(entry.nodes).to include :object + end + + it 'creates a node factory' do + expect(entry.nodes[:object]) + .to be_an_instance_of Gitlab::Ci::Config::Entry::Factory + end + + it 'returns a duplicated factory object' do + first_factory = entry.nodes[:object] + second_factory = entry.nodes[:object] + + expect(first_factory).not_to be_equal(second_factory) + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/environment_spec.rb b/spec/lib/gitlab/ci/config/entry/environment_spec.rb new file mode 100644 index 00000000000..d97806295fb --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/environment_spec.rb @@ -0,0 +1,217 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Environment do + let(:entry) { described_class.new(config) } + + before { entry.compose! } + + context 'when configuration is a string' do + let(:config) { 'production' } + + describe '#string?' do + it 'is string configuration' do + expect(entry).to be_string + end + end + + describe '#hash?' do + it 'is not hash configuration' do + expect(entry).not_to be_hash + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to include(name: 'production') + end + end + + describe '#name' do + it 'returns environment name' do + expect(entry.name).to eq 'production' + end + end + + describe '#url' do + it 'returns environment url' do + expect(entry.url).to be_nil + end + end + end + + context 'when configuration is a hash' do + let(:config) do + { name: 'development', url: 'https://example.gitlab.com' } + end + + describe '#string?' do + it 'is not string configuration' do + expect(entry).not_to be_string + end + end + + describe '#hash?' do + it 'is hash configuration' do + expect(entry).to be_hash + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns valid hash' do + expect(entry.value).to eq config + end + end + + describe '#name' do + it 'returns environment name' do + expect(entry.name).to eq 'development' + end + end + + describe '#url' do + it 'returns environment url' do + expect(entry.url).to eq 'https://example.gitlab.com' + end + end + end + + context 'when valid action is used' do + let(:config) do + { name: 'production', + action: 'start' } + end + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when invalid action is used' do + let(:config) do + { name: 'production', + action: 'invalid' } + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'contains error about invalid action' do + expect(entry.errors) + .to include 'environment action should be start or stop' + end + end + end + + context 'when on_stop is used' do + let(:config) do + { name: 'production', + on_stop: 'close_app' } + end + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when invalid on_stop is used' do + let(:config) do + { name: 'production', + on_stop: false } + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'contains error about invalid action' do + expect(entry.errors) + .to include 'environment on stop should be a string' + end + end + end + + context 'when variables are used for environment' do + let(:config) do + { name: 'review/$CI_BUILD_REF_NAME', + url: 'https://$CI_BUILD_REF_NAME.review.gitlab.com' } + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when configuration is invalid' do + context 'when configuration is an array' do + let(:config) { ['env'] } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors' do + it 'contains error about invalid type' do + expect(entry.errors) + .to include 'environment config should be a hash or a string' + end + end + end + + context 'when environment name is not present' do + let(:config) { { url: 'https://example.gitlab.com' } } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors?' do + it 'contains error about missing environment name' do + expect(entry.errors) + .to include "environment name can't be blank" + end + end + end + + context 'when invalid URL is used' do + let(:config) { { name: 'test', url: 'invalid-example.gitlab.com' } } + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + + describe '#errors?' do + it 'contains error about invalid URL' do + expect(entry.errors) + .to include "environment url must be a valid url" + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/factory_spec.rb b/spec/lib/gitlab/ci/config/entry/factory_spec.rb new file mode 100644 index 00000000000..00dad5d9591 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/factory_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Factory do + describe '#create!' do + let(:factory) { described_class.new(entry) } + let(:entry) { Gitlab::Ci::Config::Entry::Script } + + context 'when setting a concrete value' do + it 'creates entry with valid value' do + entry = factory + .value(['ls', 'pwd']) + .create! + + expect(entry.value).to eq ['ls', 'pwd'] + end + + context 'when setting description' do + it 'creates entry with description' do + entry = factory + .value(['ls', 'pwd']) + .with(description: 'test description') + .create! + + expect(entry.value).to eq ['ls', 'pwd'] + expect(entry.description).to eq 'test description' + end + end + + context 'when setting key' do + it 'creates entry with custom key' do + entry = factory + .value(['ls', 'pwd']) + .with(key: 'test key') + .create! + + expect(entry.key).to eq 'test key' + end + end + + context 'when setting a parent' do + let(:object) { Object.new } + + it 'creates entry with valid parent' do + entry = factory + .value('ls') + .with(parent: object) + .create! + + expect(entry.parent).to eq object + end + end + end + + context 'when not setting a value' do + it 'raises error' do + expect { factory.create! }.to raise_error( + Gitlab::Ci::Config::Entry::Factory::InvalidFactory + ) + end + end + + context 'when creating entry with nil value' do + it 'creates an undefined entry' do + entry = factory + .value(nil) + .create! + + expect(entry) + .to be_an_instance_of Gitlab::Ci::Config::Entry::Unspecified + end + end + + context 'when passing metadata' do + let(:entry) { spy('entry') } + + it 'passes metadata as a parameter' do + factory + .value('some value') + .metadata(some: 'hash') + .create! + + expect(entry).to have_received(:new) + .with('some value', { some: 'hash' }) + 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 new file mode 100644 index 00000000000..c7726adfd27 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -0,0 +1,299 @@ +require 'spec_helper' + +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 + end + + it 'returns a hash' do + expect(described_class.nodes).to be_a Hash + end + end + + context 'when hash is valid' do + context 'when some entries defined' do + let(:hash) do + { before_script: ['ls', 'pwd'], + image: 'ruby:2.2', + services: ['postgres:9.1', 'mysql:5.5'], + variables: { VAR: 'value' }, + after_script: ['make clean'], + stages: ['build', 'pages'], + cache: { key: 'k', untracked: true, paths: ['public/'] }, + rspec: { script: %w[rspec ls] }, + spinach: { before_script: [], variables: {}, script: 'spinach' } } + end + + describe '#compose!' do + before { global.compose! } + + it 'creates nodes hash' do + expect(global.descendants).to be_an Array + end + + it 'creates node object for each entry' do + expect(global.descendants.count).to eq 8 + end + + it 'creates node object using valid class' do + expect(global.descendants.first) + .to be_an_instance_of Gitlab::Ci::Config::Entry::Script + expect(global.descendants.second) + .to be_an_instance_of Gitlab::Ci::Config::Entry::Image + end + + it 'sets correct description for nodes' do + expect(global.descendants.first.description) + .to eq 'Script that will be executed before each job.' + expect(global.descendants.second.description) + .to eq 'Docker image that will be used to execute jobs.' + end + + describe '#leaf?' do + it 'is not leaf' do + expect(global).not_to be_leaf + end + end + end + + context 'when not composed' do + describe '#before_script' do + it 'returns nil' do + expect(global.before_script).to be nil + end + end + + describe '#leaf?' do + it 'is leaf' do + expect(global).to be_leaf + end + end + end + + context 'when composed' do + before { global.compose! } + + describe '#errors' do + it 'has no errors' do + expect(global.errors).to be_empty + end + end + + describe '#before_script' do + it 'returns correct script' do + expect(global.before_script).to eq ['ls', 'pwd'] + end + end + + describe '#image' do + it 'returns valid image' do + expect(global.image).to eq 'ruby:2.2' + end + end + + describe '#services' do + it 'returns array of services' do + expect(global.services).to eq ['postgres:9.1', 'mysql:5.5'] + end + end + + describe '#after_script' do + it 'returns after script' do + expect(global.after_script).to eq ['make clean'] + end + end + + describe '#variables' do + it 'returns variables' do + expect(global.variables).to eq(VAR: 'value') + end + end + + describe '#stages' do + context 'when stages key defined' do + it 'returns array of stages' do + expect(global.stages).to eq %w[build pages] + end + end + + context 'when deprecated types key defined' do + let(:hash) do + { types: ['test', 'deploy'], + rspec: { script: 'rspec' } } + end + + it 'returns array of types as stages' do + expect(global.stages).to eq %w[test deploy] + end + end + end + + describe '#cache' do + it 'returns cache configuration' do + expect(global.cache) + .to eq(key: 'k', untracked: true, paths: ['public/']) + end + end + + describe '#jobs' do + it 'returns jobs configuration' do + expect(global.jobs).to eq( + rspec: { name: :rspec, + script: %w[rspec ls], + before_script: ['ls', 'pwd'], + commands: "ls\npwd\nrspec\nls", + image: 'ruby:2.2', + services: ['postgres:9.1', 'mysql:5.5'], + stage: 'test', + cache: { key: 'k', untracked: true, paths: ['public/'] }, + variables: { VAR: 'value' }, + after_script: ['make clean'] }, + spinach: { name: :spinach, + before_script: [], + script: %w[spinach], + commands: 'spinach', + image: 'ruby:2.2', + services: ['postgres:9.1', 'mysql:5.5'], + stage: 'test', + cache: { key: 'k', untracked: true, paths: ['public/'] }, + variables: {}, + after_script: ['make clean'] }, + ) + end + end + end + end + + context 'when most of entires not defined' do + before { global.compose! } + + let(:hash) do + { cache: { key: 'a' }, rspec: { script: %w[ls] } } + end + + describe '#nodes' do + it 'instantizes all nodes' do + expect(global.descendants.count).to eq 8 + end + + it 'contains unspecified nodes' do + expect(global.descendants.first) + .to be_an_instance_of Gitlab::Ci::Config::Entry::Unspecified + end + end + + describe '#variables' do + it 'returns default value for variables' do + expect(global.variables).to eq({}) + end + end + + describe '#stages' do + it 'returns an array of default stages' do + expect(global.stages).to eq %w[build test deploy] + end + end + + describe '#cache' do + it 'returns correct cache definition' do + expect(global.cache).to eq(key: 'a') + end + end + end + + ## + # When nodes are specified but not defined, we assume that + # configuration is valid, and we asume that entry is simply undefined, + # despite the fact, that key is present. See issue #18775 for more + # details. + # + context 'when entires specified but not defined' do + before { global.compose! } + + let(:hash) do + { variables: nil, rspec: { script: 'rspec' } } + end + + describe '#variables' do + it 'undefined entry returns a default value' do + expect(global.variables).to eq({}) + end + end + end + end + + context 'when hash is not valid' do + before { global.compose! } + + let(:hash) do + { before_script: 'ls' } + end + + describe '#valid?' do + it 'is not valid' do + expect(global).not_to be_valid + end + end + + describe '#errors' do + it 'reports errors from child nodes' do + expect(global.errors) + .to include 'before_script config should be an array of strings' + end + end + + describe '#before_script' do + it 'returns nil' do + expect(global.before_script).to be_nil + end + end + end + + context 'when value is not a hash' do + let(:hash) { [] } + + describe '#valid?' do + it 'is not valid' do + expect(global).not_to be_valid + end + end + + describe '#errors' do + it 'returns error about invalid type' do + expect(global.errors.first).to match /should be a hash/ + end + end + end + + describe '#specified?' do + it 'is concrete entry that is defined' do + expect(global.specified?).to be true + end + end + + describe '#[]' do + before { global.compose! } + + let(:hash) do + { cache: { key: 'a' }, rspec: { script: 'ls' } } + end + + context 'when node exists' do + it 'returns correct entry' do + expect(global[:cache]) + .to be_an_instance_of Gitlab::Ci::Config::Entry::Cache + expect(global[:jobs][:rspec][:script].value).to eq ['ls'] + end + end + + context 'when node does not exist' do + it 'always return unspecified node' do + expect(global[:some][:unknown][:node]) + .not_to be_specified + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/hidden_spec.rb b/spec/lib/gitlab/ci/config/entry/hidden_spec.rb new file mode 100644 index 00000000000..459362761e6 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/hidden_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Hidden do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is correct' do + let(:config) { [:some, :array] } + + describe '#value' do + it 'returns key value' do + expect(entry.value).to eq [:some, :array] + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + context 'when config is empty' do + let(:config) { {} } + + describe '#valid' do + it 'is invalid' do + expect(entry).not_to be_valid + end + end + end + end + end + + describe '#leaf?' do + it 'is a leaf' do + expect(entry).to be_leaf + end + end + + describe '#relevant?' do + it 'is not a relevant entry' do + expect(entry).not_to be_relevant + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb new file mode 100644 index 00000000000..3c99cb0a1ee --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Image do + let(:entry) { described_class.new(config) } + + describe 'validation' do + context 'when entry config value is correct' do + let(:config) { 'ruby:2.2' } + + describe '#value' do + it 'returns image string' do + expect(entry.value).to eq 'ruby:2.2' + end + end + + describe '#errors' do + it 'does not append errors' do + expect(entry.errors).to be_empty + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + let(:config) { ['ruby:2.2'] } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'image config should be a string' + end + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb new file mode 100644 index 00000000000..c05711b6338 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -0,0 +1,140 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Job do + let(:entry) { described_class.new(config, name: :rspec) } + + describe 'validations' do + before { entry.compose! } + + context 'when entry config value is correct' do + let(:config) { { script: 'rspec' } } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when job name is empty' do + let(:entry) { described_class.new(config, name: ''.to_sym) } + + it 'reports error' do + expect(entry.errors) + .to include "job name can't be blank" + end + end + end + + context 'when entry value is not correct' do + context 'incorrect config value type' do + let(:config) { ['incorrect'] } + + describe '#errors' do + it 'reports error about a config type' do + expect(entry.errors) + .to include 'job config should be a hash' + end + end + end + + context 'when config is empty' do + let(:config) { {} } + + describe '#valid' do + it 'is invalid' do + expect(entry).not_to be_valid + end + end + end + + context 'when unknown keys detected' do + let(:config) { { unknown: true } } + + describe '#valid' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end + end + + describe '#relevant?' do + it 'is a relevant entry' do + expect(entry).to be_relevant + end + end + + describe '#compose!' do + let(:unspecified) { double('unspecified', 'specified?' => false) } + + let(:specified) do + double('specified', 'specified?' => true, value: 'specified') + end + + let(:deps) { double('deps', '[]' => unspecified) } + + context 'when job config overrides global config' do + before { entry.compose!(deps) } + + let(:config) do + { image: 'some_image', cache: { key: 'test' } } + end + + it 'overrides global config' do + expect(entry[:image].value).to eq 'some_image' + expect(entry[:cache].value).to eq(key: 'test') + end + end + + context 'when job config does not override global config' do + before do + allow(deps).to receive('[]').with(:image).and_return(specified) + entry.compose!(deps) + end + + let(:config) { { script: 'ls', cache: { key: 'test' } } } + + it 'uses config from global entry' do + expect(entry[:image].value).to eq 'specified' + expect(entry[:cache].value).to eq(key: 'test') + end + end + end + + context 'when composed' do + before { entry.compose! } + + describe '#value' do + before { entry.compose! } + + context 'when entry is correct' do + let(:config) do + { before_script: %w[ls pwd], + script: 'rspec', + after_script: %w[cleanup] } + end + + it 'returns correct value' do + expect(entry.value) + .to eq(name: :rspec, + before_script: %w[ls pwd], + script: %w[rspec], + commands: "ls\npwd\nrspec", + stage: 'test', + after_script: %w[cleanup]) + end + end + end + + describe '#commands' do + let(:config) do + { before_script: %w[ls pwd], script: 'rspec' } + end + + it 'returns a string of commands concatenated with new line character' do + expect(entry.commands).to eq "ls\npwd\nrspec" + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb new file mode 100644 index 00000000000..aaebf783962 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb @@ -0,0 +1,89 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Jobs do + let(:entry) { described_class.new(config) } + + describe 'validations' do + before { entry.compose! } + + context 'when entry config value is correct' do + let(:config) { { rspec: { script: 'rspec' } } } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'incorrect config value type' do + let(:config) { ['incorrect'] } + + it 'returns error about incorrect type' do + expect(entry.errors) + .to include 'jobs config should be a hash' + end + end + + context 'when job is unspecified' do + let(:config) { { rspec: nil } } + + it 'reports error' do + expect(entry.errors).to include "rspec config can't be blank" + end + end + + context 'when no visible jobs present' do + let(:config) { { '.hidden'.to_sym => { script: [] } } } + + it 'returns error about no visible jobs defined' do + expect(entry.errors) + .to include 'jobs config should contain at least one visible job' + end + end + end + end + end + + context 'when valid job entries composed' do + before { entry.compose! } + + let(:config) do + { rspec: { script: 'rspec' }, + spinach: { script: 'spinach' }, + '.hidden'.to_sym => {} } + end + + describe '#value' do + it 'returns key value' do + expect(entry.value).to eq( + rspec: { name: :rspec, + script: %w[rspec], + commands: 'rspec', + stage: 'test' }, + spinach: { name: :spinach, + script: %w[spinach], + commands: 'spinach', + stage: 'test' }) + end + end + + describe '#descendants' do + it 'creates valid descendant nodes' do + expect(entry.descendants.count).to eq 3 + expect(entry.descendants.first(2)) + .to all(be_an_instance_of(Gitlab::Ci::Config::Entry::Job)) + expect(entry.descendants.last) + .to be_an_instance_of(Gitlab::Ci::Config::Entry::Hidden) + end + end + + describe '#value' do + it 'returns value of visible jobs only' do + expect(entry.value.keys).to eq [:rspec, :spinach] + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/key_spec.rb b/spec/lib/gitlab/ci/config/entry/key_spec.rb new file mode 100644 index 00000000000..a55e5b4b8ac --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/key_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Key do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is correct' do + let(:config) { 'test' } + + describe '#value' do + it 'returns key value' do + expect(entry.value).to eq 'test' + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + let(:config) { [ 'incorrect' ] } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'key config should be a string or symbol' + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/paths_spec.rb b/spec/lib/gitlab/ci/config/entry/paths_spec.rb new file mode 100644 index 00000000000..e60c9aaf661 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/paths_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Paths do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is valid' do + let(:config) { ['some/file', 'some/path/'] } + + describe '#value' do + it 'returns key value' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not valid' do + let(:config) { [ 1 ] } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'paths config should be an array of strings' + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/script_spec.rb b/spec/lib/gitlab/ci/config/entry/script_spec.rb new file mode 100644 index 00000000000..aa99cee2690 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/script_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Script do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is correct' do + let(:config) { ['ls', 'pwd'] } + + describe '#value' do + it 'returns array of strings' do + expect(entry.value).to eq config + end + end + + describe '#errors' do + it 'does not append errors' do + expect(entry.errors).to be_empty + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + let(:config) { 'ls' } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'script config should be an array of strings' + end + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/services_spec.rb b/spec/lib/gitlab/ci/config/entry/services_spec.rb new file mode 100644 index 00000000000..66fad3b6b16 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/services_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Services do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is correct' do + let(:config) { ['postgres:9.1', 'mysql:5.5'] } + + describe '#value' do + it 'returns array of services as is' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + let(:config) { 'ls' } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'services config should be an array of strings' + end + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/stage_spec.rb b/spec/lib/gitlab/ci/config/entry/stage_spec.rb new file mode 100644 index 00000000000..70c8a0a355a --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/stage_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Stage do + let(:stage) { described_class.new(config) } + + describe 'validations' do + context 'when stage config value is correct' do + let(:config) { 'build' } + + describe '#value' do + it 'returns a stage key' do + expect(stage.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(stage).to be_valid + end + end + end + + context 'when value has a wrong type' do + let(:config) { { test: true } } + + it 'reports errors about wrong type' do + expect(stage.errors) + .to include 'stage config should be a string' + end + end + end + + describe '.default' do + it 'returns default stage' do + expect(described_class.default).to eq 'test' + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/stages_spec.rb b/spec/lib/gitlab/ci/config/entry/stages_spec.rb new file mode 100644 index 00000000000..182c8d867c7 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/stages_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Stages do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is correct' do + let(:config) { [:stage1, :stage2] } + + describe '#value' do + it 'returns array of stages' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + let(:config) { { test: true } } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'stages config should be an array of strings' + end + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end + + describe '.default' do + it 'returns default stages' do + expect(described_class.default).to eq %w[build test deploy] + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/trigger_spec.rb b/spec/lib/gitlab/ci/config/entry/trigger_spec.rb new file mode 100644 index 00000000000..e4ee44f1274 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/trigger_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Trigger do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is valid' do + context 'when config is a branch or tag name' do + let(:config) { %w[master feature/branch] } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + + describe '#value' do + it 'returns key value' do + expect(entry.value).to eq config + end + end + end + + context 'when config is a regexp' do + let(:config) { ['/^issue-.*$/'] } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when config is a special keyword' do + let(:config) { %w[tags triggers branches] } + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + end + + context 'when entry value is not valid' do + let(:config) { [1] } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include 'trigger config should be an array of strings or regexps' + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/undefined_spec.rb b/spec/lib/gitlab/ci/config/entry/undefined_spec.rb new file mode 100644 index 00000000000..fdf48d84192 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/undefined_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Undefined do + let(:entry) { described_class.new } + + describe '#leaf?' do + it 'is leaf node' do + expect(entry).to be_leaf + end + end + + describe '#valid?' do + it 'is always valid' do + expect(entry).to be_valid + end + end + + describe '#errors' do + it 'is does not contain errors' do + expect(entry.errors).to be_empty + end + end + + describe '#value' do + it 'returns nil' do + expect(entry.value).to eq nil + end + end + + describe '#relevant?' do + it 'is not relevant' do + expect(entry.relevant?).to eq false + end + end + + describe '#specified?' do + it 'is not defined' do + expect(entry.specified?).to eq false + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/unspecified_spec.rb b/spec/lib/gitlab/ci/config/entry/unspecified_spec.rb new file mode 100644 index 00000000000..66f88fa35b6 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/unspecified_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Unspecified do + let(:unspecified) { described_class.new(entry) } + let(:entry) { spy('Entry') } + + describe '#valid?' do + it 'delegates method to entry' do + expect(unspecified.valid?).to eq entry + end + end + + describe '#errors' do + it 'delegates method to entry' do + expect(unspecified.errors).to eq entry + end + end + + describe '#value' do + it 'delegates method to entry' do + expect(unspecified.value).to eq entry + end + end + + describe '#specified?' do + it 'is always false' do + allow(entry).to receive(:specified?).and_return(true) + + expect(unspecified.specified?).to be false + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/validatable_spec.rb b/spec/lib/gitlab/ci/config/entry/validatable_spec.rb new file mode 100644 index 00000000000..d1856801827 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/validatable_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Validatable do + let(:entry) { Class.new } + + before do + entry.include(described_class) + end + + describe '.validator' do + before do + entry.class_eval do + attr_accessor :test_attribute + + validations do + validates :test_attribute, presence: true + end + end + end + + it 'returns validator' do + expect(entry.validator.superclass) + .to be Gitlab::Ci::Config::Entry::Validator + end + + it 'returns only one validator to mitigate leaks' do + expect { entry.validator }.not_to change { entry.validator } + end + + context 'when validating entry instance' do + let(:entry_instance) { entry.new } + + context 'when attribute is valid' do + before do + entry_instance.test_attribute = 'valid' + end + + it 'instance of validator is valid' do + expect(entry.validator.new(entry_instance)).to be_valid + end + end + + context 'when attribute is not valid' do + before do + entry_instance.test_attribute = nil + end + + it 'instance of validator is invalid' do + expect(entry.validator.new(entry_instance)).to be_invalid + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/validator_spec.rb b/spec/lib/gitlab/ci/config/entry/validator_spec.rb new file mode 100644 index 00000000000..ad7e6f07d3c --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/validator_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Validator do + let(:validator) { Class.new(described_class) } + let(:validator_instance) { validator.new(node) } + let(:node) { spy('node') } + + before do + allow(node).to receive(:key).and_return('node') + allow(node).to receive(:ancestors).and_return([]) + end + + describe 'delegated validator' do + before do + validator.class_eval do + validates :test_attribute, presence: true + end + end + + context 'when node is valid' do + before do + allow(node).to receive(:test_attribute).and_return('valid value') + end + + it 'validates attribute in node' do + expect(node).to receive(:test_attribute) + expect(validator_instance).to be_valid + end + + it 'returns no errors' do + validator_instance.validate + + expect(validator_instance.messages).to be_empty + end + end + + context 'when node is invalid' do + before do + allow(node).to receive(:test_attribute).and_return(nil) + end + + it 'validates attribute in node' do + expect(node).to receive(:test_attribute) + expect(validator_instance).to be_invalid + end + + it 'returns errors' do + validator_instance.validate + + expect(validator_instance.messages) + .to include "node test attribute can't be blank" + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb new file mode 100644 index 00000000000..58327d08904 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Variables do + let(:entry) { described_class.new(config) } + + describe 'validations' do + context 'when entry config value is correct' do + let(:config) do + { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } + end + + describe '#value' do + it 'returns hash with key value strings' do + expect(entry.value).to eq config + end + end + + describe '#errors' do + it 'does not append errors' do + expect(entry.errors).to be_empty + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + let(:config) { [ :VAR, 'test' ] } + + describe '#errors' do + it 'saves errors' do + expect(entry.errors) + .to include /should be a hash of key value pairs/ + end + end + + describe '#valid?' do + it 'is not valid' do + expect(entry).not_to be_valid + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/node/artifacts_spec.rb b/spec/lib/gitlab/ci/config/node/artifacts_spec.rb deleted file mode 100644 index c09a0a9c793..00000000000 --- a/spec/lib/gitlab/ci/config/node/artifacts_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Artifacts do - let(:entry) { described_class.new(config) } - - describe 'validation' do - context 'when entry config value is correct' do - let(:config) { { paths: %w[public/] } } - - describe '#value' do - it 'returns artifacs configuration' do - expect(entry.value).to eq config - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - describe '#errors' do - context 'when value of attribute is invalid' do - let(:config) { { name: 10 } } - - it 'reports error' do - expect(entry.errors) - .to include 'artifacts name should be a string' - end - end - - context 'when there is an unknown key present' do - let(:config) { { test: 100 } } - - it 'reports error' do - expect(entry.errors) - .to include 'artifacts config contains unknown keys: test' - end - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/attributable_spec.rb b/spec/lib/gitlab/ci/config/node/attributable_spec.rb deleted file mode 100644 index 24d9daafd88..00000000000 --- a/spec/lib/gitlab/ci/config/node/attributable_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Attributable do - let(:node) { Class.new } - let(:instance) { node.new } - - before do - node.include(described_class) - - node.class_eval do - attributes :name, :test - end - end - - context 'config is a hash' do - before do - allow(instance) - .to receive(:config) - .and_return({ name: 'some name', test: 'some test' }) - end - - it 'returns the value of config' do - expect(instance.name).to eq 'some name' - expect(instance.test).to eq 'some test' - end - - it 'returns no method error for unknown attributes' do - expect { instance.unknown }.to raise_error(NoMethodError) - end - end - - context 'config is not a hash' do - before do - allow(instance) - .to receive(:config) - .and_return('some test') - end - - it 'returns nil' do - expect(instance.test).to be_nil - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/boolean_spec.rb b/spec/lib/gitlab/ci/config/node/boolean_spec.rb deleted file mode 100644 index deafa8bf8a7..00000000000 --- a/spec/lib/gitlab/ci/config/node/boolean_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Boolean do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is valid' do - let(:config) { false } - - describe '#value' do - it 'returns key value' do - expect(entry.value).to eq false - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not valid' do - let(:config) { ['incorrect'] } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'boolean config should be a boolean value' - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/cache_spec.rb b/spec/lib/gitlab/ci/config/node/cache_spec.rb deleted file mode 100644 index e251210949c..00000000000 --- a/spec/lib/gitlab/ci/config/node/cache_spec.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Cache do - let(:entry) { described_class.new(config) } - - describe 'validations' do - before { entry.compose! } - - context 'when entry config value is correct' do - let(:config) do - { key: 'some key', - untracked: true, - paths: ['some/path/'] } - end - - describe '#value' do - it 'returns hash value' do - expect(entry.value).to eq config - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - describe '#errors' do - context 'when is not a hash' do - let(:config) { 'ls' } - - it 'reports errors with config value' do - expect(entry.errors) - .to include 'cache config should be a hash' - end - end - - context 'when descendants are invalid' do - let(:config) { { key: 1 } } - - it 'reports error with descendants' do - expect(entry.errors) - .to include 'key config should be a string or symbol' - end - end - - context 'when there is an unknown key present' do - let(:config) { { invalid: true } } - - it 'reports error with descendants' do - expect(entry.errors) - .to include 'cache config contains unknown keys: invalid' - end - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/commands_spec.rb b/spec/lib/gitlab/ci/config/node/commands_spec.rb deleted file mode 100644 index e373c40706f..00000000000 --- a/spec/lib/gitlab/ci/config/node/commands_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Commands do - let(:entry) { described_class.new(config) } - - context 'when entry config value is an array' do - let(:config) { ['ls', 'pwd'] } - - describe '#value' do - it 'returns array of strings' do - expect(entry.value).to eq config - end - end - - describe '#errors' do - it 'does not append errors' do - expect(entry.errors).to be_empty - end - end - end - - context 'when entry config value is a string' do - let(:config) { 'ls' } - - describe '#value' do - it 'returns array with single element' do - expect(entry.value).to eq ['ls'] - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not valid' do - let(:config) { 1 } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'commands config should be a ' \ - 'string or an array of strings' - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/configurable_spec.rb b/spec/lib/gitlab/ci/config/node/configurable_spec.rb deleted file mode 100644 index c468ecf957b..00000000000 --- a/spec/lib/gitlab/ci/config/node/configurable_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Configurable do - let(:node) { Class.new } - - before do - node.include(described_class) - end - - describe 'validations' do - let(:validator) { node.validator.new(instance) } - - before do - node.class_eval do - attr_reader :config - - def initialize(config) - @config = config - end - end - - validator.validate - end - - context 'when node validator is invalid' do - let(:instance) { node.new('ls') } - - it 'returns invalid validator' do - expect(validator).to be_invalid - end - end - - context 'when node instance is valid' do - let(:instance) { node.new(key: 'value') } - - it 'returns valid validator' do - expect(validator).to be_valid - end - end - end - - describe 'configured nodes' do - before do - node.class_eval do - node :object, Object, description: 'test object' - end - end - - describe '.nodes' do - it 'has valid nodes' do - expect(node.nodes).to include :object - end - - it 'creates a node factory' do - expect(node.nodes[:object]) - .to be_an_instance_of Gitlab::Ci::Config::Node::Factory - end - - it 'returns a duplicated factory object' do - first_factory = node.nodes[:object] - second_factory = node.nodes[:object] - - expect(first_factory).not_to be_equal(second_factory) - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/environment_spec.rb b/spec/lib/gitlab/ci/config/node/environment_spec.rb deleted file mode 100644 index df925ff1afd..00000000000 --- a/spec/lib/gitlab/ci/config/node/environment_spec.rb +++ /dev/null @@ -1,217 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Environment do - let(:entry) { described_class.new(config) } - - before { entry.compose! } - - context 'when configuration is a string' do - let(:config) { 'production' } - - describe '#string?' do - it 'is string configuration' do - expect(entry).to be_string - end - end - - describe '#hash?' do - it 'is not hash configuration' do - expect(entry).not_to be_hash - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - - describe '#value' do - it 'returns valid hash' do - expect(entry.value).to include(name: 'production') - end - end - - describe '#name' do - it 'returns environment name' do - expect(entry.name).to eq 'production' - end - end - - describe '#url' do - it 'returns environment url' do - expect(entry.url).to be_nil - end - end - end - - context 'when configuration is a hash' do - let(:config) do - { name: 'development', url: 'https://example.gitlab.com' } - end - - describe '#string?' do - it 'is not string configuration' do - expect(entry).not_to be_string - end - end - - describe '#hash?' do - it 'is hash configuration' do - expect(entry).to be_hash - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - - describe '#value' do - it 'returns valid hash' do - expect(entry.value).to eq config - end - end - - describe '#name' do - it 'returns environment name' do - expect(entry.name).to eq 'development' - end - end - - describe '#url' do - it 'returns environment url' do - expect(entry.url).to eq 'https://example.gitlab.com' - end - end - end - - context 'when valid action is used' do - let(:config) do - { name: 'production', - action: 'start' } - end - - it 'is valid' do - expect(entry).to be_valid - end - end - - context 'when invalid action is used' do - let(:config) do - { name: 'production', - action: 'invalid' } - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - - describe '#errors' do - it 'contains error about invalid action' do - expect(entry.errors) - .to include 'environment action should be start or stop' - end - end - end - - context 'when on_stop is used' do - let(:config) do - { name: 'production', - on_stop: 'close_app' } - end - - it 'is valid' do - expect(entry).to be_valid - end - end - - context 'when invalid on_stop is used' do - let(:config) do - { name: 'production', - on_stop: false } - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - - describe '#errors' do - it 'contains error about invalid action' do - expect(entry.errors) - .to include 'environment on stop should be a string' - end - end - end - - context 'when variables are used for environment' do - let(:config) do - { name: 'review/$CI_BUILD_REF_NAME', - url: 'https://$CI_BUILD_REF_NAME.review.gitlab.com' } - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when configuration is invalid' do - context 'when configuration is an array' do - let(:config) { ['env'] } - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - - describe '#errors' do - it 'contains error about invalid type' do - expect(entry.errors) - .to include 'environment config should be a hash or a string' - end - end - end - - context 'when environment name is not present' do - let(:config) { { url: 'https://example.gitlab.com' } } - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - - describe '#errors?' do - it 'contains error about missing environment name' do - expect(entry.errors) - .to include "environment name can't be blank" - end - end - end - - context 'when invalid URL is used' do - let(:config) { { name: 'test', url: 'invalid-example.gitlab.com' } } - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - - describe '#errors?' do - it 'contains error about invalid URL' do - expect(entry.errors) - .to include "environment url must be a valid url" - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/factory_spec.rb b/spec/lib/gitlab/ci/config/node/factory_spec.rb deleted file mode 100644 index a699089c563..00000000000 --- a/spec/lib/gitlab/ci/config/node/factory_spec.rb +++ /dev/null @@ -1,87 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Factory do - describe '#create!' do - let(:factory) { described_class.new(node) } - let(:node) { Gitlab::Ci::Config::Node::Script } - - context 'when setting a concrete value' do - it 'creates entry with valid value' do - entry = factory - .value(['ls', 'pwd']) - .create! - - expect(entry.value).to eq ['ls', 'pwd'] - end - - context 'when setting description' do - it 'creates entry with description' do - entry = factory - .value(['ls', 'pwd']) - .with(description: 'test description') - .create! - - expect(entry.value).to eq ['ls', 'pwd'] - expect(entry.description).to eq 'test description' - end - end - - context 'when setting key' do - it 'creates entry with custom key' do - entry = factory - .value(['ls', 'pwd']) - .with(key: 'test key') - .create! - - expect(entry.key).to eq 'test key' - end - end - - context 'when setting a parent' do - let(:object) { Object.new } - - it 'creates entry with valid parent' do - entry = factory - .value('ls') - .with(parent: object) - .create! - - expect(entry.parent).to eq object - end - end - end - - context 'when not setting a value' do - it 'raises error' do - expect { factory.create! }.to raise_error( - Gitlab::Ci::Config::Node::Factory::InvalidFactory - ) - end - end - - context 'when creating entry with nil value' do - it 'creates an undefined entry' do - entry = factory - .value(nil) - .create! - - expect(entry) - .to be_an_instance_of Gitlab::Ci::Config::Node::Unspecified - end - end - - context 'when passing metadata' do - let(:node) { spy('node') } - - it 'passes metadata as a parameter' do - factory - .value('some value') - .metadata(some: 'hash') - .create! - - expect(node).to have_received(:new) - .with('some value', { some: 'hash' }) - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/global_spec.rb b/spec/lib/gitlab/ci/config/node/global_spec.rb deleted file mode 100644 index 12232ff7e2f..00000000000 --- a/spec/lib/gitlab/ci/config/node/global_spec.rb +++ /dev/null @@ -1,299 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::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 - end - - it 'returns a hash' do - expect(described_class.nodes).to be_a Hash - end - end - - context 'when hash is valid' do - context 'when some entries defined' do - let(:hash) do - { before_script: ['ls', 'pwd'], - image: 'ruby:2.2', - services: ['postgres:9.1', 'mysql:5.5'], - variables: { VAR: 'value' }, - after_script: ['make clean'], - stages: ['build', 'pages'], - cache: { key: 'k', untracked: true, paths: ['public/'] }, - rspec: { script: %w[rspec ls] }, - spinach: { before_script: [], variables: {}, script: 'spinach' } } - end - - describe '#compose!' do - before { global.compose! } - - it 'creates nodes hash' do - expect(global.descendants).to be_an Array - end - - it 'creates node object for each entry' do - expect(global.descendants.count).to eq 8 - end - - it 'creates node object using valid class' do - expect(global.descendants.first) - .to be_an_instance_of Gitlab::Ci::Config::Node::Script - expect(global.descendants.second) - .to be_an_instance_of Gitlab::Ci::Config::Node::Image - end - - it 'sets correct description for nodes' do - expect(global.descendants.first.description) - .to eq 'Script that will be executed before each job.' - expect(global.descendants.second.description) - .to eq 'Docker image that will be used to execute jobs.' - end - - describe '#leaf?' do - it 'is not leaf' do - expect(global).not_to be_leaf - end - end - end - - context 'when not composed' do - describe '#before_script' do - it 'returns nil' do - expect(global.before_script).to be nil - end - end - - describe '#leaf?' do - it 'is leaf' do - expect(global).to be_leaf - end - end - end - - context 'when composed' do - before { global.compose! } - - describe '#errors' do - it 'has no errors' do - expect(global.errors).to be_empty - end - end - - describe '#before_script' do - it 'returns correct script' do - expect(global.before_script).to eq ['ls', 'pwd'] - end - end - - describe '#image' do - it 'returns valid image' do - expect(global.image).to eq 'ruby:2.2' - end - end - - describe '#services' do - it 'returns array of services' do - expect(global.services).to eq ['postgres:9.1', 'mysql:5.5'] - end - end - - describe '#after_script' do - it 'returns after script' do - expect(global.after_script).to eq ['make clean'] - end - end - - describe '#variables' do - it 'returns variables' do - expect(global.variables).to eq(VAR: 'value') - end - end - - describe '#stages' do - context 'when stages key defined' do - it 'returns array of stages' do - expect(global.stages).to eq %w[build pages] - end - end - - context 'when deprecated types key defined' do - let(:hash) do - { types: ['test', 'deploy'], - rspec: { script: 'rspec' } } - end - - it 'returns array of types as stages' do - expect(global.stages).to eq %w[test deploy] - end - end - end - - describe '#cache' do - it 'returns cache configuration' do - expect(global.cache) - .to eq(key: 'k', untracked: true, paths: ['public/']) - end - end - - describe '#jobs' do - it 'returns jobs configuration' do - expect(global.jobs).to eq( - rspec: { name: :rspec, - script: %w[rspec ls], - before_script: ['ls', 'pwd'], - commands: "ls\npwd\nrspec\nls", - image: 'ruby:2.2', - services: ['postgres:9.1', 'mysql:5.5'], - stage: 'test', - cache: { key: 'k', untracked: true, paths: ['public/'] }, - variables: { VAR: 'value' }, - after_script: ['make clean'] }, - spinach: { name: :spinach, - before_script: [], - script: %w[spinach], - commands: 'spinach', - image: 'ruby:2.2', - services: ['postgres:9.1', 'mysql:5.5'], - stage: 'test', - cache: { key: 'k', untracked: true, paths: ['public/'] }, - variables: {}, - after_script: ['make clean'] }, - ) - end - end - end - end - - context 'when most of entires not defined' do - before { global.compose! } - - let(:hash) do - { cache: { key: 'a' }, rspec: { script: %w[ls] } } - end - - describe '#nodes' do - it 'instantizes all nodes' do - expect(global.descendants.count).to eq 8 - end - - it 'contains unspecified nodes' do - expect(global.descendants.first) - .to be_an_instance_of Gitlab::Ci::Config::Node::Unspecified - end - end - - describe '#variables' do - it 'returns default value for variables' do - expect(global.variables).to eq({}) - end - end - - describe '#stages' do - it 'returns an array of default stages' do - expect(global.stages).to eq %w[build test deploy] - end - end - - describe '#cache' do - it 'returns correct cache definition' do - expect(global.cache).to eq(key: 'a') - end - end - end - - ## - # When nodes are specified but not defined, we assume that - # configuration is valid, and we asume that entry is simply undefined, - # despite the fact, that key is present. See issue #18775 for more - # details. - # - context 'when entires specified but not defined' do - before { global.compose! } - - let(:hash) do - { variables: nil, rspec: { script: 'rspec' } } - end - - describe '#variables' do - it 'undefined entry returns a default value' do - expect(global.variables).to eq({}) - end - end - end - end - - context 'when hash is not valid' do - before { global.compose! } - - let(:hash) do - { before_script: 'ls' } - end - - describe '#valid?' do - it 'is not valid' do - expect(global).not_to be_valid - end - end - - describe '#errors' do - it 'reports errors from child nodes' do - expect(global.errors) - .to include 'before_script config should be an array of strings' - end - end - - describe '#before_script' do - it 'returns nil' do - expect(global.before_script).to be_nil - end - end - end - - context 'when value is not a hash' do - let(:hash) { [] } - - describe '#valid?' do - it 'is not valid' do - expect(global).not_to be_valid - end - end - - describe '#errors' do - it 'returns error about invalid type' do - expect(global.errors.first).to match /should be a hash/ - end - end - end - - describe '#specified?' do - it 'is concrete entry that is defined' do - expect(global.specified?).to be true - end - end - - describe '#[]' do - before { global.compose! } - - let(:hash) do - { cache: { key: 'a' }, rspec: { script: 'ls' } } - end - - context 'when node exists' do - it 'returns correct entry' do - expect(global[:cache]) - .to be_an_instance_of Gitlab::Ci::Config::Node::Cache - expect(global[:jobs][:rspec][:script].value).to eq ['ls'] - end - end - - context 'when node does not exist' do - it 'always return unspecified node' do - expect(global[:some][:unknown][:node]) - .not_to be_specified - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/hidden_spec.rb b/spec/lib/gitlab/ci/config/node/hidden_spec.rb deleted file mode 100644 index 61e2a554419..00000000000 --- a/spec/lib/gitlab/ci/config/node/hidden_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Hidden do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is correct' do - let(:config) { [:some, :array] } - - describe '#value' do - it 'returns key value' do - expect(entry.value).to eq [:some, :array] - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - context 'when config is empty' do - let(:config) { {} } - - describe '#valid' do - it 'is invalid' do - expect(entry).not_to be_valid - end - end - end - end - end - - describe '#leaf?' do - it 'is a leaf' do - expect(entry).to be_leaf - end - end - - describe '#relevant?' do - it 'is not a relevant entry' do - expect(entry).not_to be_relevant - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/image_spec.rb b/spec/lib/gitlab/ci/config/node/image_spec.rb deleted file mode 100644 index d11bb39f328..00000000000 --- a/spec/lib/gitlab/ci/config/node/image_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Image do - let(:entry) { described_class.new(config) } - - describe 'validation' do - context 'when entry config value is correct' do - let(:config) { 'ruby:2.2' } - - describe '#value' do - it 'returns image string' do - expect(entry.value).to eq 'ruby:2.2' - end - end - - describe '#errors' do - it 'does not append errors' do - expect(entry.errors).to be_empty - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - let(:config) { ['ruby:2.2'] } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'image config should be a string' - end - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/job_spec.rb b/spec/lib/gitlab/ci/config/node/job_spec.rb deleted file mode 100644 index 91f676dae03..00000000000 --- a/spec/lib/gitlab/ci/config/node/job_spec.rb +++ /dev/null @@ -1,140 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Job do - let(:entry) { described_class.new(config, name: :rspec) } - - describe 'validations' do - before { entry.compose! } - - context 'when entry config value is correct' do - let(:config) { { script: 'rspec' } } - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - - context 'when job name is empty' do - let(:entry) { described_class.new(config, name: ''.to_sym) } - - it 'reports error' do - expect(entry.errors) - .to include "job name can't be blank" - end - end - end - - context 'when entry value is not correct' do - context 'incorrect config value type' do - let(:config) { ['incorrect'] } - - describe '#errors' do - it 'reports error about a config type' do - expect(entry.errors) - .to include 'job config should be a hash' - end - end - end - - context 'when config is empty' do - let(:config) { {} } - - describe '#valid' do - it 'is invalid' do - expect(entry).not_to be_valid - end - end - end - - context 'when unknown keys detected' do - let(:config) { { unknown: true } } - - describe '#valid' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - end - end - end - - describe '#relevant?' do - it 'is a relevant entry' do - expect(entry).to be_relevant - end - end - - describe '#compose!' do - let(:unspecified) { double('unspecified', 'specified?' => false) } - - let(:specified) do - double('specified', 'specified?' => true, value: 'specified') - end - - let(:deps) { double('deps', '[]' => unspecified) } - - context 'when job config overrides global config' do - before { entry.compose!(deps) } - - let(:config) do - { image: 'some_image', cache: { key: 'test' } } - end - - it 'overrides global config' do - expect(entry[:image].value).to eq 'some_image' - expect(entry[:cache].value).to eq(key: 'test') - end - end - - context 'when job config does not override global config' do - before do - allow(deps).to receive('[]').with(:image).and_return(specified) - entry.compose!(deps) - end - - let(:config) { { script: 'ls', cache: { key: 'test' } } } - - it 'uses config from global entry' do - expect(entry[:image].value).to eq 'specified' - expect(entry[:cache].value).to eq(key: 'test') - end - end - end - - context 'when composed' do - before { entry.compose! } - - describe '#value' do - before { entry.compose! } - - context 'when entry is correct' do - let(:config) do - { before_script: %w[ls pwd], - script: 'rspec', - after_script: %w[cleanup] } - end - - it 'returns correct value' do - expect(entry.value) - .to eq(name: :rspec, - before_script: %w[ls pwd], - script: %w[rspec], - commands: "ls\npwd\nrspec", - stage: 'test', - after_script: %w[cleanup]) - end - end - end - - describe '#commands' do - let(:config) do - { before_script: %w[ls pwd], script: 'rspec' } - end - - it 'returns a string of commands concatenated with new line character' do - expect(entry.commands).to eq "ls\npwd\nrspec" - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/jobs_spec.rb b/spec/lib/gitlab/ci/config/node/jobs_spec.rb deleted file mode 100644 index 929809339ef..00000000000 --- a/spec/lib/gitlab/ci/config/node/jobs_spec.rb +++ /dev/null @@ -1,89 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Jobs do - let(:entry) { described_class.new(config) } - - describe 'validations' do - before { entry.compose! } - - context 'when entry config value is correct' do - let(:config) { { rspec: { script: 'rspec' } } } - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - describe '#errors' do - context 'incorrect config value type' do - let(:config) { ['incorrect'] } - - it 'returns error about incorrect type' do - expect(entry.errors) - .to include 'jobs config should be a hash' - end - end - - context 'when job is unspecified' do - let(:config) { { rspec: nil } } - - it 'reports error' do - expect(entry.errors).to include "rspec config can't be blank" - end - end - - context 'when no visible jobs present' do - let(:config) { { '.hidden'.to_sym => { script: [] } } } - - it 'returns error about no visible jobs defined' do - expect(entry.errors) - .to include 'jobs config should contain at least one visible job' - end - end - end - end - end - - context 'when valid job entries composed' do - before { entry.compose! } - - let(:config) do - { rspec: { script: 'rspec' }, - spinach: { script: 'spinach' }, - '.hidden'.to_sym => {} } - end - - describe '#value' do - it 'returns key value' do - expect(entry.value).to eq( - rspec: { name: :rspec, - script: %w[rspec], - commands: 'rspec', - stage: 'test' }, - spinach: { name: :spinach, - script: %w[spinach], - commands: 'spinach', - stage: 'test' }) - end - end - - describe '#descendants' do - it 'creates valid descendant nodes' do - expect(entry.descendants.count).to eq 3 - expect(entry.descendants.first(2)) - .to all(be_an_instance_of(Gitlab::Ci::Config::Node::Job)) - expect(entry.descendants.last) - .to be_an_instance_of(Gitlab::Ci::Config::Node::Hidden) - end - end - - describe '#value' do - it 'returns value of visible jobs only' do - expect(entry.value.keys).to eq [:rspec, :spinach] - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/key_spec.rb b/spec/lib/gitlab/ci/config/node/key_spec.rb deleted file mode 100644 index 8cda43173fe..00000000000 --- a/spec/lib/gitlab/ci/config/node/key_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Key do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is correct' do - let(:config) { 'test' } - - describe '#value' do - it 'returns key value' do - expect(entry.value).to eq 'test' - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - let(:config) { [ 'incorrect' ] } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'key config should be a string or symbol' - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/paths_spec.rb b/spec/lib/gitlab/ci/config/node/paths_spec.rb deleted file mode 100644 index 6fd744b3975..00000000000 --- a/spec/lib/gitlab/ci/config/node/paths_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Paths do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is valid' do - let(:config) { ['some/file', 'some/path/'] } - - describe '#value' do - it 'returns key value' do - expect(entry.value).to eq config - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not valid' do - let(:config) { [ 1 ] } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'paths config should be an array of strings' - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/script_spec.rb b/spec/lib/gitlab/ci/config/node/script_spec.rb deleted file mode 100644 index 219a7e981d3..00000000000 --- a/spec/lib/gitlab/ci/config/node/script_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Script do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is correct' do - let(:config) { ['ls', 'pwd'] } - - describe '#value' do - it 'returns array of strings' do - expect(entry.value).to eq config - end - end - - describe '#errors' do - it 'does not append errors' do - expect(entry.errors).to be_empty - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - let(:config) { 'ls' } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'script config should be an array of strings' - end - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/services_spec.rb b/spec/lib/gitlab/ci/config/node/services_spec.rb deleted file mode 100644 index be0fe46befd..00000000000 --- a/spec/lib/gitlab/ci/config/node/services_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Services do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is correct' do - let(:config) { ['postgres:9.1', 'mysql:5.5'] } - - describe '#value' do - it 'returns array of services as is' do - expect(entry.value).to eq config - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - let(:config) { 'ls' } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'services config should be an array of strings' - end - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/stage_spec.rb b/spec/lib/gitlab/ci/config/node/stage_spec.rb deleted file mode 100644 index fb9ec70762a..00000000000 --- a/spec/lib/gitlab/ci/config/node/stage_spec.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Stage do - let(:stage) { described_class.new(config) } - - describe 'validations' do - context 'when stage config value is correct' do - let(:config) { 'build' } - - describe '#value' do - it 'returns a stage key' do - expect(stage.value).to eq config - end - end - - describe '#valid?' do - it 'is valid' do - expect(stage).to be_valid - end - end - end - - context 'when value has a wrong type' do - let(:config) { { test: true } } - - it 'reports errors about wrong type' do - expect(stage.errors) - .to include 'stage config should be a string' - end - end - end - - describe '.default' do - it 'returns default stage' do - expect(described_class.default).to eq 'test' - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/stages_spec.rb b/spec/lib/gitlab/ci/config/node/stages_spec.rb deleted file mode 100644 index 1a3818d8997..00000000000 --- a/spec/lib/gitlab/ci/config/node/stages_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Stages do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is correct' do - let(:config) { [:stage1, :stage2] } - - describe '#value' do - it 'returns array of stages' do - expect(entry.value).to eq config - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - let(:config) { { test: true } } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'stages config should be an array of strings' - end - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - end - end - - describe '.default' do - it 'returns default stages' do - expect(described_class.default).to eq %w[build test deploy] - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/trigger_spec.rb b/spec/lib/gitlab/ci/config/node/trigger_spec.rb deleted file mode 100644 index a4a3e36754e..00000000000 --- a/spec/lib/gitlab/ci/config/node/trigger_spec.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Trigger do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is valid' do - context 'when config is a branch or tag name' do - let(:config) { %w[master feature/branch] } - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - - describe '#value' do - it 'returns key value' do - expect(entry.value).to eq config - end - end - end - - context 'when config is a regexp' do - let(:config) { ['/^issue-.*$/'] } - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when config is a special keyword' do - let(:config) { %w[tags triggers branches] } - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - end - - context 'when entry value is not valid' do - let(:config) { [1] } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include 'trigger config should be an array of strings or regexps' - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/undefined_spec.rb b/spec/lib/gitlab/ci/config/node/undefined_spec.rb deleted file mode 100644 index 6bde8602963..00000000000 --- a/spec/lib/gitlab/ci/config/node/undefined_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Undefined do - let(:entry) { described_class.new } - - describe '#leaf?' do - it 'is leaf node' do - expect(entry).to be_leaf - end - end - - describe '#valid?' do - it 'is always valid' do - expect(entry).to be_valid - end - end - - describe '#errors' do - it 'is does not contain errors' do - expect(entry.errors).to be_empty - end - end - - describe '#value' do - it 'returns nil' do - expect(entry.value).to eq nil - end - end - - describe '#relevant?' do - it 'is not relevant' do - expect(entry.relevant?).to eq false - end - end - - describe '#specified?' do - it 'is not defined' do - expect(entry.specified?).to eq false - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/unspecified_spec.rb b/spec/lib/gitlab/ci/config/node/unspecified_spec.rb deleted file mode 100644 index ba3ceef24ce..00000000000 --- a/spec/lib/gitlab/ci/config/node/unspecified_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Unspecified do - let(:unspecified) { described_class.new(entry) } - let(:entry) { spy('Entry') } - - describe '#valid?' do - it 'delegates method to entry' do - expect(unspecified.valid?).to eq entry - end - end - - describe '#errors' do - it 'delegates method to entry' do - expect(unspecified.errors).to eq entry - end - end - - describe '#value' do - it 'delegates method to entry' do - expect(unspecified.value).to eq entry - end - end - - describe '#specified?' do - it 'is always false' do - allow(entry).to receive(:specified?).and_return(true) - - expect(unspecified.specified?).to be false - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/validatable_spec.rb b/spec/lib/gitlab/ci/config/node/validatable_spec.rb deleted file mode 100644 index 64b77fd6e03..00000000000 --- a/spec/lib/gitlab/ci/config/node/validatable_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Validatable do - let(:node) { Class.new } - - before do - node.include(described_class) - end - - describe '.validator' do - before do - node.class_eval do - attr_accessor :test_attribute - - validations do - validates :test_attribute, presence: true - end - end - end - - it 'returns validator' do - expect(node.validator.superclass) - .to be Gitlab::Ci::Config::Node::Validator - end - - it 'returns only one validator to mitigate leaks' do - expect { node.validator }.not_to change { node.validator } - end - - context 'when validating node instance' do - let(:node_instance) { node.new } - - context 'when attribute is valid' do - before do - node_instance.test_attribute = 'valid' - end - - it 'instance of validator is valid' do - expect(node.validator.new(node_instance)).to be_valid - end - end - - context 'when attribute is not valid' do - before do - node_instance.test_attribute = nil - end - - it 'instance of validator is invalid' do - expect(node.validator.new(node_instance)).to be_invalid - end - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/validator_spec.rb b/spec/lib/gitlab/ci/config/node/validator_spec.rb deleted file mode 100644 index 090fd63b844..00000000000 --- a/spec/lib/gitlab/ci/config/node/validator_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Validator do - let(:validator) { Class.new(described_class) } - let(:validator_instance) { validator.new(node) } - let(:node) { spy('node') } - - before do - allow(node).to receive(:key).and_return('node') - allow(node).to receive(:ancestors).and_return([]) - end - - describe 'delegated validator' do - before do - validator.class_eval do - validates :test_attribute, presence: true - end - end - - context 'when node is valid' do - before do - allow(node).to receive(:test_attribute).and_return('valid value') - end - - it 'validates attribute in node' do - expect(node).to receive(:test_attribute) - expect(validator_instance).to be_valid - end - - it 'returns no errors' do - validator_instance.validate - - expect(validator_instance.messages).to be_empty - end - end - - context 'when node is invalid' do - before do - allow(node).to receive(:test_attribute).and_return(nil) - end - - it 'validates attribute in node' do - expect(node).to receive(:test_attribute) - expect(validator_instance).to be_invalid - end - - it 'returns errors' do - validator_instance.validate - - expect(validator_instance.messages) - .to include "node test attribute can't be blank" - end - end - end -end diff --git a/spec/lib/gitlab/ci/config/node/variables_spec.rb b/spec/lib/gitlab/ci/config/node/variables_spec.rb deleted file mode 100644 index 4b6d971ec71..00000000000 --- a/spec/lib/gitlab/ci/config/node/variables_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -require 'spec_helper' - -describe Gitlab::Ci::Config::Node::Variables do - let(:entry) { described_class.new(config) } - - describe 'validations' do - context 'when entry config value is correct' do - let(:config) do - { 'VARIABLE_1' => 'value 1', 'VARIABLE_2' => 'value 2' } - end - - describe '#value' do - it 'returns hash with key value strings' do - expect(entry.value).to eq config - end - end - - describe '#errors' do - it 'does not append errors' do - expect(entry.errors).to be_empty - end - end - - describe '#valid?' do - it 'is valid' do - expect(entry).to be_valid - end - end - end - - context 'when entry value is not correct' do - let(:config) { [ :VAR, 'test' ] } - - describe '#errors' do - it 'saves errors' do - expect(entry.errors) - .to include /should be a hash of key value pairs/ - end - end - - describe '#valid?' do - it 'is not valid' do - expect(entry).not_to be_valid - end - end - end - end -end -- cgit v1.2.1 From a761d293662e48efca9c0607f0624ba8eec1b634 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 14 Nov 2016 10:51:56 +0100 Subject: Change name of method for setting CI config entries --- spec/lib/gitlab/ci/config/entry/configurable_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb index aff70ab6751..ae7e628b5b5 100644 --- a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb @@ -39,10 +39,10 @@ describe Gitlab::Ci::Config::Entry::Configurable do end end - describe 'configured nodes' do + describe 'configured entries' do before do entry.class_eval do - node :object, Object, description: 'test object' + entry :object, Object, description: 'test object' end end -- cgit v1.2.1 From b16780f76671ba704bfc4ee75d1f555b4dfc3035 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 14 Nov 2016 12:12:01 +0000 Subject: Fixed issue boards when not logged in --- spec/features/boards/boards_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 6cb8753e8fc..4aa84fb65d9 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -659,6 +659,10 @@ describe 'Issue Boards', feature: true, js: true do wait_for_vue_resource end + it 'displays lists' do + expect(page).to have_selector('.board') + end + it 'does not show create new list' do expect(page).not_to have_selector('.js-new-board-list') end -- cgit v1.2.1 From d945300b8e49c927da8a12ba3a8bac68dbc4b9fc Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 14 Nov 2016 13:54:23 +0100 Subject: Check permissions before stopping CI environments --- spec/services/ci/stop_environment_service_spec.rb | 72 +++++++++++++++-------- 1 file changed, 49 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/services/ci/stop_environment_service_spec.rb b/spec/services/ci/stop_environment_service_spec.rb index 047f9b0b2ca..e044b40679a 100644 --- a/spec/services/ci/stop_environment_service_spec.rb +++ b/spec/services/ci/stop_environment_service_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Ci::StopEnvironmentService, services: true do - let(:project) { create(:project) } + let(:project) { create(:project, :private) } let(:user) { create(:user) } let(:service) { described_class.new(project, user) } @@ -12,38 +12,46 @@ describe Ci::StopEnvironmentService, services: true do create(:environment, :with_review_app, project: project) end - it 'stops environment' do - expect_any_instance_of(Environment).to receive(:stop!) + context 'when user has permission to stop environment' do + before do + project.team << [user, :developer] + end - service.execute('master') - end + it 'stops environment' do + expect_environment_stopped_on('master') + end - context 'when specified branch does not exist' do - it 'does not stop environment' do - expect_any_instance_of(Environment).not_to receive(:stop!) + context 'when specified branch does not exist' do + it 'does not stop environment' do + expect_environment_not_stopped_on('non/existent/branch') + end + end - service.execute('non/existent/branch') + context 'when no branch not specified' do + it 'does not stop environment' do + expect_environment_not_stopped_on(nil) + end end - end - context 'when no branch not specified' do - it 'does not stop environment' do - expect_any_instance_of(Environment).not_to receive(:stop!) + context 'when environment is not stoppable' do + before do + allow_any_instance_of(Environment) + .to receive(:stoppable?).and_return(false) + end - service.execute(nil) + it 'does not stop environment' do + expect_environment_not_stopped_on('master') + end end end - context 'when environment is not stoppable' do + context 'when user does not have permission to stop environment' do before do - allow_any_instance_of(Environment) - .to receive(:stoppable?).and_return(false) + project.team << [user, :guest] end it 'does not stop environment' do - expect_any_instance_of(Environment).not_to receive(:stop!) - - service.execute('master') + expect_environment_not_stopped_on('master') end end end @@ -53,10 +61,14 @@ describe Ci::StopEnvironmentService, services: true do create(:environment, project: project) end - it 'does not stop environment' do - expect_any_instance_of(Environment).not_to receive(:stop!) + context 'when user has permission to stop environments' do + before do + project.team << [user, :master] + end - service.execute('master') + it 'does not stop environment' do + expect_environment_not_stopped_on('master') + end end end @@ -67,4 +79,18 @@ describe Ci::StopEnvironmentService, services: true do end end end + + def expect_environment_stopped_on(branch) + expect_any_instance_of(Environment) + .to receive(:stop!) + + service.execute(branch) + end + + def expect_environment_not_stopped_on(branch) + expect_any_instance_of(Environment) + .not_to receive(:stop!) + + service.execute(branch) + end end -- cgit v1.2.1 From 990765edf354a7bbb39d3897780fb85bf8d6fa48 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 14 Nov 2016 13:57:09 +0100 Subject: Improve name of service that stops CI environments --- spec/services/ci/stop_environment_service_spec.rb | 96 ---------------------- spec/services/ci/stop_environments_service_spec.rb | 96 ++++++++++++++++++++++ 2 files changed, 96 insertions(+), 96 deletions(-) delete mode 100644 spec/services/ci/stop_environment_service_spec.rb create mode 100644 spec/services/ci/stop_environments_service_spec.rb (limited to 'spec') diff --git a/spec/services/ci/stop_environment_service_spec.rb b/spec/services/ci/stop_environment_service_spec.rb deleted file mode 100644 index e044b40679a..00000000000 --- a/spec/services/ci/stop_environment_service_spec.rb +++ /dev/null @@ -1,96 +0,0 @@ -require 'spec_helper' - -describe Ci::StopEnvironmentService, services: true do - let(:project) { create(:project, :private) } - let(:user) { create(:user) } - - let(:service) { described_class.new(project, user) } - - describe '#execute' do - context 'when environment with review app exists' do - before do - create(:environment, :with_review_app, project: project) - end - - context 'when user has permission to stop environment' do - before do - project.team << [user, :developer] - end - - it 'stops environment' do - expect_environment_stopped_on('master') - end - - context 'when specified branch does not exist' do - it 'does not stop environment' do - expect_environment_not_stopped_on('non/existent/branch') - end - end - - context 'when no branch not specified' do - it 'does not stop environment' do - expect_environment_not_stopped_on(nil) - end - end - - context 'when environment is not stoppable' do - before do - allow_any_instance_of(Environment) - .to receive(:stoppable?).and_return(false) - end - - it 'does not stop environment' do - expect_environment_not_stopped_on('master') - end - end - end - - context 'when user does not have permission to stop environment' do - before do - project.team << [user, :guest] - end - - it 'does not stop environment' do - expect_environment_not_stopped_on('master') - end - end - end - - context 'when there is no environment associated with review app' do - before do - create(:environment, project: project) - end - - context 'when user has permission to stop environments' do - before do - project.team << [user, :master] - end - - it 'does not stop environment' do - expect_environment_not_stopped_on('master') - end - end - end - - context 'when environment does not exist' do - it 'does not raise error' do - expect { service.execute('master') } - .not_to raise_error - end - end - end - - def expect_environment_stopped_on(branch) - expect_any_instance_of(Environment) - .to receive(:stop!) - - service.execute(branch) - end - - def expect_environment_not_stopped_on(branch) - expect_any_instance_of(Environment) - .not_to receive(:stop!) - - service.execute(branch) - end -end diff --git a/spec/services/ci/stop_environments_service_spec.rb b/spec/services/ci/stop_environments_service_spec.rb new file mode 100644 index 00000000000..c3e1af3afe2 --- /dev/null +++ b/spec/services/ci/stop_environments_service_spec.rb @@ -0,0 +1,96 @@ +require 'spec_helper' + +describe Ci::StopEnvironmentsService, services: true do + let(:project) { create(:project, :private) } + let(:user) { create(:user) } + + let(:service) { described_class.new(project, user) } + + describe '#execute' do + context 'when environment with review app exists' do + before do + create(:environment, :with_review_app, project: project) + end + + context 'when user has permission to stop environment' do + before do + project.team << [user, :developer] + end + + it 'stops environment' do + expect_environment_stopped_on('master') + end + + context 'when specified branch does not exist' do + it 'does not stop environment' do + expect_environment_not_stopped_on('non/existent/branch') + end + end + + context 'when no branch not specified' do + it 'does not stop environment' do + expect_environment_not_stopped_on(nil) + end + end + + context 'when environment is not stoppable' do + before do + allow_any_instance_of(Environment) + .to receive(:stoppable?).and_return(false) + end + + it 'does not stop environment' do + expect_environment_not_stopped_on('master') + end + end + end + + context 'when user does not have permission to stop environment' do + before do + project.team << [user, :guest] + end + + it 'does not stop environment' do + expect_environment_not_stopped_on('master') + end + end + end + + context 'when there is no environment associated with review app' do + before do + create(:environment, project: project) + end + + context 'when user has permission to stop environments' do + before do + project.team << [user, :master] + end + + it 'does not stop environment' do + expect_environment_not_stopped_on('master') + end + end + end + + context 'when environment does not exist' do + it 'does not raise error' do + expect { service.execute('master') } + .not_to raise_error + end + end + end + + def expect_environment_stopped_on(branch) + expect_any_instance_of(Environment) + .to receive(:stop!) + + service.execute(branch) + end + + def expect_environment_not_stopped_on(branch) + expect_any_instance_of(Environment) + .not_to receive(:stop!) + + service.execute(branch) + end +end -- cgit v1.2.1 From ceb06983ec186bcc1c6fce28613bdb92297e5bf1 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 14 Nov 2016 14:10:54 +0100 Subject: Make it possible to fabricate environment on branch --- spec/factories/environments.rb | 9 +++++++-- spec/services/ci/stop_environments_service_spec.rb | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/factories/environments.rb b/spec/factories/environments.rb index bb6558a403f..0852dda6b29 100644 --- a/spec/factories/environments.rb +++ b/spec/factories/environments.rb @@ -8,16 +8,21 @@ FactoryGirl.define do trait :with_review_app do |environment| project + transient do + ref 'master' + end + # At this point `review app` is an ephemeral concept related to # deployments being deployed for given environment. There is no # first-class `review app` available so we need to create set of # interconnected objects to simulate a review app. # - after(:create) do |environment| + after(:create) do |environment, evaluator| deployment = create(:deployment, environment: environment, project: environment.project, - sha: environment.project.commit.id) + ref: evaluator.ref, + sha: environment.project.commit(evaluator.ref).id) teardown_build = create(:ci_build, :manual, name: "#{deployment.environment.name}:teardown", diff --git a/spec/services/ci/stop_environments_service_spec.rb b/spec/services/ci/stop_environments_service_spec.rb index c3e1af3afe2..6f7d1a5d28d 100644 --- a/spec/services/ci/stop_environments_service_spec.rb +++ b/spec/services/ci/stop_environments_service_spec.rb @@ -9,7 +9,8 @@ describe Ci::StopEnvironmentsService, services: true do describe '#execute' do context 'when environment with review app exists' do before do - create(:environment, :with_review_app, project: project) + create(:environment, :with_review_app, project: project, + ref: 'feature') end context 'when user has permission to stop environment' do @@ -17,8 +18,16 @@ describe Ci::StopEnvironmentsService, services: true do project.team << [user, :developer] end - it 'stops environment' do - expect_environment_stopped_on('master') + context 'when environment is associated with removed branch' do + it 'stops environment' do + expect_environment_stopped_on('feature') + end + end + + context 'when environment is associated with different branch' do + it 'does not stop environment' do + expect_environment_not_stopped_on('master') + end end context 'when specified branch does not exist' do @@ -40,7 +49,7 @@ describe Ci::StopEnvironmentsService, services: true do end it 'does not stop environment' do - expect_environment_not_stopped_on('master') + expect_environment_not_stopped_on('feature') end end end -- cgit v1.2.1 From 84ac742fa6caf6e525e690d6f929f8931902fb9b Mon Sep 17 00:00:00 2001 From: Francesco Coda Zabetta Date: Mon, 14 Nov 2016 15:52:43 +0100 Subject: fix labels API adding missing parameter (current_user) --- spec/requests/api/labels_spec.rb | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 5d84976c9c3..39fe6e64653 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -17,6 +17,8 @@ describe API::API, api: true do group = create(:group) group_label = create(:group_label, title: 'feature', group: group) project.update(group: group) + create(:labeled_issue, project: project, labels: [group_label], author: user) + create(:labeled_issue, project: project, labels: [label1], author: user, state: :closed) expected_keys = [ 'id', 'name', 'color', 'description', 'open_issues_count', 'closed_issues_count', 'open_merge_requests_count', @@ -30,14 +32,24 @@ describe API::API, api: true do expect(json_response.size).to eq(3) expect(json_response.first.keys).to match_array expected_keys expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) - expect(json_response.last['name']).to eq(label1.name) - expect(json_response.last['color']).to be_present - expect(json_response.last['description']).to be_nil - expect(json_response.last['open_issues_count']).to eq(0) - expect(json_response.last['closed_issues_count']).to eq(0) - expect(json_response.last['open_merge_requests_count']).to eq(0) - expect(json_response.last['priority']).to be_nil - expect(json_response.last['subscribed']).to be_falsey + + label1_response = json_response.select{|l| l['name'] == label1.title}.first + group_label_response = json_response.select{|l| l['name'] == group_label.title}.first + priority_label_response = json_response.select{|l| l['name'] == priority_label.title}.first + + expect(label1_response['open_issues_count']).to eq(0) + expect(label1_response['closed_issues_count']).to eq(1) + expect(group_label_response['open_issues_count']).to eq(1) + expect(group_label_response['closed_issues_count']).to eq(0) + expect(priority_label_response['open_issues_count']).to eq(0) + expect(priority_label_response['closed_issues_count']).to eq(0) + + expect(label1_response['name']).to eq(label1.name) + expect(label1_response['color']).to be_present + expect(label1_response['description']).to be_nil + expect(label1_response['open_merge_requests_count']).to eq(0) + expect(label1_response['priority']).to be_nil + expect(label1_response['subscribed']).to be_falsey end end -- cgit v1.2.1 From 0f61bb2dc5298a7e06f8e211adcf46dd282b9c86 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 27 Aug 2016 20:59:48 -0700 Subject: Fix Error 500 when creating a merge request that contains an image that was deleted and added MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce: 1. Start with a repo with an image 2. Add a commit to delete the image 3. Add another commit to replace the image with another image In a diff comparison, we really just compare about what the image was before the diff, not the direct parent of the last commit. This MR fixes that. Closes #3893, gitlab-org/gitlab-ee#678 Signed-off-by: Rémy Coutable --- spec/features/merge_requests/create_new_mr_spec.rb | 10 +++++++++ spec/lib/gitlab/diff/file_spec.rb | 24 ++++++++++++++++++++++ spec/support/test_env.rb | 1 + 3 files changed, 35 insertions(+) (limited to 'spec') diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb index c68e1ea4af9..584574cc91a 100644 --- a/spec/features/merge_requests/create_new_mr_spec.rb +++ b/spec/features/merge_requests/create_new_mr_spec.rb @@ -67,4 +67,14 @@ feature 'Create New Merge Request', feature: true, js: true do expect(page).to have_content('Source branch "non-exist-source" does not exist') expect(page).to have_content('Target branch "non-exist-target" does not exist') end + + context 'when a branch contains commits that both delete and add the same image' do + it 'renders the diff successfully' do + visit new_namespace_project_merge_request_path(project.namespace, project, merge_request: { target_branch: 'master', source_branch: 'deleted-image-test' }) + + click_link "Changes" + + expect(page).to have_content "6049019_460s.jpg" + end + end end diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index 0650cb291e5..38475792d93 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -46,4 +46,28 @@ describe Gitlab::Diff::File, lib: true do expect(diff_file.collapsed?).to eq(false) end end + + describe '#old_content_commit' do + it 'returns base commit' do + old_content_commit = diff_file.old_content_commit + + expect(old_content_commit.id).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') + end + end + + describe '#old_blob' do + it 'returns blob of commit of base commit' do + old_data = diff_file.old_blob.data + + expect(old_data).to include('raise "System commands must be given as an array of strings"') + end + end + + describe '#blob' do + it 'returns blob of new commit' do + data = diff_file.blob.data + + expect(data).to include('raise RuntimeError, "System commands must be given as an array of strings"') + end + end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 103f7542286..4cf81be3adc 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -35,6 +35,7 @@ module TestEnv 'conflict-missing-side' => 'eb227b3', 'conflict-non-utf8' => 'd0a293c', 'conflict-too-large' => '39fa04f', + 'deleted-image-test' => '6c17798' } # gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily -- cgit v1.2.1 From d5981dd44db4b36ad3d6b5005cd942bc295ace58 Mon Sep 17 00:00:00 2001 From: Francesco Coda Zabetta Date: Mon, 14 Nov 2016 16:05:39 +0100 Subject: fix style --- spec/requests/api/labels_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 39fe6e64653..9f0500bd443 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -33,9 +33,9 @@ describe API::API, api: true do expect(json_response.first.keys).to match_array expected_keys expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) - label1_response = json_response.select{|l| l['name'] == label1.title}.first - group_label_response = json_response.select{|l| l['name'] == group_label.title}.first - priority_label_response = json_response.select{|l| l['name'] == priority_label.title}.first + label1_response = json_response.select{ |l| l['name'] == label1.title }.first + group_label_response = json_response.select{ |l| l['name'] == group_label.title }.first + priority_label_response = json_response.select{ |l| l['name'] == priority_label.title }.first expect(label1_response['open_issues_count']).to eq(0) expect(label1_response['closed_issues_count']).to eq(1) -- cgit v1.2.1 From c57c83336d8dc8b4cb82e51cd40b72795bdf01bf Mon Sep 17 00:00:00 2001 From: Francesco Coda Zabetta Date: Mon, 14 Nov 2016 16:15:53 +0100 Subject: fix style --- spec/requests/api/labels_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 9f0500bd443..64a99e42c28 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -33,9 +33,9 @@ describe API::API, api: true do expect(json_response.first.keys).to match_array expected_keys expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) - label1_response = json_response.select{ |l| l['name'] == label1.title }.first - group_label_response = json_response.select{ |l| l['name'] == group_label.title }.first - priority_label_response = json_response.select{ |l| l['name'] == priority_label.title }.first + label1_response = json_response.select { |l| l['name'] == label1.title }.first + group_label_response = json_response.select { |l| l['name'] == group_label.title }.first + priority_label_response = json_response.select { |l| l['name'] == priority_label.title }.first expect(label1_response['open_issues_count']).to eq(0) expect(label1_response['closed_issues_count']).to eq(1) -- cgit v1.2.1 From 5f2d45c956eba7e24f5f8572409230383b663bfe Mon Sep 17 00:00:00 2001 From: Cagdas Gerede Date: Tue, 15 Nov 2016 01:59:11 +0300 Subject: Add authentication for for create action. Add more tests for for new and create actions --- spec/controllers/projects/forks_controller_spec.rb | 61 +++++++++++++++++++--- 1 file changed, 55 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index d29404e4a11..ad1f4b849e5 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -69,15 +69,64 @@ describe Projects::ForksController do end describe 'GET new' do - context 'when user is not logged in' do - before { sign_out(user) } + def get_new + get :new, + namespace_id: project.namespace.to_param, + project_id: project.to_param + end + + context 'when user is signed in' do + + it 'responds with status 200' do + sign_in(user) + + get_new + + expect(response).to have_http_status(200) + end + end + + context 'when user is not signed in' do + + it 'redirects to the sign-in page' do + sign_out(user) + + get_new + + expect(response).to redirect_to(new_user_session_path) + end + end + end + + describe 'POST create' do + def post_create + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + namespace_key: user.namespace.id + end + + context 'when user is signed in' do + + it 'responds with status 302' do + sign_in(user) + + post_create + + expect(response).to have_http_status(302) + expected_import_url = namespace_project_import_url(user.namespace, project) + expect(response.headers['Location']).to eq(expected_import_url) + end + end + + context 'when user is not signed in' do it 'redirects to the sign-in page' do - get :new, - namespace_id: project.namespace.to_param, - project_id: project.to_param + sign_out(user) + + post_create - expect(response).to redirect_to(root_path + 'users/sign_in') + expect(response).to redirect_to(new_user_session_path) end end end -- cgit v1.2.1 From a88b2d3b019cd696404d20f8042a555ec0081143 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 14 Nov 2016 14:35:29 +0100 Subject: Add feature tests for environments auto-close --- spec/features/environments_spec.rb | 42 ++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 10ca835e6ca..8b34cb13b9d 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -6,8 +6,8 @@ feature 'Environments', feature: true do given(:role) { :developer } background do - login_as(user) project.team << [user, role] + login_as(user) end describe 'when showing environments' do @@ -16,7 +16,7 @@ feature 'Environments', feature: true do given!(:manual) { } before do - visit namespace_project_environments_path(project.namespace, project) + visit_environments(project) end context 'shows two tabs' do @@ -142,7 +142,7 @@ feature 'Environments', feature: true do given!(:manual) { } before do - visit namespace_project_environment_path(project.namespace, project, environment) + visit_environment(environment) end context 'without deployments' do @@ -234,7 +234,7 @@ feature 'Environments', feature: true do describe 'when creating a new environment' do before do - visit namespace_project_environments_path(project.namespace, project) + visit_environments(project) end context 'when logged as developer' do @@ -273,4 +273,38 @@ feature 'Environments', feature: true do end end end + + feature 'auto-close environment when branch deleted' do + given(:project) { create(:project) } + + given!(:environment) do + create(:environment, :with_review_app, project: project, + ref: 'feature') + end + + scenario 'user visits environment page' do + visit_environment(environment) + + expect(page).to have_link('Stop') + end + + scenario 'user deletes the branch with running environment' do + visit namespace_project_branches_path(project.namespace, project) + + page.within('.js-branch-feature') { find('a.btn-remove').click } + visit_environment(environment) + + expect(page).to have_no_link('Stop') + end + end + + def visit_environments(project) + visit namespace_project_environments_path(project.namespace, project) + end + + def visit_environment(environment) + visit namespace_project_environment_path(environment.project.namespace, + environment.project, + environment) + end end -- cgit v1.2.1 From a58e2f4762d8f0fc52b0a4dc5a65c28258603c11 Mon Sep 17 00:00:00 2001 From: Francesco Coda Zabetta Date: Tue, 15 Nov 2016 09:50:39 +0100 Subject: use Enumerable#find insted of select + first --- spec/requests/api/labels_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 64a99e42c28..151b5c33e3a 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -33,9 +33,9 @@ describe API::API, api: true do expect(json_response.first.keys).to match_array expected_keys expect(json_response.map { |l| l['name'] }).to match_array([group_label.name, priority_label.name, label1.name]) - label1_response = json_response.select { |l| l['name'] == label1.title }.first - group_label_response = json_response.select { |l| l['name'] == group_label.title }.first - priority_label_response = json_response.select { |l| l['name'] == priority_label.title }.first + label1_response = json_response.find { |l| l['name'] == label1.title } + group_label_response = json_response.find { |l| l['name'] == group_label.title } + priority_label_response = json_response.find { |l| l['name'] == priority_label.title } expect(label1_response['open_issues_count']).to eq(0) expect(label1_response['closed_issues_count']).to eq(1) -- cgit v1.2.1 From 2a53d6c21aed285ce08a4c4431154e9182beb069 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 15 Nov 2016 10:27:40 +0100 Subject: Add minimial test coverage for delete branch service --- spec/services/delete_branch_service_spec.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 spec/services/delete_branch_service_spec.rb (limited to 'spec') diff --git a/spec/services/delete_branch_service_spec.rb b/spec/services/delete_branch_service_spec.rb new file mode 100644 index 00000000000..2603a930a08 --- /dev/null +++ b/spec/services/delete_branch_service_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe DeleteBranchService, services: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:service) { described_class.new(project, user) } + + describe '#execute' do + let(:result) { service.execute('feature') } + + context 'when user has access to push to repository' do + before do + project.team << [user, :developer] + end + + it 'removes the branch' do + expect(result[:status]).to eq :success + end + end + + context 'when user does not have access to push to repository' do + it 'does not remove branch' do + expect(result[:status]).to eq :error + expect(result[:message]).to eq 'You dont have push access to repo' + end + end + end +end -- cgit v1.2.1 From 9dbb0417ba683ff220ba62ecb79e6375496ad79d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 8 Nov 2016 09:28:52 +0100 Subject: Grapify the merge request API --- spec/requests/api/merge_requests_spec.rb | 6 ------ 1 file changed, 6 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index bae4fa11ec2..7b3d1460c90 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -494,12 +494,6 @@ describe API::API, api: true do expect(json_response['milestone']['id']).to eq(milestone.id) end - it "returns 400 when source_branch is specified" do - put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), - source_branch: "master", target_branch: "master" - expect(response).to have_http_status(400) - end - it "returns merge_request with renamed target_branch" do put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), target_branch: "wiki" expect(response).to have_http_status(200) -- cgit v1.2.1 From e552e1fc22c66c593c4479d85b7a770fda09e5d0 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 15 Nov 2016 10:32:37 +0100 Subject: Extend tests for delete branch service --- spec/services/delete_branch_service_spec.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/services/delete_branch_service_spec.rb b/spec/services/delete_branch_service_spec.rb index 2603a930a08..336f5dafb5b 100644 --- a/spec/services/delete_branch_service_spec.rb +++ b/spec/services/delete_branch_service_spec.rb @@ -2,27 +2,40 @@ require 'spec_helper' describe DeleteBranchService, services: true do let(:project) { create(:project) } + let(:repository) { project.repository } let(:user) { create(:user) } let(:service) { described_class.new(project, user) } describe '#execute' do - let(:result) { service.execute('feature') } - context 'when user has access to push to repository' do before do project.team << [user, :developer] end it 'removes the branch' do + expect(branch_exists?('feature')).to be true + + result = service.execute('feature') + expect(result[:status]).to eq :success + expect(branch_exists?('feature')).to be false end end context 'when user does not have access to push to repository' do it 'does not remove branch' do + expect(branch_exists?('feature')).to be true + + result = service.execute('feature') + expect(result[:status]).to eq :error expect(result[:message]).to eq 'You dont have push access to repo' + expect(branch_exists?('feature')).to be true end end end + + def branch_exists?(branch_name) + repository.ref_exists?("refs/heads/#{branch_name}") + end end -- cgit v1.2.1 From 94a9effeec183894123f4ea7ad9faa19da3e6b0b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 15 Nov 2016 10:34:27 +0100 Subject: Test call to after branch delete hooks in service --- spec/services/delete_branch_service_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spec') diff --git a/spec/services/delete_branch_service_spec.rb b/spec/services/delete_branch_service_spec.rb index 336f5dafb5b..3ca4eb14518 100644 --- a/spec/services/delete_branch_service_spec.rb +++ b/spec/services/delete_branch_service_spec.rb @@ -20,6 +20,12 @@ describe DeleteBranchService, services: true do expect(result[:status]).to eq :success expect(branch_exists?('feature')).to be false end + + it 'calls after branch delete hooks' do + expect(service).to receive(:execute_after_branch_delete_hooks) + + service.execute('feature') + end end context 'when user does not have access to push to repository' do @@ -32,6 +38,12 @@ describe DeleteBranchService, services: true do expect(result[:message]).to eq 'You dont have push access to repo' expect(branch_exists?('feature')).to be true end + + it 'does not call after branch delete hooks' do + expect(service).not_to receive(:execute_after_branch_delete_hooks) + + service.execute('feature') + end end end -- cgit v1.2.1 From 54c2e234f491fa4b94f40cc997544a029b28d7b8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 15 Nov 2016 10:38:08 +0100 Subject: Add test example for after branch delete service --- spec/services/after_branch_delete_service_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 spec/services/after_branch_delete_service_spec.rb (limited to 'spec') diff --git a/spec/services/after_branch_delete_service_spec.rb b/spec/services/after_branch_delete_service_spec.rb new file mode 100644 index 00000000000..d29e0addb53 --- /dev/null +++ b/spec/services/after_branch_delete_service_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe AfterBranchDeleteService, services: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:service) { described_class.new(project, user) } + + describe '#execute' do + it 'stops environments attached to branch' do + expect(service).to receive(:stop_environments) + + service.execute('feature') + end + end +end -- cgit v1.2.1 From 8966c6e33daec5480f19149d2a6102107833afe0 Mon Sep 17 00:00:00 2001 From: Francesco Coda Zabetta Date: Tue, 15 Nov 2016 11:45:57 +0100 Subject: add tests --- spec/requests/api/labels_spec.rb | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 151b5c33e3a..77dfebf1a98 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -19,6 +19,8 @@ describe API::API, api: true do project.update(group: group) create(:labeled_issue, project: project, labels: [group_label], author: user) create(:labeled_issue, project: project, labels: [label1], author: user, state: :closed) + create(:labeled_merge_request, labels: [priority_label], author: user, source_project: project ) + expected_keys = [ 'id', 'name', 'color', 'description', 'open_issues_count', 'closed_issues_count', 'open_merge_requests_count', @@ -39,17 +41,30 @@ describe API::API, api: true do expect(label1_response['open_issues_count']).to eq(0) expect(label1_response['closed_issues_count']).to eq(1) - expect(group_label_response['open_issues_count']).to eq(1) - expect(group_label_response['closed_issues_count']).to eq(0) - expect(priority_label_response['open_issues_count']).to eq(0) - expect(priority_label_response['closed_issues_count']).to eq(0) - + expect(label1_response['open_merge_requests_count']).to eq(0) expect(label1_response['name']).to eq(label1.name) expect(label1_response['color']).to be_present expect(label1_response['description']).to be_nil - expect(label1_response['open_merge_requests_count']).to eq(0) expect(label1_response['priority']).to be_nil expect(label1_response['subscribed']).to be_falsey + + expect(group_label_response['open_issues_count']).to eq(1) + expect(group_label_response['closed_issues_count']).to eq(0) + expect(group_label_response['open_merge_requests_count']).to eq(0) + expect(group_label_response['name']).to eq(group_label.name) + expect(group_label_response['color']).to be_present + expect(group_label_response['description']).to be_nil + expect(group_label_response['priority']).to be_nil + expect(group_label_response['subscribed']).to be_falsey + + expect(priority_label_response['open_issues_count']).to eq(0) + expect(priority_label_response['closed_issues_count']).to eq(0) + expect(priority_label_response['open_merge_requests_count']).to eq(1) + expect(priority_label_response['name']).to eq(priority_label.name) + expect(priority_label_response['color']).to be_present + expect(priority_label_response['description']).to be_nil + expect(priority_label_response['priority']).to eq(3) + expect(priority_label_response['subscribed']).to be_falsey end end -- cgit v1.2.1 From 4dab79c5c6aa1eed1295663fe91c62ea0062f8d2 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 27 Oct 2016 17:05:02 +0200 Subject: Update the updated_at of a build while patching the trace --- spec/requests/ci/api/builds_spec.rb | 86 ++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 6d49c42c215..a611c5e3823 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -213,26 +213,102 @@ describe Ci::API::API do let(:build) { create(:ci_build, :pending, :trace, runner_id: runner.id) } let(:headers) { { Ci::API::Helpers::BUILD_TOKEN_HEADER => build.token, 'Content-Type' => 'text/plain' } } let(:headers_with_range) { headers.merge({ 'Content-Range' => '11-20' }) } + let(:update_interval) { 10.seconds.to_i } + + def patch_the_trace(content = ' appended', request_headers = nil) + unless request_headers + offset = build.trace_length + limit = offset + content.length - 1 + request_headers = headers.merge({ 'Content-Range' => "#{offset}-#{limit}" }) + end + + Timecop.travel(build.updated_at + update_interval) do + patch ci_api("/builds/#{build.id}/trace.txt"), content, request_headers + build.reload + end + end + + def initial_patch_the_trace + patch_the_trace(' appended', headers_with_range) + end + + def force_patch_the_trace + 2.times { patch_the_trace('') } + end before do build.run! - patch ci_api("/builds/#{build.id}/trace.txt"), ' appended', headers_with_range + initial_patch_the_trace end context 'when request is valid' do it 'gets correct response' do expect(response.status).to eq 202 + expect(build.reload.trace).to eq 'BUILD TRACE appended' expect(response.header).to have_key 'Range' expect(response.header).to have_key 'Build-Status' end - it { expect(build.reload.trace).to eq 'BUILD TRACE appended' } + context 'when build has been updated recently' do + it { expect{ patch_the_trace }.not_to change { build.updated_at }} + + it 'changes the build trace' do + patch_the_trace + + expect(build.reload.trace).to eq 'BUILD TRACE appended appended' + end + + context 'when Runner makes a force-patch' do + it { expect{ force_patch_the_trace }.not_to change { build.updated_at }} + + it "doesn't change the build.trace" do + force_patch_the_trace + + expect(build.reload.trace).to eq 'BUILD TRACE appended' + end + end + end + + context 'when build was not updated recently' do + let(:update_interval) { 15.minutes.to_i } + + it { expect { patch_the_trace }.to change { build.updated_at } } + + it 'changes the build.trace' do + patch_the_trace + + expect(build.reload.trace).to eq 'BUILD TRACE appended appended' + end + + context 'when Runner makes a force-patch' do + it { expect { force_patch_the_trace }.to change { build.updated_at } } + + it "doesn't change the build.trace" do + force_patch_the_trace + + expect(build.reload.trace).to eq 'BUILD TRACE appended' + end + end + end + end + + context 'when Runner makes a force-patch' do + before do + force_patch_the_trace + end + + it 'gets correct response' do + expect(response.status).to eq 202 + expect(build.reload.trace).to eq 'BUILD TRACE appended' + expect(response.header).to have_key 'Range' + expect(response.header).to have_key 'Build-Status' + end end context 'when content-range start is too big' do let(:headers_with_range) { headers.merge({ 'Content-Range' => '15-20' }) } - it 'gets correct response' do + it 'gets 416 error response with range headers' do expect(response.status).to eq 416 expect(response.header).to have_key 'Range' expect(response.header['Range']).to eq '0-11' @@ -242,7 +318,7 @@ describe Ci::API::API do context 'when content-range start is too small' do let(:headers_with_range) { headers.merge({ 'Content-Range' => '8-20' }) } - it 'gets correct response' do + it 'gets 416 error response with range headers' do expect(response.status).to eq 416 expect(response.header).to have_key 'Range' expect(response.header['Range']).to eq '0-11' @@ -250,7 +326,7 @@ describe Ci::API::API do end context 'when Content-Range header is missing' do - let(:headers_with_range) { headers.merge({}) } + let(:headers_with_range) { headers } it { expect(response.status).to eq 400 } end -- cgit v1.2.1 From ac12c1d271f8ba365f3b38baad3940e7244bbb96 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 7 Nov 2016 16:54:39 +0100 Subject: Grapify the group API --- spec/requests/api/groups_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index b29a13b1d8b..d79b204a24e 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -167,7 +167,7 @@ describe API::API, api: true do end it 'returns 404 for a non existing group' do - put api('/groups/1328', user1) + put api('/groups/1328', user1), name: new_group_name expect(response).to have_http_status(404) end -- cgit v1.2.1 From ff8194e0ec16092419862011d7cc048baa149c42 Mon Sep 17 00:00:00 2001 From: Dmitry Poray Date: Mon, 7 Nov 2016 20:11:54 +0300 Subject: Add ref parameter for triggerring builds with gitlab webhook from other project. --- spec/requests/api/triggers_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb index 8ba2eccf66c..c890a51ae42 100644 --- a/spec/requests/api/triggers_spec.rb +++ b/spec/requests/api/triggers_spec.rb @@ -54,6 +54,13 @@ describe API::API do expect(pipeline.builds.size).to eq(5) end + it 'creates builds on webhook from other gitlab repository and branch' do + expect do + post api("/projects/#{project.id}/ref/master/trigger/builds?token=#{trigger_token}"), { ref: 'refs/heads/other-branch' } + end.to change(project.builds, :count).by(5) + expect(response).to have_http_status(201) + end + it 'returns bad request with no builds created if there\'s no commit for that ref' do post api("/projects/#{project.id}/trigger/builds"), options.merge(ref: 'other-branch') expect(response).to have_http_status(400) -- cgit v1.2.1 From c9d93f645aed1fbb9196616afb0110a585882fc1 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Tue, 15 Nov 2016 14:21:05 +0000 Subject: moves empty view logic onto empty partial to make it reusable and fixes tests --- spec/helpers/preferences_helper_spec.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb index 2bd4eace89f..02b464f7e07 100644 --- a/spec/helpers/preferences_helper_spec.rb +++ b/spec/helpers/preferences_helper_spec.rb @@ -87,17 +87,18 @@ describe PreferencesHelper do end describe 'default_project_view' do - let(:project) { create(:project) } - context 'user not signed in' do - before { stub_user } + before do + @project = create(:project) + stub_user + end it 'returns readme view if repository is not empty' do expect(helper.default_project_view).to eq('readme') end it 'returns activity if repository is empty' do - expect(project).to receive(:empty_repo?).and_return(true) + expect(@project).to receive(:empty_repo?).and_return(true) expect(helper.default_project_view).to eq('empty') end -- cgit v1.2.1 From 7cefaea876da9e25a1c3ea870f4e4b070a196905 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 15 Nov 2016 14:08:06 +0000 Subject: explicitly disable eslint inline --- spec/javascripts/application_spec.js | 2 +- spec/javascripts/awards_handler_spec.js | 2 +- spec/javascripts/behaviors/autosize_spec.js | 2 +- spec/javascripts/behaviors/quick_submit_spec.js | 2 +- spec/javascripts/behaviors/requires_input_spec.js | 2 +- spec/javascripts/extensions/array_spec.js | 2 +- spec/javascripts/extensions/jquery_spec.js | 2 +- spec/javascripts/fixtures/emoji_menu.js | 2 +- spec/javascripts/graphs/stat_graph_contributors_graph_spec.js | 2 +- spec/javascripts/graphs/stat_graph_contributors_util_spec.js | 2 +- spec/javascripts/graphs/stat_graph_spec.js | 2 +- spec/javascripts/header_spec.js | 2 +- spec/javascripts/issue_spec.js | 2 +- spec/javascripts/line_highlighter_spec.js | 2 +- spec/javascripts/merge_request_spec.js | 2 +- spec/javascripts/merge_request_tabs_spec.js | 2 +- spec/javascripts/merge_request_widget_spec.js | 2 +- spec/javascripts/new_branch_spec.js | 2 +- spec/javascripts/notes_spec.js | 2 +- spec/javascripts/project_title_spec.js | 2 +- spec/javascripts/right_sidebar_spec.js | 2 +- spec/javascripts/search_autocomplete_spec.js | 2 +- spec/javascripts/shortcuts_issuable_spec.js | 2 +- spec/javascripts/spec_helper.js | 2 +- spec/javascripts/syntax_highlight_spec.js | 2 +- spec/javascripts/u2f/authenticate_spec.js | 2 +- spec/javascripts/u2f/mock_u2f_device.js | 2 +- spec/javascripts/u2f/register_spec.js | 2 +- spec/javascripts/zen_mode_spec.js | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/application_spec.js b/spec/javascripts/application_spec.js index 16e908f3a81..7e38abc608e 100644 --- a/spec/javascripts/application_spec.js +++ b/spec/javascripts/application_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, padded-blocks, max-len */ /*= require lib/utils/common_utils */ diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js index 3d705e1cb2e..ac1404f6e1c 100644 --- a/spec/javascripts/awards_handler_spec.js +++ b/spec/javascripts/awards_handler_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, comma-dangle, no-undef, new-parens, no-unused-vars, quotes, jasmine/no-spec-dupes, prefer-template, padded-blocks, max-len */ /*= require awards_handler */ /*= require jquery */ diff --git a/spec/javascripts/behaviors/autosize_spec.js b/spec/javascripts/behaviors/autosize_spec.js index 36254a7370e..b4573e53a4e 100644 --- a/spec/javascripts/behaviors/autosize_spec.js +++ b/spec/javascripts/behaviors/autosize_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, comma-dangle, no-return-assign, padded-blocks, max-len */ /*= require behaviors/autosize */ diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js index 7370ccb4a08..efb1203eb2f 100644 --- a/spec/javascripts/behaviors/quick_submit_spec.js +++ b/spec/javascripts/behaviors/quick_submit_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, no-return-assign, comma-dangle, no-undef, jasmine/no-spec-dupes, new-cap, padded-blocks, max-len */ /*= require behaviors/quick_submit */ diff --git a/spec/javascripts/behaviors/requires_input_spec.js b/spec/javascripts/behaviors/requires_input_spec.js index 32469a4fd1f..c3f4c867d6a 100644 --- a/spec/javascripts/behaviors/requires_input_spec.js +++ b/spec/javascripts/behaviors/requires_input_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, padded-blocks */ /*= require behaviors/requires_input */ diff --git a/spec/javascripts/extensions/array_spec.js b/spec/javascripts/extensions/array_spec.js index f28983d7764..c56e6c7789b 100644 --- a/spec/javascripts/extensions/array_spec.js +++ b/spec/javascripts/extensions/array_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, padded-blocks */ /*= require extensions/array */ diff --git a/spec/javascripts/extensions/jquery_spec.js b/spec/javascripts/extensions/jquery_spec.js index 9c361bb0867..76309930f27 100644 --- a/spec/javascripts/extensions/jquery_spec.js +++ b/spec/javascripts/extensions/jquery_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, padded-blocks */ /*= require extensions/jquery */ diff --git a/spec/javascripts/fixtures/emoji_menu.js b/spec/javascripts/fixtures/emoji_menu.js index 41cf40c29cf..3d776bb9277 100644 --- a/spec/javascripts/fixtures/emoji_menu.js +++ b/spec/javascripts/fixtures/emoji_menu.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, padded-blocks */ (function() { window.emojiMenu = "
    \n \n
    \n
    \n Emoticons\n
    \n
      \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    • \n \n
    • \n
    \n
    \n
    "; diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js index 8c66c45ba79..a406e6cc36a 100644 --- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable quotes, no-undef, indent, semi, object-curly-spacing, jasmine/no-suite-dupes, vars-on-top, no-var, padded-blocks, spaced-comment, max-len */ //= require graphs/stat_graph_contributors_graph describe("ContributorsGraph", function () { diff --git a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js index 920e4ee0892..96f39abe13e 100644 --- a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable quotes, padded-blocks, no-var, camelcase, object-curly-spacing, semi, indent, object-property-newline, comma-dangle, comma-spacing, no-undef, spaced-comment, max-len, key-spacing, vars-on-top, quote-props, no-multi-spaces, max-len */ //= require graphs/stat_graph_contributors_util describe("ContributorsStatGraphUtil", function () { diff --git a/spec/javascripts/graphs/stat_graph_spec.js b/spec/javascripts/graphs/stat_graph_spec.js index ae2821ecad9..f78573b992b 100644 --- a/spec/javascripts/graphs/stat_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable quotes, padded-blocks, no-undef, semi */ //= require graphs/stat_graph describe("StatGraph", function () { diff --git a/spec/javascripts/header_spec.js b/spec/javascripts/header_spec.js index 9a859655d8b..d2bcbc37b64 100644 --- a/spec/javascripts/header_spec.js +++ b/spec/javascripts/header_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, padded-blocks, no-var */ /*= require header */ /*= require lib/utils/text_utility */ /*= require jquery */ diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js index 949114185cf..beef46122ab 100644 --- a/spec/javascripts/issue_spec.js +++ b/spec/javascripts/issue_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-use-before-define, indent, no-undef, no-trailing-spaces, comma-dangle, padded-blocks, max-len */ /*= require lib/utils/text_utility */ /*= require issue */ diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js index e0192a2d624..b8b174a2e53 100644 --- a/spec/javascripts/line_highlighter_spec.js +++ b/spec/javascripts/line_highlighter_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-undef, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, no-plusplus, jasmine/no-spec-dupes, no-underscore-dangle, padded-blocks, max-len */ /*= require line_highlighter */ diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js index 83d279ab414..cbe2634d3a4 100644 --- a/spec/javascripts/merge_request_spec.js +++ b/spec/javascripts/merge_request_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-return-assign, no-undef, padded-blocks */ /*= require merge_request */ diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js index 6a53c6aa6ac..971222c44e1 100644 --- a/spec/javascripts/merge_request_tabs_spec.js +++ b/spec/javascripts/merge_request_tabs_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, comma-dangle, dot-notation, quotes, no-undef, no-return-assign, no-underscore-dangle, camelcase, padded-blocks, max-len */ /*= require merge_request_tabs */ //= require breakpoints diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 91f19aca719..8c5afc2ff3c 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, quotes, comma-dangle, dot-notation, indent, quote-props, no-var, padded-blocks, max-len */ /*= require merge_request_widget */ /*= require lib/utils/timeago.js */ diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js index c092424ec32..8828970d984 100644 --- a/spec/javascripts/new_branch_spec.js +++ b/spec/javascripts/new_branch_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, no-undef, quotes, padded-blocks, max-len */ /*= require jquery-ui/autocomplete */ /*= require new_branch_form */ diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js index 2e3a4b66e2d..51f2ae8bcbd 100644 --- a/spec/javascripts/notes_spec.js +++ b/spec/javascripts/notes_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-unused-expressions, no-undef, no-var, object-shorthand, comma-dangle, semi, padded-blocks, max-len */ /*= require notes */ /*= require autosize */ /*= require gl_form */ diff --git a/spec/javascripts/project_title_spec.js b/spec/javascripts/project_title_spec.js index 1963857bba3..49211a6b852 100644 --- a/spec/javascripts/project_title_spec.js +++ b/spec/javascripts/project_title_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-unused-expressions, no-return-assign, no-undef, no-param-reassign, no-var, new-cap, wrap-iife, no-unused-vars, quotes, padded-blocks, max-len */ /*= require bootstrap */ /*= require select2 */ diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js index ef03d1147de..83ebbd63f3a 100644 --- a/spec/javascripts/right_sidebar_spec.js +++ b/spec/javascripts/right_sidebar_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-undef, no-return-assign, new-cap, vars-on-top, semi, padded-blocks, max-len */ /*= require right_sidebar */ /*= require jquery */ diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index 29080804960..1b7f642d59e 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, max-len, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, comma-dangle, object-shorthand, prefer-template, quotes, new-parens, vars-on-top, new-cap, padded-blocks, max-len */ /*= require gl_dropdown */ /*= require search_autocomplete */ diff --git a/spec/javascripts/shortcuts_issuable_spec.js b/spec/javascripts/shortcuts_issuable_spec.js index 1f36a048153..7d36d79b687 100644 --- a/spec/javascripts/shortcuts_issuable_spec.js +++ b/spec/javascripts/shortcuts_issuable_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-return-assign, no-undef, no-var, quotes, padded-blocks, max-len */ /*= require shortcuts_issuable */ diff --git a/spec/javascripts/spec_helper.js b/spec/javascripts/spec_helper.js index 9cb8243ee2c..8a64de4dd43 100644 --- a/spec/javascripts/spec_helper.js +++ b/spec/javascripts/spec_helper.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren */ // PhantomJS (Teaspoons default driver) doesn't have support for // Function.prototype.bind, which has caused confusion. Use this polyfill to // avoid the confusion. diff --git a/spec/javascripts/syntax_highlight_spec.js b/spec/javascripts/syntax_highlight_spec.js index 498f0f06797..ac411f6c306 100644 --- a/spec/javascripts/syntax_highlight_spec.js +++ b/spec/javascripts/syntax_highlight_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, no-return-assign, quotes, padded-blocks */ /*= require syntax_highlight */ diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js index 024a91f0a80..944df6d23f7 100644 --- a/spec/javascripts/u2f/authenticate_spec.js +++ b/spec/javascripts/u2f/authenticate_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, new-parens, no-undef, quotes, comma-dangle, no-var, one-var, one-var-declaration-per-line, padded-blocks, max-len */ /*= require u2f/authenticate */ /*= require u2f/util */ diff --git a/spec/javascripts/u2f/mock_u2f_device.js b/spec/javascripts/u2f/mock_u2f_device.js index ad133682fb1..1459f968c3d 100644 --- a/spec/javascripts/u2f/mock_u2f_device.js +++ b/spec/javascripts/u2f/mock_u2f_device.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-unused-expressions, no-return-assign, no-param-reassign, padded-blocks, max-len */ (function() { var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; diff --git a/spec/javascripts/u2f/register_spec.js b/spec/javascripts/u2f/register_spec.js index abea76f622f..0c73c5772bd 100644 --- a/spec/javascripts/u2f/register_spec.js +++ b/spec/javascripts/u2f/register_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, new-parens, no-undef, quotes, no-var, one-var, one-var-declaration-per-line, comma-dangle, padded-blocks, max-len */ /*= require u2f/register */ /*= require u2f/util */ diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js index 65b6e3dce33..a18e8aee9b1 100644 --- a/spec/javascripts/zen_mode_spec.js +++ b/spec/javascripts/zen_mode_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable */ +/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-undef, object-shorthand, comma-dangle, no-return-assign, new-cap, padded-blocks, max-len */ /*= require zen_mode */ -- cgit v1.2.1 From 5bc19dec54643fe045b40206232fd93fbe4befb1 Mon Sep 17 00:00:00 2001 From: Cagdas Gerede Date: Tue, 15 Nov 2016 21:23:20 +0300 Subject: Remove newlines between context and it in addition to testing redirection for create action to import path --- spec/controllers/projects/forks_controller_spec.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index ad1f4b849e5..028ea067a97 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -76,7 +76,6 @@ describe Projects::ForksController do end context 'when user is signed in' do - it 'responds with status 200' do sign_in(user) @@ -87,7 +86,6 @@ describe Projects::ForksController do end context 'when user is not signed in' do - it 'redirects to the sign-in page' do sign_out(user) @@ -107,20 +105,17 @@ describe Projects::ForksController do end context 'when user is signed in' do - it 'responds with status 302' do sign_in(user) post_create expect(response).to have_http_status(302) - expected_import_url = namespace_project_import_url(user.namespace, project) - expect(response.headers['Location']).to eq(expected_import_url) + expect(response).to redirect_to(namespace_project_import_path(user.namespace, project)) end end context 'when user is not signed in' do - it 'redirects to the sign-in page' do sign_out(user) -- cgit v1.2.1 From 5ac2c5839ac47d39b962cbfd236a61eadd5eb2c6 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 15 Nov 2016 13:24:25 -0600 Subject: Create separate view for pipeline view with tabs --- spec/features/projects/pipelines_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/projects/pipelines_spec.rb b/spec/features/projects/pipelines_spec.rb index db56a50e058..77184ede784 100644 --- a/spec/features/projects/pipelines_spec.rb +++ b/spec/features/projects/pipelines_spec.rb @@ -156,7 +156,10 @@ describe "Pipelines" do @external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external') end - before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) } + before do + visit namespace_project_pipeline_path(project.namespace, project, pipeline) + find('.builds-tab').click + end it 'shows a list of builds' do expect(page).to have_content('Test') -- cgit v1.2.1 From 34a86120ed52b5e77ef2cd51a60bed1208671639 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Wed, 16 Nov 2016 00:16:45 +0500 Subject: Use setter for key instead AR callback ref: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6763 --- spec/models/key_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 7fc6ed1dd54..ba9cdf7dddb 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -82,4 +82,14 @@ describe Key, models: true do @key.destroy end end + + describe '#key=' do + let(:valid_key) do + "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0= dummy@gitlab.com" + end + + it 'strips white spaces' do + expect(described_class.new(key: " #{valid_key} ").key).to eq(valid_key) + end + end end -- cgit v1.2.1 From 2a951840451cf86f3ddfa4675cb3a5e360b89867 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Wed, 16 Nov 2016 00:27:49 +0500 Subject: Remove instance vars from key model tests --- spec/models/key_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index ba9cdf7dddb..1a26cee9f3d 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -71,15 +71,15 @@ describe Key, models: true do context 'callbacks' do it 'adds new key to authorized_file' do - @key = build(:personal_key, id: 7) - expect(GitlabShellWorker).to receive(:perform_async).with(:add_key, @key.shell_id, @key.key) - @key.save + key = build(:personal_key, id: 7) + expect(GitlabShellWorker).to receive(:perform_async).with(:add_key, key.shell_id, key.key) + key.save! end it 'removes key from authorized_file' do - @key = create(:personal_key) - expect(GitlabShellWorker).to receive(:perform_async).with(:remove_key, @key.shell_id, @key.key) - @key.destroy + key = create(:personal_key) + expect(GitlabShellWorker).to receive(:perform_async).with(:remove_key, key.shell_id, key.key) + key.destroy end end -- cgit v1.2.1 From dbf5c8abfe44ce8bf4a9517a8acead961edb3e3e Mon Sep 17 00:00:00 2001 From: the-undefined Date: Tue, 15 Nov 2016 07:10:43 +0000 Subject: Move 'Search Snippets' Spinach feature to Rspec This commit moves the `search_snippets.feature` Spinach test to a Rspec feature, as part of deprecating the Spinach test suite. - Remove Spinach discover snippets feature and steps - Remove unused `SharedSearch` module - Add Rspec feature scenarios --- spec/features/snippets/search_snippets_spec.rb | 66 ++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 spec/features/snippets/search_snippets_spec.rb (limited to 'spec') diff --git a/spec/features/snippets/search_snippets_spec.rb b/spec/features/snippets/search_snippets_spec.rb new file mode 100644 index 00000000000..146cd3af848 --- /dev/null +++ b/spec/features/snippets/search_snippets_spec.rb @@ -0,0 +1,66 @@ +require 'rails_helper' + +feature 'Search Snippets', feature: true do + scenario 'User searches for snippets by title' do + public_snippet = create(:personal_snippet, :public, title: 'Beginning and Middle') + private_snippet = create(:personal_snippet, :private, title: 'Middle and End') + + login_as private_snippet.author + visit dashboard_snippets_path + + page.within '.search' do + fill_in 'search', with: 'Middle' + click_button 'Go' + end + + click_link 'Titles and Filenames' + + expect(page).to have_link(public_snippet.title) + expect(page).to have_link(private_snippet.title) + end + + scenario 'User searches for snippet contents' do + create(:personal_snippet, + :public, + title: 'Many lined snippet', + content: <<-CONTENT.strip_heredoc + |line one + |line two + |line three + |line four + |line five + |line six + |line seven + |line eight + |line nine + |line ten + |line eleven + |line twelve + |line thirteen + |line fourteen + CONTENT + ) + + login_as create(:user) + visit dashboard_snippets_path + + page.within '.search' do + fill_in 'search', with: 'line seven' + click_button 'Go' + end + + expect(page).to have_content('line seven') + + # 3 lines before the matched line should be visible + expect(page).to have_content('line six') + expect(page).to have_content('line five') + expect(page).to have_content('line four') + expect(page).not_to have_content('line three') + + # 3 lines after the matched line should be visible + expect(page).to have_content('line eight') + expect(page).to have_content('line nine') + expect(page).to have_content('line ten') + expect(page).not_to have_content('line eleven') + end +end -- cgit v1.2.1 From 8c3e6987d931847b72752dfcac4215dbdc47fd88 Mon Sep 17 00:00:00 2001 From: Lucas Deschamps Date: Wed, 9 Nov 2016 07:59:51 +0100 Subject: Navigation bar issuables counters reflects dashboard issuables counters --- spec/features/dashboard/issuables_counter_spec.rb | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 spec/features/dashboard/issuables_counter_spec.rb (limited to 'spec') diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb new file mode 100644 index 00000000000..699bc102790 --- /dev/null +++ b/spec/features/dashboard/issuables_counter_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe 'Navigation bar counter', feature: true, js: true, caching: true do + let(:user) { create(:user) } + let(:project) { create(:project, namespace: user.namespace) } + + before do + login_as(user) + visit issues_dashboard_path + end + + it 'reflects dashboard issues count' do + create(:issue, project: project, assignee: user) + visit issues_dashboard_path + + dashboard_count = find('li.active span.badge') + nav_count = find('.dashboard-shortcuts-issues span.count') + + expect(dashboard_count).to have_content('0') + expect(nav_count).to have_content('0') + end + + it 'reflects dashboard merge requests count' do + create(:merge_request, assignee: user) + visit merge_requests_dashboard_path + + dashboard_count = find('li.active span.badge') + nav_count = find('.dashboard-shortcuts-merge_requests span.count') + + expect(dashboard_count).to have_content('0') + expect(nav_count).to have_content('0') + end +end -- cgit v1.2.1 From 677af1dd30f9b44a7be9eaa68bddda38331b8bbb Mon Sep 17 00:00:00 2001 From: Lucas Deschamps Date: Wed, 9 Nov 2016 23:15:29 +0100 Subject: Improve changes after MR review. --- spec/features/dashboard/issuables_counter_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb index 699bc102790..f134eee19eb 100644 --- a/spec/features/dashboard/issuables_counter_spec.rb +++ b/spec/features/dashboard/issuables_counter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'Navigation bar counter', feature: true, js: true, caching: true do let(:user) { create(:user) } - let(:project) { create(:project, namespace: user.namespace) } + let(:project) { create(:empty_project, namespace: user.namespace) } before do login_as(user) -- cgit v1.2.1 From 7fa366107b30fa0ccac758ff9e6854f86e54b116 Mon Sep 17 00:00:00 2001 From: Lucas Deschamps Date: Thu, 10 Nov 2016 23:41:25 +0100 Subject: Improve issuables_counter_spec relevance. --- spec/features/dashboard/issuables_counter_spec.rb | 33 +++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb index f134eee19eb..1960552b411 100644 --- a/spec/features/dashboard/issuables_counter_spec.rb +++ b/spec/features/dashboard/issuables_counter_spec.rb @@ -1,33 +1,50 @@ require 'spec_helper' -describe 'Navigation bar counter', feature: true, js: true, caching: true do +describe 'Navigation bar counter', feature: true, js: true do let(:user) { create(:user) } let(:project) { create(:empty_project, namespace: user.namespace) } before do login_as(user) - visit issues_dashboard_path end it 'reflects dashboard issues count' do - create(:issue, project: project, assignee: user) + issue = create(:issue, project: project, assignee: user) + visit issues_dashboard_path + + dashboard_count = find('li.active span.badge') + nav_count = find('.dashboard-shortcuts-issues span.count') + + expect(nav_count).to have_content('1') + expect(dashboard_count).to have_content('1') + + issue.assignee = nil visit issues_dashboard_path dashboard_count = find('li.active span.badge') nav_count = find('.dashboard-shortcuts-issues span.count') - expect(dashboard_count).to have_content('0') - expect(nav_count).to have_content('0') + expect(nav_count).to have_content('1') + expect(dashboard_count).to have_content('1') end it 'reflects dashboard merge requests count' do - create(:merge_request, assignee: user) + merge_request = create(:merge_request, source_project: project, assignee: user) + visit merge_requests_dashboard_path + + dashboard_count = find('li.active span.badge') + nav_count = find('.dashboard-shortcuts-merge_requests span.count') + + expect(nav_count).to have_content('1') + expect(dashboard_count).to have_content('1') + + merge_request.assignee = nil visit merge_requests_dashboard_path dashboard_count = find('li.active span.badge') nav_count = find('.dashboard-shortcuts-merge_requests span.count') - expect(dashboard_count).to have_content('0') - expect(nav_count).to have_content('0') + expect(nav_count).to have_content('1') + expect(dashboard_count).to have_content('1') end end -- cgit v1.2.1 From 3d13096f7198ed1ec4b7c568977877452f842394 Mon Sep 17 00:00:00 2001 From: Lucas Deschamps Date: Tue, 15 Nov 2016 09:05:19 +0100 Subject: Refactor issuables_counter_spec. --- spec/features/dashboard/issuables_counter_spec.rb | 40 ++++++++++------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb index 1960552b411..41dcfe439c2 100644 --- a/spec/features/dashboard/issuables_counter_spec.rb +++ b/spec/features/dashboard/issuables_counter_spec.rb @@ -1,50 +1,44 @@ require 'spec_helper' -describe 'Navigation bar counter', feature: true, js: true do +describe 'Navigation bar counter', feature: true, js: true, caching: true do let(:user) { create(:user) } let(:project) { create(:empty_project, namespace: user.namespace) } + let(:issue) { create(:issue, project: project) } + let(:merge_request) { create(:merge_request, source_project: project) } before do + issue.update(assignee: user) + merge_request.update(assignee: user) login_as(user) end it 'reflects dashboard issues count' do - issue = create(:issue, project: project, assignee: user) visit issues_dashboard_path - dashboard_count = find('li.active span.badge') - nav_count = find('.dashboard-shortcuts-issues span.count') - - expect(nav_count).to have_content('1') - expect(dashboard_count).to have_content('1') + expect_counters('issues', '1') - issue.assignee = nil + issue.update(assignee: nil) visit issues_dashboard_path - dashboard_count = find('li.active span.badge') - nav_count = find('.dashboard-shortcuts-issues span.count') - - expect(nav_count).to have_content('1') - expect(dashboard_count).to have_content('1') + expect_counters('issues', '1') end it 'reflects dashboard merge requests count' do - merge_request = create(:merge_request, source_project: project, assignee: user) visit merge_requests_dashboard_path - dashboard_count = find('li.active span.badge') - nav_count = find('.dashboard-shortcuts-merge_requests span.count') - - expect(nav_count).to have_content('1') - expect(dashboard_count).to have_content('1') + expect_counters('merge_requests', '1') - merge_request.assignee = nil + merge_request.update(assignee: nil) visit merge_requests_dashboard_path + expect_counters('merge_requests', '1') + end + + def expect_counters(issuable_type, count) dashboard_count = find('li.active span.badge') - nav_count = find('.dashboard-shortcuts-merge_requests span.count') + nav_count = find(".dashboard-shortcuts-#{issuable_type} span.count") - expect(nav_count).to have_content('1') - expect(dashboard_count).to have_content('1') + expect(nav_count).to have_content(count) + expect(dashboard_count).to have_content(count) end end -- cgit v1.2.1 From 00d9d7678b9df3a25c4f4e8f210c9d17a798c9cd Mon Sep 17 00:00:00 2001 From: Ben Bodenmiller Date: Wed, 16 Nov 2016 01:49:45 -0800 Subject: fix "Without projects" filter --- spec/models/user_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'spec') diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 3b152e15b61..0dd63017780 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -490,6 +490,28 @@ describe User, models: true do end end + describe '.without_projects' do + let!(:project) { create(:empty_project, :public) } + let!(:user) { create(:user) } + let!(:user_without_project) { create(:user) } + let!(:user_without_project2) { create(:user) } + + before do + # add user to project + project.team << [user, :master] + + # create invite to projet + create(:project_member, :developer, project: project, invite_token: '1234', invite_email: 'inviteduser1@example.com') + + # create request to join project + project.request_access(user_without_project2) + end + + it { expect(User.without_projects).not_to include user } + it { expect(User.without_projects).to include user_without_project } + it { expect(User.without_projects).to include user_without_project2 } + end + describe '.not_in_project' do before do User.delete_all -- cgit v1.2.1 From d9d69d7ba7dd660c9b3e0ab30b58891a8b760328 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 16 Nov 2016 11:26:36 +0100 Subject: Add specs for environments recently updated on branch --- spec/models/environment_spec.rb | 21 +++++++++++++++++++++ spec/models/project_spec.rb | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) (limited to 'spec') diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index a94e6d0165f..60bbe3fcd72 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -166,4 +166,25 @@ describe Environment, models: true do end end end + + describe 'recently_updated_on_branch?' do + subject { environment.recently_updated_on_branch?('feature') } + + context 'when last deployment to environment is the most recent one' do + before do + create(:deployment, environment: environment, ref: 'feature') + end + + it { is_expected.to be true } + end + + context 'when last deployment to environment is not the most recent' do + before do + create(:deployment, environment: environment, ref: 'feature') + create(:deployment, environment: environment, ref: 'master') + end + + it { is_expected.to be false } + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index d835eac34c2..dd30ec123a7 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1688,6 +1688,48 @@ describe Project, models: true do end end + describe '#environments_recently_updated_on_branch' do + let(:project) { create(:project) } + let(:environment) { create(:environment, project: project) } + + context 'when last deployment to environment is the most recent one' do + before do + create(:deployment, environment: environment, ref: 'feature') + end + + it 'finds recently updated environment' do + expect(project.environments_recently_updated_on_branch('feature')) + .to contain_exactly(environment) + end + end + + context 'when last deployment to environment is not the most recent' do + before do + create(:deployment, environment: environment, ref: 'feature') + create(:deployment, environment: environment, ref: 'master') + end + + it 'does not find environment' do + expect(project.environments_recently_updated_on_branch('feature')) + .to be_empty + end + end + + context 'when there are two environments that deploy to the same branch' do + let(:second_environment) { create(:environment, project: project) } + + before do + create(:deployment, environment: environment, ref: 'feature') + create(:deployment, environment: second_environment, ref: 'feature') + end + + it 'finds both environments' do + expect(project.environments_recently_updated_on_branch('feature')) + .to contain_exactly(environment, second_environment) + end + end + end + def enable_lfs allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) end -- cgit v1.2.1 From f913170e2f76ef44800f0272cb7fb40b9d6709ee Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Wed, 16 Nov 2016 11:33:20 +0100 Subject: Do not create a MergeRequestDiff record when source branch is deleted In order to have a valid MergeRequestDiff record when need head_commit_sha. When a source branch is deleted head_commit_sha is nil. This causes an exception in merge request "Changes" tab. --- spec/services/merge_requests/refresh_service_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index e515bc9f89c..0220f7e1db2 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -227,6 +227,16 @@ describe MergeRequests::RefreshService, services: true do end end + context 'when the source branch is deleted' do + it 'does not create a MergeRequestDiff record' do + refresh_service = service.new(@project, @user) + + expect do + refresh_service.execute(@oldrev, Gitlab::Git::BLANK_SHA, 'refs/heads/master') + end.not_to change { MergeRequestDiff.count } + end + end + def reload_mrs @merge_request.reload @fork_merge_request.reload -- cgit v1.2.1 From 72f538731a233ab0f75e4ac139452806e2ee8cf0 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 16 Nov 2016 12:23:39 +0100 Subject: Remove redundant call to after branch delete service --- spec/features/environments_spec.rb | 17 ++++++++++++++++- spec/services/delete_branch_service_spec.rb | 12 ------------ 2 files changed, 16 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 8b34cb13b9d..e57c355916d 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -291,11 +291,26 @@ feature 'Environments', feature: true do scenario 'user deletes the branch with running environment' do visit namespace_project_branches_path(project.namespace, project) - page.within('.js-branch-feature') { find('a.btn-remove').click } + remove_branch_with_hooks(project, user, 'feature') do + page.within('.js-branch-feature') { find('a.btn-remove').click } + end + visit_environment(environment) expect(page).to have_no_link('Stop') end + + def remove_branch_with_hooks(project, user, branch) + params = { + oldrev: project.commit(branch).id, + newrev: Gitlab::Git::BLANK_SHA, + ref: "refs/heads/#{branch}" + } + + yield + + GitPushService.new(project, user, params).execute + end end def visit_environments(project) diff --git a/spec/services/delete_branch_service_spec.rb b/spec/services/delete_branch_service_spec.rb index 3ca4eb14518..336f5dafb5b 100644 --- a/spec/services/delete_branch_service_spec.rb +++ b/spec/services/delete_branch_service_spec.rb @@ -20,12 +20,6 @@ describe DeleteBranchService, services: true do expect(result[:status]).to eq :success expect(branch_exists?('feature')).to be false end - - it 'calls after branch delete hooks' do - expect(service).to receive(:execute_after_branch_delete_hooks) - - service.execute('feature') - end end context 'when user does not have access to push to repository' do @@ -38,12 +32,6 @@ describe DeleteBranchService, services: true do expect(result[:message]).to eq 'You dont have push access to repo' expect(branch_exists?('feature')).to be true end - - it 'does not call after branch delete hooks' do - expect(service).not_to receive(:execute_after_branch_delete_hooks) - - service.execute('feature') - end end end -- cgit v1.2.1 From 3cf516cd201e0802d284d664e50dfde409047ca4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 16 Nov 2016 12:33:04 +0100 Subject: Add comment related to workaround used in specs --- spec/features/environments_spec.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index e57c355916d..1fe509c2cac 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -300,6 +300,9 @@ feature 'Environments', feature: true do expect(page).to have_no_link('Stop') end + ## + # This is a workaround for problem described in #24543 + # def remove_branch_with_hooks(project, user, branch) params = { oldrev: project.commit(branch).id, -- cgit v1.2.1 From ca89b6e3d2af2e78b2b726c468caa2c9f678544c Mon Sep 17 00:00:00 2001 From: Herbert Kagumba Date: Wed, 16 Nov 2016 14:09:40 +0300 Subject: Change the slack notification comment link. --- .../project_services/slack_service/note_message_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb index 38cfe4ad3e3..97f818125d3 100644 --- a/spec/models/project_services/slack_service/note_message_spec.rb +++ b/spec/models/project_services/slack_service/note_message_spec.rb @@ -37,8 +37,8 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on commits' do message = SlackService::NoteMessage.new(@args) - expect(message.pretext).to eq("test.user commented on " \ - " in : " \ + expect(message.pretext).to eq("test.user in : " \ "*Added a commit message*") expected_attachments = [ { @@ -63,8 +63,8 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on a merge request' do message = SlackService::NoteMessage.new(@args) - expect(message.pretext).to eq("test.user commented on " \ - " in : " \ + expect(message.pretext).to eq("test.user in : " \ "*merge request title*") expected_attachments = [ { @@ -90,8 +90,8 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on an issue' do message = SlackService::NoteMessage.new(@args) expect(message.pretext).to eq( - "test.user commented on " \ - " in : " \ + "test.user in : " \ "*issue title*") expected_attachments = [ { @@ -115,8 +115,8 @@ describe SlackService::NoteMessage, models: true do it 'returns a message regarding notes on a project snippet' do message = SlackService::NoteMessage.new(@args) - expect(message.pretext).to eq("test.user commented on " \ - " in : " \ + expect(message.pretext).to eq("test.user in : " \ "*snippet title*") expected_attachments = [ { -- cgit v1.2.1 From ef3be00a0297dfa31002616df6ee49a0e2132cb7 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Wed, 16 Nov 2016 12:46:07 +0100 Subject: Defer saving project services to the database if there are no user changes --- spec/models/project_spec.rb | 6 ------ spec/models/service_spec.rb | 10 +++------- spec/requests/api/services_spec.rb | 3 +-- spec/services/projects/create_service_spec.rb | 20 +++++++++++++------- 4 files changed, 17 insertions(+), 22 deletions(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0810d06b50f..642f1edfe3f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -496,9 +496,6 @@ describe Project, models: true do end it 'returns nil and does not query services when there is no external issue tracker' do - project.build_missing_services - project.reload - expect(project).not_to receive(:services) expect(project.external_issue_tracker).to eq(nil) @@ -506,9 +503,6 @@ describe Project, models: true do it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do ext_project.reload # Factory returns a project with changed attributes - ext_project.build_missing_services - ext_project.reload - expect(ext_project).to receive(:services).once.and_call_original 2.times { expect(ext_project.external_issue_tracker).to be_a_kind_of(RedmineService) } diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 43937a54b2c..b1615a95004 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -53,7 +53,7 @@ describe Service, models: true do describe "Template" do describe "for pushover service" do - let(:service_template) do + let!(:service_template) do PushoverService.create( template: true, properties: { @@ -66,13 +66,9 @@ describe Service, models: true do let(:project) { create(:project) } describe 'is prefilled for projects pushover service' do - before do - service_template - project.build_missing_services - end - it "has all fields prefilled" do - service = project.pushover_service + service = project.find_or_initialize_service('pushover') + expect(service.template).to eq(false) expect(service.device).to eq('MyDevice') expect(service.sound).to eq('mic') diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 375671bca4c..2aadab3cbe1 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -56,8 +56,7 @@ describe API::API, api: true do # inject some properties into the service before do - project.build_missing_services - service_object = project.send(service_method) + service_object = project.find_or_initialize_service(service) service_object.properties = service_attrs service_object.save end diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 876bfaf085c..2cf9883113c 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -10,13 +10,6 @@ describe Projects::CreateService, services: true do } end - it 'creates services on Project creation' do - project = create_project(@user, @opts) - project.reload - - expect(project.services).not_to be_empty - end - it 'creates labels on Project creation if there are templates' do Label.create(title: "bug", template: true) project = create_project(@user, @opts) @@ -137,6 +130,19 @@ describe Projects::CreateService, services: true do expect(project.namespace).to eq(@user.namespace) end end + + context 'when there is an active service template' do + before do + create(:service, project: nil, template: true, active: true) + end + + it 'creates a service from this template' do + project = create_project(@user, @opts) + project.reload + + expect(project.services.count).to eq 1 + end + end end def create_project(user, opts) -- cgit v1.2.1 From aa9a289ce55d5099e6a65f25e7c3b38f66148aca Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 11 Nov 2016 15:40:19 +0100 Subject: Make mail_room idle_timeout option configurable. --- spec/config/mail_room_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb index 22bf3055538..294fae95752 100644 --- a/spec/config/mail_room_spec.rb +++ b/spec/config/mail_room_spec.rb @@ -47,6 +47,7 @@ describe 'mail_room.yml' do expect(mailbox[:email]).to eq('gitlab-incoming@gmail.com') expect(mailbox[:password]).to eq('[REDACTED]') expect(mailbox[:name]).to eq('inbox') + expect(mailbox[:idle_timeout]).to eq(60) redis_url = gitlab_redis.url sentinels = gitlab_redis.sentinels -- cgit v1.2.1 From cd476336d9c8f07c5a70fb05f646727965139706 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 25 Oct 2016 13:50:27 +0100 Subject: tests --- spec/features/environments_spec.rb | 484 ++++++++++++++++++++----------------- 1 file changed, 259 insertions(+), 225 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index b565586ee14..c8ea4bb3945 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -1,7 +1,10 @@ require 'spec_helper' +require 'rails_helper' -feature 'Environments', feature: true do - given(:project) { create(:empty_project) } +feature 'Environments', feature: true, js:true do + include WaitForVueResource + + given(:project) { create(:project) } given(:user) { create(:user) } given(:role) { :developer } @@ -15,18 +18,17 @@ feature 'Environments', feature: true do given!(:deployment) { } given!(:manual) { } - before do - visit namespace_project_environments_path(project.namespace, project) - end - - context 'shows two tabs' do - scenario 'shows "Available" and "Stopped" tab with links' do + context 'without environments' do + before do + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource + end + + scenario 'does show "Available" and "Stopped" tab with links' do expect(page).to have_link('Available') expect(page).to have_link('Stopped') end - end - context 'without environments' do scenario 'does show no environments' do expect(page).to have_content('You don\'t have any environments right now.') end @@ -36,239 +38,271 @@ feature 'Environments', feature: true do expect(page.find('.js-stopped-environments-count').text).to eq('0') end end - - context 'with environments' do + + context 'loading environments' do given(:environment) { create(:environment, project: project) } + + before do + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource + end - scenario 'does show environment name' do - expect(page).to have_link(environment.name) + scenario 'does show loading spinner' do + expect(page).to have_selector('.environments-list-loading') end + end + context 'with environments' do + let(:environment1) { create(:environment, project: project) } + let(:environment2) { create(:environment, project: project) } + + before do + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource + expect(page).to have_selector('.table.ci-table.environments') + end + + scenario 'does show "Available" and "Stopped" tab with links' do + expect(page).to have_link('Stopped') + expect(page).to have_link('Available') + end + + scenario 'does show environment name' do + expect(page).to have_link(environment1.name) + end + scenario 'does show number of available and stopped environments' do expect(page.find('.js-available-environments-count').text).to eq('1') expect(page.find('.js-stopped-environments-count').text).to eq('0') end - + context 'without deployments' do scenario 'does show no deployments' do expect(page).to have_content('No deployments yet') end end - context 'with deployments' do - given(:deployment) { create(:deployment, environment: environment) } - - scenario 'does show deployment SHA' do - expect(page).to have_link(deployment.short_sha) - end - - scenario 'does show deployment internal id' do - expect(page).to have_content(deployment.iid) - end - - context 'with build and manual actions' do - given(:pipeline) { create(:ci_pipeline, project: project) } - given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - - scenario 'does show a play button' do - expect(page).to have_link(manual.name.humanize) - end - - scenario 'does allow to play manual action' do - expect(manual).to be_skipped - expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } - expect(page).to have_content(manual.name) - expect(manual.reload).to be_pending - end - - scenario 'does show build name and id' do - expect(page).to have_link("#{build.name} (##{build.id})") - end - - scenario 'does not show stop button' do - expect(page).not_to have_selector('.stop-env-link') - end - - scenario 'does not show external link button' do - expect(page).not_to have_css('external-url') - end - - context 'with external_url' do - given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } - given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - - scenario 'does show an external link button' do - expect(page).to have_link(nil, href: environment.external_url) - end - end - - context 'with stop action' do - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } - given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - - scenario 'does show stop button' do - expect(page).to have_selector('.stop-env-link') - end - - scenario 'starts build when stop button clicked' do - first('.stop-env-link').click - - expect(page).to have_content('close_app') - end - - context 'for reporter' do - let(:role) { :reporter } - - scenario 'does not show stop button' do - expect(page).not_to have_selector('.stop-env-link') - end - end - end - end - end - end - - scenario 'does have a New environment button' do - expect(page).to have_link('New environment') + # context 'with deployments' do + # given(:deployment) { create(:deployment, environment: environment) } + # + # scenario 'does show deployment SHA' do + # expect(page).to have_link(deployment.short_sha) + # end + # + # scenario 'does show deployment internal id' do + # expect(page).to have_content(deployment.iid) + # end + # + # context 'with build and manual actions' do + # given(:pipeline) { create(:ci_pipeline, project: project) } + # given(:build) { create(:ci_build, pipeline: pipeline) } + # given(:deployment) { create(:deployment, environment: environment, deployable: build) } + # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + # + # scenario 'does show a play button' do + # expect(page).to have_link(manual.name.humanize) + # end + # + # scenario 'does allow to play manual action' do + # expect(manual).to be_skipped + # expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + # expect(page).to have_content(manual.name) + # expect(manual.reload).to be_pending + # end + # + # scenario 'does show build name and id' do + # expect(page).to have_link("#{build.name} (##{build.id})") + # end + # + # scenario 'does not show stop button' do + # expect(page).not_to have_selector('.stop-env-link') + # end + # + # scenario 'does not show external link button' do + # expect(page).not_to have_css('external-url') + # end + # + # # context 'with external_url' do + # given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + # given(:build) { create(:ci_build, pipeline: pipeline) } + # given(:deployment) { create(:deployment, environment: environment, deployable: build) } + # + # scenario 'does show an external link button' do + # expect(page).to have_link(nil, href: environment.external_url) + # end + # end + # + # # context 'with stop action' do + # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + # given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + # + # scenario 'does show stop button' do + # expect(page).to have_selector('.stop-env-link') + # end + # + # scenario 'starts build when stop button clicked' do + # first('.stop-env-link').click + # + # expect(page).to have_content('close_app') + # end + # + # context 'for reporter' do + # let(:role) { :reporter } + # + # scenario 'does not show stop button' do + # expect(page).not_to have_selector('.stop-env-link') + # end + # end + # end + # end + # end end - end - - describe 'when showing the environment' do - given(:environment) { create(:environment, project: project) } - given!(:deployment) { } - given!(:manual) { } - - before do - visit namespace_project_environment_path(project.namespace, project, environment) - end - - context 'without deployments' do - scenario 'does show no deployments' do - expect(page).to have_content('You don\'t have any deployments right now.') - end - end - - context 'with deployments' do - given(:deployment) { create(:deployment, environment: environment) } - - scenario 'does show deployment SHA' do - expect(page).to have_link(deployment.short_sha) - end - - scenario 'does not show a re-deploy button for deployment without build' do - expect(page).not_to have_link('Re-deploy') - end - - context 'with build' do - given(:pipeline) { create(:ci_pipeline, project: project) } - given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - - scenario 'does show build name' do - expect(page).to have_link("#{build.name} (##{build.id})") - end - - scenario 'does show re-deploy button' do - expect(page).to have_link('Re-deploy') - end - - scenario 'does not show stop button' do - expect(page).not_to have_link('Stop') - end - - context 'with manual action' do - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - - scenario 'does show a play button' do - expect(page).to have_link(manual.name.humanize) - end - - scenario 'does allow to play manual action' do - expect(manual).to be_skipped - expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } - expect(page).to have_content(manual.name) - expect(manual.reload).to be_pending - end - - context 'with external_url' do - given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } - given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - - scenario 'does show an external link button' do - expect(page).to have_link(nil, href: environment.external_url) - end - end - - context 'with stop action' do - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } - given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - - scenario 'does show stop button' do - expect(page).to have_link('Stop') - end - - scenario 'does allow to stop environment' do - click_link('Stop') - - expect(page).to have_content('close_app') - end - - context 'for reporter' do - let(:role) { :reporter } - - scenario 'does not show stop button' do - expect(page).not_to have_link('Stop') - end - end - end - end - end - end - end - - describe 'when creating a new environment' do - before do - visit namespace_project_environments_path(project.namespace, project) - end - - context 'when logged as developer' do + + context 'can create new environment' do before do - click_link 'New environment' - end - - context 'for valid name' do - before do - fill_in('Name', with: 'production') - click_on 'Save' - end - - scenario 'does create a new pipeline' do - expect(page).to have_content('Production') - end - end - - context 'for invalid name' do - before do - fill_in('Name', with: 'name,with,commas') - click_on 'Save' - end - - scenario 'does show errors' do - expect(page).to have_content('Name can contain only letters') - end + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource end - end - - context 'when logged as reporter' do - given(:role) { :reporter } - - scenario 'does not have a New environment link' do - expect(page).not_to have_link('New environment') + + scenario 'does have a New environment button' do + expect(page).to have_link('New environment') end end end + + # describe 'when showing the environment' do + # given(:environment) { create(:environment, project: project) } + # given!(:deployment) { } + # given!(:manual) { } + # + # before do + # visit namespace_project_environment_path(project.namespace, project, environment) + # end + # + # context 'without deployments' do + # scenario 'does show no deployments' do + # expect(page).to have_content('You don\'t have any deployments right now.') + # end + # end + # + # context 'with deployments' do + # given(:deployment) { create(:deployment, environment: environment) } + # + # scenario 'does show deployment SHA' do + # expect(page).to have_link(deployment.short_sha) + # end + # + # scenario 'does not show a re-deploy button for deployment without build' do + # expect(page).not_to have_link('Re-deploy') + # end + # + # context 'with build' do + # given(:pipeline) { create(:ci_pipeline, project: project) } + # given(:build) { create(:ci_build, pipeline: pipeline) } + # given(:deployment) { create(:deployment, environment: environment, deployable: build) } + # + # scenario 'does show build name' do + # expect(page).to have_link("#{build.name} (##{build.id})") + # end + # + # scenario 'does show re-deploy button' do + # expect(page).to have_link('Re-deploy') + # end + # + # scenario 'does not show stop button' do + # expect(page).not_to have_link('Stop') + # end + # + # context 'with manual action' do + # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + # + # scenario 'does show a play button' do + # expect(page).to have_link(manual.name.humanize) + # end + # + # scenario 'does allow to play manual action' do + # expect(manual).to be_skipped + # expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + # expect(page).to have_content(manual.name) + # expect(manual.reload).to be_pending + # end + # + # context 'with external_url' do + # given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + # given(:build) { create(:ci_build, pipeline: pipeline) } + # given(:deployment) { create(:deployment, environment: environment, deployable: build) } + # + # scenario 'does show an external link button' do + # expect(page).to have_link(nil, href: environment.external_url) + # end + # end + # + # context 'with stop action' do + # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + # given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + # + # scenario 'does show stop button' do + # expect(page).to have_link('Stop') + # end + # + # scenario 'does allow to stop environment' do + # click_link('Stop') + # + # expect(page).to have_content('close_app') + # end + # + # context 'for reporter' do + # let(:role) { :reporter } + # + # scenario 'does not show stop button' do + # expect(page).not_to have_link('Stop') + # end + # end + # end + # end + # end + # end + # end + + # describe 'when creating a new environment' do + # before do + # visit namespace_project_environments_path(project.namespace, project) + # end + # + # context 'when logged as developer' do + # before do + # click_link 'New environment' + # end + # + # context 'for valid name' do + # before do + # fill_in('Name', with: 'production') + # click_on 'Save' + # end + # + # scenario 'does create a new pipeline' do + # expect(page).to have_content('Production') + # end + # end + # + # context 'for invalid name' do + # before do + # fill_in('Name', with: 'name,with,commas') + # click_on 'Save' + # end + # + # scenario 'does show errors' do + # expect(page).to have_content('Name can contain only letters') + # end + # end + # end + # + # context 'when logged as reporter' do + # given(:role) { :reporter } + # + # scenario 'does not have a New environment link' do + # expect(page).not_to have_link('New environment') + # end + # end + # end end -- cgit v1.2.1 From 1906a32bc03179aa15777073de0ff20547bc7f6a Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 25 Oct 2016 14:55:57 +0100 Subject: Fix SCSS lint errors Fixes some tests --- spec/features/environments_spec.rb | 473 +++++++++++++++++++------------------ 1 file changed, 237 insertions(+), 236 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index c8ea4bb3945..62fc56f2f46 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -12,18 +12,32 @@ feature 'Environments', feature: true, js:true do login_as(user) project.team << [user, role] end - - describe 'when showing environments' do + + describe 'Loading environments' do given!(:environment) { } given!(:deployment) { } given!(:manual) { } - context 'without environments' do + context 'loading environments' do before do visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource end - + + scenario 'does show loading spinner' do + expect(page).to have_selector('.environments-list-loading') + end + end + end + + describe 'when showing environments' do + + before do + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource + end + + context 'without environments' do + scenario 'does show "Available" and "Stopped" tab with links' do expect(page).to have_link('Available') expect(page).to have_link('Stopped') @@ -38,37 +52,17 @@ feature 'Environments', feature: true, js:true do expect(page.find('.js-stopped-environments-count').text).to eq('0') end end - - context 'loading environments' do - given(:environment) { create(:environment, project: project) } - - before do - visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource - end - - scenario 'does show loading spinner' do - expect(page).to have_selector('.environments-list-loading') - end - end context 'with environments' do - let(:environment1) { create(:environment, project: project) } - let(:environment2) { create(:environment, project: project) } - - before do - visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource - expect(page).to have_selector('.table.ci-table.environments') - end - + given!(:environment) { create(:environment, project: project) } + scenario 'does show "Available" and "Stopped" tab with links' do expect(page).to have_link('Stopped') expect(page).to have_link('Available') end scenario 'does show environment name' do - expect(page).to have_link(environment1.name) + expect(page).to have_link(environment.name) end scenario 'does show number of available and stopped environments' do @@ -77,85 +71,92 @@ feature 'Environments', feature: true, js:true do end context 'without deployments' do + + before do + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource + end + scenario 'does show no deployments' do expect(page).to have_content('No deployments yet') end end - # context 'with deployments' do - # given(:deployment) { create(:deployment, environment: environment) } - # - # scenario 'does show deployment SHA' do - # expect(page).to have_link(deployment.short_sha) - # end - # - # scenario 'does show deployment internal id' do - # expect(page).to have_content(deployment.iid) - # end - # - # context 'with build and manual actions' do - # given(:pipeline) { create(:ci_pipeline, project: project) } - # given(:build) { create(:ci_build, pipeline: pipeline) } - # given(:deployment) { create(:deployment, environment: environment, deployable: build) } - # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - # - # scenario 'does show a play button' do - # expect(page).to have_link(manual.name.humanize) - # end - # - # scenario 'does allow to play manual action' do - # expect(manual).to be_skipped - # expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } - # expect(page).to have_content(manual.name) - # expect(manual.reload).to be_pending - # end - # - # scenario 'does show build name and id' do - # expect(page).to have_link("#{build.name} (##{build.id})") - # end - # - # scenario 'does not show stop button' do - # expect(page).not_to have_selector('.stop-env-link') - # end - # - # scenario 'does not show external link button' do - # expect(page).not_to have_css('external-url') - # end - # - # # context 'with external_url' do - # given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } - # given(:build) { create(:ci_build, pipeline: pipeline) } - # given(:deployment) { create(:deployment, environment: environment, deployable: build) } - # - # scenario 'does show an external link button' do - # expect(page).to have_link(nil, href: environment.external_url) - # end - # end - # - # # context 'with stop action' do - # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } - # given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - # - # scenario 'does show stop button' do - # expect(page).to have_selector('.stop-env-link') - # end - # - # scenario 'starts build when stop button clicked' do - # first('.stop-env-link').click - # - # expect(page).to have_content('close_app') - # end - # - # context 'for reporter' do - # let(:role) { :reporter } - # - # scenario 'does not show stop button' do - # expect(page).not_to have_selector('.stop-env-link') - # end - # end - # end - # end - # end + context 'with deployments' do + let!(:environment) { create(:environment, project: project) } + given(:deployment) { create(:deployment, environment: environment) } + + scenario 'does show deployment SHA' do + expect(page).to have_link(deployment.short_sha) + end + + scenario 'does show deployment internal id' do + expect(page).to have_content(deployment.iid) + end + + context 'with build and manual actions' do + given(:pipeline) { create(:ci_pipeline, project: project) } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + + scenario 'does show a play button' do + expect(page).to have_link(manual.name.humanize) + end + + scenario 'does allow to play manual action' do + expect(manual).to be_skipped + expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + expect(page).to have_content(manual.name) + expect(manual.reload).to be_pending + end + + scenario 'does show build name and id' do + expect(page).to have_link("#{build.name} (##{build.id})") + end + + scenario 'does not show stop button' do + expect(page).not_to have_selector('.stop-env-link') + end + + scenario 'does not show external link button' do + expect(page).not_to have_css('external-url') + end + + context 'with external_url' do + given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show an external link button' do + expect(page).to have_link(nil, href: environment.external_url) + end + end + + context 'with stop action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + scenario 'does show stop button' do + expect(page).to have_selector('.stop-env-link') + end + + scenario 'starts build when stop button clicked' do + first('.stop-env-link').click + + expect(page).to have_content('close_app') + end + + context 'for reporter' do + let(:role) { :reporter } + + scenario 'does not show stop button' do + expect(page).not_to have_selector('.stop-env-link') + end + end + end + end + end end context 'can create new environment' do @@ -170,139 +171,139 @@ feature 'Environments', feature: true, js:true do end end - # describe 'when showing the environment' do - # given(:environment) { create(:environment, project: project) } - # given!(:deployment) { } - # given!(:manual) { } - # - # before do - # visit namespace_project_environment_path(project.namespace, project, environment) - # end - # - # context 'without deployments' do - # scenario 'does show no deployments' do - # expect(page).to have_content('You don\'t have any deployments right now.') - # end - # end - # - # context 'with deployments' do - # given(:deployment) { create(:deployment, environment: environment) } - # - # scenario 'does show deployment SHA' do - # expect(page).to have_link(deployment.short_sha) - # end - # - # scenario 'does not show a re-deploy button for deployment without build' do - # expect(page).not_to have_link('Re-deploy') - # end - # - # context 'with build' do - # given(:pipeline) { create(:ci_pipeline, project: project) } - # given(:build) { create(:ci_build, pipeline: pipeline) } - # given(:deployment) { create(:deployment, environment: environment, deployable: build) } - # - # scenario 'does show build name' do - # expect(page).to have_link("#{build.name} (##{build.id})") - # end - # - # scenario 'does show re-deploy button' do - # expect(page).to have_link('Re-deploy') - # end - # - # scenario 'does not show stop button' do - # expect(page).not_to have_link('Stop') - # end - # - # context 'with manual action' do - # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - # - # scenario 'does show a play button' do - # expect(page).to have_link(manual.name.humanize) - # end - # - # scenario 'does allow to play manual action' do - # expect(manual).to be_skipped - # expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } - # expect(page).to have_content(manual.name) - # expect(manual.reload).to be_pending - # end - # - # context 'with external_url' do - # given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } - # given(:build) { create(:ci_build, pipeline: pipeline) } - # given(:deployment) { create(:deployment, environment: environment, deployable: build) } - # - # scenario 'does show an external link button' do - # expect(page).to have_link(nil, href: environment.external_url) - # end - # end - # - # context 'with stop action' do - # given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } - # given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - # - # scenario 'does show stop button' do - # expect(page).to have_link('Stop') - # end - # - # scenario 'does allow to stop environment' do - # click_link('Stop') - # - # expect(page).to have_content('close_app') - # end - # - # context 'for reporter' do - # let(:role) { :reporter } - # - # scenario 'does not show stop button' do - # expect(page).not_to have_link('Stop') - # end - # end - # end - # end - # end - # end - # end + describe 'when showing the environment' do + given(:environment) { create(:environment, project: project) } + given!(:deployment) { } + given!(:manual) { } + + before do + visit namespace_project_environment_path(project.namespace, project, environment) + end + + context 'without deployments' do + scenario 'does show no deployments' do + expect(page).to have_content('You don\'t have any deployments right now.') + end + end + + context 'with deployments' do + given(:deployment) { create(:deployment, environment: environment) } + + scenario 'does show deployment SHA' do + expect(page).to have_link(deployment.short_sha) + end + + scenario 'does not show a re-deploy button for deployment without build' do + expect(page).not_to have_link('Re-deploy') + end + + context 'with build' do + given(:pipeline) { create(:ci_pipeline, project: project) } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show build name' do + expect(page).to have_link("#{build.name} (##{build.id})") + end + + scenario 'does show re-deploy button' do + expect(page).to have_link('Re-deploy') + end + + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop') + end + + context 'with manual action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + + scenario 'does show a play button' do + expect(page).to have_link(manual.name.humanize) + end + + scenario 'does allow to play manual action' do + expect(manual).to be_skipped + expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + expect(page).to have_content(manual.name) + expect(manual.reload).to be_pending + end + + context 'with external_url' do + given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show an external link button' do + expect(page).to have_link(nil, href: environment.external_url) + end + end + + context 'with stop action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + scenario 'does show stop button' do + expect(page).to have_link('Stop') + end + + scenario 'does allow to stop environment' do + click_link('Stop') + + expect(page).to have_content('close_app') + end + + context 'for reporter' do + let(:role) { :reporter } + + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop') + end + end + end + end + end + end + end - # describe 'when creating a new environment' do - # before do - # visit namespace_project_environments_path(project.namespace, project) - # end - # - # context 'when logged as developer' do - # before do - # click_link 'New environment' - # end - # - # context 'for valid name' do - # before do - # fill_in('Name', with: 'production') - # click_on 'Save' - # end - # - # scenario 'does create a new pipeline' do - # expect(page).to have_content('Production') - # end - # end - # - # context 'for invalid name' do - # before do - # fill_in('Name', with: 'name,with,commas') - # click_on 'Save' - # end - # - # scenario 'does show errors' do - # expect(page).to have_content('Name can contain only letters') - # end - # end - # end - # - # context 'when logged as reporter' do - # given(:role) { :reporter } - # - # scenario 'does not have a New environment link' do - # expect(page).not_to have_link('New environment') - # end - # end - # end + describe 'when creating a new environment' do + before do + visit namespace_project_environments_path(project.namespace, project) + end + + context 'when logged as developer' do + before do + click_link 'New environment' + end + + context 'for valid name' do + before do + fill_in('Name', with: 'production') + click_on 'Save' + end + + scenario 'does create a new pipeline' do + expect(page).to have_content('Production') + end + end + + context 'for invalid name' do + before do + fill_in('Name', with: 'name,with,commas') + click_on 'Save' + end + + scenario 'does show errors' do + expect(page).to have_content('Name can contain only letters') + end + end + end + + context 'when logged as reporter' do + given(:role) { :reporter } + + scenario 'does not have a New environment link' do + expect(page).not_to have_link('New environment') + end + end + end end -- cgit v1.2.1 From 9a7fa3b6d38f6ac9dbdfef793d66cb6d21c6431e Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 25 Oct 2016 15:14:08 +0100 Subject: Adds tests for environments store --- .../environments/environments_store_spec.js.es6 | 19 ++++++ spec/javascripts/environments/mock_data.js.es6 | 77 ++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 spec/javascripts/environments/environments_store_spec.js.es6 create mode 100644 spec/javascripts/environments/mock_data.js.es6 (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 new file mode 100644 index 00000000000..19c71305aa6 --- /dev/null +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -0,0 +1,19 @@ +//= require vue +//= require vue-resource +//= require lib/utils/url_utility +//= require ./mock_data +// + +(() => { + beforeEach(() => { + gl.environmentsService = new EnvironmentsService('test/environments'); + gl.environmentsList.EnvironmentsStore.create(); + }); + + describe('Store', () => { + it('starts with a blank state', () => { + expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(0); + }); + + }); +})(); diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6 new file mode 100644 index 00000000000..8d12965332e --- /dev/null +++ b/spec/javascripts/environments/mock_data.js.es6 @@ -0,0 +1,77 @@ +const environmentsList = [ + { + "id": 15, + "project_id": 11, + "name": "production", + "created_at": "2016-10-18T10:47:46.840Z", + "updated_at": "2016-10-19T15:49:24.378Z", + "external_url": "https://test.com", + "environment_type": null, + "state": "available", + "last_deployment": { + "id": 57, + "iid": 5, + "project_id": 11, + "environment_id": 15, + "ref": "master", + "tag": false, + "sha": "edf8704ba6cea79be4634b82927e9ff534068428", + "user_id": 1, + "deployable_id": 1170, + "deployable_type": "CommitStatus", + "on_stop": null, + "short_sha": "edf8704b", + "commit_title": "Update .gitlab-ci.yml", + "commit": { + "id": "edf8704ba6cea79be4634b82927e9ff534068428", + "message": "Update .gitlab-ci.yml", + "parent_ids": ["f215999006bd3d5c89b9b1e8c0873c9aca0f913a"], + "authored_date": "2016-10-19T16:49:09.000+01:00", + "author_name": "Administrator", + "author_email": "admin@example.com", + "committed_date": "2016-10-19T16:49:09.000+01:00", + "committer_name": "Administrator", + "committer_email": "admin@example.com" + }, + "user": { + "id": 1, + "name": "Administrator", + "username": "root", + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon" + }, + "deployable": { + "id": 1170, + "name": "deploy", + "tag": false, + "ref": "master" + } + }, + "project": { + "id": 11, + "name": "review-apps", + "path": "review-apps", + "namespace_id": 1, + "namespace": { + "id": 1, + "name": "root" + } + } + },{ + "id": 18, + "project_id": 11, + "name": "review/test-environment", + "created_at": "2016-10-19T14:59:59.303Z", + "updated_at": "2016-10-19T14:59:59.303Z", + "external_url": "http://test1.com", + "environment_type": "review", + "state": "available", + "project": { + "id": 11, + "name": "review-apps", + "namespace": { + "id": 1, + "name": "root" + } + } + } +]; \ No newline at end of file -- cgit v1.2.1 From 3c383f9f76a8cec6ecf69a012567cb70b8466897 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 26 Oct 2016 09:17:32 +0100 Subject: Fixes filter --- .../environments/environments_store_spec.js.es6 | 4 +++- spec/javascripts/environments/mock_data.js.es6 | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index 19c71305aa6..ccf6ae971c3 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -1,6 +1,8 @@ //= require vue //= require vue-resource //= require lib/utils/url_utility +//= require environments/services/environments_service +//= require environments/stores/environments_store //= require ./mock_data // @@ -14,6 +16,6 @@ it('starts with a blank state', () => { expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(0); }); - + }); })(); diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6 index 8d12965332e..87420a32450 100644 --- a/spec/javascripts/environments/mock_data.js.es6 +++ b/spec/javascripts/environments/mock_data.js.es6 @@ -73,5 +73,23 @@ const environmentsList = [ "name": "root" } } + }, + { + "id": 18, + "project_id": 11, + "name": "review/test-environment-1", + "created_at": "2016-10-19T14:59:59.303Z", + "updated_at": "2016-10-19T14:59:59.303Z", + "external_url": "http://test-1.com", + "environment_type": "review", + "state": "stopped", + "project": { + "id": 11, + "name": "review-apps", + "namespace": { + "id": 1, + "name": "root" + } + } } -]; \ No newline at end of file +]; -- cgit v1.2.1 From dcafd476dbc11eb6f2e7327d96868bf2c2d165a9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 26 Oct 2016 16:00:16 +0100 Subject: Removes trailing whitespace --- spec/javascripts/environments/environments_store_spec.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index ccf6ae971c3..482b562fdce 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -4,14 +4,14 @@ //= require environments/services/environments_service //= require environments/stores/environments_store //= require ./mock_data -// +// (() => { beforeEach(() => { gl.environmentsService = new EnvironmentsService('test/environments'); gl.environmentsList.EnvironmentsStore.create(); }); - + describe('Store', () => { it('starts with a blank state', () => { expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(0); -- cgit v1.2.1 From b1ec3cb8d2776070c80cba21d08774e563b42f84 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 26 Oct 2016 18:17:00 +0100 Subject: Adds tests for environment store. --- .../environments/environments_store_spec.js.es6 | 51 ++++++++++++-- spec/javascripts/environments/mock_data.js.es6 | 81 ++-------------------- 2 files changed, 50 insertions(+), 82 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index 482b562fdce..db4ce41701c 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -1,21 +1,58 @@ //= require vue -//= require vue-resource -//= require lib/utils/url_utility -//= require environments/services/environments_service -//= require environments/stores/environments_store +//= require environments/stores/environmnets_store //= require ./mock_data -// (() => { + beforeEach(() => { - gl.environmentsService = new EnvironmentsService('test/environments'); gl.environmentsList.EnvironmentsStore.create(); }); describe('Store', () => { - it('starts with a blank state', () => { + it('should start with a blank state', () => { expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(0); + expect(gl.environmentsList.EnvironmentsStore.state.stoppedCounter).toBe(0); + expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(0) }); + describe('store environments', () => { + beforeEach(() => { + gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList); + }); + + it('should count stopped environments and save the count in the state', () => { + + + expect(gl.environmentsList.EnvironmentsStore.state.stoppedCounter).toBe(1); + }); + + it('should count available environments and save the count in the state', () => { + + expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(2); + }); + + it('should store environments with same environment_type as sibilings', () => { + + expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(2); + + const parentFolder = gl.environmentsList.EnvironmentsStore.state.environments.filter((env) => { + return env.children && env.children.length > 0; + }); + + expect(parentFolder[0].children.length).toBe(2); + expect(parentFolder[0].children[0].environment_type).toBe('review'); + expect(parentFolder[0].children[1].environment_type).toBe('review'); + expect(parentFolder[0].children[0].name).toBe('review/test-environment') + expect(parentFolder[0].children[1].name).toBe('review/test-environment-1'); + }); + + it('should sort the environments alphabetically', () => { + const { environments } = gl.environmentsList.EnvironmentsStore.state; + + expect(environments[0].name).toBe('production'); + expect(environments[1].children[0].name).toBe('review/test-environment'); + expect(environments[1].children[1].name).toBe('review/test-environment-1'); + }); + }); }); })(); diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6 index 87420a32450..35d94e3ab44 100644 --- a/spec/javascripts/environments/mock_data.js.es6 +++ b/spec/javascripts/environments/mock_data.js.es6 @@ -3,93 +3,24 @@ const environmentsList = [ "id": 15, "project_id": 11, "name": "production", - "created_at": "2016-10-18T10:47:46.840Z", - "updated_at": "2016-10-19T15:49:24.378Z", "external_url": "https://test.com", "environment_type": null, - "state": "available", - "last_deployment": { - "id": 57, - "iid": 5, - "project_id": 11, - "environment_id": 15, - "ref": "master", - "tag": false, - "sha": "edf8704ba6cea79be4634b82927e9ff534068428", - "user_id": 1, - "deployable_id": 1170, - "deployable_type": "CommitStatus", - "on_stop": null, - "short_sha": "edf8704b", - "commit_title": "Update .gitlab-ci.yml", - "commit": { - "id": "edf8704ba6cea79be4634b82927e9ff534068428", - "message": "Update .gitlab-ci.yml", - "parent_ids": ["f215999006bd3d5c89b9b1e8c0873c9aca0f913a"], - "authored_date": "2016-10-19T16:49:09.000+01:00", - "author_name": "Administrator", - "author_email": "admin@example.com", - "committed_date": "2016-10-19T16:49:09.000+01:00", - "committer_name": "Administrator", - "committer_email": "admin@example.com" - }, - "user": { - "id": 1, - "name": "Administrator", - "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon" - }, - "deployable": { - "id": 1170, - "name": "deploy", - "tag": false, - "ref": "master" - } - }, - "project": { - "id": 11, - "name": "review-apps", - "path": "review-apps", - "namespace_id": 1, - "namespace": { - "id": 1, - "name": "root" - } - } - },{ + "state": "available" + }, + { "id": 18, "project_id": 11, "name": "review/test-environment", - "created_at": "2016-10-19T14:59:59.303Z", - "updated_at": "2016-10-19T14:59:59.303Z", "external_url": "http://test1.com", "environment_type": "review", - "state": "available", - "project": { - "id": 11, - "name": "review-apps", - "namespace": { - "id": 1, - "name": "root" - } - } + "state": "available" }, { - "id": 18, + "id": 19, "project_id": 11, "name": "review/test-environment-1", - "created_at": "2016-10-19T14:59:59.303Z", - "updated_at": "2016-10-19T14:59:59.303Z", "external_url": "http://test-1.com", "environment_type": "review", - "state": "stopped", - "project": { - "id": 11, - "name": "review-apps", - "namespace": { - "id": 1, - "name": "root" - } - } + "state": "stopped" } ]; -- cgit v1.2.1 From 14345b21509aa874cf8748a2ddcf34d3a632bd6c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 27 Oct 2016 10:51:44 +0100 Subject: Fix whitespace --- spec/javascripts/environments/environments_store_spec.js.es6 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index db4ce41701c..8d0fea934c3 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -21,20 +21,16 @@ }); it('should count stopped environments and save the count in the state', () => { - - expect(gl.environmentsList.EnvironmentsStore.state.stoppedCounter).toBe(1); }); it('should count available environments and save the count in the state', () => { - expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(2); }); it('should store environments with same environment_type as sibilings', () => { - expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(2); - + const parentFolder = gl.environmentsList.EnvironmentsStore.state.environments.filter((env) => { return env.children && env.children.length > 0; }); -- cgit v1.2.1 From 4388d90370310a570c5450b6c10eba7533ce1827 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 7 Nov 2016 10:03:19 +0100 Subject: Add controller specs for environments index action --- .../projects/environments_controller_spec.rb | 33 ++++++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 768105cae95..bc5e2711125 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Projects::EnvironmentsController do + include ApiHelpers + let(:environment) { create(:environment) } let(:project) { environment.project } let(:user) { create(:user) } @@ -11,6 +13,27 @@ describe Projects::EnvironmentsController do sign_in(user) end + describe 'GET index' do + context 'when standardrequest has been made' do + it 'responds with status code 200' do + get :index, environment_params + + expect(response).to be_ok + end + end + + context 'when requesting JSON response' do + it 'responds with correct JSON' do + get :index, environment_params(format: :json) + + first_environment = json_response.first + + expect(first_environment).not_to be_empty + expect(first_environment['name']). to eq environment.name + end + end + end + describe 'GET show' do context 'with valid id' do it 'responds with a status code 200' do @@ -48,11 +71,9 @@ describe Projects::EnvironmentsController do end end - def environment_params - { - namespace_id: project.namespace, - project_id: project, - id: environment.id - } + def environment_params(opts = {}) + opts.reverse_merge(namespace_id: project.namespace, + project_id: project, + id: environment.id) end end -- cgit v1.2.1 From a8508608eaf8440da7e55686c649f7209621494c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 7 Nov 2016 21:11:58 +0000 Subject: Fixes the tests --- .../environments/environments_store_spec.js.es6 | 26 ++-- spec/javascripts/environments/mock_data.js.es6 | 148 ++++++++++++++++++--- 2 files changed, 142 insertions(+), 32 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index 8d0fea934c3..bc16c90e9be 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -1,9 +1,8 @@ //= require vue //= require environments/stores/environmnets_store //= require ./mock_data - +/* globals environmentsList */ (() => { - beforeEach(() => { gl.environmentsList.EnvironmentsStore.create(); }); @@ -12,12 +11,12 @@ it('should start with a blank state', () => { expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(0); expect(gl.environmentsList.EnvironmentsStore.state.stoppedCounter).toBe(0); - expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(0) + expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(0); }); describe('store environments', () => { beforeEach(() => { - gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList); + gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList); }); it('should count stopped environments and save the count in the state', () => { @@ -25,29 +24,30 @@ }); it('should count available environments and save the count in the state', () => { - expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(2); + expect(gl.environmentsList.EnvironmentsStore.state.availableCounter).toBe(3); }); it('should store environments with same environment_type as sibilings', () => { - expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(2); + expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(3); - const parentFolder = gl.environmentsList.EnvironmentsStore.state.environments.filter((env) => { - return env.children && env.children.length > 0; - }); + const parentFolder = gl.environmentsList.EnvironmentsStore.state.environments + .filter(env => env.children && env.children.length > 0); expect(parentFolder[0].children.length).toBe(2); expect(parentFolder[0].children[0].environment_type).toBe('review'); expect(parentFolder[0].children[1].environment_type).toBe('review'); - expect(parentFolder[0].children[0].name).toBe('review/test-environment') - expect(parentFolder[0].children[1].name).toBe('review/test-environment-1'); + expect(parentFolder[0].children[0].name).toBe('test-environment'); + expect(parentFolder[0].children[1].name).toBe('test-environment-1'); }); it('should sort the environments alphabetically', () => { const { environments } = gl.environmentsList.EnvironmentsStore.state; expect(environments[0].name).toBe('production'); - expect(environments[1].children[0].name).toBe('review/test-environment'); - expect(environments[1].children[1].name).toBe('review/test-environment-1'); + expect(environments[1].name).toBe('review'); + expect(environments[1].children[0].name).toBe('test-environment'); + expect(environments[1].children[1].name).toBe('test-environment-1'); + expect(environments[2].name).toBe('review_app') }); }); }); diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6 index 35d94e3ab44..1142ace5846 100644 --- a/spec/javascripts/environments/mock_data.js.es6 +++ b/spec/javascripts/environments/mock_data.js.es6 @@ -1,26 +1,136 @@ +/* eslint-disable no-unused-vars */ const environmentsList = [ { - "id": 15, - "project_id": 11, - "name": "production", - "external_url": "https://test.com", - "environment_type": null, - "state": "available" + id: 31, + name: 'production', + state: 'available', + external_url: 'https://www.gitlab.com', + environment_type: null, + last_deployment: { + id: 64, + iid: 5, + sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + ref: { + name: 'master', + ref_url: 'http://localhost:3000/root/ci-folders/tree/master', + }, + tag: false, + 'last?': true, + user: { + name: 'Administrator', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + commit: { + id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + short_id: '500aabcb', + title: 'Update .gitlab-ci.yml', + author_name: 'Administrator', + author_email: 'admin@example.com', + created_at: '2016-11-07T18:28:13.000+00:00', + message: 'Update .gitlab-ci.yml', + author: { + name: 'Administrator', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + commit_url: 'http://localhost:3000/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + }, + deployable: { + id: 1278, + name: 'build', + build_url: 'http://localhost:3000/root/ci-folders/builds/1278', + retry_url: 'http://localhost:3000/root/ci-folders/builds/1278/retry', + }, + manual_actions: [], + }, + 'stoppable?': true, + environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-07T11:11:16.525Z', }, { - "id": 18, - "project_id": 11, - "name": "review/test-environment", - "external_url": "http://test1.com", - "environment_type": "review", - "state": "available" + id: 32, + name: 'review_app', + state: 'stopped', + external_url: 'https://www.gitlab.com', + environment_type: null, + last_deployment: { + id: 64, + iid: 5, + sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + ref: { + name: 'master', + ref_url: 'http://localhost:3000/root/ci-folders/tree/master', + }, + tag: false, + 'last?': true, + user: { + name: 'Administrator', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + commit: { + id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + short_id: '500aabcb', + title: 'Update .gitlab-ci.yml', + author_name: 'Administrator', + author_email: 'admin@example.com', + created_at: '2016-11-07T18:28:13.000+00:00', + message: 'Update .gitlab-ci.yml', + author: { + name: 'Administrator', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + commit_url: 'http://localhost:3000/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + }, + deployable: { + id: 1278, + name: 'build', + build_url: 'http://localhost:3000/root/ci-folders/builds/1278', + retry_url: 'http://localhost:3000/root/ci-folders/builds/1278/retry', + }, + manual_actions: [], + }, + 'stoppable?': false, + environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-07T11:11:16.525Z', }, { - "id": 19, - "project_id": 11, - "name": "review/test-environment-1", - "external_url": "http://test-1.com", - "environment_type": "review", - "state": "stopped" - } + id: 33, + name: 'test-environment', + state: 'available', + environment_type: 'review', + last_deployment: null, + 'stoppable?': true, + environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-07T11:11:16.525Z', + }, + { + id: 34, + name: 'test-environment-1', + state: 'available', + environment_type: 'review', + last_deployment: null, + 'stoppable?': true, + environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-07T11:11:16.525Z', + }, ]; + -- cgit v1.2.1 From c3db10d3fb32babb608bb191596e3462454ac41f Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 7 Nov 2016 21:53:20 +0000 Subject: Removes loading assertions --- spec/features/environments_spec.rb | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 62fc56f2f46..edabb97e761 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -12,32 +12,14 @@ feature 'Environments', feature: true, js:true do login_as(user) project.team << [user, role] end - - describe 'Loading environments' do - given!(:environment) { } - given!(:deployment) { } - given!(:manual) { } - - context 'loading environments' do - before do - visit namespace_project_environments_path(project.namespace, project) - end - - scenario 'does show loading spinner' do - expect(page).to have_selector('.environments-list-loading') - end - end - end describe 'when showing environments' do - before do visit namespace_project_environments_path(project.namespace, project) wait_for_vue_resource end context 'without environments' do - scenario 'does show "Available" and "Stopped" tab with links' do expect(page).to have_link('Available') expect(page).to have_link('Stopped') -- cgit v1.2.1 From 9bf6d3abeba3b318741ab7ef0d4513c57f5112be Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 8 Nov 2016 10:33:36 +0000 Subject: Adds a list of environments --- spec/features/environments_spec.rb | 49 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index edabb97e761..595cf28ee77 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -1,17 +1,28 @@ -require 'spec_helper' require 'rails_helper' feature 'Environments', feature: true, js:true do include WaitForVueResource - given(:project) { create(:project) } - given(:user) { create(:user) } - given(:role) { :developer } - + let(:json) { serializer.as_json } + let(:project) { create(:empty_project, :public) } + let(:user) { create(:user) } + let(:role) { :developer } + + let(:serializer) do + described_class + .new(user: user, project: project) + .represent(resource) + end + background do login_as(user) project.team << [user, role] end + + before do + visit namespace_project_environments_path(project.namespace, project) + wait_for_vue_resource + end describe 'when showing environments' do before do @@ -36,15 +47,15 @@ feature 'Environments', feature: true, js:true do end context 'with environments' do - given!(:environment) { create(:environment, project: project) } - + let(:resource) { create_list(:environment, 2) } + scenario 'does show "Available" and "Stopped" tab with links' do expect(page).to have_link('Stopped') expect(page).to have_link('Available') end - scenario 'does show environment name' do - expect(page).to have_link(environment.name) + scenario 'does show environments table' do + expect(page).to have_selector('.table-holder') end scenario 'does show number of available and stopped environments' do @@ -53,20 +64,13 @@ feature 'Environments', feature: true, js:true do end context 'without deployments' do - - before do - visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource - end - scenario 'does show no deployments' do expect(page).to have_content('No deployments yet') end end - + context 'with deployments' do - let!(:environment) { create(:environment, project: project) } - given(:deployment) { create(:deployment, environment: environment) } + # TODO add environment with deployment scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) @@ -142,17 +146,12 @@ feature 'Environments', feature: true, js:true do end context 'can create new environment' do - before do - visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource - end - scenario 'does have a New environment button' do expect(page).to have_link('New environment') end end end - + describe 'when showing the environment' do given(:environment) { create(:environment, project: project) } given!(:deployment) { } @@ -246,7 +245,7 @@ feature 'Environments', feature: true, js:true do end end end - + describe 'when creating a new environment' do before do visit namespace_project_environments_path(project.namespace, project) -- cgit v1.2.1 From a31578aa505088a347bfc6ae2483d8c563d1fee9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 8 Nov 2016 11:25:14 +0000 Subject: Remove unused block --- spec/features/environments_spec.rb | 5 ----- 1 file changed, 5 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index 595cf28ee77..d60a6be397d 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -18,11 +18,6 @@ feature 'Environments', feature: true, js:true do login_as(user) project.team << [user, role] end - - before do - visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource - end describe 'when showing environments' do before do -- cgit v1.2.1 From 3fef5e66dba055e32dda1ccc887ad630d1e61c87 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 9 Nov 2016 10:55:00 +0000 Subject: Adds template functions Adds commit component --- spec/javascripts/environments/environments_store_spec.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index bc16c90e9be..5e35949ac9c 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -47,7 +47,7 @@ expect(environments[1].name).toBe('review'); expect(environments[1].children[0].name).toBe('test-environment'); expect(environments[1].children[1].name).toBe('test-environment-1'); - expect(environments[2].name).toBe('review_app') + expect(environments[2].name).toBe('review_app'); }); }); }); -- cgit v1.2.1 From 30c6a7d3acf658253af158ff7069081cf4b109ad Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 10 Nov 2016 18:58:35 +0000 Subject: Adds tests Adds tests. Changes instance into a constructor Adds tests for environments component Adds tests assertations Adds external URL test Adds tests for Rollback component Adds tests for stop component Adds tests for actions component Fix environment item Init environment item tests --- spec/features/environments_spec.rb | 4 + .../environments/environment_actions_spec.js.es6 | 37 +++++ .../environment_external_url_spec.js.es6 | 22 +++ .../environments/environment_item_spec.js.es6 | 157 +++++++++++++++++++ .../environments/environment_rollback_spec.js.es6 | 48 ++++++ .../environments/environment_spec.js.es6 | 172 +++++++++++++++++++++ .../environments/environment_stop_spec.js.es6 | 34 ++++ .../fixtures/environments/element.html.haml | 1 + .../fixtures/environments/environments.html.haml | 9 ++ .../environments_no_permission.html.haml | 9 ++ .../fixtures/environments/table.html.haml | 11 ++ .../vue_common_components/commit_spec.js.es6 | 89 +++++++++++ 12 files changed, 593 insertions(+) create mode 100644 spec/javascripts/environments/environment_actions_spec.js.es6 create mode 100644 spec/javascripts/environments/environment_external_url_spec.js.es6 create mode 100644 spec/javascripts/environments/environment_item_spec.js.es6 create mode 100644 spec/javascripts/environments/environment_rollback_spec.js.es6 create mode 100644 spec/javascripts/environments/environment_spec.js.es6 create mode 100644 spec/javascripts/environments/environment_stop_spec.js.es6 create mode 100644 spec/javascripts/fixtures/environments/element.html.haml create mode 100644 spec/javascripts/fixtures/environments/environments.html.haml create mode 100644 spec/javascripts/fixtures/environments/environments_no_permission.html.haml create mode 100644 spec/javascripts/fixtures/environments/table.html.haml create mode 100644 spec/javascripts/vue_common_components/commit_spec.js.es6 (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index d60a6be397d..f4c0b093246 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -43,6 +43,10 @@ feature 'Environments', feature: true, js:true do context 'with environments' do let(:resource) { create_list(:environment, 2) } + before do + endpoint = namespace_project_environments_path(project.namespace, project) + stub_request(:any, endpoint).to_return(body: [{"name": "test"}]) + end scenario 'does show "Available" and "Stopped" tab with links' do expect(page).to have_link('Stopped') diff --git a/spec/javascripts/environments/environment_actions_spec.js.es6 b/spec/javascripts/environments/environment_actions_spec.js.es6 new file mode 100644 index 00000000000..1097582a8e9 --- /dev/null +++ b/spec/javascripts/environments/environment_actions_spec.js.es6 @@ -0,0 +1,37 @@ +//= require vue +//= require environments/components/environment_actions + +describe('Actions Component', () => { + fixture.preload('environments/element.html'); + + beforeEach(() => { + fixture.load('environments/element.html'); + }); + + it('Should render a dropdown with the provided actions', () => { + const actionsMock = [ + { + name: 'bar', + play_url: 'https://gitlab.com/play', + }, + { + name: 'foo', + play_url: '#', + }, + ]; + + const component = new window.gl.environmentsList.ActionsComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + actions: actionsMock, + }, + }); + + expect( + component.$el.querySelectorAll('.dropdown-menu li').length + ).toEqual(actionsMock.length); + expect( + component.$el.querySelector('.dropdown-menu li a').getAttribute('href') + ).toEqual(actionsMock[0].play_url); + }); +}); diff --git a/spec/javascripts/environments/environment_external_url_spec.js.es6 b/spec/javascripts/environments/environment_external_url_spec.js.es6 new file mode 100644 index 00000000000..156506ef28f --- /dev/null +++ b/spec/javascripts/environments/environment_external_url_spec.js.es6 @@ -0,0 +1,22 @@ +//= require vue +//= require environments/components/environment_external_url + +describe('External URL Component', () => { + fixture.preload('environments/element.html'); + beforeEach(() => { + fixture.load('environments/element.html'); + }); + + it('should link to the provided external_url', () => { + const externalURL = 'https://gitlab.com'; + const component = new window.gl.environmentsList.ExternalUrlComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + external_url: externalURL, + }, + }); + + expect(component.$el.getAttribute('href')).toEqual(externalURL); + expect(component.$el.querySelector('fa-external-link')).toBeDefined(); + }); +}); diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js.es6 new file mode 100644 index 00000000000..f357e11dc8e --- /dev/null +++ b/spec/javascripts/environments/environment_item_spec.js.es6 @@ -0,0 +1,157 @@ +//= require vue +//= require environments/components/environment_item + +describe('Environment item', () => { + fixture.preload('environments/table.html'); + beforeEach(() => { + fixture.load('environments/table.html'); + }); + + describe('When item is folder', () => { + let mockItem; + let component; + + beforeEach(() => { + mockItem = { + name: 'review', + children: [ + { + name: 'review-app', + id: 1, + state: 'available', + external_url: '', + last_deployment: {}, + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-10T15:55:58.778Z', + }, + { + name: 'production', + id: 2, + state: 'available', + external_url: '', + last_deployment: {}, + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-10T15:55:58.778Z', + }, + ], + }; + + component = new window.gl.environmentsList.EnvironmentItem({ + el: document.querySelector('tr#environment-row'), + propsData: { + model: mockItem, + 'can-create-deployment': false, + 'can-read-environment': true, + }, + }); + }); + + it('Should render clickable folder icon and name', () => { + expect(document.querySelector('.folder-name').textContent).toContain(mockItem.name); + expect(document.querySelector('.folder-icon')).toBeDefined(); + }); + + it('Should render the number of children in a badge', () => { + expect(document.querySelector('.folder-name .badge').textContent).toContain(mockItem.children.length); + }); + + it('Should not render any information other than the name', () => { + }); + + describe('when clicked', () => { + it('Should render child row', () => { + }); + }); + }); + + describe('when item is not folder', () => { + it('should render environment name', () => { + + }); + + describe('With deployment', () => { + it('should render deployment internal id', () => { + + }); + + it('should link to deployment', () => { + + }); + + describe('With user information', () => { + it('should render user avatar with link to profile', () => { + + }); + }); + + describe('With build url', () => { + it('Should link to build url provided', () => { + + }); + + it('Should render deployable name and id', () => { + + }); + }); + + describe('With commit information', () => { + it('should render commit component', () => {}); + }); + + it('Should render timeago created date', () => { + + }); + }); + + describe('Without deployment', () => { + it('should render no deployments information', () => { + + }); + }); + + describe('With manual actions', () => { + describe('With create deployment permission', () => { + it('Should render actions component', () => { + + }); + }); + describe('Without create deployment permission', () => { + it('should not render actions component', () => { + + }); + }); + }); + + describe('With external URL', () => { + it('should render external url component', () => { + + }); + }); + + describe('With stop action', () => { + describe('With create deployment permission', () => { + it('Should render stop action component', () => { + + }); + }); + describe('Without create deployment permission', () => { + it('should not render stop action component', () => { + + }); + }); + }); + + describe('With retry action', () => { + describe('With create deployment permission', () => { + it('Should render rollback component', () => { + + }); + }); + describe('Without create deployment permission', () => { + it('should not render rollback component', () => { + + }); + }); + }); + }); +}); diff --git a/spec/javascripts/environments/environment_rollback_spec.js.es6 b/spec/javascripts/environments/environment_rollback_spec.js.es6 new file mode 100644 index 00000000000..29449bbbd9e --- /dev/null +++ b/spec/javascripts/environments/environment_rollback_spec.js.es6 @@ -0,0 +1,48 @@ +//= require vue +//= require environments/components/environment_rollback +describe('Rollback Component', () => { + fixture.preload('environments/element.html'); + + const retryURL = 'https://gitlab.com/retry'; + + beforeEach(() => { + fixture.load('environments/element.html'); + }); + + it('Should link to the provided retry_url', () => { + const component = new window.gl.environmentsList.RollbackComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + retry_url: retryURL, + is_last_deployment: true, + }, + }); + + expect(component.$el.getAttribute('href')).toEqual(retryURL); + }); + + it('Should render Re-deploy label when is_last_deployment is true', () => { + const component = new window.gl.environmentsList.RollbackComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + retry_url: retryURL, + is_last_deployment: true, + }, + }); + + expect(component.$el.querySelector('span').textContent).toContain('Re-deploy'); + }); + + + it('Should render Rollback label when is_last_deployment is false', () => { + const component = new window.gl.environmentsList.RollbackComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + retry_url: retryURL, + is_last_deployment: false, + }, + }); + + expect(component.$el.querySelector('span').textContent).toContain('Rollback'); + }); +}); diff --git a/spec/javascripts/environments/environment_spec.js.es6 b/spec/javascripts/environments/environment_spec.js.es6 new file mode 100644 index 00000000000..07eb9938c58 --- /dev/null +++ b/spec/javascripts/environments/environment_spec.js.es6 @@ -0,0 +1,172 @@ +//= require vue +//= require environments/stores/environments_store +//= require environments/components/environment + +/* globals environmentsList */ +describe('Environments', () => { + fixture.preload('environments/environments.html'); + fixture.preload('environments/environments_no_permission.html'); + let Store; + let component; + + beforeEach(() => { + Store = window.gl.environmentsList.EnvironmentsStore; + }); + + describe('While loading', () => { + beforeEach(() => { + fixture.load('environments/environments.html'); + component = new window.gl.environmentsList.EnvironmentsComponent({ + el: document.querySelector('#environments-list-view'), + propsData: { + store: Store.create(), + }, + }); + }); + + it('Should render two tabs', () => { + expect(component.$el.querySelectorAll('ul li').length).toEqual(2); + }); + + it('Should render bagdes with zeros in both tabs indicating the number of available environments', () => { + expect( + component.$el.querySelector('.js-available-environments-count').textContent + ).toContain('0'); + expect( + component.$el.querySelector('.js-stopped-environments-count').textContent + ).toContain('0'); + }); + + it('Should render loading icon', () => { + expect( + component.$el.querySelector('environments-list-loading') + ).toBeDefined(); + }); + }); + + describe('Without environments', () => { + beforeEach(() => { + fixture.load('environments/environments.html'); + + spyOn(component, 'ready').and.callFake(() => { + return { + then: callback => callback([]), + json: () => ({ then: cb => cb([]) }), + }; + }); + + component = new window.gl.environmentsList.EnvironmentsComponent({ + el: document.querySelector('#environments-list-view'), + propsData: { + store: Store.create(), + }, + }); + }); + + it('Should render two tabs', () => { + expect(component.$el.querySelectorAll('ul li').length).toEqual(2); + }); + + it('Should render bagdes with zeros in both tabs indicating the number of available environments', () => { + expect( + component.$el.querySelector('.js-available-environments-count').textContent + ).toContain('0'); + expect( + component.$el.querySelector('.js-stopped-environments-count').textContent + ).toContain('0'); + }); + + it('Should render blank state information', () => { + expect( + component.$el.querySelector('.blank-state-title').textContent + ).toEqual('You don\'t have any environments right now.'); + + expect( + component.$el.querySelector('.blank-state-text').textContent + ).toEqual('Environments are places where code gets deployed, such as staging or production.'); + }); + + it('Should render the provided help url', () => { + expect( + component.$el.querySelector('.blank-state a').getAttribute('href') + ).toEqual(component.$data.helpPagePath); + }); + + describe('With create permission', () => { + it('Should render new environment button', () => { + expect( + component.$el.querySelector('a.btn-create').getAttribute('href') + ).toEqual(component.$data.newEnvironmentPath); + expect( + component.$el.querySelector('a.btn-create').textContent + ).toEqual('New environment'); + }); + }); + + describe('Without create permission', () => { + beforeEach('Load fixture without permission', () => { + fixture.load('environments/environments_no_permission.html'); + component = new window.gl.environmentsList.EnvironmentsComponent({ + el: document.querySelector('#environments-list-view'), + propsData: { + store: Store.create(), + }, + }); + }); + + it('Should not render new environment button', () => { + + }); + }); + }); + + describe('With environments', () => { + describe('Tabs behavior', () => { + it('Should render two tabs', () => { + + }); + + it('Should render badges with the correct count', () => { + + }); + + describe('When clicking in the available tab', () => { + it('Should make Available tab active', () => { + + }); + + it('Should make visible only available environments', () => { + + }); + }); + + describe('When clicking in the stopped tab', () => { + it('Should make Stopped tab active', () => { + + }); + + it('Should make visible only stopped environments', () => { + + }); + }); + }); + + describe('With create permissions', () => { + it('Should render new environment button', () => { + + }); + }); + + describe('Without create permissions', () => { + it('Should not render the new environment button', () => { + }); + }); + + it('Should render a table', () => { + }); + + it('Should render table pagination', () => { + + }); + }); +}); diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js.es6 new file mode 100644 index 00000000000..07a68bf28fb --- /dev/null +++ b/spec/javascripts/environments/environment_stop_spec.js.es6 @@ -0,0 +1,34 @@ +//= require vue +//= require environments/components/environment_stop +describe('Stop Component', () => { + fixture.preload('environments/element.html'); + beforeEach(() => { + fixture.load('environments/element.html'); + }); + + it('should link to the provided URL', () => { + const stopURL = 'https://gitlab.com/stop'; + const component = new window.gl.environmentsList.StopComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + stop_url: stopURL, + }, + }); + expect(component.$el.getAttribute('href')).toEqual(stopURL); + }); + + describe('When clicked', () => { + it('Should open popup with confirmation warning', () => { + const component = new window.gl.environmentsList.StopComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + stop_url: '#', + }, + }); + + const spy = spyOn(window, 'confirm'); + component.$el.click(); + expect(spy).toHaveBeenCalled(); + }); + }); +}); diff --git a/spec/javascripts/fixtures/environments/element.html.haml b/spec/javascripts/fixtures/environments/element.html.haml new file mode 100644 index 00000000000..d709c863137 --- /dev/null +++ b/spec/javascripts/fixtures/environments/element.html.haml @@ -0,0 +1 @@ +.test-dom-element \ No newline at end of file diff --git a/spec/javascripts/fixtures/environments/environments.html.haml b/spec/javascripts/fixtures/environments/environments.html.haml new file mode 100644 index 00000000000..dd1d6855ce2 --- /dev/null +++ b/spec/javascripts/fixtures/environments/environments.html.haml @@ -0,0 +1,9 @@ +%div + #environments-list-view{ data: { environments_data: "https://gitlab.com/foo/environments", + "can-create-deployment" => "true", + "can-read-environment" => "true", + "can-create-environmnet" => "true", + "project-environments-path" => "https://gitlab.com/foo/environments", + "project-stopped-environments-path" => "https://gitlab.com/foo/environments?scope=stopped", + "new-environment-path" => "https://gitlab.com/foo/environments/new", + "help-page-path" => "https://gitlab.com/help_page"}} \ No newline at end of file diff --git a/spec/javascripts/fixtures/environments/environments_no_permission.html.haml b/spec/javascripts/fixtures/environments/environments_no_permission.html.haml new file mode 100644 index 00000000000..71cf7db7a34 --- /dev/null +++ b/spec/javascripts/fixtures/environments/environments_no_permission.html.haml @@ -0,0 +1,9 @@ +%div + #environments-list-view{ data: { environments_data: "https://gitlab.com/foo/environments", + "can-create-deployment" => "false", + "can-read-environment" => "true", + "can-create-environmnet" => "false", + "project-environments-path" => "https://gitlab.com/foo/environments", + "project-stopped-environments-path" => "https://gitlab.com/foo/environments?scope=stopped", + "new-environment-path" => "https://gitlab.com/foo/environments/new", + "help-page-path" => "https://gitlab.com/help_page"}} \ No newline at end of file diff --git a/spec/javascripts/fixtures/environments/table.html.haml b/spec/javascripts/fixtures/environments/table.html.haml new file mode 100644 index 00000000000..1ea1725c561 --- /dev/null +++ b/spec/javascripts/fixtures/environments/table.html.haml @@ -0,0 +1,11 @@ +%table + %thead + %tr + %th Environment + %th Last deployment + %th Build + %th Commit + %th + %th + %tbody + %tr#environment-row diff --git a/spec/javascripts/vue_common_components/commit_spec.js.es6 b/spec/javascripts/vue_common_components/commit_spec.js.es6 new file mode 100644 index 00000000000..4f158e8ffa5 --- /dev/null +++ b/spec/javascripts/vue_common_components/commit_spec.js.es6 @@ -0,0 +1,89 @@ +/*= require vue_common_components/commit */ +/* eslint-disable */ + +describe('Commit component', () => { + const getRenderedText = (Component, propsData) => { + const Constructor = Vue.extend(Component); + const vm = new Constructor({propsData}).$mount(); + return vm.$el.textContent; + }; + + const MyComponent = window.gl.commitComponent; + + describe('When `ref` is provided', () => { + const props = { + tag: true, + ref: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master' + }, + commit_url: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + short_sha: 'b7836edd', + title: 'Commit message', + author: { + avatar_url: 'https://gitlab.com/uploads/user/avatar/300478/avatar.png', + web_url: 'https://gitlab.com/jschatz1', + username: 'jschatz1' + } + }; + + it('should render a tag icon if it represents a tag', () => { + const renderedText = getRenderedText(MyComponent, props); + + }); + + it('should render a code-fork icon if it does not represent a tag', () => { + + }); + + it('should render a link to the ref url', () => { + + }); + + it('should render the ref name', () => { + + }); + }); +}); + +it('should render the commit icon as an svg', () => { + +}); + +it('should render the commit short sha with a link to the commit url', () => { + +}); + +describe('Given commit title and author props', () => { + it('Should render a link to the author profile', () => { + + }); + + it('Should render the author avatar with title and alt attributes', () => { + + }); +}); + +describe('When commit title is not provided', () => { + it('Should render default message', () => { + + }); +}); + +describe('Given no ref prop', () => { + it('Should render without errors', () => { + + }); +}); + +describe('Given no title prop', () => { + it('Should render without errors', () => { + + }); +}); + +describe('Given no author prop', () => { + it('Should render without errors', () => { + + }); +}); \ No newline at end of file -- cgit v1.2.1 From 56aaa3973b5e62ee8527be073246c138ab83fdc6 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 14 Nov 2016 15:58:51 +0000 Subject: Revert changes made on rspec tests for environment --- spec/features/environments_spec.rb | 163 +++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 89 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index f4c0b093246..b565586ee14 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -1,36 +1,32 @@ -require 'rails_helper' - -feature 'Environments', feature: true, js:true do - include WaitForVueResource - - let(:json) { serializer.as_json } - let(:project) { create(:empty_project, :public) } - let(:user) { create(:user) } - let(:role) { :developer } - - let(:serializer) do - described_class - .new(user: user, project: project) - .represent(resource) - end - +require 'spec_helper' + +feature 'Environments', feature: true do + given(:project) { create(:empty_project) } + given(:user) { create(:user) } + given(:role) { :developer } + background do login_as(user) project.team << [user, role] end describe 'when showing environments' do + given!(:environment) { } + given!(:deployment) { } + given!(:manual) { } + before do visit namespace_project_environments_path(project.namespace, project) - wait_for_vue_resource end - context 'without environments' do - scenario 'does show "Available" and "Stopped" tab with links' do + context 'shows two tabs' do + scenario 'shows "Available" and "Stopped" tab with links' do expect(page).to have_link('Available') expect(page).to have_link('Stopped') end + end + context 'without environments' do scenario 'does show no environments' do expect(page).to have_content('You don\'t have any environments right now.') end @@ -42,99 +38,90 @@ feature 'Environments', feature: true, js:true do end context 'with environments' do - let(:resource) { create_list(:environment, 2) } - before do - endpoint = namespace_project_environments_path(project.namespace, project) - stub_request(:any, endpoint).to_return(body: [{"name": "test"}]) - end - - scenario 'does show "Available" and "Stopped" tab with links' do - expect(page).to have_link('Stopped') - expect(page).to have_link('Available') - end - - scenario 'does show environments table' do - expect(page).to have_selector('.table-holder') + given(:environment) { create(:environment, project: project) } + + scenario 'does show environment name' do + expect(page).to have_link(environment.name) end - + scenario 'does show number of available and stopped environments' do expect(page.find('.js-available-environments-count').text).to eq('1') expect(page.find('.js-stopped-environments-count').text).to eq('0') end - + context 'without deployments' do scenario 'does show no deployments' do expect(page).to have_content('No deployments yet') end end - + context 'with deployments' do - # TODO add environment with deployment - + given(:deployment) { create(:deployment, environment: environment) } + scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) end - + scenario 'does show deployment internal id' do expect(page).to have_content(deployment.iid) end - + context 'with build and manual actions' do given(:pipeline) { create(:ci_pipeline, project: project) } given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - + scenario 'does show a play button' do expect(page).to have_link(manual.name.humanize) end - + scenario 'does allow to play manual action' do expect(manual).to be_skipped expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end - + scenario 'does show build name and id' do expect(page).to have_link("#{build.name} (##{build.id})") end - + scenario 'does not show stop button' do expect(page).not_to have_selector('.stop-env-link') end - + scenario 'does not show external link button' do expect(page).not_to have_css('external-url') end - - context 'with external_url' do + + context 'with external_url' do given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } - + scenario 'does show an external link button' do expect(page).to have_link(nil, href: environment.external_url) end end - - context 'with stop action' do + + context 'with stop action' do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - + scenario 'does show stop button' do expect(page).to have_selector('.stop-env-link') end - + scenario 'starts build when stop button clicked' do first('.stop-env-link').click - + expect(page).to have_content('close_app') end - + context 'for reporter' do let(:role) { :reporter } - + scenario 'does not show stop button' do expect(page).not_to have_selector('.stop-env-link') end @@ -143,98 +130,96 @@ feature 'Environments', feature: true, js:true do end end end - - context 'can create new environment' do - scenario 'does have a New environment button' do - expect(page).to have_link('New environment') - end + + scenario 'does have a New environment button' do + expect(page).to have_link('New environment') end end - - describe 'when showing the environment' do + + describe 'when showing the environment' do given(:environment) { create(:environment, project: project) } given!(:deployment) { } given!(:manual) { } - + before do visit namespace_project_environment_path(project.namespace, project, environment) end - + context 'without deployments' do scenario 'does show no deployments' do expect(page).to have_content('You don\'t have any deployments right now.') end end - + context 'with deployments' do given(:deployment) { create(:deployment, environment: environment) } - + scenario 'does show deployment SHA' do expect(page).to have_link(deployment.short_sha) end - + scenario 'does not show a re-deploy button for deployment without build' do expect(page).not_to have_link('Re-deploy') end - + context 'with build' do given(:pipeline) { create(:ci_pipeline, project: project) } given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } - + scenario 'does show build name' do expect(page).to have_link("#{build.name} (##{build.id})") end - + scenario 'does show re-deploy button' do expect(page).to have_link('Re-deploy') end - + scenario 'does not show stop button' do expect(page).not_to have_link('Stop') end - + context 'with manual action' do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - + scenario 'does show a play button' do expect(page).to have_link(manual.name.humanize) end - + scenario 'does allow to play manual action' do expect(manual).to be_skipped expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } expect(page).to have_content(manual.name) expect(manual.reload).to be_pending end - + context 'with external_url' do given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } given(:build) { create(:ci_build, pipeline: pipeline) } given(:deployment) { create(:deployment, environment: environment, deployable: build) } - + scenario 'does show an external link button' do expect(page).to have_link(nil, href: environment.external_url) end end - + context 'with stop action' do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - + scenario 'does show stop button' do expect(page).to have_link('Stop') end - + scenario 'does allow to stop environment' do click_link('Stop') - + expect(page).to have_content('close_app') end - + context 'for reporter' do let(:role) { :reporter } - + scenario 'does not show stop button' do expect(page).not_to have_link('Stop') end @@ -244,43 +229,43 @@ feature 'Environments', feature: true, js:true do end end end - + describe 'when creating a new environment' do before do visit namespace_project_environments_path(project.namespace, project) end - + context 'when logged as developer' do before do click_link 'New environment' end - + context 'for valid name' do before do fill_in('Name', with: 'production') click_on 'Save' end - + scenario 'does create a new pipeline' do expect(page).to have_content('Production') end end - + context 'for invalid name' do before do fill_in('Name', with: 'name,with,commas') click_on 'Save' end - + scenario 'does show errors' do expect(page).to have_content('Name can contain only letters') end end end - + context 'when logged as reporter' do given(:role) { :reporter } - + scenario 'does not have a New environment link' do expect(page).not_to have_link('New environment') end -- cgit v1.2.1 From dd80e09a7bcd4da9d4505090499e0da6e8555a9c Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 14 Nov 2016 17:22:21 +0000 Subject: Adds tests --- .../environments/environment_item_spec.js.es6 | 118 +++++++++++++++++++-- 1 file changed, 108 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js.es6 index f357e11dc8e..1029d632054 100644 --- a/spec/javascripts/environments/environment_item_spec.js.es6 +++ b/spec/javascripts/environments/environment_item_spec.js.es6 @@ -9,7 +9,6 @@ describe('Environment item', () => { describe('When item is folder', () => { let mockItem; - let component; beforeEach(() => { mockItem = { @@ -35,38 +34,137 @@ describe('Environment item', () => { }, ], }; + }); - component = new window.gl.environmentsList.EnvironmentItem({ + it('Should render clickable folder icon and name', () => { + const component = new window.gl.environmentsList.EnvironmentItem({ el: document.querySelector('tr#environment-row'), propsData: { model: mockItem, + toggleRow: () => {}, 'can-create-deployment': false, 'can-read-environment': true, }, }); - }); - it('Should render clickable folder icon and name', () => { - expect(document.querySelector('.folder-name').textContent).toContain(mockItem.name); - expect(document.querySelector('.folder-icon')).toBeDefined(); + expect(component.$el.querySelector('.folder-name').textContent).toContain(mockItem.name); + expect(component.$el.querySelector('.folder-icon')).toBeDefined(); }); it('Should render the number of children in a badge', () => { - expect(document.querySelector('.folder-name .badge').textContent).toContain(mockItem.children.length); - }); + const component = new window.gl.environmentsList.EnvironmentItem({ + el: document.querySelector('tr#environment-row'), + propsData: { + model: mockItem, + toggleRow: () => {}, + 'can-create-deployment': false, + 'can-read-environment': true, + }, + }); - it('Should not render any information other than the name', () => { + expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(mockItem.children.length); }); describe('when clicked', () => { - it('Should render child row', () => { + it('Should call the given prop', () => { + const component = new window.gl.environmentsList.EnvironmentItem({ + el: document.querySelector('tr#environment-row'), + propsData: { + model: mockItem, + toggleRow: () => { + console.log('here!'); + }, + 'can-create-deployment': false, + 'can-read-environment': true, + }, + }); + + spyOn(component.$options.propsData, 'toggleRow'); + component.$el.querySelector('.folder-name').click(); + + expect(component.$options.propsData.toggleRow).toHaveBeenCalled(); }); }); }); describe('when item is not folder', () => { + let environment; + + beforeEach(() => { + environment = { + id: 31, + name: 'production', + state: 'stopped', + external_url: 'http://external.com', + environment_type: null, + last_deployment: { + id: 66, + iid: 6, + sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + ref: { + name: 'master', + ref_url: 'http://localhost:3000/root/ci-folders/tree/master', + }, + tag: true, + 'last?': true, + user: { + name: 'Administrator', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + commit: { + id: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + short_id: '500aabcb', + title: 'Update .gitlab-ci.yml', + author_name: 'Administrator', + author_email: 'admin@example.com', + created_at: '2016-11-07T18:28:13.000+00:00', + message: 'Update .gitlab-ci.yml', + author: { + name: 'Administrator', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + commit_url: 'http://localhost:3000/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + }, + deployable: { + id: 1279, + name: 'deploy', + build_url: 'http://localhost:3000/root/ci-folders/builds/1279', + retry_url: 'http://localhost:3000/root/ci-folders/builds/1279/retry', + }, + manual_actions: [ + { + name: 'action', + play_url: 'http://localhost:3000/play', + }, + ], + }, + 'stoppable?': true, + environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + created_at: '2016-11-07T11:11:16.525Z', + updated_at: '2016-11-10T15:55:58.778Z', + }; + }); + it('should render environment name', () => { + const component = new window.gl.environmentsList.EnvironmentItem({ + el: document.querySelector('tr#environment-row'), + propsData: { + model: environment, + toggleRow: () => {}, + 'can-create-deployment': false, + 'can-read-environment': true, + }, + }); + debugger; }); describe('With deployment', () => { -- cgit v1.2.1 From ed07264532cac11b1f7cc4c68627cb7bfb7e41fc Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Tue, 15 Nov 2016 12:07:11 +0000 Subject: Adds props validation Improves documentation Adds tests Fix prop validation for objects Finish tests for environment item Adds tests for toggle folder function Environment tests Adds tests --- spec/features/environments_spec.rb | 3 +- .../environments/environment_item_spec.js.es6 | 136 ++++++---------- .../environments/environment_spec.js.es6 | 172 --------------------- .../environments/environments_store_spec.js.es6 | 17 +- .../fixtures/environments/environments.html.haml | 8 +- .../environments_no_permission.html.haml | 9 -- 6 files changed, 70 insertions(+), 275 deletions(-) delete mode 100644 spec/javascripts/environments/environment_spec.js.es6 delete mode 100644 spec/javascripts/fixtures/environments/environments_no_permission.html.haml (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index b565586ee14..f36a895a037 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Environments', feature: true do +feature 'Environments', feature: true, js:true do given(:project) { create(:empty_project) } given(:user) { create(:user) } given(:role) { :developer } @@ -59,6 +59,7 @@ feature 'Environments', feature: true do given(:deployment) { create(:deployment, environment: environment) } scenario 'does show deployment SHA' do + puts page.body expect(page).to have_link(deployment.short_sha) end diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js.es6 index 1029d632054..7559258426b 100644 --- a/spec/javascripts/environments/environment_item_spec.js.es6 +++ b/spec/javascripts/environments/environment_item_spec.js.es6 @@ -9,6 +9,7 @@ describe('Environment item', () => { describe('When item is folder', () => { let mockItem; + let component; beforeEach(() => { mockItem = { @@ -34,61 +35,31 @@ describe('Environment item', () => { }, ], }; - }); - it('Should render clickable folder icon and name', () => { - const component = new window.gl.environmentsList.EnvironmentItem({ + component = new window.gl.environmentsList.EnvironmentItem({ el: document.querySelector('tr#environment-row'), propsData: { model: mockItem, toggleRow: () => {}, - 'can-create-deployment': false, - 'can-read-environment': true, + canCreateDeployment: false, + canReadEnvironment: true, }, }); + }); + it('Should render folder icon and name', () => { expect(component.$el.querySelector('.folder-name').textContent).toContain(mockItem.name); expect(component.$el.querySelector('.folder-icon')).toBeDefined(); }); it('Should render the number of children in a badge', () => { - const component = new window.gl.environmentsList.EnvironmentItem({ - el: document.querySelector('tr#environment-row'), - propsData: { - model: mockItem, - toggleRow: () => {}, - 'can-create-deployment': false, - 'can-read-environment': true, - }, - }); - expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(mockItem.children.length); }); - - describe('when clicked', () => { - it('Should call the given prop', () => { - const component = new window.gl.environmentsList.EnvironmentItem({ - el: document.querySelector('tr#environment-row'), - propsData: { - model: mockItem, - toggleRow: () => { - console.log('here!'); - }, - 'can-create-deployment': false, - 'can-read-environment': true, - }, - }); - - spyOn(component.$options.propsData, 'toggleRow'); - component.$el.querySelector('.folder-name').click(); - - expect(component.$options.propsData.toggleRow).toHaveBeenCalled(); - }); - }); }); describe('when item is not folder', () => { let environment; + let component; beforeEach(() => { environment = { @@ -151,104 +122,93 @@ describe('Environment item', () => { created_at: '2016-11-07T11:11:16.525Z', updated_at: '2016-11-10T15:55:58.778Z', }; - }); - it('should render environment name', () => { - const component = new window.gl.environmentsList.EnvironmentItem({ + component = new window.gl.environmentsList.EnvironmentItem({ el: document.querySelector('tr#environment-row'), propsData: { model: environment, toggleRow: () => {}, - 'can-create-deployment': false, - 'can-read-environment': true, + canCreateDeployment: true, + canReadEnvironment: true, }, }); + }); - debugger; + it('should render environment name', () => { + expect(component.$el.querySelector('.environment-name').textContent).toEqual(environment.name); }); describe('With deployment', () => { it('should render deployment internal id', () => { + expect( + component.$el.querySelector('.deployment-column span').textContent + ).toContain(environment.last_deployment.iid); - }); - - it('should link to deployment', () => { - + expect( + component.$el.querySelector('.deployment-column span').textContent + ).toContain('#'); }); describe('With user information', () => { it('should render user avatar with link to profile', () => { - + expect( + component.$el.querySelector('.js-deploy-user-container').getAttribute('href') + ).toEqual(environment.last_deployment.user.web_url); }); }); describe('With build url', () => { it('Should link to build url provided', () => { - + expect( + component.$el.querySelector('.build-link').getAttribute('href') + ).toEqual(environment.last_deployment.deployable.build_url); }); it('Should render deployable name and id', () => { - + expect( + component.$el.querySelector('.build-link').getAttribute('href') + ).toEqual(environment.last_deployment.deployable.build_url); }); }); describe('With commit information', () => { - it('should render commit component', () => {}); - }); - - it('Should render timeago created date', () => { - - }); - }); - - describe('Without deployment', () => { - it('should render no deployments information', () => { - + it('should render commit component', () => { + expect( + component.$el.querySelector('.js-commit-component') + ).toBeDefined(); + }); }); }); describe('With manual actions', () => { - describe('With create deployment permission', () => { - it('Should render actions component', () => { - - }); - }); - describe('Without create deployment permission', () => { - it('should not render actions component', () => { - - }); + it('Should render actions component', () => { + expect( + component.$el.querySelector('.js-manual-actions-container') + ).toBeDefined(); }); }); describe('With external URL', () => { it('should render external url component', () => { - + expect( + component.$el.querySelector('.js-external-url-container') + ).toBeDefined(); }); }); describe('With stop action', () => { - describe('With create deployment permission', () => { - it('Should render stop action component', () => { - - }); - }); - describe('Without create deployment permission', () => { - it('should not render stop action component', () => { - - }); + it('Should render stop action component', () => { + expect( + component.$el.querySelector('.js-stop-component-container') + ).toBeDefined(); }); }); describe('With retry action', () => { - describe('With create deployment permission', () => { - it('Should render rollback component', () => { - - }); - }); - describe('Without create deployment permission', () => { - it('should not render rollback component', () => { - - }); + it('Should render rollback component', () => { + expect( + component.$el.querySelector('.js-rollback-component-container') + ).toBeDefined(); }); }); }); diff --git a/spec/javascripts/environments/environment_spec.js.es6 b/spec/javascripts/environments/environment_spec.js.es6 deleted file mode 100644 index 07eb9938c58..00000000000 --- a/spec/javascripts/environments/environment_spec.js.es6 +++ /dev/null @@ -1,172 +0,0 @@ -//= require vue -//= require environments/stores/environments_store -//= require environments/components/environment - -/* globals environmentsList */ -describe('Environments', () => { - fixture.preload('environments/environments.html'); - fixture.preload('environments/environments_no_permission.html'); - let Store; - let component; - - beforeEach(() => { - Store = window.gl.environmentsList.EnvironmentsStore; - }); - - describe('While loading', () => { - beforeEach(() => { - fixture.load('environments/environments.html'); - component = new window.gl.environmentsList.EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - propsData: { - store: Store.create(), - }, - }); - }); - - it('Should render two tabs', () => { - expect(component.$el.querySelectorAll('ul li').length).toEqual(2); - }); - - it('Should render bagdes with zeros in both tabs indicating the number of available environments', () => { - expect( - component.$el.querySelector('.js-available-environments-count').textContent - ).toContain('0'); - expect( - component.$el.querySelector('.js-stopped-environments-count').textContent - ).toContain('0'); - }); - - it('Should render loading icon', () => { - expect( - component.$el.querySelector('environments-list-loading') - ).toBeDefined(); - }); - }); - - describe('Without environments', () => { - beforeEach(() => { - fixture.load('environments/environments.html'); - - spyOn(component, 'ready').and.callFake(() => { - return { - then: callback => callback([]), - json: () => ({ then: cb => cb([]) }), - }; - }); - - component = new window.gl.environmentsList.EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - propsData: { - store: Store.create(), - }, - }); - }); - - it('Should render two tabs', () => { - expect(component.$el.querySelectorAll('ul li').length).toEqual(2); - }); - - it('Should render bagdes with zeros in both tabs indicating the number of available environments', () => { - expect( - component.$el.querySelector('.js-available-environments-count').textContent - ).toContain('0'); - expect( - component.$el.querySelector('.js-stopped-environments-count').textContent - ).toContain('0'); - }); - - it('Should render blank state information', () => { - expect( - component.$el.querySelector('.blank-state-title').textContent - ).toEqual('You don\'t have any environments right now.'); - - expect( - component.$el.querySelector('.blank-state-text').textContent - ).toEqual('Environments are places where code gets deployed, such as staging or production.'); - }); - - it('Should render the provided help url', () => { - expect( - component.$el.querySelector('.blank-state a').getAttribute('href') - ).toEqual(component.$data.helpPagePath); - }); - - describe('With create permission', () => { - it('Should render new environment button', () => { - expect( - component.$el.querySelector('a.btn-create').getAttribute('href') - ).toEqual(component.$data.newEnvironmentPath); - expect( - component.$el.querySelector('a.btn-create').textContent - ).toEqual('New environment'); - }); - }); - - describe('Without create permission', () => { - beforeEach('Load fixture without permission', () => { - fixture.load('environments/environments_no_permission.html'); - component = new window.gl.environmentsList.EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - propsData: { - store: Store.create(), - }, - }); - }); - - it('Should not render new environment button', () => { - - }); - }); - }); - - describe('With environments', () => { - describe('Tabs behavior', () => { - it('Should render two tabs', () => { - - }); - - it('Should render badges with the correct count', () => { - - }); - - describe('When clicking in the available tab', () => { - it('Should make Available tab active', () => { - - }); - - it('Should make visible only available environments', () => { - - }); - }); - - describe('When clicking in the stopped tab', () => { - it('Should make Stopped tab active', () => { - - }); - - it('Should make visible only stopped environments', () => { - - }); - }); - }); - - describe('With create permissions', () => { - it('Should render new environment button', () => { - - }); - }); - - describe('Without create permissions', () => { - it('Should not render the new environment button', () => { - }); - }); - - it('Should render a table', () => { - }); - - it('Should render table pagination', () => { - - }); - }); -}); diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index 5e35949ac9c..82d9599f372 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -1,5 +1,5 @@ //= require vue -//= require environments/stores/environmnets_store +//= require environments/stores/environments_store //= require ./mock_data /* globals environmentsList */ (() => { @@ -50,5 +50,20 @@ expect(environments[2].name).toBe('review_app'); }); }); + + describe('toggleFolder', () => { + beforeEach(() => { + gl.environmentsList.EnvironmentsStore.storeEnvironments(environmentsList); + }); + + it('should toggle the open property for the given environment', () => { + gl.environmentsList.EnvironmentsStore.toggleFolder('review'); + + const { environments } = gl.environmentsList.EnvironmentsStore.state; + const environment = environments.filter(env => env['vue-isChildren'] === true && env.name === 'review'); + + expect(environment[0].isOpen).toBe(true); + }); + }); }); })(); diff --git a/spec/javascripts/fixtures/environments/environments.html.haml b/spec/javascripts/fixtures/environments/environments.html.haml index dd1d6855ce2..d89bc50c1f0 100644 --- a/spec/javascripts/fixtures/environments/environments.html.haml +++ b/spec/javascripts/fixtures/environments/environments.html.haml @@ -1,9 +1,9 @@ %div - #environments-list-view{ data: { environments_data: "https://gitlab.com/foo/environments", - "can-create-deployment" => "true", + #environments-list-view{ data: { environments_data: "https://gitlab.com/foo/environments", + "can-create-deployment" => "true", "can-read-environment" => "true", - "can-create-environmnet" => "true", + "can-create-environment" => "true", "project-environments-path" => "https://gitlab.com/foo/environments", "project-stopped-environments-path" => "https://gitlab.com/foo/environments?scope=stopped", "new-environment-path" => "https://gitlab.com/foo/environments/new", - "help-page-path" => "https://gitlab.com/help_page"}} \ No newline at end of file + "help-page-path" => "https://gitlab.com/help_page"}} diff --git a/spec/javascripts/fixtures/environments/environments_no_permission.html.haml b/spec/javascripts/fixtures/environments/environments_no_permission.html.haml deleted file mode 100644 index 71cf7db7a34..00000000000 --- a/spec/javascripts/fixtures/environments/environments_no_permission.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -%div - #environments-list-view{ data: { environments_data: "https://gitlab.com/foo/environments", - "can-create-deployment" => "false", - "can-read-environment" => "true", - "can-create-environmnet" => "false", - "project-environments-path" => "https://gitlab.com/foo/environments", - "project-stopped-environments-path" => "https://gitlab.com/foo/environments?scope=stopped", - "new-environment-path" => "https://gitlab.com/foo/environments/new", - "help-page-path" => "https://gitlab.com/help_page"}} \ No newline at end of file -- cgit v1.2.1 From b210cbca6cad033f58e62dad08ebd30b77036126 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 11:23:36 +0000 Subject: Fix eslint errors Fix rubocop error --- spec/features/environments_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index f36a895a037..fbf0b6392b9 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Environments', feature: true, js:true do +feature 'Environments', feature: true, js: true do given(:project) { create(:empty_project) } given(:user) { create(:user) } given(:role) { :developer } -- cgit v1.2.1 From f55206cea522e35673092158fba2c57a4c0454de Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 11:53:05 +0000 Subject: Adds missing tests for commit component --- .../vue_common_components/commit_spec.js.es6 | 175 +++++++++++++-------- 1 file changed, 107 insertions(+), 68 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/vue_common_components/commit_spec.js.es6 b/spec/javascripts/vue_common_components/commit_spec.js.es6 index 4f158e8ffa5..2345e0af8eb 100644 --- a/spec/javascripts/vue_common_components/commit_spec.js.es6 +++ b/spec/javascripts/vue_common_components/commit_spec.js.es6 @@ -1,89 +1,128 @@ -/*= require vue_common_components/commit */ -/* eslint-disable */ +//= require vue_common_component/commit describe('Commit component', () => { - const getRenderedText = (Component, propsData) => { - const Constructor = Vue.extend(Component); - const vm = new Constructor({propsData}).$mount(); - return vm.$el.textContent; - }; - - const MyComponent = window.gl.commitComponent; - - describe('When `ref` is provided', () => { - const props = { - tag: true, - ref: { - name: 'master', - ref_url: 'http://localhost/namespace2/gitlabhq/tree/master' + + let props; + let component; + + + it('should render a code-fork icon if it does not represent a tag', () => { + fixture.set('
    '); + component = new window.gl.CommitComponent({ + el: document.querySelector('.test-commit-container'), + propsData: { + tag: false, + ref: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master', + }, + commit_url: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + short_sha: 'b7836edd', + title: 'Commit message', + author: { + avatar_url: 'https://gitlab.com/uploads/user/avatar/300478/avatar.png', + web_url: 'https://gitlab.com/jschatz1', + username: 'jschatz1', + }, }, - commit_url: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', - short_sha: 'b7836edd', - title: 'Commit message', - author: { - avatar_url: 'https://gitlab.com/uploads/user/avatar/300478/avatar.png', - web_url: 'https://gitlab.com/jschatz1', - username: 'jschatz1' - } - }; + }); - it('should render a tag icon if it represents a tag', () => { - const renderedText = getRenderedText(MyComponent, props); + expect(component.$el.querySelector('.icon-container i').classList).toContain('fa-code-fork'); + }); + describe('Given all the props', () => { + beforeEach(() => { + fixture.set('
    '); + + props = { + tag: true, + ref: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master', + }, + commit_url: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + short_sha: 'b7836edd', + title: 'Commit message', + author: { + avatar_url: 'https://gitlab.com/uploads/user/avatar/300478/avatar.png', + web_url: 'https://gitlab.com/jschatz1', + username: 'jschatz1', + }, + }; + + component = new window.gl.CommitComponent({ + el: document.querySelector('.test-commit-container'), + propsData: props, + }); }); - it('should render a code-fork icon if it does not represent a tag', () => { - + it('should render a tag icon if it represents a tag', () => { + expect(component.$el.querySelector('.icon-container i').classList).toContain('fa-tag'); }); it('should render a link to the ref url', () => { - + expect(component.$el.querySelector('.branch-name').getAttribute('href')).toEqual(props.ref.ref_url); }); it('should render the ref name', () => { - + expect(component.$el.querySelector('.branch-name').textContent).toContain(props.ref.name); }); - }); -}); - -it('should render the commit icon as an svg', () => { - -}); - -it('should render the commit short sha with a link to the commit url', () => { -}); - -describe('Given commit title and author props', () => { - it('Should render a link to the author profile', () => { - - }); - - it('Should render the author avatar with title and alt attributes', () => { - - }); -}); - -describe('When commit title is not provided', () => { - it('Should render default message', () => { - - }); -}); + it('should render the commit short sha with a link to the commit url', () => { + expect(component.$el.querySelector('.commit-id').getAttribute('href')).toEqual(props.commit_url); + expect(component.$el.querySelector('.commit-id').textContent).toContain(props.short_sha); + }); -describe('Given no ref prop', () => { - it('Should render without errors', () => { + describe('Given commit title and author props', () => { + it('Should render a link to the author profile', () => { + expect( + component.$el.querySelector('.commit-title .avatar-image-container').getAttribute('href') + ).toEqual(props.author.web_url); + }); + + it('Should render the author avatar with title and alt attributes', () => { + expect( + component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('title') + ).toContain(props.author.username); + expect( + component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('alt') + ).toContain(`${props.author.username}'s avatar`); + }); + }); + it('should render the commit title', () => { + expect( + component.$el.querySelector('a.commit-row-message').getAttribute('href') + ).toEqual(props.commit_url); + expect( + component.$el.querySelector('a.commit-row-message').textContent + ).toContain(props.title); + }); }); -}); - -describe('Given no title prop', () => { - it('Should render without errors', () => { + describe('When commit title is not provided', () => { + it('Should render default message', () => { + fixture.set('
    '); + props = { + tag: false, + ref: { + name: 'master', + ref_url: 'http://localhost/namespace2/gitlabhq/tree/master', + }, + commit_url: 'https://gitlab.com/gitlab-org/gitlab-ce/commit/b7836eddf62d663c665769e1b0960197fd215067', + short_sha: 'b7836edd', + title: null, + author: {}, + }; + + component = new window.gl.CommitComponent({ + el: document.querySelector('.test-commit-container'), + propsData: props, + }); + + expect( + component.$el.querySelector('.commit-title span').textContent + ).toContain('Cant find HEAD commit for this branch'); + }); }); }); - -describe('Given no author prop', () => { - it('Should render without errors', () => { - - }); -}); \ No newline at end of file -- cgit v1.2.1 From a5632e802b72db01c0fb0b8bec77c0fc28b41427 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 10 Nov 2016 19:27:09 +0200 Subject: Search for a filename in a project --- spec/helpers/search_helper_spec.rb | 32 ---------------- spec/lib/gitlab/project_search_results_spec.rb | 51 ++++++++++++++++++++++++-- spec/models/repository_spec.rb | 34 ++++++++++++++--- 3 files changed, 75 insertions(+), 42 deletions(-) (limited to 'spec') diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index 64aa41020c9..4b2ca3514f8 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -6,38 +6,6 @@ describe SearchHelper do str end - describe 'parsing result' do - let(:project) { create(:project) } - let(:repository) { project.repository } - let(:results) { repository.search_files('feature', 'master') } - let(:search_result) { results.first } - - subject { helper.parse_search_result(search_result) } - - it "returns a valid OpenStruct object" do - is_expected.to be_an OpenStruct - expect(subject.filename).to eq('CHANGELOG') - expect(subject.basename).to eq('CHANGELOG') - expect(subject.ref).to eq('master') - expect(subject.startline).to eq(188) - expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") - end - - context "when filename has extension" do - let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" } - - it { expect(subject.filename).to eq('CONTRIBUTE.md') } - it { expect(subject.basename).to eq('CONTRIBUTE') } - end - - context "when file under directory" do - let(:search_result) { "master:a/b/c.md:5:a b c\n" } - - it { expect(subject.filename).to eq('a/b/c.md') } - it { expect(subject.basename).to eq('a/b/c') } - end - end - describe 'search_autocomplete_source' do context "with no current user" do before do diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index 29abb4d4d07..a0fdad87eee 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -6,22 +6,65 @@ describe Gitlab::ProjectSearchResults, lib: true do let(:query) { 'hello world' } describe 'initialize with empty ref' do - let(:results) { Gitlab::ProjectSearchResults.new(user, project, query, '') } + let(:results) { described_class.new(user, project, query, '') } it { expect(results.project).to eq(project) } - it { expect(results.repository_ref).to be_nil } it { expect(results.query).to eq('hello world') } end describe 'initialize with ref' do let(:ref) { 'refs/heads/test' } - let(:results) { Gitlab::ProjectSearchResults.new(user, project, query, ref) } + let(:results) { described_class.new(user, project, query, ref) } it { expect(results.project).to eq(project) } it { expect(results.repository_ref).to eq(ref) } it { expect(results.query).to eq('hello world') } end + describe 'blob search' do + let(:results) { described_class.new(user, project, 'files').objects('blobs') } + + it 'finds by name' do + expect(results).to include(["files/images/wm.svg", nil]) + end + + it 'finds by content' do + blob = results.select { |result| result.first == "CHANGELOG" }.flatten.last + + expect(blob.filename).to eq("CHANGELOG") + end + + describe 'parsing results' do + let(:results) { project.repository.search_files_by_content('feature', 'master') } + let(:search_result) { results.first } + + subject { described_class.parse_search_result(search_result) } + + it "returns a valid OpenStruct object" do + is_expected.to be_an OpenStruct + expect(subject.filename).to eq('CHANGELOG') + expect(subject.basename).to eq('CHANGELOG') + expect(subject.ref).to eq('master') + expect(subject.startline).to eq(188) + expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") + end + + context "when filename has extension" do + let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" } + + it { expect(subject.filename).to eq('CONTRIBUTE.md') } + it { expect(subject.basename).to eq('CONTRIBUTE') } + end + + context "when file under directory" do + let(:search_result) { "master:a/b/c.md:5:a b c\n" } + + it { expect(subject.filename).to eq('a/b/c.md') } + it { expect(subject.basename).to eq('a/b/c') } + end + end + end + describe 'confidential issues' do let(:query) { 'issue' } let(:author) { create(:user) } @@ -66,7 +109,7 @@ describe Gitlab::ProjectSearchResults, lib: true do end it 'lists project confidential issues for assignee' do - results = described_class.new(assignee, project.id, query) + results = described_class.new(assignee, project, query) issues = results.objects('issues') expect(issues).to include issue diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index fe26b4ac18c..3bd5741f2b7 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -393,33 +393,33 @@ describe Repository, models: true do end end - describe "search_files" do - let(:results) { repository.search_files('feature', 'master') } + describe "search_files_by_content" do + let(:results) { repository.search_files_by_content('feature', 'master') } subject { results } it { is_expected.to be_an Array } it 'regex-escapes the query string' do - results = repository.search_files("test\\", 'master') + results = repository.search_files_by_content("test\\", 'master') expect(results.first).not_to start_with('fatal:') end it 'properly handles an unmatched parenthesis' do - results = repository.search_files("test(", 'master') + results = repository.search_files_by_content("test(", 'master') expect(results.first).not_to start_with('fatal:') end it 'properly handles when query is not present' do - results = repository.search_files('', 'master') + results = repository.search_files_by_content('', 'master') expect(results).to match_array([]) end it 'properly handles query when repo is empty' do repository = create(:empty_project).repository - results = repository.search_files('test', 'master') + results = repository.search_files_by_content('test', 'master') expect(results).to match_array([]) end @@ -432,6 +432,28 @@ describe Repository, models: true do end end + describe "search_files_by_name" do + let(:results) { repository.search_files_by_name('files', 'master') } + + it 'returns result' do + expect(results.first).to eq('files/html/500.html') + end + + it 'properly handles when query is not present' do + results = repository.search_files_by_name('', 'master') + + expect(results).to match_array([]) + end + + it 'properly handles query when repo is empty' do + repository = create(:empty_project).repository + + results = repository.search_files_by_name('test', 'master') + + expect(results).to match_array([]) + end + end + describe '#create_ref' do it 'redirects the call to fetch_ref' do ref, ref_path = '1', '2' -- cgit v1.2.1 From 596bbf670c95a513cce703dce756e957a143c596 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 15 Nov 2016 03:57:43 +0100 Subject: Send registry_url with build data to GitLab Runner --- spec/requests/ci/api/builds_spec.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'spec') diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 6d49c42c215..bd4d3d61714 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -17,6 +17,10 @@ describe Ci::API::API do let!(:build) { create(:ci_build, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) } let(:user_agent) { 'gitlab-ci-multi-runner 1.5.2 (1-5-stable; go1.6.3; linux/amd64)' } + before do + stub_container_registry_config(enabled: false) + end + shared_examples 'no builds available' do context 'when runner sends version in User-Agent' do context 'for stable version' do @@ -53,6 +57,31 @@ describe Ci::API::API do it 'updates runner info' do expect { register_builds }.to change { runner.reload.contacted_at } end + + context 'when registry is enabled' do + before do + stub_container_registry_config(enabled: true, host_port: 'registry.example.com:5005') + end + + it 'sends registry_url key' do + register_builds info: { platform: :darwin } + + expect(json_response).to have_key('registry_url') + expect(json_response['registry_url']).to eq("registry.example.com:5005") + end + end + + context 'when registry is disabled' do + before do + stub_container_registry_config(enabled: false, host_port: 'registry.example.com:5005') + end + + it 'does not send registry_url key' do + register_builds info: { platform: :darwin } + + expect(json_response).not_to have_key('registry_url') + end + end end context 'when builds are finished' do -- cgit v1.2.1 From c44474150c8a82e62ed1e0ed5758b1f38bbf7c41 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 16 Nov 2016 11:51:47 +0200 Subject: Limit labels returned for a specific project as an administrator Prior, an administrator viewing a project's Labels page would see _all_ labels from every project they had access to, rather than only the labels of that specific project (if any). This was not an information disclosure, as admins have access to everything, but it was a performance issue. --- spec/finders/labels_finder_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec') diff --git a/spec/finders/labels_finder_spec.rb b/spec/finders/labels_finder_spec.rb index 10cfb66ec1c..9085cc8debf 100644 --- a/spec/finders/labels_finder_spec.rb +++ b/spec/finders/labels_finder_spec.rb @@ -64,6 +64,21 @@ describe LabelsFinder do expect(finder.execute).to eq [group_label_2, project_label_1, group_label_1] end + + context 'as an administrator' do + it 'does not return labels from another project' do + # Purposefully creating a project with _nothing_ associated to it + isolated_project = create(:empty_project) + admin = create(:admin) + + # project_3 has a label associated to it, which we don't want coming + # back when we ask for the isolated project's labels + project_3.team << [admin, :reporter] + finder = described_class.new(admin, project_id: isolated_project.id) + + expect(finder.execute).to be_empty + end + end end context 'filtering by title' do -- cgit v1.2.1 From 7bab27914262dc82b7c115e1ca542cd32dca7b43 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 16 Nov 2016 14:12:19 +0100 Subject: Fix view that embeds abilities for the environments --- spec/features/environments_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index fbf0b6392b9..fe470fefca5 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -59,7 +59,6 @@ feature 'Environments', feature: true, js: true do given(:deployment) { create(:deployment, environment: environment) } scenario 'does show deployment SHA' do - puts page.body expect(page).to have_link(deployment.short_sha) end -- cgit v1.2.1 From d64183e1fa26ab77107e3a2a20be1fe4df3a1875 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 16 Nov 2016 14:56:30 +0100 Subject: Add most of specs for chat names --- spec/factories/chat_names.rb | 16 +++++++++ spec/lib/gitlab/chat_name_token_spec.rb | 39 ++++++++++++++++++++++ spec/models/chat_name_spec.rb | 16 +++++++++ spec/models/user_spec.rb | 1 + .../chat_names/authorize_user_service_spec.rb | 27 +++++++++++++++ spec/services/chat_names/find_user_service_spec.rb | 36 ++++++++++++++++++++ 6 files changed, 135 insertions(+) create mode 100644 spec/factories/chat_names.rb create mode 100644 spec/lib/gitlab/chat_name_token_spec.rb create mode 100644 spec/models/chat_name_spec.rb create mode 100644 spec/services/chat_names/authorize_user_service_spec.rb create mode 100644 spec/services/chat_names/find_user_service_spec.rb (limited to 'spec') diff --git a/spec/factories/chat_names.rb b/spec/factories/chat_names.rb new file mode 100644 index 00000000000..24225468d55 --- /dev/null +++ b/spec/factories/chat_names.rb @@ -0,0 +1,16 @@ +FactoryGirl.define do + factory :chat_name, class: ChatName do + user factory: :user + service factory: :service + + team_id 'T0001' + team_domain 'Awesome Team' + + sequence :chat_id do |n| + "U#{n}" + end + sequence :chat_name do |n| + "user#{n}" + end + end +end diff --git a/spec/lib/gitlab/chat_name_token_spec.rb b/spec/lib/gitlab/chat_name_token_spec.rb new file mode 100644 index 00000000000..8d7e7a99059 --- /dev/null +++ b/spec/lib/gitlab/chat_name_token_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe Gitlab::ChatNameToken, lib: true do + context 'when using unknown token' do + let(:token) { } + + subject { described_class.new(token).get } + + it 'returns empty data' do + is_expected.to be_nil + end + end + + context 'when storing data' do + let(:data) { + { key: 'value' } + } + + subject { described_class.new(@token) } + + before do + @token = described_class.new.store!(data) + end + + it 'returns stored data' do + expect(subject.get).to eq(data) + end + + context 'and after deleting them' do + before do + subject.delete + end + + it 'data are removed' do + expect(subject.get).to be_nil + end + end + end +end diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb new file mode 100644 index 00000000000..b02971cab82 --- /dev/null +++ b/spec/models/chat_name_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe ChatName, models: true do + subject { create(:chat_name) } + + it { is_expected.to belong_to(:service) } + it { is_expected.to belong_to(:user) } + + it { is_expected.to validate_presence_of(:user) } + it { is_expected.to validate_presence_of(:service) } + it { is_expected.to validate_presence_of(:team_id) } + it { is_expected.to validate_presence_of(:chat_id) } + + it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:service_id) } + it { is_expected.to validate_uniqueness_of(:chat_id).scoped_to(:service_id, :team_id) } +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 3b152e15b61..be6767855c7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -33,6 +33,7 @@ describe User, models: true do it { is_expected.to have_many(:award_emoji).dependent(:destroy) } it { is_expected.to have_many(:builds).dependent(:nullify) } it { is_expected.to have_many(:pipelines).dependent(:nullify) } + it { is_expected.to have_many(:chat_names).dependent(:destroy) } describe '#group_members' do it 'does not include group memberships for which user is a requester' do diff --git a/spec/services/chat_names/authorize_user_service_spec.rb b/spec/services/chat_names/authorize_user_service_spec.rb new file mode 100644 index 00000000000..f8c26e51bfc --- /dev/null +++ b/spec/services/chat_names/authorize_user_service_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe ChatNames::AuthorizeUserService, services: true do + describe '#execute' do + let(:service) { create(:service) } + + subject { described_class.new(service, params).execute } + + context 'when all parameters are valid' do + let(:params) { { team_id: 'T0001', team_domain: 'myteam', user_id: 'U0001', user_name: 'user' } } + + it 'requests a new token' do + is_expected.to include('http') + is_expected.to include('://') + is_expected.to include('token=') + end + end + + context 'when there are missing parameters' do + let(:params) { { } } + + it 'does not request a new token' do + is_expected.to be_nil + end + end + end +end diff --git a/spec/services/chat_names/find_user_service_spec.rb b/spec/services/chat_names/find_user_service_spec.rb new file mode 100644 index 00000000000..cf5844069f9 --- /dev/null +++ b/spec/services/chat_names/find_user_service_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe ChatNames::FindUserService, services: true do + describe '#execute' do + let(:service) { create(:service) } + + subject { described_class.new(service, params).execute } + + context 'find user mapping' do + let(:user) { create(:user) } + let!(:chat_name) { create(:chat_name, user: user, service: service) } + + context 'when existing user is requested' do + let(:params) { { team_id: chat_name.team_id, user_id: chat_name.chat_id } } + + it 'returns existing user' do + is_expected.to eq(user) + end + + it 'updates when last time chat name was used' do + subject + + expect(chat_name.reload.used_at).to be_like_time(Time.now) + end + end + + context 'when different user is requested' do + let(:params) { { team_id: chat_name.team_id, user_id: 'non-existing-user' } } + + it 'returns existing user' do + is_expected.to be_nil + end + end + end + end +end -- cgit v1.2.1 From 1c994dbc05c147714479288126742f3fee158fd8 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 15 Nov 2016 15:02:44 +0000 Subject: Fix POST /internal/allowed to cope with gitlab-shell v4.0.0 project paths gitlab-shell v3.6.6 would give project paths like so: * namespace/project gitlab-shell v4.0.0 can give project paths like so: * /namespace1/namespace2/project * /namespace/project * /path/to/repository/storage/namespace1/namespace2/project * /path/to/repository/storage/namespace/project --- spec/models/repository_spec.rb | 10 ------- spec/requests/api/api_internal_helpers_spec.rb | 32 +++++++++++++++++++++++ spec/requests/api/internal_spec.rb | 36 ++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 spec/requests/api/api_internal_helpers_spec.rb (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index fe26b4ac18c..c93ec08b822 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1534,14 +1534,4 @@ describe Repository, models: true do end.to raise_error(Repository::CommitError) end end - - describe '#remove_storage_from_path' do - let(:storage_path) { project.repository_storage_path } - let(:project_path) { project.path_with_namespace } - let(:full_path) { File.join(storage_path, project_path) } - - it { expect(Repository.remove_storage_from_path(full_path)).to eq(project_path) } - it { expect(Repository.remove_storage_from_path(project_path)).to eq(project_path) } - it { expect(Repository.remove_storage_from_path(storage_path)).to eq('') } - end end diff --git a/spec/requests/api/api_internal_helpers_spec.rb b/spec/requests/api/api_internal_helpers_spec.rb new file mode 100644 index 00000000000..be4bc39ada2 --- /dev/null +++ b/spec/requests/api/api_internal_helpers_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe ::API::Helpers::InternalHelpers do + include ::API::Helpers::InternalHelpers + + describe '.clean_project_path' do + project = 'namespace/project' + namespaced = File.join('namespace2', project) + + { + File.join(Dir.pwd, project) => project, + File.join(Dir.pwd, namespaced) => namespaced, + project => project, + namespaced => namespaced, + project + '.git' => project, + namespaced + '.git' => namespaced, + "/" + project => project, + "/" + namespaced => namespaced, + }.each do |project_path, expected| + context project_path do + # Relative and absolute storage paths, with and without trailing / + ['.', './', Dir.pwd, Dir.pwd + '/'].each do |storage_path| + context "storage path is #{storage_path}" do + subject { clean_project_path(project_path, [storage_path]) } + + it { is_expected.to eq(expected) } + end + end + end + end + end +end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index f0f590b0331..8f1a1f9e827 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -191,6 +191,26 @@ describe API::API, api: true do expect(json_response["status"]).to be_truthy expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) end + + context 'project as /namespace/project' do + it do + pull(key, project_with_repo_path('/' + project.path_with_namespace)) + + expect(response).to have_http_status(200) + expect(json_response["status"]).to be_truthy + expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) + end + end + + context 'project as namespace/project' do + it do + pull(key, project_with_repo_path(project.path_with_namespace)) + + expect(response).to have_http_status(200) + expect(json_response["status"]).to be_truthy + expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) + end + end end end @@ -299,7 +319,7 @@ describe API::API, api: true do context 'project does not exist' do it do - pull(key, OpenStruct.new(path_with_namespace: 'gitlab/notexists')) + pull(key, project_with_repo_path('gitlab/notexist')) expect(response).to have_http_status(200) expect(json_response["status"]).to be_falsey @@ -392,11 +412,17 @@ describe API::API, api: true do end end + def project_with_repo_path(path) + double().tap do |fake_project| + allow(fake_project).to receive_message_chain('repository.path_to_repo' => path) + end + end + def pull(key, project, protocol = 'ssh') post( api("/internal/allowed"), key_id: key.id, - project: project.path_with_namespace, + project: project.repository.path_to_repo, action: 'git-upload-pack', secret_token: secret_token, protocol: protocol @@ -408,7 +434,7 @@ describe API::API, api: true do api("/internal/allowed"), changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master', key_id: key.id, - project: project.path_with_namespace, + project: project.repository.path_to_repo, action: 'git-receive-pack', secret_token: secret_token, protocol: protocol @@ -420,7 +446,7 @@ describe API::API, api: true do api("/internal/allowed"), ref: 'master', key_id: key.id, - project: project.path_with_namespace, + project: project.repository.path_to_repo, action: 'git-upload-archive', secret_token: secret_token, protocol: 'ssh' @@ -432,7 +458,7 @@ describe API::API, api: true do api("/internal/lfs_authenticate"), key_id: key_id, secret_token: secret_token, - project: project.path_with_namespace + project: project.repository.path_to_repo ) end end -- cgit v1.2.1 From d47fca53db5840e85d38b35058d4bbd94ea917db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 16 Nov 2016 15:17:09 +0100 Subject: Allow commit note to be visible if repo is visible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/models/event_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'spec') diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 29a3af68a9b..b684053cd02 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -94,6 +94,7 @@ describe Event, models: true do let(:admin) { create(:admin) } let(:issue) { create(:issue, project: project, author: author, assignee: assignee) } let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) } + let(:note_on_commit) { create(:note_on_commit, project: project) } let(:note_on_issue) { create(:note_on_issue, noteable: issue, project: project) } let(:note_on_confidential_issue) { create(:note_on_issue, noteable: confidential_issue, project: project) } let(:event) { Event.new(project: project, target: target, author_id: author.id) } @@ -103,6 +104,32 @@ describe Event, models: true do project.team << [guest, :guest] end + context 'commit note event' do + let(:target) { note_on_commit } + + it do + aggregate_failures do + expect(event.visible_to_user?(non_member)).to eq true + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq true + expect(event.visible_to_user?(admin)).to eq true + end + end + + context 'private project' do + let(:project) { create(:empty_project, :private) } + + it do + aggregate_failures do + expect(event.visible_to_user?(non_member)).to eq false + expect(event.visible_to_user?(member)).to eq true + expect(event.visible_to_user?(guest)).to eq false + expect(event.visible_to_user?(admin)).to eq true + end + end + end + end + context 'issue event' do context 'for non confidential issues' do let(:target) { issue } -- cgit v1.2.1 From 4f0a169810621bfb15304b30d0a9916625cf4547 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 14:47:34 +0000 Subject: Fix eslint Remove unused method --- spec/javascripts/vue_common_components/commit_spec.js.es6 | 2 -- 1 file changed, 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/vue_common_components/commit_spec.js.es6 b/spec/javascripts/vue_common_components/commit_spec.js.es6 index 2345e0af8eb..0e3b82967c1 100644 --- a/spec/javascripts/vue_common_components/commit_spec.js.es6 +++ b/spec/javascripts/vue_common_components/commit_spec.js.es6 @@ -1,11 +1,9 @@ //= require vue_common_component/commit describe('Commit component', () => { - let props; let component; - it('should render a code-fork icon if it does not represent a tag', () => { fixture.set('
    '); component = new window.gl.CommitComponent({ -- cgit v1.2.1 From cb34be7dd224aebe4adf7ea8a11663bf5e82d103 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 16 Nov 2016 22:52:37 +0800 Subject: Fix pipeline author for Slack and use pipeline id rather than using SHA for the pipeline link. --- spec/models/project_services/slack_service/pipeline_message_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/slack_service/pipeline_message_spec.rb b/spec/models/project_services/slack_service/pipeline_message_spec.rb index babb3909f56..363138a9454 100644 --- a/spec/models/project_services/slack_service/pipeline_message_spec.rb +++ b/spec/models/project_services/slack_service/pipeline_message_spec.rb @@ -15,7 +15,7 @@ describe SlackService::PipelineMessage do }, project: { path_with_namespace: 'project_name', web_url: 'example.gitlab.com' }, - commit: { author_name: 'hacker' } + user: { name: 'hacker' } } end @@ -48,7 +48,7 @@ describe SlackService::PipelineMessage do def build_message(status_text = status) ":" \ - " Pipeline " \ + " Pipeline " \ " of branch" \ " by hacker #{status_text} in #{duration} #{'second'.pluralize(duration)}" end -- cgit v1.2.1 From ba2e7deea4a9a164fb5e3b7d4f30fbbe464ad8e9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 16:28:02 +0000 Subject: Fixes broken tests --- spec/features/environment_spec.rb | 107 +++++++++++++++++++++++++++++++++++++ spec/features/environments_spec.rb | 98 +-------------------------------- 2 files changed, 109 insertions(+), 96 deletions(-) create mode 100644 spec/features/environment_spec.rb (limited to 'spec') diff --git a/spec/features/environment_spec.rb b/spec/features/environment_spec.rb new file mode 100644 index 00000000000..3bf2fd54088 --- /dev/null +++ b/spec/features/environment_spec.rb @@ -0,0 +1,107 @@ +require 'spec_helper' + +feature 'Environments', feature: true do + given(:project) { create(:empty_project) } + given(:user) { create(:user) } + given(:role) { :developer } + + background do + login_as(user) + project.team << [user, role] + end + + describe 'when showing the environment' do + given(:environment) { create(:environment, project: project) } + given!(:deployment) { } + given!(:manual) { } + + before do + visit namespace_project_environment_path(project.namespace, project, environment) + end + + context 'without deployments' do + scenario 'does show no deployments' do + expect(page).to have_content('You don\'t have any deployments right now.') + end + end + + context 'with deployments' do + given(:deployment) { create(:deployment, environment: environment) } + + scenario 'does show deployment SHA' do + expect(page).to have_link(deployment.short_sha) + end + + scenario 'does not show a re-deploy button for deployment without build' do + expect(page).not_to have_link('Re-deploy') + end + + context 'with build' do + given(:pipeline) { create(:ci_pipeline, project: project) } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show build name' do + expect(page).to have_link("#{build.name} (##{build.id})") + end + + scenario 'does show re-deploy button' do + expect(page).to have_link('Re-deploy') + end + + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop') + end + + context 'with manual action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + + scenario 'does show a play button' do + + expect(page).to have_link(manual.name.humanize) + end + + scenario 'does allow to play manual action' do + expect(manual).to be_skipped + expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } + expect(page).to have_content(manual.name) + expect(manual.reload).to be_pending + end + + context 'with external_url' do + given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } + given(:build) { create(:ci_build, pipeline: pipeline) } + given(:deployment) { create(:deployment, environment: environment, deployable: build) } + + scenario 'does show an external link button' do + expect(page).to have_link(nil, href: environment.external_url) + end + end + + context 'with stop action' do + given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } + + scenario 'does show stop button' do + expect(page).to have_link('Stop') + end + + scenario 'does allow to stop environment' do + click_link('Stop') + + expect(page).to have_content('close_app') + end + + context 'for reporter' do + let(:role) { :reporter } + + scenario 'does not show stop button' do + expect(page).not_to have_link('Stop') + end + end + end + end + end + end + end +end diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index fe470fefca5..b932d672548 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -84,7 +84,7 @@ feature 'Environments', feature: true, js: true do end scenario 'does show build name and id' do - expect(page).to have_link("#{build.name} (##{build.id})") + expect(page).to have_link("#{build.name} ##{build.id}") end scenario 'does not show stop button' do @@ -114,7 +114,7 @@ feature 'Environments', feature: true, js: true do end scenario 'starts build when stop button clicked' do - first('.stop-env-link').click + page.find('.stop-env-link').click expect(page).to have_content('close_app') end @@ -136,100 +136,6 @@ feature 'Environments', feature: true, js: true do end end - describe 'when showing the environment' do - given(:environment) { create(:environment, project: project) } - given!(:deployment) { } - given!(:manual) { } - - before do - visit namespace_project_environment_path(project.namespace, project, environment) - end - - context 'without deployments' do - scenario 'does show no deployments' do - expect(page).to have_content('You don\'t have any deployments right now.') - end - end - - context 'with deployments' do - given(:deployment) { create(:deployment, environment: environment) } - - scenario 'does show deployment SHA' do - expect(page).to have_link(deployment.short_sha) - end - - scenario 'does not show a re-deploy button for deployment without build' do - expect(page).not_to have_link('Re-deploy') - end - - context 'with build' do - given(:pipeline) { create(:ci_pipeline, project: project) } - given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - - scenario 'does show build name' do - expect(page).to have_link("#{build.name} (##{build.id})") - end - - scenario 'does show re-deploy button' do - expect(page).to have_link('Re-deploy') - end - - scenario 'does not show stop button' do - expect(page).not_to have_link('Stop') - end - - context 'with manual action' do - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } - - scenario 'does show a play button' do - expect(page).to have_link(manual.name.humanize) - end - - scenario 'does allow to play manual action' do - expect(manual).to be_skipped - expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } - expect(page).to have_content(manual.name) - expect(manual.reload).to be_pending - end - - context 'with external_url' do - given(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') } - given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - - scenario 'does show an external link button' do - expect(page).to have_link(nil, href: environment.external_url) - end - end - - context 'with stop action' do - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } - given(:deployment) { create(:deployment, environment: environment, deployable: build, on_stop: 'close_app') } - - scenario 'does show stop button' do - expect(page).to have_link('Stop') - end - - scenario 'does allow to stop environment' do - click_link('Stop') - - expect(page).to have_content('close_app') - end - - context 'for reporter' do - let(:role) { :reporter } - - scenario 'does not show stop button' do - expect(page).not_to have_link('Stop') - end - end - end - end - end - end - end - describe 'when creating a new environment' do before do visit namespace_project_environments_path(project.namespace, project) -- cgit v1.2.1 From 9c3f9d84646013b8a9bf605b29d18189693e1c79 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 16:49:13 +0000 Subject: Adds new line to eof --- spec/javascripts/fixtures/environments/element.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/fixtures/environments/element.html.haml b/spec/javascripts/fixtures/environments/element.html.haml index d709c863137..8d7aeb23356 100644 --- a/spec/javascripts/fixtures/environments/element.html.haml +++ b/spec/javascripts/fixtures/environments/element.html.haml @@ -1 +1 @@ -.test-dom-element \ No newline at end of file +.test-dom-element -- cgit v1.2.1 From 1571d4686d0fbb41d603ee0deafe208f5d23e5c1 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 17:05:35 +0000 Subject: Fix broken url for stop action --- spec/features/environments_spec.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index b932d672548..fe5a783a386 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -59,6 +59,7 @@ feature 'Environments', feature: true, js: true do given(:deployment) { create(:deployment, environment: environment) } scenario 'does show deployment SHA' do + # TODO: Fix me! expect(page).to have_link(deployment.short_sha) end @@ -73,11 +74,15 @@ feature 'Environments', feature: true, js: true do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } scenario 'does show a play button' do + # TODO: Fix me! + binding.pry expect(page).to have_link(manual.name.humanize) end scenario 'does allow to play manual action' do expect(manual).to be_skipped + # TODO: Fix me! + binding.pry expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } expect(page).to have_content(manual.name) expect(manual.reload).to be_pending @@ -114,7 +119,7 @@ feature 'Environments', feature: true, js: true do end scenario 'starts build when stop button clicked' do - page.find('.stop-env-link').click + find('.stop-env-link').click expect(page).to have_content('close_app') end -- cgit v1.2.1 From 022764cc768ce7739eee1e097671249201cba5a4 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 16 Nov 2016 17:24:49 +0000 Subject: Tests --- spec/features/environments_spec.rb | 4 +--- spec/javascripts/environments/environment_stop_spec.js.es6 | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index fe5a783a386..a9228283272 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -75,14 +75,12 @@ feature 'Environments', feature: true, js: true do scenario 'does show a play button' do # TODO: Fix me! - binding.pry - expect(page).to have_link(manual.name.humanize) + expect(page).to have_content(manual.name.humanize) end scenario 'does allow to play manual action' do expect(manual).to be_skipped # TODO: Fix me! - binding.pry expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } expect(page).to have_content(manual.name) expect(manual.reload).to be_pending diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js.es6 index 07a68bf28fb..20eb8c92322 100644 --- a/spec/javascripts/environments/environment_stop_spec.js.es6 +++ b/spec/javascripts/environments/environment_stop_spec.js.es6 @@ -14,7 +14,7 @@ describe('Stop Component', () => { stop_url: stopURL, }, }); - expect(component.$el.getAttribute('href')).toEqual(stopURL); + expect(component.$el.getAttribute('href')).toEqual(`${stopURL}/stop`); }); describe('When clicked', () => { -- cgit v1.2.1 From 606afe2e81188b3556350e29ade7270536a6f58a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 16 Nov 2016 19:19:22 +0000 Subject: Fix some failing specs due to missing access_requestable trait --- spec/models/user_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 3159243553b..580ce4a9e0a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -491,7 +491,7 @@ describe User, models: true do end describe '.without_projects' do - let!(:project) { create(:empty_project, :public) } + let!(:project) { create(:empty_project, :public, :access_requestable) } let!(:user) { create(:user) } let!(:user_without_project) { create(:user) } let!(:user_without_project2) { create(:user) } -- cgit v1.2.1 From 536210603f2f6c8d4a27b802d69dcdf25dfd5456 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 16 Nov 2016 20:33:00 +0100 Subject: Fix environments specs for deployment with SHA --- spec/features/environments_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index a9228283272..eca67de7bcb 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -56,10 +56,14 @@ feature 'Environments', feature: true, js: true do end context 'with deployments' do - given(:deployment) { create(:deployment, environment: environment) } + given(:project) { create(:project) } + + given(:deployment) do + create(:deployment, environment: environment, + sha: project.commit.id) + end scenario 'does show deployment SHA' do - # TODO: Fix me! expect(page).to have_link(deployment.short_sha) end -- cgit v1.2.1 From 6f714dfb4a9b823ab75508f252d06e19e286d5f2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 16 Nov 2016 23:10:27 +0100 Subject: Improve code design after code review --- spec/lib/gitlab/chat_name_token_spec.rb | 4 +--- spec/services/chat_names/authorize_user_service_spec.rb | 4 +--- spec/services/chat_names/find_user_service_spec.rb | 2 +- spec/support/matchers/be_url.rb | 5 +++++ 4 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 spec/support/matchers/be_url.rb (limited to 'spec') diff --git a/spec/lib/gitlab/chat_name_token_spec.rb b/spec/lib/gitlab/chat_name_token_spec.rb index 8d7e7a99059..8c1e6efa9db 100644 --- a/spec/lib/gitlab/chat_name_token_spec.rb +++ b/spec/lib/gitlab/chat_name_token_spec.rb @@ -12,9 +12,7 @@ describe Gitlab::ChatNameToken, lib: true do end context 'when storing data' do - let(:data) { - { key: 'value' } - } + let(:data) { { key: 'value' } } subject { described_class.new(@token) } diff --git a/spec/services/chat_names/authorize_user_service_spec.rb b/spec/services/chat_names/authorize_user_service_spec.rb index f8c26e51bfc..2ecee58e92d 100644 --- a/spec/services/chat_names/authorize_user_service_spec.rb +++ b/spec/services/chat_names/authorize_user_service_spec.rb @@ -10,9 +10,7 @@ describe ChatNames::AuthorizeUserService, services: true do let(:params) { { team_id: 'T0001', team_domain: 'myteam', user_id: 'U0001', user_name: 'user' } } it 'requests a new token' do - is_expected.to include('http') - is_expected.to include('://') - is_expected.to include('token=') + is_expected.to be_url end end diff --git a/spec/services/chat_names/find_user_service_spec.rb b/spec/services/chat_names/find_user_service_spec.rb index cf5844069f9..5b885b2c657 100644 --- a/spec/services/chat_names/find_user_service_spec.rb +++ b/spec/services/chat_names/find_user_service_spec.rb @@ -20,7 +20,7 @@ describe ChatNames::FindUserService, services: true do it 'updates when last time chat name was used' do subject - expect(chat_name.reload.used_at).to be_like_time(Time.now) + expect(chat_name.reload.last_used_at).to be_like_time(Time.now) end end diff --git a/spec/support/matchers/be_url.rb b/spec/support/matchers/be_url.rb new file mode 100644 index 00000000000..f8096af1b22 --- /dev/null +++ b/spec/support/matchers/be_url.rb @@ -0,0 +1,5 @@ +RSpec::Matchers.define :be_url do |_| + match do |actual| + URI.parse(actual) rescue false + end +end -- cgit v1.2.1 From 4d7b44b5b7566988d405c4dd4e68f605586d0874 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 16 Nov 2016 23:10:53 +0100 Subject: Add specs for testing authorization and deny of chat user --- spec/features/profiles/chat_names_spec.rb | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 spec/features/profiles/chat_names_spec.rb (limited to 'spec') diff --git a/spec/features/profiles/chat_names_spec.rb b/spec/features/profiles/chat_names_spec.rb new file mode 100644 index 00000000000..6f6f7029c0b --- /dev/null +++ b/spec/features/profiles/chat_names_spec.rb @@ -0,0 +1,77 @@ +require 'rails_helper' + +feature 'Profile > Chat', feature: true do + given(:user) { create(:user) } + given(:service) { create(:service) } + + before do + login_as(user) + end + + describe 'uses authorization link' do + given(:params) do + { team_id: 'T00', team_domain: 'my_chat_team', user_id: 'U01', user_name: 'my_chat_user' } + end + given!(:authorize_url) { ChatNames::AuthorizeUserService.new(service, params).execute } + given(:authorize_path) { URI.parse(authorize_url).request_uri } + + before do + visit authorize_path + end + + context 'clicks authorize' do + before do + click_button 'Authorize' + end + + scenario 'goes to list of chat names and see chat account' do + expect(page.current_path).to eq(profile_chat_names_path) + expect(page).to have_content('my_chat_team') + expect(page).to have_content('my_chat_user') + end + + scenario 'second use of link is denied' do + visit authorize_path + + expect(page).to have_http_status(:not_found) + end + end + + context 'clicks deny' do + before do + click_button 'Deny' + end + + scenario 'goes to list of chat names and do not see chat account' do + expect(page.current_path).to eq(profile_chat_names_path) + expect(page).not_to have_content('my_chat_team') + expect(page).not_to have_content('my_chat_user') + end + + scenario 'second use of link is denied' do + visit authorize_path + + expect(page).to have_http_status(:not_found) + end + end + end + + describe 'visits chat accounts' do + given!(:chat_name) { create(:chat_name, user: user, service: service) } + + before do + visit profile_chat_names_path + end + + scenario 'sees chat user' do + expect(page).to have_content(chat_name.team_domain) + expect(page).to have_content(chat_name.chat_name) + end + + scenario 'removes chat account' do + click_link 'Remove' + + expect(page).to have_content("You don't have any active chat names.") + end + end +end -- cgit v1.2.1 From 4ce2ca4d36c402c533519c25c61cbb4eac92e719 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 15 Nov 2016 15:52:45 -0600 Subject: Fix pipelines spec --- spec/features/projects/commits/cherry_pick_spec.rb | 2 +- spec/features/projects/pipelines_spec.rb | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/commits/cherry_pick_spec.rb b/spec/features/projects/commits/cherry_pick_spec.rb index e45e3a36d01..d46d9e9399e 100644 --- a/spec/features/projects/commits/cherry_pick_spec.rb +++ b/spec/features/projects/commits/cherry_pick_spec.rb @@ -64,7 +64,7 @@ describe 'Cherry-pick Commits' do context "I cherry-pick a commit from a different branch", js: true do it do - find('.commit-action-buttons a.dropdown-toggle').click + find('.header-action-buttons a.dropdown-toggle').click find(:css, "a[href='#modal-cherry-pick-commit']").click page.within('#modal-cherry-pick-commit') do diff --git a/spec/features/projects/pipelines_spec.rb b/spec/features/projects/pipelines_spec.rb index 77184ede784..002c6f6b359 100644 --- a/spec/features/projects/pipelines_spec.rb +++ b/spec/features/projects/pipelines_spec.rb @@ -146,7 +146,8 @@ describe "Pipelines" do end describe 'GET /:project/pipelines/:id' do - let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') } + let(:project) { create(:project) } + let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) } before do @success = create(:ci_build, :success, pipeline: pipeline, stage: 'build', name: 'build') @@ -156,10 +157,7 @@ describe "Pipelines" do @external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external') end - before do - visit namespace_project_pipeline_path(project.namespace, project, pipeline) - find('.builds-tab').click - end + before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) } it 'shows a list of builds' do expect(page).to have_content('Test') -- cgit v1.2.1 From d6e00f5373e24deaa7f143f5445ae9461ef5f615 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 17 Nov 2016 00:23:05 +0100 Subject: Improve specs and add missing cases that were not supported --- spec/models/build_spec.rb | 96 +++++++++++++++++++++++ spec/models/ci/build_spec.rb | 8 ++ spec/views/projects/builds/show.html.haml_spec.rb | 2 +- 3 files changed, 105 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index ae185de9ca3..731a2274d9e 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -1052,4 +1052,100 @@ describe Ci::Build, models: true do end end end + + describe '#starts_environment?' do + subject { build.starts_environment? } + + context 'when environment is defined' do + before do + build.update(environment: 'review') + end + + it { is_expected.to be_truthy } + end + + context 'when environment is not defined' do + before do + build.update(environment: nil) + end + + it { is_expected.to be_falsey } + end + end + + describe '#stops_environment?' do + subject { build.stops_environment? } + + context 'when environment is defined' do + before do + build.update(environment: 'review') + end + + context 'no action is defined' do + it { is_expected.to be_falsey } + end + + context 'and stop action is defined' do + before do + build.update(options: { environment: { action: 'stop' } } ) + end + + it { is_expected.to be_truthy } + end + end + + context 'when environment is not defined' do + before do + build.update(environment: nil) + end + + it { is_expected.to be_falsey } + end + end + + describe '#last_deployment' do + subject { build.last_deployment } + + context 'when multiple deployments is created returns latest one' do + let!(:deployment1) { create(:deployment, deployable: build) } + let!(:deployment2) { create(:deployment, deployable: build) } + + it { is_expected.to eq(deployment2) } + end + end + + describe '#outdated_deployment?' do + subject { build.outdated_deployment? } + + context 'when build succeeded' do + let(:build) { create(:ci_build, :success) } + let!(:deployment) { create(:deployment, deployable: build) } + + context 'current deployment is latest' do + it { is_expected.to be_falsey } + end + + context 'current deployment is not latest on environment' do + let!(:deployment2) { create(:deployment, environment: deployment.environment) } + + it { is_expected.to be_truthy } + end + end + + context 'when build failed' do + let(:build) { create(:ci_build, :failed) } + + it { is_expected.to be_falsey } + end + end + + describe '#expanded_environment_name' do + subject { build.expanded_environment_name } + + context 'when environment uses variables' do + let(:build) { create(:ci_build, ref: 'master', environment: 'review/$CI_BUILD_REF_NAME') } + + it { is_expected.to eq('review/master') } + end + end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index a37a00f461a..2efe69d7adc 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -4,6 +4,14 @@ describe Ci::Build, models: true do let(:build) { create(:ci_build) } let(:test_trace) { 'This is a test' } + describe 'ss' do + it { is_expected.to belong_to(:runner) } + it { is_expected.to belong_to(:trigger_request) } + it { is_expected.to belong_to(:erased_by) } + + it { is_expected.to have_many(:deployments) } + end + describe '#trace' do it 'obfuscates project runners token' do allow(build).to receive(:raw_trace).and_return("Test: #{build.project.runners_token}") diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index fa4d66bb6cb..3b9a9c95daa 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -54,7 +54,7 @@ describe 'projects/builds/show', :view do it 'shows deployment message' do expected_text = 'This build is an out-of-date deployment ' \ - "to staging. View the most recent deployment ##{first_deployment.id}" + "to staging.\nView the most recent deployment ##{second_deployment.id}." render expect(rendered).to have_css('.environment-information', text: expected_text) -- cgit v1.2.1 From f7b0692912e0679a3e2e77b2d1bfaf305fba473a Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 10 Nov 2016 15:24:02 +0900 Subject: add parsing support for incoming html email --- spec/fixtures/emails/outlook_html.eml | 140 +++++++++++++++++++++++++++++ spec/lib/gitlab/email/reply_parser_spec.rb | 5 ++ 2 files changed, 145 insertions(+) create mode 100644 spec/fixtures/emails/outlook_html.eml (limited to 'spec') diff --git a/spec/fixtures/emails/outlook_html.eml b/spec/fixtures/emails/outlook_html.eml new file mode 100644 index 00000000000..506d69efe83 --- /dev/null +++ b/spec/fixtures/emails/outlook_html.eml @@ -0,0 +1,140 @@ + +MIME-Version: 1.0 +Received: by 10.25.161.144 with HTTP; Tue, 7 Oct 2014 22:17:17 -0700 (PDT) +X-Originating-IP: [117.207.85.84] +In-Reply-To: <5434c8b52bb3a_623ff09fec70f049749@discourse-app.mail> +References: + <5434c8b52bb3a_623ff09fec70f049749@discourse-app.mail> +Date: Wed, 8 Oct 2014 10:47:17 +0530 +Delivered-To: arpit@techapj.com +Message-ID: +Subject: Re: [Discourse] [Meta] Welcome to techAPJ's Discourse! +From: Arpit Jalan +To: Discourse Accept-Language: en-US +Content-Language: en-US +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +x-originating-ip: [134.68.31.227] +Content-Type: multipart/alternative; + boundary="_000_B0DFE1BEB3739743BC9B639D0E6BC8FF217A6341IUMSSGMBX104ads_" +MIME-Version: 1.0 + +--_000_B0DFE1BEB3739743BC9B639D0E6BC8FF217A6341IUMSSGMBX104ads_ +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: base64 + +PGh0bWwgeG1sbnM6dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwiIHhtbG5zOm89InVy +bjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIgeG1sbnM6dz0idXJuOnNjaGVt +YXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6d29yZCIgeG1sbnM6bT0iaHR0cDovL3NjaGVtYXMubWlj +cm9zb2Z0LmNvbS9vZmZpY2UvMjAwNC8xMi9vbW1sIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv +VFIvUkVDLWh0bWw0MCI+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIg +Y29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjxtZXRhIG5hbWU9IkdlbmVyYXRv +ciIgY29udGVudD0iTWljcm9zb2Z0IFdvcmQgMTQgKGZpbHRlcmVkIG1lZGl1bSkiPg0KPCEtLVtp +ZiAhbXNvXT48c3R5bGU+dlw6KiB7YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTCk7fQ0Kb1w6KiB7 +YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTCk7fQ0Kd1w6KiB7YmVoYXZpb3I6dXJsKCNkZWZhdWx0 +I1ZNTCk7fQ0KLnNoYXBlIHtiZWhhdmlvcjp1cmwoI2RlZmF1bHQjVk1MKTt9DQo8L3N0eWxlPjwh +W2VuZGlmXS0tPjxzdHlsZT48IS0tDQovKiBGb250IERlZmluaXRpb25zICovDQpAZm9udC1mYWNl +DQoJe2ZvbnQtZmFtaWx5OkNhbGlicmk7DQoJcGFub3NlLTE6MiAxNSA1IDIgMiAyIDQgMyAyIDQ7 +fQ0KQGZvbnQtZmFjZQ0KCXtmb250LWZhbWlseTpUYWhvbWE7DQoJcGFub3NlLTE6MiAxMSA2IDQg +MyA1IDQgNCAyIDQ7fQ0KLyogU3R5bGUgRGVmaW5pdGlvbnMgKi8NCnAuTXNvTm9ybWFsLCBsaS5N +c29Ob3JtYWwsIGRpdi5Nc29Ob3JtYWwNCgl7bWFyZ2luOjBpbjsNCgltYXJnaW4tYm90dG9tOi4w +MDAxcHQ7DQoJZm9udC1zaXplOjEyLjBwdDsNCglmb250LWZhbWlseToiVGltZXMgTmV3IFJvbWFu +Iiwic2VyaWYiO30NCmE6bGluaywgc3Bhbi5Nc29IeXBlcmxpbmsNCgl7bXNvLXN0eWxlLXByaW9y +aXR5Ojk5Ow0KCWNvbG9yOmJsdWU7DQoJdGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTt9DQphOnZp +c2l0ZWQsIHNwYW4uTXNvSHlwZXJsaW5rRm9sbG93ZWQNCgl7bXNvLXN0eWxlLXByaW9yaXR5Ojk5 +Ow0KCWNvbG9yOnB1cnBsZTsNCgl0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lO30NCnANCgl7bXNv +LXN0eWxlLXByaW9yaXR5Ojk5Ow0KCW1zby1tYXJnaW4tdG9wLWFsdDphdXRvOw0KCW1hcmdpbi1y +aWdodDowaW47DQoJbXNvLW1hcmdpbi1ib3R0b20tYWx0OmF1dG87DQoJbWFyZ2luLWxlZnQ6MGlu +Ow0KCWZvbnQtc2l6ZToxMi4wcHQ7DQoJZm9udC1mYW1pbHk6IlRpbWVzIE5ldyBSb21hbiIsInNl +cmlmIjt9DQpzcGFuLkVtYWlsU3R5bGUxOA0KCXttc28tc3R5bGUtdHlwZTpwZXJzb25hbC1yZXBs +eTsNCglmb250LWZhbWlseToiQ2FsaWJyaSIsInNhbnMtc2VyaWYiOw0KCWNvbG9yOiMxRjQ5N0Q7 +fQ0KLk1zb0NocERlZmF1bHQNCgl7bXNvLXN0eWxlLXR5cGU6ZXhwb3J0LW9ubHk7DQoJZm9udC1m +YW1pbHk6IkNhbGlicmkiLCJzYW5zLXNlcmlmIjt9DQpAcGFnZSBXb3JkU2VjdGlvbjENCgl7c2l6 +ZTo4LjVpbiAxMS4waW47DQoJbWFyZ2luOjEuMGluIDEuMGluIDEuMGluIDEuMGluO30NCmRpdi5X +b3JkU2VjdGlvbjENCgl7cGFnZTpXb3JkU2VjdGlvbjE7fQ0KLS0+PC9zdHlsZT48IS0tW2lmIGd0 +ZSBtc28gOV0+PHhtbD4NCjxvOnNoYXBlZGVmYXVsdHMgdjpleHQ9ImVkaXQiIHNwaWRtYXg9IjEw +MjYiIC8+DQo8L3htbD48IVtlbmRpZl0tLT48IS0tW2lmIGd0ZSBtc28gOV0+PHhtbD4NCjxvOnNo +YXBlbGF5b3V0IHY6ZXh0PSJlZGl0Ij4NCjxvOmlkbWFwIHY6ZXh0PSJlZGl0IiBkYXRhPSIxIiAv +Pg0KPC9vOnNoYXBlbGF5b3V0PjwveG1sPjwhW2VuZGlmXS0tPg0KPC9oZWFkPg0KPGJvZHkgbGFu +Zz0iRU4tVVMiIGxpbms9ImJsdWUiIHZsaW5rPSJwdXJwbGUiPg0KPGRpdiBjbGFzcz0iV29yZFNl +Y3Rpb24xIj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTEu +MHB0O2ZvbnQtZmFtaWx5OiZxdW90O0NhbGlicmkmcXVvdDssJnF1b3Q7c2Fucy1zZXJpZiZxdW90 +Oztjb2xvcjojMUY0OTdEIj5NaWNyb3NvZnQgT3V0bG9vayAyMDEwPG86cD48L286cD48L3NwYW4+ +PC9wPg0KPHAgY2xhc3M9Ik1zb05vcm1hbCI+PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMS4wcHQ7 +Zm9udC1mYW1pbHk6JnF1b3Q7Q2FsaWJyaSZxdW90OywmcXVvdDtzYW5zLXNlcmlmJnF1b3Q7O2Nv +bG9yOiMxRjQ5N0QiPjxvOnA+Jm5ic3A7PC9vOnA+PC9zcGFuPjwvcD4NCjxwIGNsYXNzPSJNc29O +b3JtYWwiPjxiPjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTAuMHB0O2ZvbnQtZmFtaWx5OiZxdW90 +O1RhaG9tYSZxdW90OywmcXVvdDtzYW5zLXNlcmlmJnF1b3Q7Ij5Gcm9tOjwvc3Bhbj48L2I+PHNw +YW4gc3R5bGU9ImZvbnQtc2l6ZToxMC4wcHQ7Zm9udC1mYW1pbHk6JnF1b3Q7VGFob21hJnF1b3Q7 +LCZxdW90O3NhbnMtc2VyaWYmcXVvdDsiPiBtaWNoYWVsIFttYWlsdG86dGFsa0BvcGVubXJzLm9y +Z10NCjxicj4NCjxiPlNlbnQ6PC9iPiBNb25kYXksIE9jdG9iZXIgMTMsIDIwMTQgOTozOCBBTTxi +cj4NCjxiPlRvOjwvYj4gUG93ZXIsIENocmlzPGJyPg0KPGI+U3ViamVjdDo8L2I+IFtQTV0gWW91 +ciBwb3N0IGluICZxdW90O0J1cmdlcmhhdXM6IE5ldyByZXN0YXVyYW50IC8gbHVuY2ggdmVudWUm +cXVvdDs8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQo8cCBjbGFzcz0iTXNvTm9ybWFsIj48bzpwPiZu +YnNwOzwvbzpwPjwvcD4NCjxkaXY+DQo8dGFibGUgY2xhc3M9Ik1zb05vcm1hbFRhYmxlIiBib3Jk +ZXI9IjAiIGNlbGxzcGFjaW5nPSIwIiBjZWxscGFkZGluZz0iMCI+DQo8dGJvZHk+DQo8dHI+DQo8 +dGQgdmFsaWduPSJ0b3AiIHN0eWxlPSJwYWRkaW5nOjBpbiAwaW4gMGluIDBpbiI+PC90ZD4NCjx0 +ZCBzdHlsZT0icGFkZGluZzowaW4gMGluIDBpbiAwaW4iPg0KPHAgY2xhc3M9Ik1zb05vcm1hbCIg +c3R5bGU9Im1hcmdpbi1ib3R0b206MTguNzVwdCI+PGEgaHJlZj0iaHR0cDovL2NsLm9wZW5tcnMu +b3JnL3RyYWNrL2NsaWNrLzMwMDM5OTA1L3RhbGsub3Blbm1ycy5vcmc/cD1leUp6SWpvaWJHbFph +MVYwZVhoQ1kwMU1SVEZzVURKbVl6VlFNMFpsZWpFNElpd2lkaUk2TVN3aWNDSTZJbnRjSW5WY0lq +b3pNREF6T1Rrd05TeGNJblpjSWpveExGd2lkWEpzWENJNlhDSm9kSFJ3Y3pwY1hGd3ZYRnhjTDNS +aGJHc3ViM0JsYm0xeWN5NXZjbWRjWEZ3dmRYTmxjbk5jWEZ3dmJXbGphR0ZsYkZ3aUxGd2lhV1Jj +SWpwY0ltUTFZbU13TjJOa05EUmpaRFE0TUdNNFlUZzJNemxqWldJMU56Z3pZbVkyWENJc1hDSjFj +bXhmYVdSelhDSTZXMXdpWWpoa09EZzFNams1TnpkbVpqWTFaV1l5TlRFM09XUmlOR1l5TVdJM056 +RmpOemhqWmpoa09Gd2lYWDBpZlEiIHRhcmdldD0iX2JsYW5rIj48Yj48c3BhbiBzdHlsZT0iZm9u +dC1zaXplOjEwLjBwdDtmb250LWZhbWlseTomcXVvdDtUYWhvbWEmcXVvdDssJnF1b3Q7c2Fucy1z +ZXJpZiZxdW90Oztjb2xvcjojMDA2Njk5O3RleHQtZGVjb3JhdGlvbjpub25lIj5taWNoYWVsPC9z +cGFuPjwvYj48L2E+PGJyPg0KPHNwYW4gc3R5bGU9ImZvbnQtc2l6ZTo4LjVwdDtmb250LWZhbWls +eTomcXVvdDtUYWhvbWEmcXVvdDssJnF1b3Q7c2Fucy1zZXJpZiZxdW90Oztjb2xvcjojOTk5OTk5 +Ij5PY3RvYmVyIDEzPC9zcGFuPg0KPG86cD48L286cD48L3A+DQo8L3RkPg0KPC90cj4NCjx0cj4N +Cjx0ZCBjb2xzcGFuPSIyIiBzdHlsZT0icGFkZGluZzozLjc1cHQgMGluIDBpbiAwaW4iPg0KPHAg +Y2xhc3M9Ik1zb05vcm1hbCIgc3R5bGU9Im1hcmdpbi1ib3R0b206MTguNzVwdCI+PGEgaHJlZj0i +aHR0cDovL2NsLm9wZW5tcnMub3JnL3RyYWNrL2NsaWNrLzMwMDM5OTA1L3RhbGsub3Blbm1ycy5v +cmc/cD1leUp6SWpvaVVFUklTVU55UjNsVk1EZEJWVmhwV25SM1dXeDRNV05zVFc1Wklpd2lkaUk2 +TVN3aWNDSTZJbnRjSW5WY0lqb3pNREF6T1Rrd05TeGNJblpjSWpveExGd2lkWEpzWENJNlhDSm9k +SFJ3Y3pwY1hGd3ZYRnhjTDNSaGJHc3ViM0JsYm0xeWN5NXZjbWRjWEZ3dmRGeGNYQzlpZFhKblpY +Sm9ZWFZ6TFc1bGR5MXlaWE4wWVhWeVlXNTBMV3gxYm1Ob0xYWmxiblZsWEZ4Y0x6WTNNbHhjWEM4 +elhDSXNYQ0pwWkZ3aU9sd2laRFZpWXpBM1kyUTBOR05rTkRnd1l6aGhPRFl6T1dObFlqVTNPRE5p +WmpaY0lpeGNJblZ5YkY5cFpITmNJanBiWENKaU56WmlZamswWlRGaU56STVaVGsyWlRSbFpXTTRO +R1JtTWpRNE1ETXdZall5WVdZeU1HTTBYQ0pkZlNKOSI+PGI+PHNwYW4gc3R5bGU9ImNvbG9yOiMw +MDY2OTk7dGV4dC1kZWNvcmF0aW9uOm5vbmUiPmh0dHBzOi8vdGFsay5vcGVubXJzLm9yZy90L2J1 +cmdlcmhhdXMtbmV3LXJlc3RhdXJhbnQtbHVuY2gtdmVudWUvNjcyLzM8L3NwYW4+PC9iPjwvYT4N +CjxvOnA+PC9vOnA+PC9wPg0KPHAgc3R5bGU9Im1hcmdpbi10b3A6MGluIj5Mb29rcyBsaWtlIHlv +dXIgcmVwbHktYnktZW1haWwgd2Fzbid0IHByb2Nlc3NlZCBjb3JyZWN0bHkgYnkgb3VyIHNvZnR3 +YXJlLiBDYW4geW91IGxldCBtZSBrbm93IHdoYXQgdmVyc2lvbi9PUyBvZiB3aGF0IGVtYWlsIHBy +b2dyYW0geW91J3JlIHVzaW5nPyBXZSB3aWxsIHdhbnQgdG8gdHJ5IHRvIGZpeCB0aGUgYnVnLiA6 +c21pbGU6PG86cD48L286cD48L3A+DQo8cCBzdHlsZT0ibWFyZ2luLXRvcDowaW4iPlRoYW5rcyE8 +bzpwPjwvbzpwPjwvcD4NCjwvdGQ+DQo8L3RyPg0KPC90Ym9keT4NCjwvdGFibGU+DQo8ZGl2IGNs +YXNzPSJNc29Ob3JtYWwiIGFsaWduPSJjZW50ZXIiIHN0eWxlPSJ0ZXh0LWFsaWduOmNlbnRlciI+ +DQo8aHIgc2l6ZT0iMSIgd2lkdGg9IjEwMCUiIGFsaWduPSJjZW50ZXIiPg0KPC9kaXY+DQo8ZGl2 +Pg0KPHA+PHNwYW4gc3R5bGU9ImNvbG9yOiM2NjY2NjYiPlRvIHJlc3BvbmQsIHJlcGx5IHRvIHRo +aXMgZW1haWwgb3IgdmlzaXQgPGEgaHJlZj0iaHR0cDovL2NsLm9wZW5tcnMub3JnL3RyYWNrL2Ns +aWNrLzMwMDM5OTA1L3RhbGsub3Blbm1ycy5vcmc/cD1leUp6SWpvaWVYaDJWbnBGTUhSMU1uRm5a +RWR1TlhFd01GcFFPVlp0VFZvNElpd2lkaUk2TVN3aWNDSTZJbnRjSW5WY0lqb3pNREF6T1Rrd05T +eGNJblpjSWpveExGd2lkWEpzWENJNlhDSm9kSFJ3Y3pwY1hGd3ZYRnhjTDNSaGJHc3ViM0JsYm0x +eWN5NXZjbWRjWEZ3dmRGeGNYQzk1YjNWeUxYQnZjM1F0YVc0dFluVnlaMlZ5YUdGMWN5MXVaWGN0 +Y21WemRHRjFjbUZ1ZEMxc2RXNWphQzEyWlc1MVpWeGNYQzgyTnpSY1hGd3ZNVndpTEZ3aWFXUmNJ +anBjSW1RMVltTXdOMk5rTkRSalpEUTRNR000WVRnMk16bGpaV0kxTnpnelltWTJYQ0lzWENKMWNt +eGZhV1J6WENJNlcxd2lZamMyWW1JNU5HVXhZamN5T1dVNU5tVTBaV1ZqT0RSa1pqSTBPREF6TUdJ +Mk1tRm1NakJqTkZ3aVhYMGlmUSI+DQo8Yj48c3BhbiBzdHlsZT0iY29sb3I6IzAwNjY5OTt0ZXh0 +LWRlY29yYXRpb246bm9uZSI+aHR0cHM6Ly90YWxrLm9wZW5tcnMub3JnL3QveW91ci1wb3N0LWlu +LWJ1cmdlcmhhdXMtbmV3LXJlc3RhdXJhbnQtbHVuY2gtdmVudWUvNjc0LzE8L3NwYW4+PC9iPjwv +YT4gaW4geW91ciBicm93c2VyLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCjwvZGl2Pg0KPGRpdj4N +CjxwPjxzcGFuIHN0eWxlPSJjb2xvcjojNjY2NjY2Ij5UbyB1bnN1YnNjcmliZSBmcm9tIHRoZXNl +IGVtYWlscywgdmlzaXQgeW91ciA8YSBocmVmPSJodHRwOi8vY2wub3Blbm1ycy5vcmcvdHJhY2sv +Y2xpY2svMzAwMzk5MDUvdGFsay5vcGVubXJzLm9yZz9wPWV5SnpJam9pZFV4dVdsZzVWRmMwT1da +V1MwWTRiRmRMZG1seVdHc3hUVjl6SWl3aWRpSTZNU3dpY0NJNkludGNJblZjSWpvek1EQXpPVGt3 +TlN4Y0luWmNJam94TEZ3aWRYSnNYQ0k2WENKb2RIUndjenBjWEZ3dlhGeGNMM1JoYkdzdWIzQmxi +bTF5Y3k1dmNtZGNYRnd2YlhsY1hGd3ZjSEpsWm1WeVpXNWpaWE5jSWl4Y0ltbGtYQ0k2WENKa05X +SmpNRGRqWkRRMFkyUTBPREJqT0dFNE5qTTVZMlZpTlRjNE0ySm1ObHdpTEZ3aWRYSnNYMmxrYzF3 +aU9sdGNJbUk0TVdVd1pqQTFORFk1TkRNME56Z3lNMkZtTWpBMk5qRmpaamMzWkdOaU4yTmhZemRt +TWpKY0lsMTlJbjAiPg0KPGI+PHNwYW4gc3R5bGU9ImNvbG9yOiMwMDY2OTk7dGV4dC1kZWNvcmF0 +aW9uOm5vbmUiPnVzZXIgcHJlZmVyZW5jZXM8L3NwYW4+PC9iPjwvYT4uPG86cD48L286cD48L3Nw +YW4+PC9wPg0KPC9kaXY+DQo8L2Rpdj4NCjxwIGNsYXNzPSJNc29Ob3JtYWwiPjxpbWcgYm9yZGVy +PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBpZD0iX3gwMDAwX2kxMDI2IiBzcmM9Imh0dHA6Ly9j +bC5vcGVubXJzLm9yZy90cmFjay9vcGVuLnBocD91PTMwMDM5OTA1JmFtcDtpZD1kNWJjMDdjZDQ0 +Y2Q0ODBjOGE4NjM5Y2ViNTc4M2JmNiI+PG86cD48L286cD48L3A+DQo8L2Rpdj4NCjwvYm9keT4N +CjwvaHRtbD4NCg== + +--_000_B0DFE1BEB3739743BC9B639D0E6BC8FF217A6341IUMSSGMBX104ads_-- diff --git a/spec/lib/gitlab/email/reply_parser_spec.rb b/spec/lib/gitlab/email/reply_parser_spec.rb index 6f8e9a4be64..7a0d6ba90cc 100644 --- a/spec/lib/gitlab/email/reply_parser_spec.rb +++ b/spec/lib/gitlab/email/reply_parser_spec.rb @@ -206,5 +206,10 @@ describe Gitlab::Email::ReplyParser, lib: true do it "properly renders email reply from MS Outlook client" do expect(test_parse_body(fixture_file("emails/outlook.eml"))).to eq("Microsoft Outlook 2010") end + + it "properly renders html-only email from MS Outlook" do + expect(test_parse_body(fixture_file("emails/outlook_html.eml"))).to eq("Microsoft Outlook 2010") + + end end end -- cgit v1.2.1 From 17341244337511a239bb7a262236b9896a0bf76d Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 10 Nov 2016 17:40:53 +0900 Subject: fix rubocop failures --- spec/lib/gitlab/email/reply_parser_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/email/reply_parser_spec.rb b/spec/lib/gitlab/email/reply_parser_spec.rb index 7a0d6ba90cc..c7a0139d32a 100644 --- a/spec/lib/gitlab/email/reply_parser_spec.rb +++ b/spec/lib/gitlab/email/reply_parser_spec.rb @@ -209,7 +209,6 @@ describe Gitlab::Email::ReplyParser, lib: true do it "properly renders html-only email from MS Outlook" do expect(test_parse_body(fixture_file("emails/outlook_html.eml"))).to eq("Microsoft Outlook 2010") - end end end -- cgit v1.2.1 From ec7db295d230ba1cec0c75ae199d60bd8f89c1d6 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 13 Oct 2016 17:11:28 +0200 Subject: Started refactoring stuff to add events to cycle analytics - Refactored cycle analytics class to extract DB logic - Reuse logic in new events fetcher - Started adding cycle analytics events class and spec (still not functional) --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 spec/lib/gitlab/cycle_analytics/events_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb new file mode 100644 index 00000000000..b68cc16f4e6 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe Gitlab::CycleAnalytics::Events do + let(:project) { create(:project) } + let(:from_date) { 10.days.ago } + let(:user) { create(:user, :admin) } + + subject { described_class.new(project: project, from: from_date) } + + before do + setup(context) + end + + describe '#issue' do + let!(:context) { create(:issue, project: project) } + + xit 'does something' do + expect(subject.issue_events).to eq([]) + end + end + + def setup(context) + create(:milestone, project: project) + create_merge_request_closing_issue(context) + end +end -- cgit v1.2.1 From 470e39d64f02def538bb6aa3e51bcf406fd2e480 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 14 Oct 2016 17:33:21 +0200 Subject: WIP - refactored some arel queries --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index b68cc16f4e6..64387ef10d3 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -15,12 +15,13 @@ describe Gitlab::CycleAnalytics::Events do let!(:context) { create(:issue, project: project) } xit 'does something' do - expect(subject.issue_events).to eq([]) + expect(subject.issue_events).to eq([context]) end end def setup(context) - create(:milestone, project: project) + milestone = create(:milestone, project: project) + context.update(milestone: milestone) create_merge_request_closing_issue(context) end end -- cgit v1.2.1 From 847d2796cfeda0347aae0649fed16250f6188ca9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 17 Oct 2016 14:57:23 +0200 Subject: fixed spec and SQL query --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 64387ef10d3..b32c4d6baa0 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -14,8 +14,24 @@ describe Gitlab::CycleAnalytics::Events do describe '#issue' do let!(:context) { create(:issue, project: project) } - xit 'does something' do - expect(subject.issue_events).to eq([context]) + it 'has an issue diff' do + expect(subject.issue_events['issue_diff']).to eq("-00:00:00.339259") + end + + it 'has a title' do + expect(subject.issue_events['title']).to eq(context.title) + end + + it 'has an iid' do + expect(subject.issue_events['iid']).to eq(context.iid) + end + + it 'has a created_at timestamp' do + expect(subject.issue_events['created_at']).to eq(context.created_at) + end + + it "has the author's name" do + expect(subject.issue_events['name']).to eq(context.author.name) end end -- cgit v1.2.1 From c545968ece739e616047c519dbc66e4e428cdd8a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 17 Oct 2016 18:03:17 +0200 Subject: fix timestamp diff and spec --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index b32c4d6baa0..543259f7cc2 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -12,10 +12,10 @@ describe Gitlab::CycleAnalytics::Events do end describe '#issue' do - let!(:context) { create(:issue, project: project) } + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } it 'has an issue diff' do - expect(subject.issue_events['issue_diff']).to eq("-00:00:00.339259") + expect(subject.issue_events['issue_diff']).to eq('2 days ago') end it 'has a title' do @@ -23,11 +23,11 @@ describe Gitlab::CycleAnalytics::Events do end it 'has an iid' do - expect(subject.issue_events['iid']).to eq(context.iid) + expect(subject.issue_events['iid']).to eq(context.iid.to_s) end it 'has a created_at timestamp' do - expect(subject.issue_events['created_at']).to eq(context.created_at) + expect(subject.issue_events['created_at']).to eq('2 days ago') end it "has the author's name" do -- cgit v1.2.1 From 1d6068a1c3c906e0e82f0dce884e59aa0da76506 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 18 Oct 2016 10:06:42 +0200 Subject: fix specs - issue events working --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 543259f7cc2..be62077f01b 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -15,23 +15,23 @@ describe Gitlab::CycleAnalytics::Events do let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } it 'has an issue diff' do - expect(subject.issue_events['issue_diff']).to eq('2 days ago') + expect(subject.issue_events.first['issue_diff']).to eq('2 days ago') end it 'has a title' do - expect(subject.issue_events['title']).to eq(context.title) + expect(subject.issue_events.first['title']).to eq(context.title) end it 'has an iid' do - expect(subject.issue_events['iid']).to eq(context.iid.to_s) + expect(subject.issue_events.first['iid']).to eq(context.iid.to_s) end it 'has a created_at timestamp' do - expect(subject.issue_events['created_at']).to eq('2 days ago') + expect(subject.issue_events.first['created_at']).to end_with('ago') end it "has the author's name" do - expect(subject.issue_events['name']).to eq(context.author.name) + expect(subject.issue_events.first['name']).to eq(context.author.name) end end -- cgit v1.2.1 From 3b5d947730eb1f979bcb9033d63bdceb11fbb8ca Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 19 Oct 2016 12:47:09 +0200 Subject: commit events and spec --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index be62077f01b..ef59e8abc58 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -11,11 +11,11 @@ describe Gitlab::CycleAnalytics::Events do setup(context) end - describe '#issue' do + describe '#issue_events' do let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } - it 'has an issue diff' do - expect(subject.issue_events.first['issue_diff']).to eq('2 days ago') + it 'has the total time' do + expect(subject.issue_events.first['total_time']).to eq('2 days') end it 'has a title' do @@ -35,6 +35,18 @@ describe Gitlab::CycleAnalytics::Events do end end + describe '#plan_events' do + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + + xit 'has the first referenced commit' do + expect(subject.plan_events.first['commit']).to eq(project.commit) + end + + it 'has the total time' do + expect(subject.plan_events.first['total_time']).to eq('2 days') + end + end + def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) -- cgit v1.2.1 From 72660d58af13b4a768840307d2870ac08dd088ef Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 19 Oct 2016 15:40:14 +0200 Subject: plan events and spec working. Also added some TODOs to the code. --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index ef59e8abc58..4f8ba465d71 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -38,8 +38,8 @@ describe Gitlab::CycleAnalytics::Events do describe '#plan_events' do let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } - xit 'has the first referenced commit' do - expect(subject.plan_events.first['commit']).to eq(project.commit) + it 'has the first referenced commit' do + expect(subject.plan_events.first['commit'].message).to eq('commit message') end it 'has the total time' do -- cgit v1.2.1 From 1a4ff5d720fa0ec65f925ef381fced3d5f9a040f Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 20 Oct 2016 10:08:53 +0200 Subject: Added code events spec and logic. Also fixed SQL issues and refactored the code a bit. --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 30 +++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 4f8ba465d71..4a329737c7e 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -43,7 +43,35 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.plan_events.first['total_time']).to eq('2 days') + expect(subject.plan_events.first['total_time']).to eq('less than a minute') + end + end + + describe '#code_events' do + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + + before do + create_commit_referencing_issue(context) + end + + it 'has the total time' do + expect(subject.code_events.first['total_time']).to eq('2 days') + end + + it 'has a title' do + expect(subject.code_events.first['title']).to eq('Awesome merge_request') + end + + it 'has an iid' do + expect(subject.code_events.first['iid']).to eq(context.iid.to_s) + end + + it 'has a created_at timestamp' do + expect(subject.code_events.first['created_at']).to end_with('ago') + end + + it "has the author's name" do + expect(subject.code_events.first['name']).to eq(context.author.name) end end -- cgit v1.2.1 From ebd5ced7eb296ce10160021d8999d21b36b24da9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 20 Oct 2016 16:20:04 +0200 Subject: Added test events specs and logic. Also fixed some SQL and refactored the pipeline worker spec. --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 24 +++++++++++++++++++++++- spec/workers/pipeline_metrics_worker_spec.rb | 18 +++++++++++------- 2 files changed, 34 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 4a329737c7e..404d9e6912c 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -55,7 +55,7 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.code_events.first['total_time']).to eq('2 days') + expect(subject.code_events.first['total_time']).to eq('less than a minute') end it 'has a title' do @@ -75,6 +75,28 @@ describe Gitlab::CycleAnalytics::Events do end end + describe '#test_events' do + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + let(:merge_request) { MergeRequest.first } + let!(:pipeline) { create(:ci_pipeline, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha, + project: context.project) } + + before do + pipeline.run! + pipeline.succeed! + end + + it 'has the build info as a pipeline' do + expect(subject.test_events.first['pipeline']).to eq(pipeline) + end + + it 'has the total time' do + expect(subject.test_events.first['total_time']).to eq('less than a minute') + end + end + def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb index 2c9e7c2cd02..2d47d93acec 100644 --- a/spec/workers/pipeline_metrics_worker_spec.rb +++ b/spec/workers/pipeline_metrics_worker_spec.rb @@ -15,32 +15,36 @@ describe PipelineMetricsWorker do end describe '#perform' do - subject { described_class.new.perform(pipeline.id) } + before do + described_class.new.perform(pipeline.id) + end context 'when pipeline is running' do let(:status) { 'running' } it 'records the build start time' do - subject - expect(merge_request.reload.metrics.latest_build_started_at).to be_like_time(pipeline.started_at) end it 'clears the build end time' do - subject - expect(merge_request.reload.metrics.latest_build_finished_at).to be_nil end + + it 'records the pipeline' do + expect(merge_request.reload.metrics.pipeline).to eq(pipeline) + end end context 'when pipeline succeeded' do let(:status) { 'success' } it 'records the build end time' do - subject - expect(merge_request.reload.metrics.latest_build_finished_at).to be_like_time(pipeline.finished_at) end + + it 'records the pipeline' do + expect(merge_request.reload.metrics.pipeline).to eq(pipeline) + end end end end -- cgit v1.2.1 From d99cec7f55fb52dcddc380592e2fbb5ffc735f74 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 21 Oct 2016 08:50:27 +0200 Subject: review events - spec and logic --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 404d9e6912c..ae1172cd653 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -97,6 +97,31 @@ describe Gitlab::CycleAnalytics::Events do end end + describe '#review_events' do + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + + it 'has the total time' do + expect(subject.review_events.first['total_time']).to eq('less than a minute') + end + + it 'has a title' do + expect(subject.review_events.first['title']).to eq('Awesome merge_request') + end + + it 'has an iid' do + expect(subject.review_events.first['iid']).to eq(context.iid.to_s) + end + + it 'has a created_at timestamp' do + expect(subject.review_events.first['created_at']).to end_with('ago') + end + + it "has the author's name" do + expect(subject.review_events.first['name']).to eq(MergeRequest.first.author.name) + end + end + + def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) -- cgit v1.2.1 From f8acc7ea77bb52531b11abea5eabd68a38236cff Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 21 Oct 2016 09:44:04 +0200 Subject: fixing spec failures --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index ae1172cd653..17db46f0d4a 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -78,10 +78,12 @@ describe Gitlab::CycleAnalytics::Events do describe '#test_events' do let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } let(:merge_request) { MergeRequest.first } - let!(:pipeline) { create(:ci_pipeline, - ref: merge_request.source_branch, - sha: merge_request.diff_head_sha, - project: context.project) } + let!(:pipeline) do + create(:ci_pipeline, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha, + project: context.project) + end before do pipeline.run! @@ -121,7 +123,6 @@ describe Gitlab::CycleAnalytics::Events do end end - def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) -- cgit v1.2.1 From 1f701cb5e2fc9ea3af98ab0e6e07a7568a0e54dc Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 21 Oct 2016 11:33:37 +0200 Subject: added staging events and spec --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 17db46f0d4a..0212ce60b92 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -123,6 +123,32 @@ describe Gitlab::CycleAnalytics::Events do end end + describe '#staging_events' do + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + let(:merge_request) { MergeRequest.first } + let!(:pipeline) do + create(:ci_pipeline, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha, + project: context.project) + end + + before do + pipeline.run! + pipeline.succeed! + merge_merge_requests_closing_issue(context) + deploy_master + end + + it 'has the build info as a pipeline' do + expect(subject.staging_events.first['pipeline']).to eq(pipeline) + end + + it 'has the total time' do + expect(subject.staging_events.first['total_time']).to eq('less than a minute') + end + end + def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) -- cgit v1.2.1 From 3cdc9af78ebb71e2b91046e9dea8695aa04f6713 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 21 Oct 2016 17:30:38 +0200 Subject: added production events and related spec --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 0212ce60b92..410310d3029 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -149,6 +149,35 @@ describe Gitlab::CycleAnalytics::Events do end end + describe '#production_events' do + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + + before do + merge_merge_requests_closing_issue(context) + deploy_master + end + + it 'has the total time' do + expect(subject.production_events.first['total_time']).to eq('2 days') + end + + it 'has a title' do + expect(subject.production_events.first['title']).to eq(context.title) + end + + it 'has an iid' do + expect(subject.production_events.first['iid']).to eq(context.iid.to_s) + end + + it 'has a created_at timestamp' do + expect(subject.production_events.first['created_at']).to end_with('ago') + end + + it "has the author's name" do + expect(subject.production_events.first['name']).to eq(context.author.name) + end + end + def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) -- cgit v1.2.1 From d4726112656df24ff7721865a96237d5168466f7 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 24 Oct 2016 15:24:56 +0100 Subject: added cycle analytics events controller and started integration spec --- .../projects/cycle_analytics_events_spec.rb | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 spec/requests/projects/cycle_analytics_events_spec.rb (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb new file mode 100644 index 00000000000..064434c127e --- /dev/null +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'cycle analytics events' do + let(:user) { create(:user) } + let(:project) { create(:project) } + + describe 'GET /:namespace/:project/cycle_analytics/events/issues' do + before do + project.team << [user, :developer] + + login_as(user) + end + + it 'lists the issue events' do + get namespace_project_cycle_analytics_issues_path(project.namespace, project, format: :json) + + expect(json_response).to eq ([]) + end + end + + def json_response + JSON.parse(response.body) + end +end -- cgit v1.2.1 From 32679232635dbd0d196a91d0788ee1135ff56b43 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 24 Oct 2016 15:49:25 +0100 Subject: added the rest of the stages to the controller and relevant specs --- .../projects/cycle_analytics_events_spec.rb | 48 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 064434c127e..51db9bb07fa 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -3,18 +3,62 @@ require 'spec_helper' describe 'cycle analytics events' do let(:user) { create(:user) } let(:project) { create(:project) } + let!(:issue) { create(:issue, project: project, created_at: 2.days.ago) } describe 'GET /:namespace/:project/cycle_analytics/events/issues' do before do project.team << [user, :developer] + milestone = create(:milestone, project: project) + issue.update(milestone: milestone) + create_merge_request_closing_issue(issue) + + merge_merge_requests_closing_issue(issue) + deploy_master + login_as(user) end it 'lists the issue events' do - get namespace_project_cycle_analytics_issues_path(project.namespace, project, format: :json) + get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json) + + expect(json_response['events']).not_to be_empty + end + + it 'lists the plan events' do + get namespace_project_cycle_analytics_plan_path(project.namespace, project, format: :json) + + expect(json_response['events']).not_to be_empty + end + + it 'lists the code events' do + get namespace_project_cycle_analytics_code_path(project.namespace, project, format: :json) + + expect(json_response['events']).not_to be_empty + end + + it 'lists the test events' do + get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json) + + expect(json_response['events']).not_to be_empty + end + + it 'lists the review events' do + get namespace_project_cycle_analytics_review_path(project.namespace, project, format: :json) + + expect(json_response['events']).not_to be_empty + end + + it 'lists the staging events' do + get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json) + + expect(json_response['events']).not_to be_empty + end + + it 'lists the production events' do + get namespace_project_cycle_analytics_production_path(project.namespace, project, format: :json) - expect(json_response).to eq ([]) + expect(json_response['events']).not_to be_empty end end -- cgit v1.2.1 From ca9ae8bf63ff94c68143823046ab2a7466f30b1c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 27 Oct 2016 17:52:42 +0100 Subject: add email to user related queries so it can be used for displaying avatar in the UI --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 410310d3029..7d544dbdb19 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -30,6 +30,10 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.issue_events.first['created_at']).to end_with('ago') end + it "has the author's email" do + expect(subject.issue_events.first['email']).to eq(context.author.email) + end + it "has the author's name" do expect(subject.issue_events.first['name']).to eq(context.author.name) end @@ -70,6 +74,10 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.code_events.first['created_at']).to end_with('ago') end + it "has the author's email" do + expect(subject.code_events.first['email']).to eq(context.author.email) + end + it "has the author's name" do expect(subject.code_events.first['name']).to eq(context.author.name) end @@ -118,6 +126,10 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.review_events.first['created_at']).to end_with('ago') end + it "has the author's email" do + expect(subject.review_events.first['email']).to eq(MergeRequest.first.author.email) + end + it "has the author's name" do expect(subject.review_events.first['name']).to eq(MergeRequest.first.author.name) end @@ -173,6 +185,10 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.production_events.first['created_at']).to end_with('ago') end + it "has the author's email" do + expect(subject.production_events.first['email']).to eq(context.author.email) + end + it "has the author's name" do expect(subject.production_events.first['name']).to eq(context.author.name) end -- cgit v1.2.1 From 9ead268cfaee7cb23fa00c7cf8bcf536cafab91a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 2 Nov 2016 16:21:49 +0100 Subject: some more integration scenarios testing order. Also, fixed bug in the staging and test stages. --- .../projects/cycle_analytics_events_spec.rb | 55 +++++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 51db9bb07fa..e2733be4c3a 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -3,66 +3,95 @@ require 'spec_helper' describe 'cycle analytics events' do let(:user) { create(:user) } let(:project) { create(:project) } - let!(:issue) { create(:issue, project: project, created_at: 2.days.ago) } describe 'GET /:namespace/:project/cycle_analytics/events/issues' do before do project.team << [user, :developer] - milestone = create(:milestone, project: project) - issue.update(milestone: milestone) - create_merge_request_closing_issue(issue) - - merge_merge_requests_closing_issue(issue) + 3.times { create_cycle } deploy_master login_as(user) end - it 'lists the issue events' do + it 'lists the issue events in the right order' do get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s + + expect(json_response['events'].first['iid']).to eq(first_issue_iid) end - it 'lists the plan events' do + it 'lists the plan events in the right order' do get namespace_project_cycle_analytics_plan_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + first_date = DateTime.parse(json_response['events'].first['commit']['authored_date']) + last_date = DateTime.parse(json_response['events'].last['commit']['authored_date']) + + expect(first_date).to be > last_date end - it 'lists the code events' do + it 'lists the code events in the right order' do get namespace_project_cycle_analytics_code_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s + + expect(json_response['events'].first['iid']).to eq(first_mr_iid) end - it 'lists the test events' do + it 'lists the test events in the right order' do get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + # TODO create builds end - it 'lists the review events' do + it 'lists the review events in the right order' do get namespace_project_cycle_analytics_review_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s + + expect(json_response['events'].first['iid']).to eq(first_mr_iid) end - it 'lists the staging events' do + it 'lists the staging events in the right order' do get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + # TODO create builds end - it 'lists the production events' do + it 'lists the production events in the right order' do get namespace_project_cycle_analytics_production_path(project.namespace, project, format: :json) expect(json_response['events']).not_to be_empty + + first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s + + expect(json_response['events'].first['iid']).to eq(first_issue_iid) end end def json_response JSON.parse(response.body) end + + def create_cycle + issue = create(:issue, project: project, created_at: 2.days.ago) + milestone = create(:milestone, project: project) + issue.update(milestone: milestone) + + create_merge_request_closing_issue(issue) + merge_merge_requests_closing_issue(issue) + end end -- cgit v1.2.1 From 8bb4750eb3987999b0ee617c29224e468e9147b3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 3 Nov 2016 11:28:14 +0100 Subject: added pipelines to integration spec --- spec/requests/projects/cycle_analytics_events_spec.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index e2733be4c3a..3ee8795ac4c 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -50,7 +50,8 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty - # TODO create builds + expect(json_response['events'].first['pipeline']).not_to be_empty + end it 'lists the review events in the right order' do @@ -68,7 +69,7 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty - # TODO create builds + expect(json_response['events'].first['pipeline']).not_to be_empty end it 'lists the production events in the right order' do @@ -90,8 +91,11 @@ describe 'cycle analytics events' do issue = create(:issue, project: project, created_at: 2.days.ago) milestone = create(:milestone, project: project) issue.update(milestone: milestone) + mr = create_merge_request_closing_issue(issue) + + pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) + pipeline.run - create_merge_request_closing_issue(issue) merge_merge_requests_closing_issue(issue) end end -- cgit v1.2.1 From 8f7266cd4b6a3e65224b55c2b91509f5ac88d837 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 3 Nov 2016 13:06:14 +0100 Subject: added missing fields to issue. Also, added a light url builder to add URLs easily from arel. Updated specs. --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 10 +++++++--- spec/requests/projects/cycle_analytics_events_spec.rb | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 7d544dbdb19..e4535f467ec 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -30,12 +30,16 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.issue_events.first['created_at']).to end_with('ago') end - it "has the author's email" do - expect(subject.issue_events.first['email']).to eq(context.author.email) + it "has the author's URL" do + expect(subject.issue_events.first['author_profile_url']).not_to be_nil + end + + it "has the author's avatar URL" do + expect(subject.issue_events.first['author_avatar_url']).not_to be_nil end it "has the author's name" do - expect(subject.issue_events.first['name']).to eq(context.author.name) + expect(subject.issue_events.first['author_name']).to eq(context.author.name) end end diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 3ee8795ac4c..9884df3f110 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -51,7 +51,6 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty expect(json_response['events'].first['pipeline']).not_to be_empty - end it 'lists the review events in the right order' do -- cgit v1.2.1 From 1b5b2eac222cc25bfe7301cdefb69a6635ef0682 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 3 Nov 2016 15:41:46 +0100 Subject: added missing fields to plan events and updated spec --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 28 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index e4535f467ec..80a66693a37 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -4,6 +4,7 @@ describe Gitlab::CycleAnalytics::Events do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } + let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } subject { described_class.new(project: project, from: from_date) } @@ -12,8 +13,6 @@ describe Gitlab::CycleAnalytics::Events do end describe '#issue_events' do - let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } - it 'has the total time' do expect(subject.issue_events.first['total_time']).to eq('2 days') end @@ -44,20 +43,32 @@ describe Gitlab::CycleAnalytics::Events do end describe '#plan_events' do - let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } + it 'has a title' do + expect(subject.plan_events.first['title']).not_to be_nil + end - it 'has the first referenced commit' do - expect(subject.plan_events.first['commit'].message).to eq('commit message') + it 'has a sha short ID' do + expect(subject.plan_events.first['sha']).not_to be_nil end it 'has the total time' do expect(subject.plan_events.first['total_time']).to eq('less than a minute') end + + it "has the author's URL" do + expect(subject.plan_events.first['author_profile_url']).not_to be_nil + end + + it "has the author's avatar URL" do + expect(subject.plan_events.first['author_avatar_url']).not_to be_nil + end + + it "has the author's name" do + expect(subject.plan_events.first['author_name']).not_to be_nil + end end describe '#code_events' do - let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } - before do create_commit_referencing_issue(context) end @@ -88,7 +99,6 @@ describe Gitlab::CycleAnalytics::Events do end describe '#test_events' do - let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } let(:merge_request) { MergeRequest.first } let!(:pipeline) do create(:ci_pipeline, @@ -140,7 +150,6 @@ describe Gitlab::CycleAnalytics::Events do end describe '#staging_events' do - let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } let(:merge_request) { MergeRequest.first } let!(:pipeline) do create(:ci_pipeline, @@ -152,6 +161,7 @@ describe Gitlab::CycleAnalytics::Events do before do pipeline.run! pipeline.succeed! + merge_merge_requests_closing_issue(context) deploy_master end -- cgit v1.2.1 From 11bad33a4206e482ffac42d75a121182a52e0cb0 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 3 Nov 2016 16:31:30 +0100 Subject: added missing fields to code events and updated spec --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 80a66693a37..32e7bd7b12c 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -89,12 +89,16 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.code_events.first['created_at']).to end_with('ago') end - it "has the author's email" do - expect(subject.code_events.first['email']).to eq(context.author.email) + it "has the author's URL" do + expect(subject.code_events.first['author_profile_url']).not_to be_nil + end + + it "has the author's avatar URL" do + expect(subject.code_events.first['author_avatar_url']).not_to be_nil end it "has the author's name" do - expect(subject.code_events.first['name']).to eq(context.author.name) + expect(subject.code_events.first['author_name']).to eq(context.author.name) end end -- cgit v1.2.1 From eccb6a5e920920bda11104ca608e652f84a944bf Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 4 Nov 2016 11:56:24 +0100 Subject: Refactored test events Now test events return the builds instead a list of pipelines to avoid calling pipeline.builds per each and get the info. Also, added missing fields/data, URLs, and fixed specs in events spec. --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 37 +++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 32e7bd7b12c..c83dafbd256 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -112,16 +112,47 @@ describe Gitlab::CycleAnalytics::Events do end before do + create(:ci_build, pipeline: pipeline, status: :success) + create(:ci_build, pipeline: pipeline, status: :success) + pipeline.run! pipeline.succeed! end - it 'has the build info as a pipeline' do - expect(subject.test_events.first['pipeline']).to eq(pipeline) + it 'has the name' do + expect(subject.test_events.first['name']).not_to be_nil + end + + it 'has the ID' do + expect(subject.test_events.first['id']).not_to be_nil + end + + it 'has the URL' do + expect(subject.test_events.first['url']).not_to be_nil + end + + it 'has the branch name' do + expect(subject.test_events.first['branch']).not_to be_nil + end + + it 'has the branch URL' do + expect(subject.test_events.first['branch_url']).not_to be_nil + end + + it 'has the short SHA' do + expect(subject.test_events.first['sha']).not_to be_nil + end + + it 'has the commit URL' do + expect(subject.test_events.first['commit_url']).not_to be_nil + end + + it 'has the date' do + expect(subject.test_events.first['date']).not_to be_nil end it 'has the total time' do - expect(subject.test_events.first['total_time']).to eq('less than a minute') + expect(subject.test_events.first['total_time']).not_to be_nil end end -- cgit v1.2.1 From bd31f24c548878597322b34965789c88ff8d2dde Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 4 Nov 2016 12:57:23 +0100 Subject: Added branch option to test events Also fixed test events ordering issue --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index c83dafbd256..a531c4c31b7 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::CycleAnalytics::Events do let(:user) { create(:user, :admin) } let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } - subject { described_class.new(project: project, from: from_date) } + subject { described_class.new(project: project, options: { from: from_date }) } before do setup(context) -- cgit v1.2.1 From beeb64610e6a1907d6675b535659a519db129453 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 4 Nov 2016 15:59:27 +0100 Subject: Refactored staging events, added missing fields and fixed specs --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 62 +++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index a531c4c31b7..815e70ab6a8 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -171,16 +171,28 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.review_events.first['iid']).to eq(context.iid.to_s) end + it 'has the URL' do + expect(subject.review_events.first['url']).not_to be_nil + end + + it 'has a state' do + expect(subject.review_events.first['state']).not_to be_nil + end + it 'has a created_at timestamp' do - expect(subject.review_events.first['created_at']).to end_with('ago') + expect(subject.review_events.first['opened_at']).not_to be_nil end - it "has the author's email" do - expect(subject.review_events.first['email']).to eq(MergeRequest.first.author.email) + it "has the author's URL" do + expect(subject.review_events.first['author_profile_url']).not_to be_nil + end + + it "has the author's avatar URL" do + expect(subject.review_events.first['author_avatar_url']).not_to be_nil end it "has the author's name" do - expect(subject.review_events.first['name']).to eq(MergeRequest.first.author.name) + expect(subject.review_events.first['author_name']).to eq(context.author.name) end end @@ -194,6 +206,9 @@ describe Gitlab::CycleAnalytics::Events do end before do + create(:ci_build, pipeline: pipeline, status: :success, author: user) + create(:ci_build, pipeline: pipeline, status: :success, author: user) + pipeline.run! pipeline.succeed! @@ -201,12 +216,45 @@ describe Gitlab::CycleAnalytics::Events do deploy_master end - it 'has the build info as a pipeline' do - expect(subject.staging_events.first['pipeline']).to eq(pipeline) + + it 'has the name' do + expect(subject.staging_events.first['name']).not_to be_nil + end + + it 'has the ID' do + expect(subject.staging_events.first['id']).not_to be_nil + end + + it 'has the URL' do + expect(subject.staging_events.first['url']).not_to be_nil + end + + it 'has the branch name' do + expect(subject.staging_events.first['branch']).not_to be_nil + end + + it 'has the branch URL' do + expect(subject.staging_events.first['branch_url']).not_to be_nil + end + + it 'has the short SHA' do + expect(subject.staging_events.first['sha']).not_to be_nil + end + + it 'has the commit URL' do + expect(subject.staging_events.first['commit_url']).not_to be_nil + end + + it 'has the date' do + expect(subject.staging_events.first['date']).not_to be_nil end it 'has the total time' do - expect(subject.staging_events.first['total_time']).to eq('less than a minute') + expect(subject.staging_events.first['total_time']).not_to be_nil + end + + it 'has the author name' do + expect(subject.staging_events.first['author_name']).not_to be_nil end end -- cgit v1.2.1 From 83130ae877ffa946ef270743905f8fe1ac123305 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 4 Nov 2016 16:16:15 +0100 Subject: Updated production events with new fields --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 815e70ab6a8..29cc3011542 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -21,6 +21,10 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.issue_events.first['title']).to eq(context.title) end + it 'has the URL' do + expect(subject.issue_events.first['url']).not_to be_nil + end + it 'has an iid' do expect(subject.issue_events.first['iid']).to eq(context.iid.to_s) end @@ -216,7 +220,6 @@ describe Gitlab::CycleAnalytics::Events do deploy_master end - it 'has the name' do expect(subject.staging_events.first['name']).not_to be_nil end @@ -274,6 +277,10 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.production_events.first['title']).to eq(context.title) end + it 'has the URL' do + expect(subject.production_events.first['url']).not_to be_nil + end + it 'has an iid' do expect(subject.production_events.first['iid']).to eq(context.iid.to_s) end @@ -282,12 +289,16 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.production_events.first['created_at']).to end_with('ago') end - it "has the author's email" do - expect(subject.production_events.first['email']).to eq(context.author.email) + it "has the author's URL" do + expect(subject.production_events.first['author_profile_url']).not_to be_nil + end + + it "has the author's avatar URL" do + expect(subject.production_events.first['author_avatar_url']).not_to be_nil end it "has the author's name" do - expect(subject.production_events.first['name']).to eq(context.author.name) + expect(subject.production_events.first['author_name']).to eq(context.author.name) end end -- cgit v1.2.1 From 449a9fb1f16ff8b0d4328c4ebd26018dcd6fce36 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 4 Nov 2016 17:14:35 +0100 Subject: fixed integration spec after big refactoring of fields per stage --- .../projects/cycle_analytics_events_spec.rb | 56 +++++++++++++--------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 9884df3f110..c0b6a97c202 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -14,71 +14,78 @@ describe 'cycle analytics events' do login_as(user) end - it 'lists the issue events in the right order' do + it 'lists the issue events' do get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['issues']).not_to be_empty first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['events'].first['iid']).to eq(first_issue_iid) + expect(json_response['issues'].first['iid']).to eq(first_issue_iid) end - it 'lists the plan events in the right order' do + it 'lists the plan events' do get namespace_project_cycle_analytics_plan_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['commits']).not_to be_empty - first_date = DateTime.parse(json_response['events'].first['commit']['authored_date']) - last_date = DateTime.parse(json_response['events'].last['commit']['authored_date']) + commits = [] - expect(first_date).to be > last_date + MergeRequest.all.each do |mr| + mr.merge_request_diff.st_commits.each do |commit| + commits << { date: commit[:authored_date], sha: commit[:id] } + end + end + + newest_sha = commits.sort_by { |k| k['date'] }.first[:sha][0...8] + + expect(json_response['commits'].first['sha']).to eq(newest_sha) end - it 'lists the code events in the right order' do + it 'lists the code events' do get namespace_project_cycle_analytics_code_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['merge_requests']).not_to be_empty first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['events'].first['iid']).to eq(first_mr_iid) + expect(json_response['merge_requests'].first['iid']).to eq(first_mr_iid) end - it 'lists the test events in the right order' do + it 'lists the test events' do get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['builds']).not_to be_empty - expect(json_response['events'].first['pipeline']).not_to be_empty + expect(json_response['builds'].first['date']).not_to be_empty end - it 'lists the review events in the right order' do + it 'lists the review events' do get namespace_project_cycle_analytics_review_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['merge_requests']).not_to be_empty first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['events'].first['iid']).to eq(first_mr_iid) + expect(json_response['merge_requests'].first['iid']).to eq(first_mr_iid) end - it 'lists the staging events in the right order' do + it 'lists the staging events' do get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['builds']).not_to be_empty - expect(json_response['events'].first['pipeline']).not_to be_empty + expect(json_response['builds'].first['date']).not_to be_empty end - it 'lists the production events in the right order' do + it 'lists the production events' do get namespace_project_cycle_analytics_production_path(project.namespace, project, format: :json) - expect(json_response['events']).not_to be_empty + expect(json_response['issues']).not_to be_empty first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['events'].first['iid']).to eq(first_issue_iid) + expect(json_response['issues'].first['iid']).to eq(first_issue_iid) end end @@ -95,6 +102,9 @@ describe 'cycle analytics events' do pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha) pipeline.run + create(:ci_build, pipeline: pipeline, status: :success, author: user) + create(:ci_build, pipeline: pipeline, status: :success, author: user) + merge_merge_requests_closing_issue(issue) end end -- cgit v1.2.1 From 192918cde949c8399d7d526a638f6e09f9fb7a5a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 7 Nov 2016 10:08:18 +0100 Subject: refactored duplicated code in controller, updated JSON array naming and fixed specs --- .../projects/cycle_analytics_events_spec.rb | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index c0b6a97c202..d57e0342544 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -17,17 +17,17 @@ describe 'cycle analytics events' do it 'lists the issue events' do get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json) - expect(json_response['issues']).not_to be_empty + expect(json_response['items']).not_to be_empty first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['issues'].first['iid']).to eq(first_issue_iid) + expect(json_response['items'].first['iid']).to eq(first_issue_iid) end it 'lists the plan events' do get namespace_project_cycle_analytics_plan_path(project.namespace, project, format: :json) - expect(json_response['commits']).not_to be_empty + expect(json_response['items']).not_to be_empty commits = [] @@ -39,53 +39,53 @@ describe 'cycle analytics events' do newest_sha = commits.sort_by { |k| k['date'] }.first[:sha][0...8] - expect(json_response['commits'].first['sha']).to eq(newest_sha) + expect(json_response['items'].first['sha']).to eq(newest_sha) end it 'lists the code events' do get namespace_project_cycle_analytics_code_path(project.namespace, project, format: :json) - expect(json_response['merge_requests']).not_to be_empty + expect(json_response['items']).not_to be_empty first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['merge_requests'].first['iid']).to eq(first_mr_iid) + expect(json_response['items'].first['iid']).to eq(first_mr_iid) end it 'lists the test events' do get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json) - expect(json_response['builds']).not_to be_empty + expect(json_response['items']).not_to be_empty - expect(json_response['builds'].first['date']).not_to be_empty + expect(json_response['items'].first['date']).not_to be_empty end it 'lists the review events' do get namespace_project_cycle_analytics_review_path(project.namespace, project, format: :json) - expect(json_response['merge_requests']).not_to be_empty + expect(json_response['items']).not_to be_empty first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['merge_requests'].first['iid']).to eq(first_mr_iid) + expect(json_response['items'].first['iid']).to eq(first_mr_iid) end it 'lists the staging events' do get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json) - expect(json_response['builds']).not_to be_empty + expect(json_response['items']).not_to be_empty - expect(json_response['builds'].first['date']).not_to be_empty + expect(json_response['items'].first['date']).not_to be_empty end it 'lists the production events' do get namespace_project_cycle_analytics_production_path(project.namespace, project, format: :json) - expect(json_response['issues']).not_to be_empty + expect(json_response['items']).not_to be_empty first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['issues'].first['iid']).to eq(first_issue_iid) + expect(json_response['items'].first['iid']).to eq(first_issue_iid) end end -- cgit v1.2.1 From 7ac7cfeb75242c4e3c5ec967425aaf598f879033 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 7 Nov 2016 15:43:55 +0100 Subject: refactored and added missing spec to light URL builder --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 2 +- spec/lib/gitlab/url_builder_spec.rb | 137 +++++++++---------------- spec/lib/light_url_builder_spec.rb | 119 +++++++++++++++++++++ 3 files changed, 166 insertions(+), 92 deletions(-) create mode 100644 spec/lib/light_url_builder_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 29cc3011542..0fb6a62f10d 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -196,7 +196,7 @@ describe Gitlab::CycleAnalytics::Events do end it "has the author's name" do - expect(subject.review_events.first['author_name']).to eq(context.author.name) + expect(subject.review_events.first['author_name']).to eq(MergeRequest.first.author.name) end end diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index a826b24419a..5d876fdb603 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -1,119 +1,74 @@ require 'spec_helper' -describe Gitlab::UrlBuilder, lib: true do - describe '.build' do - context 'when passing a Commit' do - it 'returns a proper URL' do - commit = build_stubbed(:commit) +describe Gitlab::LightUrlBuilder, lib: true do + context 'when passing a Commit' do + it 'returns a proper URL' do + commit = build_stubbed(:commit) - url = described_class.build(commit) + url = described_class.build(entity: :commit, project: commit.project, id: commit.id) - expect(url).to eq "#{Settings.gitlab['url']}/#{commit.project.path_with_namespace}/commit/#{commit.id}" - end + expect(url).to eq "#{Settings.gitlab['url']}/#{commit.project.path_with_namespace}/commit/#{commit.id}" end + end - context 'when passing an Issue' do - it 'returns a proper URL' do - issue = build_stubbed(:issue, iid: 42) + context 'when passing an Issue' do + it 'returns a proper URL' do + issue = build_stubbed(:issue, iid: 42) - url = described_class.build(issue) + url = described_class.build(entity: :issue, project: issue.project, id: issue.iid) - expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}" - end + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}" end + end - context 'when passing a MergeRequest' do - it 'returns a proper URL' do - merge_request = build_stubbed(:merge_request, iid: 42) + context 'when passing a MergeRequest' do + it 'returns a proper URL' do + merge_request = build_stubbed(:merge_request, iid: 42) - url = described_class.build(merge_request) + url = described_class.build(entity: :merge_request, project: merge_request.project, id: merge_request.iid) - expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}" - end + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}" end + end - context 'when passing a Note' do - context 'on a Commit' do - it 'returns a proper URL' do - note = build_stubbed(:note_on_commit) - - url = described_class.build(note) - - expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" - end - end - - context 'on a Commit Diff' do - it 'returns a proper URL' do - note = build_stubbed(:diff_note_on_commit) - - url = described_class.build(note) - - expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" - end - end - - context 'on an Issue' do - it 'returns a proper URL' do - issue = create(:issue, iid: 42) - note = build_stubbed(:note_on_issue, noteable: issue) - - url = described_class.build(note) - - expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}#note_#{note.id}" - end - end - - context 'on a MergeRequest' do - it 'returns a proper URL' do - merge_request = create(:merge_request, iid: 42) - note = build_stubbed(:note_on_merge_request, noteable: merge_request) - - url = described_class.build(note) - - expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" - end - end + context 'when passing a build' do + it 'returns a proper URL' do + build = build_stubbed(:ci_build, project: build_stubbed(:empty_project)) - context 'on a MergeRequest Diff' do - it 'returns a proper URL' do - merge_request = create(:merge_request, iid: 42) - note = build_stubbed(:diff_note_on_merge_request, noteable: merge_request) + url = described_class.build(entity: :build, project: build.project, id: build.id) - url = described_class.build(note) + expect(url).to eq "#{Settings.gitlab['url']}/#{build.project.path_with_namespace}/builds/#{build.id}" + end + end - expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" - end - end + context 'when passing a branch' do + it 'returns a proper URL' do + branch = 'branch_name' + project = build_stubbed(:empty_project) - context 'on a ProjectSnippet' do - it 'returns a proper URL' do - project_snippet = create(:project_snippet) - note = build_stubbed(:note_on_project_snippet, noteable: project_snippet) + url = described_class.build(entity: :branch, project: project, id: branch) - url = described_class.build(note) + expect(url).to eq "#{Settings.gitlab['url']}/#{project.path_with_namespace}/commits/#{branch}" + end + end - expect(url).to eq "#{Settings.gitlab['url']}/#{project_snippet.project.path_with_namespace}/snippets/#{note.noteable_id}#note_#{note.id}" - end - end + context 'on a User' do + it 'returns a proper URL' do + user = build_stubbed(:user) - context 'on another object' do - it 'returns a proper URL' do - project = build_stubbed(:project) + url = described_class.build(entity: :user, id: user.username) - expect { described_class.build(project) }. - to raise_error(NotImplementedError, 'No URL builder defined for Project') - end - end + expect(url).to eq "#{Settings.gitlab['url']}/#{user.username}" end + end + + context 'on a user avatar' do + it 'returns a proper URL' do + user = create(:user) - context 'when passing a WikiPage' do - it 'returns a proper URL' do - wiki_page = build(:wiki_page) - url = described_class.build(wiki_page) + url = described_class.build(entity: :user_avatar, id: user.id) - expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}" - end + expect(url).to eq user.avatar_url end end end diff --git a/spec/lib/light_url_builder_spec.rb b/spec/lib/light_url_builder_spec.rb new file mode 100644 index 00000000000..a826b24419a --- /dev/null +++ b/spec/lib/light_url_builder_spec.rb @@ -0,0 +1,119 @@ +require 'spec_helper' + +describe Gitlab::UrlBuilder, lib: true do + describe '.build' do + context 'when passing a Commit' do + it 'returns a proper URL' do + commit = build_stubbed(:commit) + + url = described_class.build(commit) + + expect(url).to eq "#{Settings.gitlab['url']}/#{commit.project.path_with_namespace}/commit/#{commit.id}" + end + end + + context 'when passing an Issue' do + it 'returns a proper URL' do + issue = build_stubbed(:issue, iid: 42) + + url = described_class.build(issue) + + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}" + end + end + + context 'when passing a MergeRequest' do + it 'returns a proper URL' do + merge_request = build_stubbed(:merge_request, iid: 42) + + url = described_class.build(merge_request) + + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}" + end + end + + context 'when passing a Note' do + context 'on a Commit' do + it 'returns a proper URL' do + note = build_stubbed(:note_on_commit) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" + end + end + + context 'on a Commit Diff' do + it 'returns a proper URL' do + note = build_stubbed(:diff_note_on_commit) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" + end + end + + context 'on an Issue' do + it 'returns a proper URL' do + issue = create(:issue, iid: 42) + note = build_stubbed(:note_on_issue, noteable: issue) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}#note_#{note.id}" + end + end + + context 'on a MergeRequest' do + it 'returns a proper URL' do + merge_request = create(:merge_request, iid: 42) + note = build_stubbed(:note_on_merge_request, noteable: merge_request) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" + end + end + + context 'on a MergeRequest Diff' do + it 'returns a proper URL' do + merge_request = create(:merge_request, iid: 42) + note = build_stubbed(:diff_note_on_merge_request, noteable: merge_request) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" + end + end + + context 'on a ProjectSnippet' do + it 'returns a proper URL' do + project_snippet = create(:project_snippet) + note = build_stubbed(:note_on_project_snippet, noteable: project_snippet) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{project_snippet.project.path_with_namespace}/snippets/#{note.noteable_id}#note_#{note.id}" + end + end + + context 'on another object' do + it 'returns a proper URL' do + project = build_stubbed(:project) + + expect { described_class.build(project) }. + to raise_error(NotImplementedError, 'No URL builder defined for Project') + end + end + end + + context 'when passing a WikiPage' do + it 'returns a proper URL' do + wiki_page = build(:wiki_page) + url = described_class.build(wiki_page) + + expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}" + end + end + end +end -- cgit v1.2.1 From 3d00503368c355a4a9a45cda0e6673580074d2da Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 9 Nov 2016 11:44:29 +0100 Subject: fixed and added missing scenario to events integration spec --- .../projects/cycle_analytics_events_spec.rb | 40 ++++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index d57e0342544..d4da8707ea5 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -17,17 +17,17 @@ describe 'cycle analytics events' do it 'lists the issue events' do get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['items'].first['iid']).to eq(first_issue_iid) + expect(json_response['events'].first['iid']).to eq(first_issue_iid) end it 'lists the plan events' do get namespace_project_cycle_analytics_plan_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty commits = [] @@ -39,53 +39,65 @@ describe 'cycle analytics events' do newest_sha = commits.sort_by { |k| k['date'] }.first[:sha][0...8] - expect(json_response['items'].first['sha']).to eq(newest_sha) + expect(json_response['events'].first['sha']).to eq(newest_sha) end it 'lists the code events' do get namespace_project_cycle_analytics_code_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['items'].first['iid']).to eq(first_mr_iid) + expect(json_response['events'].first['iid']).to eq(first_mr_iid) end it 'lists the test events' do get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty - expect(json_response['items'].first['date']).not_to be_empty + expect(json_response['events'].first['date']).not_to be_empty end it 'lists the review events' do get namespace_project_cycle_analytics_review_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['items'].first['iid']).to eq(first_mr_iid) + expect(json_response['events'].first['iid']).to eq(first_mr_iid) end it 'lists the staging events' do get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty - expect(json_response['items'].first['date']).not_to be_empty + expect(json_response['events'].first['date']).not_to be_empty end it 'lists the production events' do get namespace_project_cycle_analytics_production_path(project.namespace, project, format: :json) - expect(json_response['items']).not_to be_empty + expect(json_response['events']).not_to be_empty first_issue_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s - expect(json_response['items'].first['iid']).to eq(first_issue_iid) + expect(json_response['events'].first['iid']).to eq(first_issue_iid) + end + + context 'specific branch' do + it 'lists the test events' do + branch = MergeRequest.first.source_branch + + get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json, branch: branch) + + expect(json_response['events']).not_to be_empty + + expect(json_response['events'].first['date']).not_to be_empty + end end end -- cgit v1.2.1 From 81d0146c4cf0d34b1b81da770483ed864482149c Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Nov 2016 11:52:29 +0100 Subject: WIP - refactoring URL builder and events presenter into serializers --- spec/serializers/analytics_build_entity_spec.rb | 22 ++++++++++++++++++++ .../serializers/analytics_build_serializer_spec.rb | 24 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 spec/serializers/analytics_build_entity_spec.rb create mode 100644 spec/serializers/analytics_build_serializer_spec.rb (limited to 'spec') diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb new file mode 100644 index 00000000000..33653d5b1e0 --- /dev/null +++ b/spec/serializers/analytics_build_entity_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe AnalyticsBuildEntity do + let(:entity) do + described_class.new(build, request: double) + end + + context 'when build is a regular job' do + let(:build) { create(:ci_build) } + + subject { entity.as_json } + + it 'contains url to build page and retry action' do + expect(subject).to include(:url, :branch_url, :commit_url) + end + + it 'does not contain sensitive information' do + expect(subject).not_to include(/token/) + expect(subject).not_to include(/variables/) + end + end +end diff --git a/spec/serializers/analytics_build_serializer_spec.rb b/spec/serializers/analytics_build_serializer_spec.rb new file mode 100644 index 00000000000..24fd94810d4 --- /dev/null +++ b/spec/serializers/analytics_build_serializer_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe AnalyticsBuildSerializer do + let(:serializer) do + described_class + .new(project: project) + .represent(resource) + end + + let(:json) { serializer.as_json } + let(:project) { create(:project) } + let(:resource) { create(:ci_build) } + + context 'when there is a single object provided' do + it 'it generates payload for single object' do + expect(json).to be_an_instance_of Hash + end + + it 'contains important elements of analyticsBuild' do + expect(json) + .to include(:name, :branch, :short_sha, :date, :total_time, :url, :branch_url, :commit_url, :author) + end + end +end -- cgit v1.2.1 From 3b179bc37b940521522af6d8bf6762c2a9a0e251 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Nov 2016 14:53:06 +0100 Subject: WIP - refactored events to use build serializer, related spec passing --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 118 ++++++++++++------------ spec/serializers/analytics_build_entity_spec.rb | 9 +- 2 files changed, 66 insertions(+), 61 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 0fb6a62f10d..ebeea2be39e 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -14,61 +14,61 @@ describe Gitlab::CycleAnalytics::Events do describe '#issue_events' do it 'has the total time' do - expect(subject.issue_events.first['total_time']).to eq('2 days') + expect(subject.issue_events.first[:total_time]).to eq('2 days') end it 'has a title' do - expect(subject.issue_events.first['title']).to eq(context.title) + expect(subject.issue_events.first[:title]).to eq(context.title) end it 'has the URL' do - expect(subject.issue_events.first['url']).not_to be_nil + expect(subject.issue_events.first[:url]).not_to be_nil end it 'has an iid' do - expect(subject.issue_events.first['iid']).to eq(context.iid.to_s) + expect(subject.issue_events.first[:iid]).to eq(context.iid.to_s) end it 'has a created_at timestamp' do - expect(subject.issue_events.first['created_at']).to end_with('ago') + expect(subject.issue_events.first[:created_at]).to end_with('ago') end it "has the author's URL" do - expect(subject.issue_events.first['author_profile_url']).not_to be_nil + expect(subject.issue_events.first[:author_profile_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.issue_events.first['author_avatar_url']).not_to be_nil + expect(subject.issue_events.first[:author_avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.issue_events.first['author_name']).to eq(context.author.name) + expect(subject.issue_events.first[:author_name]).to eq(context.author.name) end end describe '#plan_events' do it 'has a title' do - expect(subject.plan_events.first['title']).not_to be_nil + expect(subject.plan_events.first[:title]).not_to be_nil end it 'has a sha short ID' do - expect(subject.plan_events.first['sha']).not_to be_nil + expect(subject.plan_events.first[:sha]).not_to be_nil end it 'has the total time' do - expect(subject.plan_events.first['total_time']).to eq('less than a minute') + expect(subject.plan_events.first[:total_time]).to eq('less than a minute') end it "has the author's URL" do - expect(subject.plan_events.first['author_profile_url']).not_to be_nil + expect(subject.plan_events.first[:author_profile_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.plan_events.first['author_avatar_url']).not_to be_nil + expect(subject.plan_events.first[:author_avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.plan_events.first['author_name']).not_to be_nil + expect(subject.plan_events.first[:author_name]).not_to be_nil end end @@ -78,31 +78,31 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.code_events.first['total_time']).to eq('less than a minute') + expect(subject.code_events.first[:total_time]).to eq('less than a minute') end it 'has a title' do - expect(subject.code_events.first['title']).to eq('Awesome merge_request') + expect(subject.code_events.first[:title]).to eq('Awesome merge_request') end it 'has an iid' do - expect(subject.code_events.first['iid']).to eq(context.iid.to_s) + expect(subject.code_events.first[:iid]).to eq(context.iid.to_s) end it 'has a created_at timestamp' do - expect(subject.code_events.first['created_at']).to end_with('ago') + expect(subject.code_events.first[:created_at]).to end_with('ago') end it "has the author's URL" do - expect(subject.code_events.first['author_profile_url']).not_to be_nil + expect(subject.code_events.first[:author_profile_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.code_events.first['author_avatar_url']).not_to be_nil + expect(subject.code_events.first[:author_avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.code_events.first['author_name']).to eq(context.author.name) + expect(subject.code_events.first[:author_name]).to eq(context.author.name) end end @@ -116,47 +116,47 @@ describe Gitlab::CycleAnalytics::Events do end before do - create(:ci_build, pipeline: pipeline, status: :success) - create(:ci_build, pipeline: pipeline, status: :success) + create(:ci_build, pipeline: pipeline, status: :success, author: user) + create(:ci_build, pipeline: pipeline, status: :success, author: user) pipeline.run! pipeline.succeed! end it 'has the name' do - expect(subject.test_events.first['name']).not_to be_nil + expect(subject.test_events.first[:name]).not_to be_nil end it 'has the ID' do - expect(subject.test_events.first['id']).not_to be_nil + expect(subject.test_events.first[:id]).not_to be_nil end it 'has the URL' do - expect(subject.test_events.first['url']).not_to be_nil + expect(subject.test_events.first[:url]).not_to be_nil end it 'has the branch name' do - expect(subject.test_events.first['branch']).not_to be_nil + expect(subject.test_events.first[:branch]).not_to be_nil end it 'has the branch URL' do - expect(subject.test_events.first['branch_url']).not_to be_nil + expect(subject.test_events.first[:branch][:url]).not_to be_nil end it 'has the short SHA' do - expect(subject.test_events.first['sha']).not_to be_nil + expect(subject.test_events.first[:short_sha]).not_to be_nil end it 'has the commit URL' do - expect(subject.test_events.first['commit_url']).not_to be_nil + expect(subject.test_events.first[:commit_url]).not_to be_nil end it 'has the date' do - expect(subject.test_events.first['date']).not_to be_nil + expect(subject.test_events.first[:date]).not_to be_nil end it 'has the total time' do - expect(subject.test_events.first['total_time']).not_to be_nil + expect(subject.test_events.first[:total_time]).not_to be_nil end end @@ -164,39 +164,39 @@ describe Gitlab::CycleAnalytics::Events do let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } it 'has the total time' do - expect(subject.review_events.first['total_time']).to eq('less than a minute') + expect(subject.review_events.first[:total_time]).to eq('less than a minute') end it 'has a title' do - expect(subject.review_events.first['title']).to eq('Awesome merge_request') + expect(subject.review_events.first[:title]).to eq('Awesome merge_request') end it 'has an iid' do - expect(subject.review_events.first['iid']).to eq(context.iid.to_s) + expect(subject.review_events.first[:iid]).to eq(context.iid.to_s) end it 'has the URL' do - expect(subject.review_events.first['url']).not_to be_nil + expect(subject.review_events.first[:url]).not_to be_nil end it 'has a state' do - expect(subject.review_events.first['state']).not_to be_nil + expect(subject.review_events.first[:state]).not_to be_nil end it 'has a created_at timestamp' do - expect(subject.review_events.first['opened_at']).not_to be_nil + expect(subject.review_events.first[:opened_at]).not_to be_nil end it "has the author's URL" do - expect(subject.review_events.first['author_profile_url']).not_to be_nil + expect(subject.review_events.first[:author_profile_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.review_events.first['author_avatar_url']).not_to be_nil + expect(subject.review_events.first[:author_avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.review_events.first['author_name']).to eq(MergeRequest.first.author.name) + expect(subject.review_events.first[:author_name]).to eq(MergeRequest.first.author.name) end end @@ -221,43 +221,43 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the name' do - expect(subject.staging_events.first['name']).not_to be_nil + expect(subject.staging_events.first[:name]).not_to be_nil end it 'has the ID' do - expect(subject.staging_events.first['id']).not_to be_nil + expect(subject.staging_events.first[:id]).not_to be_nil end it 'has the URL' do - expect(subject.staging_events.first['url']).not_to be_nil + expect(subject.staging_events.first[:url]).not_to be_nil end it 'has the branch name' do - expect(subject.staging_events.first['branch']).not_to be_nil + expect(subject.staging_events.first[:branch]).not_to be_nil end it 'has the branch URL' do - expect(subject.staging_events.first['branch_url']).not_to be_nil + expect(subject.staging_events.first[:branch_url]).not_to be_nil end it 'has the short SHA' do - expect(subject.staging_events.first['sha']).not_to be_nil + expect(subject.staging_events.first[:sha]).not_to be_nil end it 'has the commit URL' do - expect(subject.staging_events.first['commit_url']).not_to be_nil + expect(subject.staging_events.first[:commit_url]).not_to be_nil end it 'has the date' do - expect(subject.staging_events.first['date']).not_to be_nil + expect(subject.staging_events.first[:date]).not_to be_nil end it 'has the total time' do - expect(subject.staging_events.first['total_time']).not_to be_nil + expect(subject.staging_events.first[:total_time]).not_to be_nil end it 'has the author name' do - expect(subject.staging_events.first['author_name']).not_to be_nil + expect(subject.staging_events.first[:author_name]).not_to be_nil end end @@ -270,35 +270,35 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.production_events.first['total_time']).to eq('2 days') + expect(subject.production_events.first[:total_time]).to eq('2 days') end it 'has a title' do - expect(subject.production_events.first['title']).to eq(context.title) + expect(subject.production_events.first[:title]).to eq(context.title) end it 'has the URL' do - expect(subject.production_events.first['url']).not_to be_nil + expect(subject.production_events.first[:url]).not_to be_nil end it 'has an iid' do - expect(subject.production_events.first['iid']).to eq(context.iid.to_s) + expect(subject.production_events.first[:iid]).to eq(context.iid.to_s) end it 'has a created_at timestamp' do - expect(subject.production_events.first['created_at']).to end_with('ago') + expect(subject.production_events.first[:created_at]).to end_with('ago') end it "has the author's URL" do - expect(subject.production_events.first['author_profile_url']).not_to be_nil + expect(subject.production_events.first[:author_profile_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.production_events.first['author_avatar_url']).not_to be_nil + expect(subject.production_events.first[:author_avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.production_events.first['author_name']).to eq(context.author.name) + expect(subject.production_events.first[:author_name]).to eq(context.author.name) end end diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb index 33653d5b1e0..24040034f68 100644 --- a/spec/serializers/analytics_build_entity_spec.rb +++ b/spec/serializers/analytics_build_entity_spec.rb @@ -6,14 +6,19 @@ describe AnalyticsBuildEntity do end context 'when build is a regular job' do - let(:build) { create(:ci_build) } + let(:user) { create(:user) } + let(:build) { create(:ci_build, author: user) } subject { entity.as_json } - it 'contains url to build page and retry action' do + it 'contains URLs' do expect(subject).to include(:url, :branch_url, :commit_url) end + it 'contains the author' do + expect(subject).to include(:author) + end + it 'does not contain sensitive information' do expect(subject).not_to include(/token/) expect(subject).not_to include(/variables/) -- cgit v1.2.1 From 0ddf825ddf7bc480004919762b187390d0b900e9 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 14 Nov 2016 18:05:13 +0100 Subject: WIP - adding a generic entity serializer that should accept a Hash coming from Arel --- spec/serializers/analytics_generic_entity_spec.rb | 39 ++++++++++++++++++++++ .../analytics_generic_serializer_spec.rb | 24 +++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 spec/serializers/analytics_generic_entity_spec.rb create mode 100644 spec/serializers/analytics_generic_serializer_spec.rb (limited to 'spec') diff --git a/spec/serializers/analytics_generic_entity_spec.rb b/spec/serializers/analytics_generic_entity_spec.rb new file mode 100644 index 00000000000..a09dae4520c --- /dev/null +++ b/spec/serializers/analytics_generic_entity_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe AnalyticsGenericEntity do + let(:user) { create(:user) } + let(:entity_hash) { + { + total_time: "172802.724419", + title: "Eos voluptatem inventore in sed.", + iid: "1", + id: "1", + created_at: "2016-11-12 15:04:02.948604", + author: user, + entity: :merge_request + } + } + + let(:project) { create(:empty_project) } + + let(:entity) do + described_class.new(entity_hash, request: double, project: project) + end + + context 'generic entity' do + subject { entity.as_json } + + it 'contains the entity URL' do + expect(subject).to include(:url) + end + + it 'contains the author' do + expect(subject).to include(:author) + end + + it 'does not contain sensitive information' do + expect(subject).not_to include(/token/) + expect(subject).not_to include(/variables/) + end + end +end diff --git a/spec/serializers/analytics_generic_serializer_spec.rb b/spec/serializers/analytics_generic_serializer_spec.rb new file mode 100644 index 00000000000..24fd94810d4 --- /dev/null +++ b/spec/serializers/analytics_generic_serializer_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe AnalyticsBuildSerializer do + let(:serializer) do + described_class + .new(project: project) + .represent(resource) + end + + let(:json) { serializer.as_json } + let(:project) { create(:project) } + let(:resource) { create(:ci_build) } + + context 'when there is a single object provided' do + it 'it generates payload for single object' do + expect(json).to be_an_instance_of Hash + end + + it 'contains important elements of analyticsBuild' do + expect(json) + .to include(:name, :branch, :short_sha, :date, :total_time, :url, :branch_url, :commit_url, :author) + end + end +end -- cgit v1.2.1 From 6a2737e6a82875311f71f451939b2732562533d4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 09:39:45 +0100 Subject: WIP - refactor events to use a generic build entity for some of the hybrid events --- spec/serializers/analytics_build_entity_spec.rb | 6 +++--- spec/serializers/analytics_build_serializer_spec.rb | 6 ++---- spec/serializers/analytics_generic_serializer_spec.rb | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb index 24040034f68..9ac6f20fd3c 100644 --- a/spec/serializers/analytics_build_entity_spec.rb +++ b/spec/serializers/analytics_build_entity_spec.rb @@ -5,14 +5,14 @@ describe AnalyticsBuildEntity do described_class.new(build, request: double) end - context 'when build is a regular job' do + context 'build with an author' do let(:user) { create(:user) } let(:build) { create(:ci_build, author: user) } subject { entity.as_json } - it 'contains URLs' do - expect(subject).to include(:url, :branch_url, :commit_url) + it 'contains the URL' do + expect(subject).to include(:url) end it 'contains the author' do diff --git a/spec/serializers/analytics_build_serializer_spec.rb b/spec/serializers/analytics_build_serializer_spec.rb index 24fd94810d4..a0a9d9a5f12 100644 --- a/spec/serializers/analytics_build_serializer_spec.rb +++ b/spec/serializers/analytics_build_serializer_spec.rb @@ -3,12 +3,10 @@ require 'spec_helper' describe AnalyticsBuildSerializer do let(:serializer) do described_class - .new(project: project) - .represent(resource) + .new.represent(resource) end let(:json) { serializer.as_json } - let(:project) { create(:project) } let(:resource) { create(:ci_build) } context 'when there is a single object provided' do @@ -18,7 +16,7 @@ describe AnalyticsBuildSerializer do it 'contains important elements of analyticsBuild' do expect(json) - .to include(:name, :branch, :short_sha, :date, :total_time, :url, :branch_url, :commit_url, :author) + .to include(:name, :branch, :short_sha, :date, :total_time, :url, :author) end end end diff --git a/spec/serializers/analytics_generic_serializer_spec.rb b/spec/serializers/analytics_generic_serializer_spec.rb index 24fd94810d4..4d523878015 100644 --- a/spec/serializers/analytics_generic_serializer_spec.rb +++ b/spec/serializers/analytics_generic_serializer_spec.rb @@ -1,15 +1,26 @@ require 'spec_helper' -describe AnalyticsBuildSerializer do +describe AnalyticsGenericSerializer do let(:serializer) do described_class .new(project: project) .represent(resource) end + let(:user) { create(:user) } let(:json) { serializer.as_json } let(:project) { create(:project) } - let(:resource) { create(:ci_build) } + let(:resource) { + { + total_time: "172802.724419", + title: "Eos voluptatem inventore in sed.", + iid: "1", + id: "1", + created_at: "2016-11-12 15:04:02.948604", + author: user, + entity: :merge_request + } + } context 'when there is a single object provided' do it 'it generates payload for single object' do @@ -17,8 +28,7 @@ describe AnalyticsBuildSerializer do end it 'contains important elements of analyticsBuild' do - expect(json) - .to include(:name, :branch, :short_sha, :date, :total_time, :url, :branch_url, :commit_url, :author) + expect(json).to include(:title, :iid, :date, :total_time, :url, :author) end end end -- cgit v1.2.1 From 747e5c3b6fb6e744bc1fce04f94930fdbb5f9121 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 09:59:35 +0100 Subject: use request to pass extra parameters --- spec/serializers/analytics_generic_entity_spec.rb | 4 ++-- spec/serializers/analytics_generic_serializer_spec.rb | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/serializers/analytics_generic_entity_spec.rb b/spec/serializers/analytics_generic_entity_spec.rb index a09dae4520c..7c731da1dd1 100644 --- a/spec/serializers/analytics_generic_entity_spec.rb +++ b/spec/serializers/analytics_generic_entity_spec.rb @@ -10,14 +10,14 @@ describe AnalyticsGenericEntity do id: "1", created_at: "2016-11-12 15:04:02.948604", author: user, - entity: :merge_request } } let(:project) { create(:empty_project) } + let(:request) { EntityRequest.new(project: project, entity: :merge_request) } let(:entity) do - described_class.new(entity_hash, request: double, project: project) + described_class.new(entity_hash, request: request, project: project) end context 'generic entity' do diff --git a/spec/serializers/analytics_generic_serializer_spec.rb b/spec/serializers/analytics_generic_serializer_spec.rb index 4d523878015..452595fb1f5 100644 --- a/spec/serializers/analytics_generic_serializer_spec.rb +++ b/spec/serializers/analytics_generic_serializer_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe AnalyticsGenericSerializer do let(:serializer) do described_class - .new(project: project) + .new(project: project, entity: :merge_request) .represent(resource) end @@ -18,7 +18,6 @@ describe AnalyticsGenericSerializer do id: "1", created_at: "2016-11-12 15:04:02.948604", author: user, - entity: :merge_request } } -- cgit v1.2.1 From f5600997512f1068cdc36ad7d086e7447dbc6d9d Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 10:33:01 +0100 Subject: fix issue events and related spec - now using generic serializer for a hash --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 6 +++--- spec/serializers/analytics_generic_serializer_spec.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index ebeea2be39e..073469a2b80 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -34,15 +34,15 @@ describe Gitlab::CycleAnalytics::Events do end it "has the author's URL" do - expect(subject.issue_events.first[:author_profile_url]).not_to be_nil + expect(subject.issue_events.first[:author][:web_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.issue_events.first[:author_avatar_url]).not_to be_nil + expect(subject.issue_events.first[:author][:avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.issue_events.first[:author_name]).to eq(context.author.name) + expect(subject.issue_events.first[:author][:name]).to eq(context.author.name) end end diff --git a/spec/serializers/analytics_generic_serializer_spec.rb b/spec/serializers/analytics_generic_serializer_spec.rb index 452595fb1f5..9eeb7bee562 100644 --- a/spec/serializers/analytics_generic_serializer_spec.rb +++ b/spec/serializers/analytics_generic_serializer_spec.rb @@ -27,7 +27,7 @@ describe AnalyticsGenericSerializer do end it 'contains important elements of analyticsBuild' do - expect(json).to include(:title, :iid, :date, :total_time, :url, :author) + expect(json).to include(:title, :iid, :created_at, :total_time, :url, :author) end end end -- cgit v1.2.1 From 8743e59f78cd8f8701460796dcc06854281f3f73 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 11:36:39 +0100 Subject: get all stages to use serlalizers - apart from plan - WIP --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 42 +++++++++++++++----------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 073469a2b80..55ab28e2af8 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -60,15 +60,15 @@ describe Gitlab::CycleAnalytics::Events do end it "has the author's URL" do - expect(subject.plan_events.first[:author_profile_url]).not_to be_nil + expect(subject.plan_events.first[:author][:web_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.plan_events.first[:author_avatar_url]).not_to be_nil + expect(subject.plan_events.first[:author][:avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.plan_events.first[:author_name]).not_to be_nil + expect(subject.plan_events.first[:author][:name]).to eq(context.author.name) end end @@ -94,15 +94,15 @@ describe Gitlab::CycleAnalytics::Events do end it "has the author's URL" do - expect(subject.code_events.first[:author_profile_url]).not_to be_nil + expect(subject.code_events.first[:author][:web_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.code_events.first[:author_avatar_url]).not_to be_nil + expect(subject.code_events.first[:author][:avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.code_events.first[:author_name]).to eq(context.author.name) + expect(subject.code_events.first[:author][:name]).to eq(MergeRequest.first.author.name) end end @@ -184,19 +184,19 @@ describe Gitlab::CycleAnalytics::Events do end it 'has a created_at timestamp' do - expect(subject.review_events.first[:opened_at]).not_to be_nil + expect(subject.review_events.first[:created_at]).not_to be_nil end it "has the author's URL" do - expect(subject.review_events.first[:author_profile_url]).not_to be_nil + expect(subject.review_events.first[:author][:web_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.review_events.first[:author_avatar_url]).not_to be_nil + expect(subject.review_events.first[:author][:avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.review_events.first[:author_name]).to eq(MergeRequest.first.author.name) + expect(subject.review_events.first[:author][:name]).to eq(MergeRequest.first.author.name) end end @@ -237,11 +237,11 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the branch URL' do - expect(subject.staging_events.first[:branch_url]).not_to be_nil + expect(subject.staging_events.first[:branch][:url]).not_to be_nil end it 'has the short SHA' do - expect(subject.staging_events.first[:sha]).not_to be_nil + expect(subject.staging_events.first[:short_sha]).not_to be_nil end it 'has the commit URL' do @@ -256,8 +256,16 @@ describe Gitlab::CycleAnalytics::Events do expect(subject.staging_events.first[:total_time]).not_to be_nil end - it 'has the author name' do - expect(subject.staging_events.first[:author_name]).not_to be_nil + it "has the author's URL" do + expect(subject.staging_events.first[:author][:web_url]).not_to be_nil + end + + it "has the author's avatar URL" do + expect(subject.staging_events.first[:author][:avatar_url]).not_to be_nil + end + + it "has the author's name" do + expect(subject.staging_events.first[:author][:name]).to eq(MergeRequest.first.author.name) end end @@ -290,15 +298,15 @@ describe Gitlab::CycleAnalytics::Events do end it "has the author's URL" do - expect(subject.production_events.first[:author_profile_url]).not_to be_nil + expect(subject.production_events.first[:author][:web_url]).not_to be_nil end it "has the author's avatar URL" do - expect(subject.production_events.first[:author_avatar_url]).not_to be_nil + expect(subject.production_events.first[:author][:avatar_url]).not_to be_nil end it "has the author's name" do - expect(subject.production_events.first[:author_name]).to eq(context.author.name) + expect(subject.production_events.first[:author][:name]).to eq(context.author.name) end end -- cgit v1.2.1 From 73e9ec631995d5ed91a3eb5e8416c924e7d7c5ad Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 13:23:17 +0100 Subject: serialize all the things! --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 55ab28e2af8..d46e70e9ba2 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -52,7 +52,11 @@ describe Gitlab::CycleAnalytics::Events do end it 'has a sha short ID' do - expect(subject.plan_events.first[:sha]).not_to be_nil + expect(subject.plan_events.first[:short_sha]).not_to be_nil + end + + it 'has the URL' do + expect(subject.plan_events.first[:commit_url]).not_to be_nil end it 'has the total time' do @@ -68,7 +72,7 @@ describe Gitlab::CycleAnalytics::Events do end it "has the author's name" do - expect(subject.plan_events.first[:author][:name]).to eq(context.author.name) + expect(subject.plan_events.first[:author][:name]).not_to be_nil end end -- cgit v1.2.1 From f93607a305346607f4296c266d40be1692febbec Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 15:27:50 +0100 Subject: get rid of light url builder and fix wrong spec --- spec/lib/gitlab/url_builder_spec.rb | 137 ++++++++++++++++++++++++------------ 1 file changed, 91 insertions(+), 46 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index 5d876fdb603..a826b24419a 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -1,74 +1,119 @@ require 'spec_helper' -describe Gitlab::LightUrlBuilder, lib: true do - context 'when passing a Commit' do - it 'returns a proper URL' do - commit = build_stubbed(:commit) +describe Gitlab::UrlBuilder, lib: true do + describe '.build' do + context 'when passing a Commit' do + it 'returns a proper URL' do + commit = build_stubbed(:commit) - url = described_class.build(entity: :commit, project: commit.project, id: commit.id) + url = described_class.build(commit) - expect(url).to eq "#{Settings.gitlab['url']}/#{commit.project.path_with_namespace}/commit/#{commit.id}" + expect(url).to eq "#{Settings.gitlab['url']}/#{commit.project.path_with_namespace}/commit/#{commit.id}" + end end - end - context 'when passing an Issue' do - it 'returns a proper URL' do - issue = build_stubbed(:issue, iid: 42) + context 'when passing an Issue' do + it 'returns a proper URL' do + issue = build_stubbed(:issue, iid: 42) - url = described_class.build(entity: :issue, project: issue.project, id: issue.iid) + url = described_class.build(issue) - expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}" + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}" + end end - end - context 'when passing a MergeRequest' do - it 'returns a proper URL' do - merge_request = build_stubbed(:merge_request, iid: 42) + context 'when passing a MergeRequest' do + it 'returns a proper URL' do + merge_request = build_stubbed(:merge_request, iid: 42) - url = described_class.build(entity: :merge_request, project: merge_request.project, id: merge_request.iid) + url = described_class.build(merge_request) - expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}" + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}" + end end - end - context 'when passing a build' do - it 'returns a proper URL' do - build = build_stubbed(:ci_build, project: build_stubbed(:empty_project)) + context 'when passing a Note' do + context 'on a Commit' do + it 'returns a proper URL' do + note = build_stubbed(:note_on_commit) - url = described_class.build(entity: :build, project: build.project, id: build.id) + url = described_class.build(note) - expect(url).to eq "#{Settings.gitlab['url']}/#{build.project.path_with_namespace}/builds/#{build.id}" - end - end + expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" + end + end - context 'when passing a branch' do - it 'returns a proper URL' do - branch = 'branch_name' - project = build_stubbed(:empty_project) + context 'on a Commit Diff' do + it 'returns a proper URL' do + note = build_stubbed(:diff_note_on_commit) - url = described_class.build(entity: :branch, project: project, id: branch) + url = described_class.build(note) - expect(url).to eq "#{Settings.gitlab['url']}/#{project.path_with_namespace}/commits/#{branch}" - end - end + expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" + end + end - context 'on a User' do - it 'returns a proper URL' do - user = build_stubbed(:user) + context 'on an Issue' do + it 'returns a proper URL' do + issue = create(:issue, iid: 42) + note = build_stubbed(:note_on_issue, noteable: issue) - url = described_class.build(entity: :user, id: user.username) + url = described_class.build(note) - expect(url).to eq "#{Settings.gitlab['url']}/#{user.username}" - end - end + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}#note_#{note.id}" + end + end + + context 'on a MergeRequest' do + it 'returns a proper URL' do + merge_request = create(:merge_request, iid: 42) + note = build_stubbed(:note_on_merge_request, noteable: merge_request) - context 'on a user avatar' do - it 'returns a proper URL' do - user = create(:user) + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" + end + end + + context 'on a MergeRequest Diff' do + it 'returns a proper URL' do + merge_request = create(:merge_request, iid: 42) + note = build_stubbed(:diff_note_on_merge_request, noteable: merge_request) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" + end + end + + context 'on a ProjectSnippet' do + it 'returns a proper URL' do + project_snippet = create(:project_snippet) + note = build_stubbed(:note_on_project_snippet, noteable: project_snippet) + + url = described_class.build(note) + + expect(url).to eq "#{Settings.gitlab['url']}/#{project_snippet.project.path_with_namespace}/snippets/#{note.noteable_id}#note_#{note.id}" + end + end + + context 'on another object' do + it 'returns a proper URL' do + project = build_stubbed(:project) + + expect { described_class.build(project) }. + to raise_error(NotImplementedError, 'No URL builder defined for Project') + end + end + end - url = described_class.build(entity: :user_avatar, id: user.id) + context 'when passing a WikiPage' do + it 'returns a proper URL' do + wiki_page = build(:wiki_page) + url = described_class.build(wiki_page) - expect(url).to eq user.avatar_url + expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}" + end end end end -- cgit v1.2.1 From 633ddc9ed98c690c082c7347422ac85f9b592fb4 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 15 Nov 2016 16:25:37 +0100 Subject: fix authorization of builds and added relevant spec --- .../projects/cycle_analytics_events_spec.rb | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index d4da8707ea5..ef6e4c80911 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -39,7 +39,7 @@ describe 'cycle analytics events' do newest_sha = commits.sort_by { |k| k['date'] }.first[:sha][0...8] - expect(json_response['events'].first['sha']).to eq(newest_sha) + expect(json_response['events'].first['short_sha']).to eq(newest_sha) end it 'lists the code events' do @@ -99,6 +99,30 @@ describe 'cycle analytics events' do expect(json_response['events'].first['date']).not_to be_empty end end + + context 'with private project and builds' do + before do + ProjectMember.first.update(access_level: Gitlab::Access::GUEST) + end + + it 'does not list the test events' do + get namespace_project_cycle_analytics_test_path(project.namespace, project, format: :json) + + expect(response).to have_http_status(:not_found) + end + + it 'does not list the staging events' do + get namespace_project_cycle_analytics_staging_path(project.namespace, project, format: :json) + + expect(response).to have_http_status(:not_found) + end + + it 'lists the issue events' do + get namespace_project_cycle_analytics_issue_path(project.namespace, project, format: :json) + + expect(response).to have_http_status(:ok) + end + end end def json_response -- cgit v1.2.1 From cbc9f0cd1aa9f379952b6e4d3ad6df9971f9092a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 16 Nov 2016 09:58:23 +0100 Subject: fix issue with commits and also updated routes --- spec/requests/projects/cycle_analytics_events_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index ef6e4c80911..280aa2152b1 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -142,5 +142,7 @@ describe 'cycle analytics events' do create(:ci_build, pipeline: pipeline, status: :success, author: user) merge_merge_requests_closing_issue(issue) + + Issue::Metrics.update_all(first_mentioned_in_commit_at: mr.commits.last.committed_date) end end -- cgit v1.2.1 From cf2dcf043c0054785bc0258ab6393104499b8d70 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 16 Nov 2016 12:01:10 +0100 Subject: Refactor all query config stuff into separate classes and added specs --- spec/lib/gitlab/cycle_analytics/code_config_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/events_spec.rb | 6 +++++- spec/lib/gitlab/cycle_analytics/issue_config_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/plan_config_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/production_config_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/review_config_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/shared_config_spec.rb | 15 +++++++++++++++ spec/lib/gitlab/cycle_analytics/staging_config_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/test_config_spec.rb | 10 ++++++++++ spec/requests/projects/cycle_analytics_events_spec.rb | 4 +++- spec/serializers/analytics_generic_entity_spec.rb | 4 ++-- spec/serializers/analytics_generic_serializer_spec.rb | 4 ++-- 12 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 spec/lib/gitlab/cycle_analytics/code_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/issue_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/plan_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/production_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/review_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/shared_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/staging_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/test_config_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/code_config_spec.rb b/spec/lib/gitlab/cycle_analytics/code_config_spec.rb new file mode 100644 index 00000000000..7b89fdd76aa --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/code_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::CodeConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).not_to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index d46e70e9ba2..aa0e54582f1 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -9,6 +9,8 @@ describe Gitlab::CycleAnalytics::Events do subject { described_class.new(project: project, options: { from: from_date }) } before do + allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([context]) + setup(context) end @@ -317,6 +319,8 @@ describe Gitlab::CycleAnalytics::Events do def setup(context) milestone = create(:milestone, project: project) context.update(milestone: milestone) - create_merge_request_closing_issue(context) + mr = create_merge_request_closing_issue(context) + + ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.sha) end end diff --git a/spec/lib/gitlab/cycle_analytics/issue_config_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_config_spec.rb new file mode 100644 index 00000000000..ff8cd1e8068 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/issue_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::IssueConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/plan_config_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_config_spec.rb new file mode 100644 index 00000000000..92698defa5d --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/plan_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::PlanConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/production_config_spec.rb b/spec/lib/gitlab/cycle_analytics/production_config_spec.rb new file mode 100644 index 00000000000..92485777334 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/production_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::ProductionConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/review_config_spec.rb b/spec/lib/gitlab/cycle_analytics/review_config_spec.rb new file mode 100644 index 00000000000..59cb18ac16d --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/review_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::ReviewConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/shared_config_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_config_spec.rb new file mode 100644 index 00000000000..060a59151d8 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/shared_config_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +shared_examples 'default query config' do + it 'has the start attributes' do + expect(described_class.start_time_attrs).not_to be_nil + end + + it 'has the end attributes' do + expect(described_class.end_time_attrs ).not_to be_nil + end + + it 'has the projection attributes' do + expect(described_class.projections).not_to be_nil + end +end diff --git a/spec/lib/gitlab/cycle_analytics/staging_config_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_config_spec.rb new file mode 100644 index 00000000000..f13885d7f48 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/staging_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::StagingConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).not_to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/test_config_spec.rb b/spec/lib/gitlab/cycle_analytics/test_config_spec.rb new file mode 100644 index 00000000000..59421b99513 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/test_config_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_config_spec' + +describe Gitlab::CycleAnalytics::TestConfig do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).not_to eq(described_class.start_time_attrs) + end +end diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 280aa2152b1..1c78cd368db 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -12,6 +12,8 @@ describe 'cycle analytics events' do deploy_master login_as(user) + + allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([context]) end it 'lists the issue events' do @@ -143,6 +145,6 @@ describe 'cycle analytics events' do merge_merge_requests_closing_issue(issue) - Issue::Metrics.update_all(first_mentioned_in_commit_at: mr.commits.last.committed_date) + ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.sha) end end diff --git a/spec/serializers/analytics_generic_entity_spec.rb b/spec/serializers/analytics_generic_entity_spec.rb index 7c731da1dd1..3bb15cb9475 100644 --- a/spec/serializers/analytics_generic_entity_spec.rb +++ b/spec/serializers/analytics_generic_entity_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe AnalyticsGenericEntity do let(:user) { create(:user) } - let(:entity_hash) { + let(:entity_hash) do { total_time: "172802.724419", title: "Eos voluptatem inventore in sed.", @@ -11,7 +11,7 @@ describe AnalyticsGenericEntity do created_at: "2016-11-12 15:04:02.948604", author: user, } - } + end let(:project) { create(:empty_project) } let(:request) { EntityRequest.new(project: project, entity: :merge_request) } diff --git a/spec/serializers/analytics_generic_serializer_spec.rb b/spec/serializers/analytics_generic_serializer_spec.rb index 9eeb7bee562..99f2254d22c 100644 --- a/spec/serializers/analytics_generic_serializer_spec.rb +++ b/spec/serializers/analytics_generic_serializer_spec.rb @@ -10,7 +10,7 @@ describe AnalyticsGenericSerializer do let(:user) { create(:user) } let(:json) { serializer.as_json } let(:project) { create(:project) } - let(:resource) { + let(:resource) do { total_time: "172802.724419", title: "Eos voluptatem inventore in sed.", @@ -19,7 +19,7 @@ describe AnalyticsGenericSerializer do created_at: "2016-11-12 15:04:02.948604", author: user, } - } + end context 'when there is a single object provided' do it 'it generates payload for single object' do -- cgit v1.2.1 From cbd7d000395ff60fe3726e67ec351bd4d44582ec Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 16 Nov 2016 15:55:20 +0100 Subject: added custom date helper and spec and fixed some unrelated spec failures --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 14 +++---- .../projects/cycle_analytics_events_spec.rb | 22 +++-------- spec/serializers/entity_date_helper_spec.rb | 45 ++++++++++++++++++++++ 3 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 spec/serializers/entity_date_helper_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index aa0e54582f1..8e2d2f8b5bd 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -16,7 +16,7 @@ describe Gitlab::CycleAnalytics::Events do describe '#issue_events' do it 'has the total time' do - expect(subject.issue_events.first[:total_time]).to eq('2 days') + expect(subject.issue_events.first[:total_time]).not_to be_empty end it 'has a title' do @@ -62,7 +62,7 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.plan_events.first[:total_time]).to eq('less than a minute') + expect(subject.plan_events.first[:total_time]).not_to be_empty end it "has the author's URL" do @@ -84,7 +84,7 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.code_events.first[:total_time]).to eq('less than a minute') + expect(subject.code_events.first[:total_time]).not_to be_empty end it 'has a title' do @@ -162,7 +162,7 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.test_events.first[:total_time]).not_to be_nil + expect(subject.test_events.first[:total_time]).not_to be_empty end end @@ -170,7 +170,7 @@ describe Gitlab::CycleAnalytics::Events do let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } it 'has the total time' do - expect(subject.review_events.first[:total_time]).to eq('less than a minute') + expect(subject.review_events.first[:total_time]).not_to be_empty end it 'has a title' do @@ -259,7 +259,7 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.staging_events.first[:total_time]).not_to be_nil + expect(subject.staging_events.first[:total_time]).not_to be_empty end it "has the author's URL" do @@ -284,7 +284,7 @@ describe Gitlab::CycleAnalytics::Events do end it 'has the total time' do - expect(subject.production_events.first[:total_time]).to eq('2 days') + expect(subject.production_events.first[:total_time]).not_to be_empty end it 'has a title' do diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 1c78cd368db..705dbb7d1c0 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -3,17 +3,18 @@ require 'spec_helper' describe 'cycle analytics events' do let(:user) { create(:user) } let(:project) { create(:project) } + let(:issue) { create(:issue, project: project, created_at: 2.days.ago) } describe 'GET /:namespace/:project/cycle_analytics/events/issues' do before do project.team << [user, :developer] + allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) + 3.times { create_cycle } deploy_master login_as(user) - - allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([context]) end it 'lists the issue events' do @@ -31,17 +32,7 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty - commits = [] - - MergeRequest.all.each do |mr| - mr.merge_request_diff.st_commits.each do |commit| - commits << { date: commit[:authored_date], sha: commit[:id] } - end - end - - newest_sha = commits.sort_by { |k| k['date'] }.first[:sha][0...8] - - expect(json_response['events'].first['short_sha']).to eq(newest_sha) + expect(json_response['events'].first['short_sha']).to eq(MergeRequest.last.commits.first.short_id) end it 'lists the code events' do @@ -49,7 +40,7 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty - first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s + first_mr_iid = MergeRequest.order(created_at: :desc).pluck(:iid).first.to_s expect(json_response['events'].first['iid']).to eq(first_mr_iid) end @@ -67,7 +58,7 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty - first_mr_iid = Issue.order(created_at: :desc).pluck(:iid).first.to_s + first_mr_iid = MergeRequest.order(created_at: :desc).pluck(:iid).first.to_s expect(json_response['events'].first['iid']).to eq(first_mr_iid) end @@ -132,7 +123,6 @@ describe 'cycle analytics events' do end def create_cycle - issue = create(:issue, project: project, created_at: 2.days.ago) milestone = create(:milestone, project: project) issue.update(milestone: milestone) mr = create_merge_request_closing_issue(issue) diff --git a/spec/serializers/entity_date_helper_spec.rb b/spec/serializers/entity_date_helper_spec.rb new file mode 100644 index 00000000000..90e57833de7 --- /dev/null +++ b/spec/serializers/entity_date_helper_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe EntityDateHelper do + let(:date_helper_class) { Class.new { include EntityDateHelper }.new } + + it 'converts 0 seconds' do + expect(date_helper_class.distance_of_time_as_hash(0)).to eq(seconds: 0) + end + + it 'converts 40 seconds' do + expect(date_helper_class.distance_of_time_as_hash(40)).to eq(seconds: 40) + end + + it 'converts 60 seconds' do + expect(date_helper_class.distance_of_time_as_hash(60)).to eq(mins: 1) + end + + it 'converts 70 seconds' do + expect(date_helper_class.distance_of_time_as_hash(70)).to eq(mins: 1, seconds: 10) + end + + it 'converts 3600 seconds' do + expect(date_helper_class.distance_of_time_as_hash(3600)).to eq(hours: 1) + end + + it 'converts 3750 seconds' do + expect(date_helper_class.distance_of_time_as_hash(3750)).to eq(hours: 1, mins: 2, seconds: 30) + end + + it 'converts 86400 seconds' do + expect(date_helper_class.distance_of_time_as_hash(86400)).to eq(days: 1) + end + + it 'converts 86560 seconds' do + expect(date_helper_class.distance_of_time_as_hash(86560)).to eq(days: 1, mins: 2, seconds: 40) + end + + it 'converts 86760 seconds' do + expect(date_helper_class.distance_of_time_as_hash(99760)).to eq(days: 1, hours: 3, mins: 42, seconds: 40) + end + + it 'converts 986760 seconds' do + expect(date_helper_class.distance_of_time_as_hash(986760)).to eq(days: 11, hours: 10, mins: 6) + end +end \ No newline at end of file -- cgit v1.2.1 From 9e0102e494d27bbb7fcd4ae8f2b0c0bc4ce3e7ce Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 16 Nov 2016 16:09:24 +0100 Subject: small refactor - removing includes no longer needed --- spec/serializers/entity_date_helper_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/serializers/entity_date_helper_spec.rb b/spec/serializers/entity_date_helper_spec.rb index 90e57833de7..b9cc2f64831 100644 --- a/spec/serializers/entity_date_helper_spec.rb +++ b/spec/serializers/entity_date_helper_spec.rb @@ -42,4 +42,4 @@ describe EntityDateHelper do it 'converts 986760 seconds' do expect(date_helper_class.distance_of_time_as_hash(986760)).to eq(days: 11, hours: 10, mins: 6) end -end \ No newline at end of file +end -- cgit v1.2.1 From 58f78d0571ab0ba6034f6c53d16f9ca97a799706 Mon Sep 17 00:00:00 2001 From: Nur Rony Date: Sat, 8 Oct 2016 12:50:28 +0600 Subject: makes system notes less intrusive to a conversation adds dicussion icon and color change in system note links adds discussion icons and sticky note icon for other system notes for now fixes scss lint error adds faded commit lists hides first paragraph in commit list box css tweak for commit list system notes adds commit-list toggle functionality, css tweaks and css classnames more readable small css fix in header. makes links bold in system note renames class no-shade to hide-shade adds entry for this merge request in changelog removes commented line removes the avatar-icon from discussion header minor css tweaks to make the commit list alignment with header text uses monospaced font to make the commit list lined up with all removes icon from system note and align bullet list resolves scss lint warings adds helper function to extract system note message from first p tag adds helper functions to check commit list count and haml cleanup adds changelog entry under 8.14 adds changelog entry with changelog cli removes helper and regex and makes commit list li count using JS makes link in system note normal brakeman build failure resolved fixing rspec test based on new design for discussion shows system note in lowercase removes extra spaces from comments adds code commenting for functions adds semi-colon in some lines fixes rspec given when merge build success removes commented codes rewrite changelog yml file moves isMetaKey to common utils file fixes some indentation issues removes unnecessary variables and resolves some discussions replaces jQuery parent function with siblings fixes scss issues and variable spelling mistake uses constant rather using hardcoded number for visible li count in long commit list makes system note header all lowercase uses color variables and adjust gradient a little some minor changes for adding css classes renames functions name for readability changes changelog title minor scss newline changes makes system note less intrusive to a conversation --- spec/features/merge_requests/diff_notes_resolve_spec.rb | 2 +- spec/features/merge_requests/merge_when_build_succeeds_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/diff_notes_resolve_spec.rb b/spec/features/merge_requests/diff_notes_resolve_spec.rb index d5e3d8e7eff..eab64bd4b54 100644 --- a/spec/features/merge_requests/diff_notes_resolve_spec.rb +++ b/spec/features/merge_requests/diff_notes_resolve_spec.rb @@ -201,7 +201,7 @@ feature 'Diff notes resolve', feature: true, js: true do expect(first('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}") end - expect(page).to have_content('Last updated') + expect(page).not_to have_content('Last updated') page.within '.line-resolve-all-container' do expect(page).to have_content('0/1 discussion resolved') diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb index c3c3ab33872..8eceaad2457 100644 --- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb +++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb @@ -73,7 +73,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do expect(page).to have_button "Merge When Build Succeeds" visit_merge_request(merge_request) # refresh the page - expect(page).to have_content "Canceled the automatic merge" + expect(page).to have_content "canceled the automatic merge" end it "allows the user to remove the source branch" do @@ -101,7 +101,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do expect(page).not_to have_link "Merge When Build Succeeds" end end - + def visit_merge_request(merge_request) visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) end -- cgit v1.2.1 From cdb726ce202165d1ab747830d805a6144d93c5cc Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 17 Nov 2016 10:10:11 +0100 Subject: Fix code review style issues --- spec/services/chat_names/authorize_user_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/services/chat_names/authorize_user_service_spec.rb b/spec/services/chat_names/authorize_user_service_spec.rb index 2ecee58e92d..d50bfb0492c 100644 --- a/spec/services/chat_names/authorize_user_service_spec.rb +++ b/spec/services/chat_names/authorize_user_service_spec.rb @@ -15,7 +15,7 @@ describe ChatNames::AuthorizeUserService, services: true do end context 'when there are missing parameters' do - let(:params) { { } } + let(:params) { {} } it 'does not request a new token' do is_expected.to be_nil -- cgit v1.2.1 From 43906336ff24e218cb1f7024d63a22367dd7e09a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 17 Nov 2016 12:08:28 +0100 Subject: Fix tests and add has_environment? --- spec/models/build_spec.rb | 38 +++++++++++++++++++++++++++++++++++--- spec/models/ci/build_spec.rb | 4 +--- 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index 731a2274d9e..ef07f2275b1 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -1053,6 +1053,26 @@ describe Ci::Build, models: true do end end + describe '#has_environment?' do + subject { build.has_environment? } + + context 'when environment is defined' do + before do + build.update(environment: 'review') + end + + it { is_expected.to be_truthy } + end + + context 'when environment is not defined' do + before do + build.update(environment: nil) + end + + it { is_expected.to be_falsey } + end + end + describe '#starts_environment?' do subject { build.starts_environment? } @@ -1061,7 +1081,17 @@ describe Ci::Build, models: true do build.update(environment: 'review') end - it { is_expected.to be_truthy } + context 'no action is defined' do + it { is_expected.to be_truthy } + end + + context 'and start action is defined' do + before do + build.update(options: { environment: { action: 'start' } } ) + end + + it { is_expected.to be_truthy } + end end context 'when environment is not defined' do @@ -1106,11 +1136,13 @@ describe Ci::Build, models: true do describe '#last_deployment' do subject { build.last_deployment } - context 'when multiple deployments is created returns latest one' do + context 'when multiple deployments are created' do let!(:deployment1) { create(:deployment, deployable: build) } let!(:deployment2) { create(:deployment, deployable: build) } - it { is_expected.to eq(deployment2) } + it 'returns the latest one' do + is_expected.to eq(deployment2) + end end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 2efe69d7adc..a7e90c8a381 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -4,14 +4,12 @@ describe Ci::Build, models: true do let(:build) { create(:ci_build) } let(:test_trace) { 'This is a test' } - describe 'ss' do it { is_expected.to belong_to(:runner) } it { is_expected.to belong_to(:trigger_request) } it { is_expected.to belong_to(:erased_by) } it { is_expected.to have_many(:deployments) } - end - + describe '#trace' do it 'obfuscates project runners token' do allow(build).to receive(:raw_trace).and_return("Test: #{build.project.runners_token}") -- cgit v1.2.1 From 80073da95771fc51a4ac05814b0a7ceae1cbdac9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 17 Nov 2016 11:13:39 +0000 Subject: Include author in assignee dropdown search When searching for the author in the assignee dropdown it now correctly returns the user Closes #22905 --- spec/features/issues/issue_sidebar_spec.rb | 35 +++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 4b1aec8bf71..bc068b5e7e0 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -1,7 +1,9 @@ require 'rails_helper' feature 'Issue Sidebar', feature: true do - let(:project) { create(:project) } + include WaitForAjax + + let(:project) { create(:project, :public) } let(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} @@ -10,6 +12,37 @@ feature 'Issue Sidebar', feature: true do login_as(user) end + context 'assignee', js: true do + let(:user2) { create(:user) } + let(:issue2) { create(:issue, project: project, author: user2) } + + before do + project.team << [user, :developer] + visit_issue(project, issue2) + + find('.block.assignee .edit-link').click + + wait_for_ajax + end + + it 'shows author in assignee dropdown' do + page.within '.dropdown-menu-user' do + expect(page).to have_content(user2.name) + end + end + + it 'shows author when filtering assignee dropdown' do + page.within '.dropdown-menu-user' do + find('.dropdown-input-field').native.send_keys user2.name + sleep 1 # Required to wait for end of input delay + + wait_for_ajax + + expect(page).to have_content(user2.name) + end + end + end + context 'as a allowed user' do before do project.team << [user, :developer] -- cgit v1.2.1 From 73a5f331b2e7b2e224147e69c857c6306318399e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 17 Nov 2016 13:05:17 +0100 Subject: Unfold dropdown in tests for environments index --- spec/features/environments_spec.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index eca67de7bcb..aef38f9f407 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -78,15 +78,20 @@ feature 'Environments', feature: true, js: true do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } scenario 'does show a play button' do - # TODO: Fix me! + find('.dropdown-play-icon-container').click expect(page).to have_content(manual.name.humanize) end scenario 'does allow to play manual action' do expect(manual).to be_skipped - # TODO: Fix me! - expect{ click_link(manual.name.humanize) }.not_to change { Ci::Pipeline.count } - expect(page).to have_content(manual.name) + + find('.dropdown-play-icon-container').click + play_action = find('span', text: manual.name.humanize) + + expect(page).to have_content(manual.name.humanize) + expect { play_action.click }.not_to change { Ci::Pipeline.count } + + # TODO, fix me! expect(manual.reload).to be_pending end -- cgit v1.2.1 From ed39d61d746925e49d952bd8169499d3200ae68b Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 17 Nov 2016 13:22:27 +0100 Subject: refactor events facade so it uses separate classes and refactor query stuff --- spec/lib/gitlab/cycle_analytics/code_config_spec.rb | 10 ---------- spec/lib/gitlab/cycle_analytics/code_event_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/issue_config_spec.rb | 10 ---------- spec/lib/gitlab/cycle_analytics/issue_event_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/plan_config_spec.rb | 10 ---------- spec/lib/gitlab/cycle_analytics/plan_event_spec.rb | 10 ++++++++++ .../gitlab/cycle_analytics/production_config_spec.rb | 10 ---------- .../gitlab/cycle_analytics/production_event_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/review_config_spec.rb | 10 ---------- spec/lib/gitlab/cycle_analytics/review_event_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/shared_config_spec.rb | 15 --------------- spec/lib/gitlab/cycle_analytics/shared_event_spec.rb | 19 +++++++++++++++++++ .../lib/gitlab/cycle_analytics/staging_config_spec.rb | 10 ---------- spec/lib/gitlab/cycle_analytics/staging_event_spec.rb | 10 ++++++++++ spec/lib/gitlab/cycle_analytics/test_config_spec.rb | 10 ---------- spec/lib/gitlab/cycle_analytics/test_event_spec.rb | 10 ++++++++++ spec/serializers/analytics_generic_entity_spec.rb | 2 +- 17 files changed, 90 insertions(+), 86 deletions(-) delete mode 100644 spec/lib/gitlab/cycle_analytics/code_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/code_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/issue_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/issue_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/plan_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/plan_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/production_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/production_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/review_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/review_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/shared_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/shared_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/staging_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/staging_event_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/test_config_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/test_event_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/code_config_spec.rb b/spec/lib/gitlab/cycle_analytics/code_config_spec.rb deleted file mode 100644 index 7b89fdd76aa..00000000000 --- a/spec/lib/gitlab/cycle_analytics/code_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::CodeConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).not_to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/code_event_spec.rb b/spec/lib/gitlab/cycle_analytics/code_event_spec.rb new file mode 100644 index 00000000000..7b854d7fea1 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/code_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::CodeEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).not_to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/issue_config_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_config_spec.rb deleted file mode 100644 index ff8cd1e8068..00000000000 --- a/spec/lib/gitlab/cycle_analytics/issue_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::IssueConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb new file mode 100644 index 00000000000..2d7e7b1e0a5 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::IssueEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/plan_config_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_config_spec.rb deleted file mode 100644 index 92698defa5d..00000000000 --- a/spec/lib/gitlab/cycle_analytics/plan_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::PlanConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb new file mode 100644 index 00000000000..3452c146584 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::PlanEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/production_config_spec.rb b/spec/lib/gitlab/cycle_analytics/production_config_spec.rb deleted file mode 100644 index 92485777334..00000000000 --- a/spec/lib/gitlab/cycle_analytics/production_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::ProductionConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb new file mode 100644 index 00000000000..069c84efa09 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::ProductionEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/review_config_spec.rb b/spec/lib/gitlab/cycle_analytics/review_config_spec.rb deleted file mode 100644 index 59cb18ac16d..00000000000 --- a/spec/lib/gitlab/cycle_analytics/review_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::ReviewConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/review_event_spec.rb b/spec/lib/gitlab/cycle_analytics/review_event_spec.rb new file mode 100644 index 00000000000..e9aca82ecc9 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/review_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::ReviewEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/shared_config_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_config_spec.rb deleted file mode 100644 index 060a59151d8..00000000000 --- a/spec/lib/gitlab/cycle_analytics/shared_config_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -shared_examples 'default query config' do - it 'has the start attributes' do - expect(described_class.start_time_attrs).not_to be_nil - end - - it 'has the end attributes' do - expect(described_class.end_time_attrs ).not_to be_nil - end - - it 'has the projection attributes' do - expect(described_class.projections).not_to be_nil - end -end diff --git a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb new file mode 100644 index 00000000000..b15af783dfb --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +shared_examples 'default query config' do + it 'has the start attributes' do + expect(described_class.start_time_attrs).not_to be_nil + end + + it 'has the end attributes' do + expect(described_class.end_time_attrs ).not_to be_nil + end + + it 'has the projection attributes' do + expect(described_class.projections).not_to be_nil + end + + it 'implements the fetch method' do + expect(described_class.fetch).not_to raise_error + end +end diff --git a/spec/lib/gitlab/cycle_analytics/staging_config_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_config_spec.rb deleted file mode 100644 index f13885d7f48..00000000000 --- a/spec/lib/gitlab/cycle_analytics/staging_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::StagingConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).not_to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb new file mode 100644 index 00000000000..9c1bec3edb1 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::StagingEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).not_to eq(described_class.start_time_attrs) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/test_config_spec.rb b/spec/lib/gitlab/cycle_analytics/test_config_spec.rb deleted file mode 100644 index 59421b99513..00000000000 --- a/spec/lib/gitlab/cycle_analytics/test_config_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec_helper' -require 'lib/gitlab/cycle_analytics/shared_config_spec' - -describe Gitlab::CycleAnalytics::TestConfig do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).not_to eq(described_class.start_time_attrs) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/test_event_spec.rb b/spec/lib/gitlab/cycle_analytics/test_event_spec.rb new file mode 100644 index 00000000000..7238b9a34b3 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/test_event_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' +require 'lib/gitlab/cycle_analytics/shared_event_spec' + +describe Gitlab::CycleAnalytics::TestEvent do + it_behaves_like 'default query config' + + it 'has the default order' do + expect(described_class.order).not_to eq(described_class.start_time_attrs) + end +end diff --git a/spec/serializers/analytics_generic_entity_spec.rb b/spec/serializers/analytics_generic_entity_spec.rb index 3bb15cb9475..68086216ba9 100644 --- a/spec/serializers/analytics_generic_entity_spec.rb +++ b/spec/serializers/analytics_generic_entity_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe AnalyticsGenericEntity do +describe AnalyticsIssueEntity do let(:user) { create(:user) } let(:entity_hash) do { -- cgit v1.2.1 From f0ed5fea81b537ae6c0262ed8f6249b47acafcdf Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Wed, 16 Nov 2016 18:20:05 +0000 Subject: adds fix for security issue when annonymous user does not have access to repository we now display the activity feed instead of the readme --- spec/helpers/preferences_helper_spec.rb | 36 ++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb index 02b464f7e07..77841e85223 100644 --- a/spec/helpers/preferences_helper_spec.rb +++ b/spec/helpers/preferences_helper_spec.rb @@ -86,21 +86,43 @@ describe PreferencesHelper do end end - describe 'default_project_view' do + describe '#default_project_view' do context 'user not signed in' do before do - @project = create(:project) + helper.instance_variable_set(:@project, project) stub_user end - it 'returns readme view if repository is not empty' do - expect(helper.default_project_view).to eq('readme') + context 'when repository is empty' do + let(:project) { create(:project_empty_repo, :public) } + + it 'returns activity if user has repository access' do + allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(true) + + expect(helper.default_project_view).to eq('activity') + end + + it 'returns activity if user does not have repository access' do + allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(false) + + expect(helper.default_project_view).to eq('activity') + end end - it 'returns activity if repository is empty' do - expect(@project).to receive(:empty_repo?).and_return(true) + context 'when repository is not empty' do + let(:project) { create(:project, :public) } + + it 'returns readme if user has repository access' do + allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(true) + + expect(helper.default_project_view).to eq('readme') + end + + it 'returns activity if user does not have repository access' do + allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(false) - expect(helper.default_project_view).to eq('empty') + expect(helper.default_project_view).to eq('activity') + end end end end -- cgit v1.2.1 From af80fcb477d13c240d8f58abab7d2b88a11ca7b5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 17 Nov 2016 14:14:23 +0100 Subject: fix specs --- spec/lib/gitlab/cycle_analytics/shared_event_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb index b15af783dfb..1e76edce633 100644 --- a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb @@ -5,15 +5,15 @@ shared_examples 'default query config' do expect(described_class.start_time_attrs).not_to be_nil end + it 'has the stage attribute' do + expect(described_class.stage).not_to be_nil + end + it 'has the end attributes' do - expect(described_class.end_time_attrs ).not_to be_nil + expect(described_class.end_time_attrs).not_to be_nil end it 'has the projection attributes' do expect(described_class.projections).not_to be_nil end - - it 'implements the fetch method' do - expect(described_class.fetch).not_to raise_error - end end -- cgit v1.2.1 From 54ee0df78a3e025ff2c1250d20e8518c9753ff34 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 17 Nov 2016 16:08:05 +0100 Subject: Do not use absolute URLS in entities use relative --- spec/serializers/build_entity_spec.rb | 10 +++++----- spec/serializers/commit_entity_spec.rb | 4 ++-- spec/serializers/deployment_entity_spec.rb | 2 +- spec/serializers/environment_entity_spec.rb | 2 +- spec/serializers/environment_serializer_spec.rb | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index 2734f5bedca..6dcfaec259e 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -10,9 +10,9 @@ describe BuildEntity do context 'when build is a regular job' do let(:build) { create(:ci_build) } - it 'contains url to build page and retry action' do - expect(subject).to include(:build_url, :retry_url) - expect(subject).not_to include(:play_url) + it 'contains paths to build page and retry action' do + expect(subject).to include(:build_path, :retry_path) + expect(subject).not_to include(:play_path) end it 'does not contain sensitive information' do @@ -24,8 +24,8 @@ describe BuildEntity do context 'when build is a manual action' do let(:build) { create(:ci_build, :manual) } - it 'contains url to play action' do - expect(subject).to include(:play_url) + it 'contains path to play action' do + expect(subject).to include(:play_path) end end end diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb index 628e35c9a28..a44a23ef619 100644 --- a/spec/serializers/commit_entity_spec.rb +++ b/spec/serializers/commit_entity_spec.rb @@ -31,8 +31,8 @@ describe CommitEntity do end end - it 'contains commit URL' do - expect(subject).to include(:commit_url) + it 'contains path to commit' do + expect(subject).to include(:commit_path) end it 'needs to receive project in the request' do diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb index 51b6de91571..ea87771e2a2 100644 --- a/spec/serializers/deployment_entity_spec.rb +++ b/spec/serializers/deployment_entity_spec.rb @@ -15,6 +15,6 @@ describe DeploymentEntity do it 'exposes nested information about branch' do expect(subject[:ref][:name]).to eq 'master' - expect(subject[:ref][:ref_url]).not_to be_empty + expect(subject[:ref][:ref_path]).not_to be_empty end end diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb index 4ca8c299147..57728ce3181 100644 --- a/spec/serializers/environment_entity_spec.rb +++ b/spec/serializers/environment_entity_spec.rb @@ -13,6 +13,6 @@ describe EnvironmentEntity do end it 'exposes core elements of environment' do - expect(subject).to include(:id, :name, :state, :environment_url) + expect(subject).to include(:id, :name, :state, :environment_path) end end diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index 37bc086826c..8f95c9250b0 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -33,7 +33,7 @@ describe EnvironmentSerializer do it 'contains important elements of environment' do expect(json) - .to include(:name, :external_url, :environment_url, :last_deployment) + .to include(:name, :external_url, :environment_path, :last_deployment) end it 'contains relevant information about last deployment' do -- cgit v1.2.1 From 9b0e7b9041bf52a5e81c658a149efca77c8a2d10 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 17 Nov 2016 16:15:10 +0100 Subject: Fix test case for environments related to deployments --- spec/features/environments_spec.rb | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/environments_spec.rb b/spec/features/environments_spec.rb index aef38f9f407..9c15a815d0d 100644 --- a/spec/features/environments_spec.rb +++ b/spec/features/environments_spec.rb @@ -74,24 +74,31 @@ feature 'Environments', feature: true, js: true do context 'with build and manual actions' do given(:pipeline) { create(:ci_pipeline, project: project) } given(:build) { create(:ci_build, pipeline: pipeline) } - given(:deployment) { create(:deployment, environment: environment, deployable: build) } - given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } + + given(:manual) do + create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') + end + + given(:deployment) do + create(:deployment, environment: environment, + deployable: build, + sha: project.commit.id) + end scenario 'does show a play button' do find('.dropdown-play-icon-container').click expect(page).to have_content(manual.name.humanize) end - scenario 'does allow to play manual action' do + scenario 'does allow to play manual action', js: true do expect(manual).to be_skipped find('.dropdown-play-icon-container').click - play_action = find('span', text: manual.name.humanize) - expect(page).to have_content(manual.name.humanize) - expect { play_action.click }.not_to change { Ci::Pipeline.count } - # TODO, fix me! + expect { click_link(manual.name.humanize) } + .not_to change { Ci::Pipeline.count } + expect(manual.reload).to be_pending end -- cgit v1.2.1 From d5b673da79c7c350090dc9982a9a2477fac56eb5 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Thu, 17 Nov 2016 18:00:37 +0100 Subject: more refactoring and added some auth checks --- spec/lib/gitlab/cycle_analytics/events_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb index 8e2d2f8b5bd..9aeaa6b3ee8 100644 --- a/spec/lib/gitlab/cycle_analytics/events_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::CycleAnalytics::Events do let(:user) { create(:user, :admin) } let!(:context) { create(:issue, project: project, created_at: 2.days.ago) } - subject { described_class.new(project: project, options: { from: from_date }) } + subject { described_class.new(project: project, options: { from: from_date, current_user: user }) } before do allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([context]) -- cgit v1.2.1 From 4fcae04f7bb4823d740a18419f21b8d154b4ef89 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 31 Oct 2016 15:40:27 -0200 Subject: Add project_id to subscriptions --- spec/models/subscription_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 spec/models/subscription_spec.rb (limited to 'spec') diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb new file mode 100644 index 00000000000..6cd6e01d0c7 --- /dev/null +++ b/spec/models/subscription_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Subscription, models: true do + describe 'relationships' do + it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:subscribable) } + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:subscribable) } + it { is_expected.to validate_presence_of(:user) } + end +end -- cgit v1.2.1 From bde0202693508aa9eb3ce76876b1c64120d51ef3 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 31 Oct 2016 16:36:28 -0200 Subject: Add unique index to subscriptions on subscribable and user and project --- spec/factories/subscriptions.rb | 7 +++++++ spec/models/subscription_spec.rb | 6 ++++++ 2 files changed, 13 insertions(+) create mode 100644 spec/factories/subscriptions.rb (limited to 'spec') diff --git a/spec/factories/subscriptions.rb b/spec/factories/subscriptions.rb new file mode 100644 index 00000000000..b11b0a0a17b --- /dev/null +++ b/spec/factories/subscriptions.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :subscription do + user + project factory: :empty_project + subscribable factory: :issue + end +end diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb index 6cd6e01d0c7..ab674958387 100644 --- a/spec/models/subscription_spec.rb +++ b/spec/models/subscription_spec.rb @@ -11,5 +11,11 @@ describe Subscription, models: true do it { is_expected.to validate_presence_of(:project) } it { is_expected.to validate_presence_of(:subscribable) } it { is_expected.to validate_presence_of(:user) } + + it 'validates uniqueness of project_id scoped to subscribable_id, subscribable_type, and user_id' do + create(:subscription) + + expect(subject).to validate_uniqueness_of(:project_id).scoped_to([:subscribable_id, :subscribable_type, :user_id]) + end end end -- cgit v1.2.1 From 9a2157a64684a32ba815cd33b0f48cd7ad3945a5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 31 Oct 2016 17:19:14 -0200 Subject: Refactoring Subscribable concern to accept a project --- spec/models/concerns/subscribable_spec.rb | 44 ++++++++++++++++--------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'spec') diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb index b7fc5a92497..0a96cbbe166 100644 --- a/spec/models/concerns/subscribable_spec.rb +++ b/spec/models/concerns/subscribable_spec.rb @@ -1,67 +1,69 @@ require 'spec_helper' describe Subscribable, 'Subscribable' do - let(:resource) { create(:issue) } - let(:user) { create(:user) } + let(:project) { create(:empty_project) } + let(:resource) { create(:issue, project: project) } + let(:user) { create(:user) } describe '#subscribed?' do it 'returns false when no subcription exists' do - expect(resource.subscribed?(user)).to be_falsey + expect(resource.subscribed?(user, project)).to be_falsey end it 'returns true when a subcription exists and subscribed is true' do - resource.subscriptions.create(user: user, subscribed: true) + resource.subscriptions.create(user: user, project: project, subscribed: true) - expect(resource.subscribed?(user)).to be_truthy + expect(resource.subscribed?(user, project)).to be_truthy end it 'returns false when a subcription exists and subscribed is false' do - resource.subscriptions.create(user: user, subscribed: false) + resource.subscriptions.create(user: user, project: project, subscribed: false) - expect(resource.subscribed?(user)).to be_falsey + expect(resource.subscribed?(user, project)).to be_falsey end end + describe '#subscribers' do it 'returns [] when no subcribers exists' do - expect(resource.subscribers).to be_empty + expect(resource.subscribers(project)).to be_empty end it 'returns the subscribed users' do - resource.subscriptions.create(user: user, subscribed: true) - resource.subscriptions.create(user: create(:user), subscribed: false) + resource.subscriptions.create(user: user, project: project, subscribed: true) + resource.subscriptions.create(user: create(:user), project: project, subscribed: false) - expect(resource.subscribers).to eq [user] + expect(resource.subscribers(project)).to eq [user] end end describe '#toggle_subscription' do it 'toggles the current subscription state for the given user' do - expect(resource.subscribed?(user)).to be_falsey + expect(resource.subscribed?(user, project)).to be_falsey - resource.toggle_subscription(user) + resource.toggle_subscription(user, project) - expect(resource.subscribed?(user)).to be_truthy + expect(resource.subscribed?(user, project)).to be_truthy end end describe '#subscribe' do it 'subscribes the given user' do - expect(resource.subscribed?(user)).to be_falsey + expect(resource.subscribed?(user, project)).to be_falsey - resource.subscribe(user) + resource.subscribe(user, project) - expect(resource.subscribed?(user)).to be_truthy + expect(resource.subscribed?(user, project)).to be_truthy end end describe '#unsubscribe' do it 'unsubscribes the given current user' do - resource.subscriptions.create(user: user, subscribed: true) - expect(resource.subscribed?(user)).to be_truthy + resource.subscriptions.create(user: user, project: project, subscribed: true) + expect(resource.subscribed?(user, project)).to be_truthy - resource.unsubscribe(user) + resource.unsubscribe(user, project) - expect(resource.subscribed?(user)).to be_falsey + expect(resource.subscribed?(user, project)).to be_falsey end end end -- cgit v1.2.1 From 38f16582725709ee89c7eeadd4415ed3e2fa57dc Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 1 Nov 2016 00:02:27 -0200 Subject: Refactoring notification service to find subscriptions per project --- spec/services/notification_service_spec.rb | 116 ++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 37 deletions(-) (limited to 'spec') diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 8ce35354c22..3a5bd4a4084 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -342,7 +342,9 @@ describe NotificationService, services: true do end describe 'Issues' do - let(:project) { create(:empty_project, :public) } + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let(:another_project) { create(:empty_project, :public, namespace: group) } let(:issue) { create :issue, project: project, assignee: create(:user), description: 'cc @participant' } before do @@ -377,13 +379,21 @@ describe NotificationService, services: true do end it "emails subscribers of the issue's labels" do - subscriber = create(:user) - label = create(:label, issues: [issue]) + user_1 = create(:user) + user_2 = create(:user) + user_3 = create(:user) + label = create(:label, project: project, issues: [issue]) + group_label = create(:group_label, group: group, issues: [issue]) issue.reload - label.toggle_subscription(subscriber) + label.toggle_subscription(user_1) + group_label.toggle_subscription(user_2, project) + group_label.toggle_subscription(user_3, another_project) + notification.new_issue(issue, @u_disabled) - should_email(subscriber) + should_email(user_1) + should_email(user_2) + should_not_email(user_3) end context 'confidential issues' do @@ -399,7 +409,7 @@ describe NotificationService, services: true do project.team << [member, :developer] project.team << [guest, :guest] - label = create(:label, issues: [confidential_issue]) + label = create(:label, project: project, issues: [confidential_issue]) confidential_issue.reload label.toggle_subscription(non_member) label.toggle_subscription(author) @@ -554,20 +564,28 @@ describe NotificationService, services: true do end describe '#relabeled_issue' do - let(:label) { create(:label, issues: [issue]) } - let(:label2) { create(:label) } - let!(:subscriber_to_label) { create(:user).tap { |u| label.toggle_subscription(u) } } - let!(:subscriber_to_label2) { create(:user).tap { |u| label2.toggle_subscription(u) } } + let(:group_label_1) { create(:group_label, group: group, title: 'Group Label 1', issues: [issue]) } + let(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') } + let(:label_1) { create(:label, project: project, title: 'Label 1', issues: [issue]) } + let(:label_2) { create(:label, project: project, title: 'Label 2') } + let!(:subscriber_to_group_label_1) { create(:user).tap { |u| group_label_1.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2) { create(:user).tap { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2_on_another_project) { create(:user).tap { |u| group_label_2.toggle_subscription(u, another_project) } } + let!(:subscriber_to_label_1) { create(:user).tap { |u| label_1.toggle_subscription(u) } } + let!(:subscriber_to_label_2) { create(:user).tap { |u| label_2.toggle_subscription(u) } } it "emails subscribers of the issue's added labels only" do - notification.relabeled_issue(issue, [label2], @u_disabled) + notification.relabeled_issue(issue, [group_label_2, label_2], @u_disabled) - should_not_email(subscriber_to_label) - should_email(subscriber_to_label2) + should_not_email(subscriber_to_label_1) + should_not_email(subscriber_to_group_label_1) + should_not_email(subscriber_to_group_label_2_on_another_project) + should_email(subscriber_to_group_label_2) + should_email(subscriber_to_label_2) end it "doesn't send email to anyone but subscribers of the given labels" do - notification.relabeled_issue(issue, [label2], @u_disabled) + notification.relabeled_issue(issue, [group_label_2, label_2], @u_disabled) should_not_email(issue.assignee) should_not_email(issue.author) @@ -578,8 +596,11 @@ describe NotificationService, services: true do should_not_email(@watcher_and_subscriber) should_not_email(@unsubscriber) should_not_email(@u_participating) - should_not_email(subscriber_to_label) - should_email(subscriber_to_label2) + should_not_email(subscriber_to_label_1) + should_not_email(subscriber_to_group_label_1) + should_not_email(subscriber_to_group_label_2_on_another_project) + should_email(subscriber_to_group_label_2) + should_email(subscriber_to_label_2) end context 'confidential issues' do @@ -590,8 +611,8 @@ describe NotificationService, services: true do let(:guest) { create(:user) } let(:admin) { create(:admin) } let(:confidential_issue) { create(:issue, :confidential, project: project, title: 'Confidential issue', author: author, assignee: assignee) } - let!(:label_1) { create(:label, issues: [confidential_issue]) } - let!(:label_2) { create(:label) } + let!(:label_1) { create(:label, project: project, issues: [confidential_issue]) } + let!(:label_2) { create(:label, project: project) } it "emails subscribers of the issue's labels that can read the issue" do project.team << [member, :developer] @@ -725,7 +746,9 @@ describe NotificationService, services: true do end describe 'Merge Requests' do - let(:project) { create(:project, :public) } + let(:group) { create(:group) } + let(:project) { create(:project, :public, namespace: group) } + let(:another_project) { create(:empty_project, :public, namespace: group) } let(:merge_request) { create :merge_request, source_project: project, assignee: create(:user), description: 'cc @participant' } before do @@ -758,12 +781,20 @@ describe NotificationService, services: true do end it "emails subscribers of the merge request's labels" do - subscriber = create(:user) - label = create(:label, merge_requests: [merge_request]) - label.toggle_subscription(subscriber) + user_1 = create(:user) + user_2 = create(:user) + user_3 = create(:user) + label = create(:label, project: project, merge_requests: [merge_request]) + group_label = create(:group_label, group: group, merge_requests: [merge_request]) + label.toggle_subscription(user_1) + group_label.toggle_subscription(user_2, project) + group_label.toggle_subscription(user_3, another_project) + notification.new_merge_request(merge_request, @u_disabled) - should_email(subscriber) + should_email(user_1) + should_email(user_2) + should_not_email(user_3) end context 'participating' do @@ -857,20 +888,28 @@ describe NotificationService, services: true do end describe '#relabel_merge_request' do - let(:label) { create(:label, merge_requests: [merge_request]) } - let(:label2) { create(:label) } - let!(:subscriber_to_label) { create(:user).tap { |u| label.toggle_subscription(u) } } - let!(:subscriber_to_label2) { create(:user).tap { |u| label2.toggle_subscription(u) } } + let(:group_label_1) { create(:group_label, group: group, title: 'Group Label 1', merge_requests: [merge_request]) } + let(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') } + let(:label_1) { create(:label, project: project, title: 'Label 1', merge_requests: [merge_request]) } + let(:label_2) { create(:label, project: project, title: 'Label 2') } + let!(:subscriber_to_group_label_1) { create(:user).tap { |u| group_label_1.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2) { create(:user).tap { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2_on_another_project) { create(:user).tap { |u| group_label_2.toggle_subscription(u, another_project) } } + let!(:subscriber_to_label_1) { create(:user).tap { |u| label_1.toggle_subscription(u) } } + let!(:subscriber_to_label_2) { create(:user).tap { |u| label_2.toggle_subscription(u) } } it "emails subscribers of the merge request's added labels only" do - notification.relabeled_merge_request(merge_request, [label2], @u_disabled) + notification.relabeled_merge_request(merge_request, [group_label_2, label_2], @u_disabled) - should_not_email(subscriber_to_label) - should_email(subscriber_to_label2) + should_not_email(subscriber_to_label_1) + should_not_email(subscriber_to_group_label_1) + should_not_email(subscriber_to_group_label_2_on_another_project) + should_email(subscriber_to_group_label_2) + should_email(subscriber_to_label_2) end it "doesn't send email to anyone but subscribers of the given labels" do - notification.relabeled_merge_request(merge_request, [label2], @u_disabled) + notification.relabeled_merge_request(merge_request, [group_label_2, label_2], @u_disabled) should_not_email(merge_request.assignee) should_not_email(merge_request.author) @@ -881,8 +920,11 @@ describe NotificationService, services: true do should_not_email(@unsubscriber) should_not_email(@u_participating) should_not_email(@u_lazy_participant) - should_not_email(subscriber_to_label) - should_email(subscriber_to_label2) + should_not_email(subscriber_to_label_1) + should_not_email(subscriber_to_group_label_1) + should_not_email(subscriber_to_group_label_2_on_another_project) + should_email(subscriber_to_group_label_2) + should_email(subscriber_to_label_2) end end @@ -1290,10 +1332,10 @@ describe NotificationService, services: true do project.team << [@unsubscriber, :master] project.team << [@watcher_and_subscriber, :master] - issuable.subscriptions.create(user: @subscriber, subscribed: true) - issuable.subscriptions.create(user: @subscribed_participant, subscribed: true) - issuable.subscriptions.create(user: @unsubscriber, subscribed: false) + issuable.subscriptions.create(user: @subscriber, project: project, subscribed: true) + issuable.subscriptions.create(user: @subscribed_participant, project: project, subscribed: true) + issuable.subscriptions.create(user: @unsubscriber, project: project, subscribed: false) # Make the watcher a subscriber to detect dupes - issuable.subscriptions.create(user: @watcher_and_subscriber, subscribed: true) + issuable.subscriptions.create(user: @watcher_and_subscriber, project: project, subscribed: true) end end -- cgit v1.2.1 From 091efb315296306fd8c8d7c109ad6df77e7f28d5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 1 Nov 2016 00:14:53 -0200 Subject: Fix specs to pass a project when creating subscriptions --- spec/controllers/sent_notifications_controller_spec.rb | 4 ++-- spec/models/concerns/issuable_spec.rb | 10 ++++++---- spec/services/issuable/bulk_update_service_spec.rb | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb index 191e290a118..5ddfe84440e 100644 --- a/spec/controllers/sent_notifications_controller_spec.rb +++ b/spec/controllers/sent_notifications_controller_spec.rb @@ -7,7 +7,7 @@ describe SentNotificationsController, type: :controller do let(:issue) do create(:issue, project: project, author: user) do |issue| - issue.subscriptions.create(user: user, subscribed: true) + issue.subscriptions.create(user: user, project: project, subscribed: true) end end @@ -85,7 +85,7 @@ describe SentNotificationsController, type: :controller do context 'when the force param is not passed' do let(:merge_request) do create(:merge_request, source_project: project, author: user) do |merge_request| - merge_request.subscriptions.create(user: user, subscribed: true) + merge_request.subscriptions.create(user: user, project: project, subscribed: true) end end let(:sent_notification) { create(:sent_notification, noteable: merge_request, recipient: user) } diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 6e987967ca5..e8fead767f2 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -176,6 +176,8 @@ describe Issue, "Issuable" do end describe '#subscribed?' do + let(:project) { issue.project } + context 'user is not a participant in the issue' do before { allow(issue).to receive(:participants).with(user).and_return([]) } @@ -184,13 +186,13 @@ describe Issue, "Issuable" do end it 'returns true when a subcription exists and subscribed is true' do - issue.subscriptions.create(user: user, subscribed: true) + issue.subscriptions.create(user: user, project: project, subscribed: true) expect(issue.subscribed?(user)).to be_truthy end it 'returns false when a subcription exists and subscribed is false' do - issue.subscriptions.create(user: user, subscribed: false) + issue.subscriptions.create(user: user, project: project, subscribed: false) expect(issue.subscribed?(user)).to be_falsey end @@ -204,13 +206,13 @@ describe Issue, "Issuable" do end it 'returns true when a subcription exists and subscribed is true' do - issue.subscriptions.create(user: user, subscribed: true) + issue.subscriptions.create(user: user, project: project, subscribed: true) expect(issue.subscribed?(user)).to be_truthy end it 'returns false when a subcription exists and subscribed is false' do - issue.subscriptions.create(user: user, subscribed: false) + issue.subscriptions.create(user: user, project: project, subscribed: false) expect(issue.subscribed?(user)).to be_falsey end diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb index 6f7ce8ca992..f4a53f7e4c6 100644 --- a/spec/services/issuable/bulk_update_service_spec.rb +++ b/spec/services/issuable/bulk_update_service_spec.rb @@ -267,7 +267,7 @@ describe Issuable::BulkUpdateService, services: true do describe 'unsubscribe from issues' do let(:issues) do create_list(:closed_issue, 2, project: project) do |issue| - issue.subscriptions.create(user: user, subscribed: true) + issue.subscriptions.create(user: user, project: project, subscribed: true) end end -- cgit v1.2.1 From 4a29fde577a7d5d7c46ffff7c5feb79be23cdaa8 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 1 Nov 2016 15:02:58 -0200 Subject: Allow users to subscribe to group labels at project-level --- .../controllers/projects/labels_controller_spec.rb | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 8faecec0063..2b51bae926b 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -72,14 +72,8 @@ describe Projects::LabelsController do end describe 'POST #generate' do - let(:admin) { create(:admin) } - - before do - sign_in(admin) - end - context 'personal project' do - let(:personal_project) { create(:empty_project) } + let(:personal_project) { create(:empty_project, namespace: user.namespace) } it 'creates labels' do post :generate, namespace_id: personal_project.namespace.to_param, project_id: personal_project.to_param @@ -96,4 +90,22 @@ describe Projects::LabelsController do end end end + + describe 'POST #toggle_subscription' do + it 'allows user to toggle subscription on project labels' do + label = create(:label, project: project) + + post :toggle_subscription, namespace_id: project.namespace.to_param, project_id: project.to_param, id: label.id + + expect(response).to have_http_status(200) + end + + it 'allows user to toggle subscription on group labels' do + group_label = create(:group_label, group: group) + + post :toggle_subscription, namespace_id: project.namespace.to_param, project_id: project.to_param, id: group_label.id + + expect(response).to have_http_status(200) + end + end end -- cgit v1.2.1 From 0c052f116c9e093936847280e833ca8985d2d94c Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 4 Nov 2016 16:19:08 -0200 Subject: Remove default value for `project` argument on subscribable concern --- .../projects/boards/issues_controller_spec.rb | 2 +- .../sent_notifications_controller_spec.rb | 14 +++---- spec/features/unsubscribe_links_spec.rb | 14 +++---- spec/models/concerns/issuable_spec.rb | 12 +++--- spec/requests/api/issues_spec.rb | 4 +- spec/requests/api/labels_spec.rb | 6 +-- spec/services/issuable/bulk_update_service_spec.rb | 4 +- spec/services/issues/update_service_spec.rb | 2 +- .../services/merge_requests/update_service_spec.rb | 2 +- spec/services/notification_service_spec.rb | 48 +++++++++++----------- .../slash_commands/interpret_service_spec.rb | 4 +- .../issuable_slash_commands_shared_examples.rb | 10 ++--- 12 files changed, 61 insertions(+), 61 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb index cbe0417a4a7..299d2c981d3 100644 --- a/spec/controllers/projects/boards/issues_controller_spec.rb +++ b/spec/controllers/projects/boards/issues_controller_spec.rb @@ -25,7 +25,7 @@ describe Projects::Boards::IssuesController do create(:labeled_issue, project: project, labels: [planning]) create(:labeled_issue, project: project, labels: [development], due_date: Date.tomorrow) create(:labeled_issue, project: project, labels: [development], assignee: johndoe) - issue.subscribe(johndoe) + issue.subscribe(johndoe, project) list_issues user: user, board: board, list: list2 diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb index 5ddfe84440e..954fc2eaf21 100644 --- a/spec/controllers/sent_notifications_controller_spec.rb +++ b/spec/controllers/sent_notifications_controller_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe SentNotificationsController, type: :controller do let(:user) { create(:user) } let(:project) { create(:empty_project) } - let(:sent_notification) { create(:sent_notification, noteable: issue, recipient: user) } + let(:sent_notification) { create(:sent_notification, project: project, noteable: issue, recipient: user) } let(:issue) do create(:issue, project: project, author: user) do |issue| @@ -17,7 +17,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key, force: true) } it 'unsubscribes the user' do - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end it 'sets the flash message' do @@ -33,7 +33,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key) } it 'does not unsubscribe the user' do - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'does not set the flash message' do @@ -53,7 +53,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key.reverse) } it 'does not unsubscribe the user' do - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'does not set the flash message' do @@ -69,7 +69,7 @@ describe SentNotificationsController, type: :controller do before { get(:unsubscribe, id: sent_notification.reply_key, force: true) } it 'unsubscribes the user' do - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end it 'sets the flash message' do @@ -88,11 +88,11 @@ describe SentNotificationsController, type: :controller do merge_request.subscriptions.create(user: user, project: project, subscribed: true) end end - let(:sent_notification) { create(:sent_notification, noteable: merge_request, recipient: user) } + let(:sent_notification) { create(:sent_notification, project: project, noteable: merge_request, recipient: user) } before { get(:unsubscribe, id: sent_notification.reply_key) } it 'unsubscribes the user' do - expect(merge_request.subscribed?(user)).to be_falsey + expect(merge_request.subscribed?(user, project)).to be_falsey end it 'sets the flash message' do diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb index 33b52d1547e..e2d9cfdd0b0 100644 --- a/spec/features/unsubscribe_links_spec.rb +++ b/spec/features/unsubscribe_links_spec.rb @@ -26,11 +26,11 @@ describe 'Unsubscribe links', feature: true do expect(current_path).to eq unsubscribe_sent_notification_path(SentNotification.last) expect(page).to have_text(%(Unsubscribe from issue #{issue.title} (#{issue.to_reference}))) expect(page).to have_text(%(Are you sure you want to unsubscribe from issue #{issue.title} (#{issue.to_reference})?)) - expect(issue.subscribed?(recipient)).to be_truthy + expect(issue.subscribed?(recipient, project)).to be_truthy click_link 'Unsubscribe' - expect(issue.subscribed?(recipient)).to be_falsey + expect(issue.subscribed?(recipient, project)).to be_falsey expect(current_path).to eq new_user_session_path end @@ -38,11 +38,11 @@ describe 'Unsubscribe links', feature: true do visit body_link expect(current_path).to eq unsubscribe_sent_notification_path(SentNotification.last) - expect(issue.subscribed?(recipient)).to be_truthy + expect(issue.subscribed?(recipient, project)).to be_truthy click_link 'Cancel' - expect(issue.subscribed?(recipient)).to be_truthy + expect(issue.subscribed?(recipient, project)).to be_truthy expect(current_path).to eq new_user_session_path end end @@ -51,7 +51,7 @@ describe 'Unsubscribe links', feature: true do visit header_link expect(page).to have_text('unsubscribed') - expect(issue.subscribed?(recipient)).to be_falsey + expect(issue.subscribed?(recipient, project)).to be_falsey end end @@ -62,14 +62,14 @@ describe 'Unsubscribe links', feature: true do visit body_link expect(page).to have_text('unsubscribed') - expect(issue.subscribed?(recipient)).to be_falsey + expect(issue.subscribed?(recipient, project)).to be_falsey end it 'unsubscribes from the issue when visiting the link from the header' do visit header_link expect(page).to have_text('unsubscribed') - expect(issue.subscribed?(recipient)).to be_falsey + expect(issue.subscribed?(recipient, project)).to be_falsey end end end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index e8fead767f2..6f84bffe046 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -182,19 +182,19 @@ describe Issue, "Issuable" do before { allow(issue).to receive(:participants).with(user).and_return([]) } it 'returns false when no subcription exists' do - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end it 'returns true when a subcription exists and subscribed is true' do issue.subscriptions.create(user: user, project: project, subscribed: true) - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'returns false when a subcription exists and subscribed is false' do issue.subscriptions.create(user: user, project: project, subscribed: false) - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end end @@ -202,19 +202,19 @@ describe Issue, "Issuable" do before { allow(issue).to receive(:participants).with(user).and_return([user]) } it 'returns false when no subcription exists' do - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'returns true when a subcription exists and subscribed is true' do issue.subscriptions.create(user: user, project: project, subscribed: true) - expect(issue.subscribed?(user)).to be_truthy + expect(issue.subscribed?(user, project)).to be_truthy end it 'returns false when a subcription exists and subscribed is false' do issue.subscriptions.create(user: user, project: project, subscribed: false) - expect(issue.subscribed?(user)).to be_falsey + expect(issue.subscribed?(user, project)).to be_falsey end end end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index beed53d1e5c..7bae055b241 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -637,7 +637,7 @@ describe API::API, api: true do it "sends notifications for subscribers of newly added labels" do label = project.labels.first - label.toggle_subscription(user2) + label.toggle_subscription(user2, project) perform_enqueued_jobs do post api("/projects/#{project.id}/issues", user), @@ -828,7 +828,7 @@ describe API::API, api: true do it "sends notifications for subscribers of newly added labels when issue is updated" do label = create(:label, title: 'foo', color: '#FFAABB', project: project) - label.toggle_subscription(user2) + label.toggle_subscription(user2, project) perform_enqueued_jobs do put api("/projects/#{project.id}/issues/#{issue.id}", user), diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index 77dfebf1a98..aaf41639277 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -339,7 +339,7 @@ describe API::API, api: true do end context "when user is already subscribed to label" do - before { label1.subscribe(user) } + before { label1.subscribe(user, project) } it "returns 304" do post api("/projects/#{project.id}/labels/#{label1.id}/subscription", user) @@ -358,7 +358,7 @@ describe API::API, api: true do end describe "DELETE /projects/:id/labels/:label_id/subscription" do - before { label1.subscribe(user) } + before { label1.subscribe(user, project) } context "when label_id is a label title" do it "unsubscribes from the label" do @@ -381,7 +381,7 @@ describe API::API, api: true do end context "when user is already unsubscribed from label" do - before { label1.unsubscribe(user) } + before { label1.unsubscribe(user, project) } it "returns 304" do delete api("/projects/#{project.id}/labels/#{label1.id}/subscription", user) diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb index f4a53f7e4c6..5f3020b6525 100644 --- a/spec/services/issuable/bulk_update_service_spec.rb +++ b/spec/services/issuable/bulk_update_service_spec.rb @@ -260,7 +260,7 @@ describe Issuable::BulkUpdateService, services: true do it 'subscribes the given user' do bulk_update(issues, subscription_event: 'subscribe') - expect(issues).to all(be_subscribed(user)) + expect(issues).to all(be_subscribed(user, project)) end end @@ -275,7 +275,7 @@ describe Issuable::BulkUpdateService, services: true do bulk_update(issues, subscription_event: 'unsubscribe') issues.each do |issue| - expect(issue).not_to be_subscribed(user) + expect(issue).not_to be_subscribed(user, project) end end end diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 1638a46ed51..4777a90639e 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -215,7 +215,7 @@ describe Issues::UpdateService, services: true do let!(:subscriber) do create(:user).tap do |u| - label.toggle_subscription(u) + label.toggle_subscription(u, project) project.team << [u, :developer] end end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 2433a7dad06..cb5d7cdb467 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -199,7 +199,7 @@ describe MergeRequests::UpdateService, services: true do context 'when the issue is relabeled' do let!(:non_subscriber) { create(:user) } - let!(:subscriber) { create(:user).tap { |u| label.toggle_subscription(u) } } + let!(:subscriber) { create(:user) { |u| label.toggle_subscription(u, project) } } before do project.team << [non_subscriber, :developer] diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 3a5bd4a4084..64e378d8328 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -385,7 +385,7 @@ describe NotificationService, services: true do label = create(:label, project: project, issues: [issue]) group_label = create(:group_label, group: group, issues: [issue]) issue.reload - label.toggle_subscription(user_1) + label.toggle_subscription(user_1, project) group_label.toggle_subscription(user_2, project) group_label.toggle_subscription(user_3, another_project) @@ -411,12 +411,12 @@ describe NotificationService, services: true do label = create(:label, project: project, issues: [confidential_issue]) confidential_issue.reload - label.toggle_subscription(non_member) - label.toggle_subscription(author) - label.toggle_subscription(assignee) - label.toggle_subscription(member) - label.toggle_subscription(guest) - label.toggle_subscription(admin) + label.toggle_subscription(non_member, project) + label.toggle_subscription(author, project) + label.toggle_subscription(assignee, project) + label.toggle_subscription(member, project) + label.toggle_subscription(guest, project) + label.toggle_subscription(admin, project) reset_delivered_emails! @@ -568,11 +568,11 @@ describe NotificationService, services: true do let(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') } let(:label_1) { create(:label, project: project, title: 'Label 1', issues: [issue]) } let(:label_2) { create(:label, project: project, title: 'Label 2') } - let!(:subscriber_to_group_label_1) { create(:user).tap { |u| group_label_1.toggle_subscription(u, project) } } - let!(:subscriber_to_group_label_2) { create(:user).tap { |u| group_label_2.toggle_subscription(u, project) } } - let!(:subscriber_to_group_label_2_on_another_project) { create(:user).tap { |u| group_label_2.toggle_subscription(u, another_project) } } - let!(:subscriber_to_label_1) { create(:user).tap { |u| label_1.toggle_subscription(u) } } - let!(:subscriber_to_label_2) { create(:user).tap { |u| label_2.toggle_subscription(u) } } + let!(:subscriber_to_group_label_1) { create(:user) { |u| group_label_1.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2_on_another_project) { create(:user) { |u| group_label_2.toggle_subscription(u, another_project) } } + let!(:subscriber_to_label_1) { create(:user) { |u| label_1.toggle_subscription(u, project) } } + let!(:subscriber_to_label_2) { create(:user) { |u| label_2.toggle_subscription(u, project) } } it "emails subscribers of the issue's added labels only" do notification.relabeled_issue(issue, [group_label_2, label_2], @u_disabled) @@ -618,12 +618,12 @@ describe NotificationService, services: true do project.team << [member, :developer] project.team << [guest, :guest] - label_2.toggle_subscription(non_member) - label_2.toggle_subscription(author) - label_2.toggle_subscription(assignee) - label_2.toggle_subscription(member) - label_2.toggle_subscription(guest) - label_2.toggle_subscription(admin) + label_2.toggle_subscription(non_member, project) + label_2.toggle_subscription(author, project) + label_2.toggle_subscription(assignee, project) + label_2.toggle_subscription(member, project) + label_2.toggle_subscription(guest, project) + label_2.toggle_subscription(admin, project) reset_delivered_emails! @@ -786,7 +786,7 @@ describe NotificationService, services: true do user_3 = create(:user) label = create(:label, project: project, merge_requests: [merge_request]) group_label = create(:group_label, group: group, merge_requests: [merge_request]) - label.toggle_subscription(user_1) + label.toggle_subscription(user_1, project) group_label.toggle_subscription(user_2, project) group_label.toggle_subscription(user_3, another_project) @@ -892,11 +892,11 @@ describe NotificationService, services: true do let(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') } let(:label_1) { create(:label, project: project, title: 'Label 1', merge_requests: [merge_request]) } let(:label_2) { create(:label, project: project, title: 'Label 2') } - let!(:subscriber_to_group_label_1) { create(:user).tap { |u| group_label_1.toggle_subscription(u, project) } } - let!(:subscriber_to_group_label_2) { create(:user).tap { |u| group_label_2.toggle_subscription(u, project) } } - let!(:subscriber_to_group_label_2_on_another_project) { create(:user).tap { |u| group_label_2.toggle_subscription(u, another_project) } } - let!(:subscriber_to_label_1) { create(:user).tap { |u| label_1.toggle_subscription(u) } } - let!(:subscriber_to_label_2) { create(:user).tap { |u| label_2.toggle_subscription(u) } } + let!(:subscriber_to_group_label_1) { create(:user) { |u| group_label_1.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_to_group_label_2_on_another_project) { create(:user) { |u| group_label_2.toggle_subscription(u, another_project) } } + let!(:subscriber_to_label_1) { create(:user) { |u| label_1.toggle_subscription(u, project) } } + let!(:subscriber_to_label_2) { create(:user) { |u| label_2.toggle_subscription(u, project) } } it "emails subscribers of the merge request's added labels only" do notification.relabeled_merge_request(merge_request, [group_label_2, label_2], @u_disabled) diff --git a/spec/services/slash_commands/interpret_service_spec.rb b/spec/services/slash_commands/interpret_service_spec.rb index b57e338b782..becf627a4f5 100644 --- a/spec/services/slash_commands/interpret_service_spec.rb +++ b/spec/services/slash_commands/interpret_service_spec.rb @@ -169,7 +169,7 @@ describe SlashCommands::InterpretService, services: true do shared_examples 'unsubscribe command' do it 'populates subscription_event: "unsubscribe" if content contains /unsubscribe' do - issuable.subscribe(developer) + issuable.subscribe(developer, project) _, updates = service.execute(content, issuable) expect(updates).to eq(subscription_event: 'unsubscribe') @@ -321,7 +321,7 @@ describe SlashCommands::InterpretService, services: true do it_behaves_like 'multiple label with same argument' do let(:content) { %(/label ~"#{inprogress.title}" \n/label ~#{inprogress.title}) } let(:issuable) { issue } - end + end it_behaves_like 'unlabel command' do let(:content) { %(/unlabel ~"#{inprogress.title}") } diff --git a/spec/support/features/issuable_slash_commands_shared_examples.rb b/spec/support/features/issuable_slash_commands_shared_examples.rb index 5e3b8f2b23e..194620d0a68 100644 --- a/spec/support/features/issuable_slash_commands_shared_examples.rb +++ b/spec/support/features/issuable_slash_commands_shared_examples.rb @@ -230,31 +230,31 @@ shared_examples 'issuable record that supports slash commands in its description context "with a note subscribing to the #{issuable_type}" do it "creates a new todo for the #{issuable_type}" do - expect(issuable.subscribed?(master)).to be_falsy + expect(issuable.subscribed?(master, project)).to be_falsy write_note("/subscribe") expect(page).not_to have_content '/subscribe' expect(page).to have_content 'Your commands have been executed!' - expect(issuable.subscribed?(master)).to be_truthy + expect(issuable.subscribed?(master, project)).to be_truthy end end context "with a note unsubscribing to the #{issuable_type} as done" do before do - issuable.subscribe(master) + issuable.subscribe(master, project) end it "creates a new todo for the #{issuable_type}" do - expect(issuable.subscribed?(master)).to be_truthy + expect(issuable.subscribed?(master, project)).to be_truthy write_note("/unsubscribe") expect(page).not_to have_content '/unsubscribe' expect(page).to have_content 'Your commands have been executed!' - expect(issuable.subscribed?(master)).to be_falsy + expect(issuable.subscribed?(master, project)).to be_falsy end end end -- cgit v1.2.1 From 9dfbe1d2a1e71ddc1f30c21a238ff8d73f271eba Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 4 Nov 2016 16:22:57 -0200 Subject: Add helper method to toggle label subscription on labels controller spec --- spec/controllers/projects/labels_controller_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index 2b51bae926b..ec6cea5c0f4 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -95,7 +95,7 @@ describe Projects::LabelsController do it 'allows user to toggle subscription on project labels' do label = create(:label, project: project) - post :toggle_subscription, namespace_id: project.namespace.to_param, project_id: project.to_param, id: label.id + toggle_subscription(label) expect(response).to have_http_status(200) end @@ -103,9 +103,13 @@ describe Projects::LabelsController do it 'allows user to toggle subscription on group labels' do group_label = create(:group_label, group: group) - post :toggle_subscription, namespace_id: project.namespace.to_param, project_id: project.to_param, id: group_label.id + toggle_subscription(group_label) expect(response).to have_http_status(200) end + + def toggle_subscription(label) + post :toggle_subscription, namespace_id: project.namespace.to_param, project_id: project.to_param, id: label.to_param + end end end -- cgit v1.2.1 From 0aac2e0706cd767993148826d723aa3641cbb2a4 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 14 Nov 2016 20:42:22 -0200 Subject: Allow subscriptions to be created without a project --- spec/models/concerns/subscribable_spec.rb | 109 ++++++++++++++++++++++------- spec/models/subscription_spec.rb | 1 - spec/services/notification_service_spec.rb | 24 +++++-- 3 files changed, 102 insertions(+), 32 deletions(-) (limited to 'spec') diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb index 0a96cbbe166..58f5c164116 100644 --- a/spec/models/concerns/subscribable_spec.rb +++ b/spec/models/concerns/subscribable_spec.rb @@ -3,23 +3,43 @@ require 'spec_helper' describe Subscribable, 'Subscribable' do let(:project) { create(:empty_project) } let(:resource) { create(:issue, project: project) } - let(:user) { create(:user) } + let(:user_1) { create(:user) } describe '#subscribed?' do - it 'returns false when no subcription exists' do - expect(resource.subscribed?(user, project)).to be_falsey - end + context 'without project' do + it 'returns false when no subscription exists' do + expect(resource.subscribed?(user_1)).to be_falsey + end + + it 'returns true when a subcription exists and subscribed is true' do + resource.subscriptions.create(user: user_1, subscribed: true) + + expect(resource.subscribed?(user_1)).to be_truthy + end - it 'returns true when a subcription exists and subscribed is true' do - resource.subscriptions.create(user: user, project: project, subscribed: true) + it 'returns false when a subcription exists and subscribed is false' do + resource.subscriptions.create(user: user_1, subscribed: false) - expect(resource.subscribed?(user, project)).to be_truthy + expect(resource.subscribed?(user_1)).to be_falsey + end end - it 'returns false when a subcription exists and subscribed is false' do - resource.subscriptions.create(user: user, project: project, subscribed: false) + context 'with project' do + it 'returns false when no subscription exists' do + expect(resource.subscribed?(user_1, project)).to be_falsey + end + + it 'returns true when a subcription exists and subscribed is true' do + resource.subscriptions.create(user: user_1, project: project, subscribed: true) + + expect(resource.subscribed?(user_1, project)).to be_truthy + end - expect(resource.subscribed?(user, project)).to be_falsey + it 'returns false when a subcription exists and subscribed is false' do + resource.subscriptions.create(user: user_1, project: project, subscribed: false) + + expect(resource.subscribed?(user_1, project)).to be_falsey + end end end @@ -29,41 +49,80 @@ describe Subscribable, 'Subscribable' do end it 'returns the subscribed users' do - resource.subscriptions.create(user: user, project: project, subscribed: true) + user_2 = create(:user) + resource.subscriptions.create(user: user_1, subscribed: true) + resource.subscriptions.create(user: user_2, project: project, subscribed: true) resource.subscriptions.create(user: create(:user), project: project, subscribed: false) - expect(resource.subscribers(project)).to eq [user] + expect(resource.subscribers(project)).to contain_exactly(user_1, user_2) end end describe '#toggle_subscription' do - it 'toggles the current subscription state for the given user' do - expect(resource.subscribed?(user, project)).to be_falsey + context 'without project' do + it 'toggles the current subscription state for the given user' do + expect(resource.subscribed?(user_1)).to be_falsey + + resource.toggle_subscription(user_1) + + expect(resource.subscribed?(user_1)).to be_truthy + end + end - resource.toggle_subscription(user, project) + context 'with project' do + it 'toggles the current subscription state for the given user' do + expect(resource.subscribed?(user_1, project)).to be_falsey - expect(resource.subscribed?(user, project)).to be_truthy + resource.toggle_subscription(user_1, project) + + expect(resource.subscribed?(user_1, project)).to be_truthy + end end end describe '#subscribe' do - it 'subscribes the given user' do - expect(resource.subscribed?(user, project)).to be_falsey + context 'without project' do + it 'subscribes the given user' do + expect(resource.subscribed?(user_1)).to be_falsey + + resource.subscribe(user_1) + + expect(resource.subscribed?(user_1)).to be_truthy + end + end + + context 'with project' do + it 'subscribes the given user' do + expect(resource.subscribed?(user_1, project)).to be_falsey - resource.subscribe(user, project) + resource.subscribe(user_1, project) - expect(resource.subscribed?(user, project)).to be_truthy + expect(resource.subscribed?(user_1, project)).to be_truthy + end end end describe '#unsubscribe' do - it 'unsubscribes the given current user' do - resource.subscriptions.create(user: user, project: project, subscribed: true) - expect(resource.subscribed?(user, project)).to be_truthy + context 'without project' do + it 'unsubscribes the given current user' do + resource.subscriptions.create(user: user_1, subscribed: true) + expect(resource.subscribed?(user_1)).to be_truthy + + resource.unsubscribe(user_1) + + expect(resource.subscribed?(user_1)).to be_falsey + end + end + + context 'with project' do + it 'unsubscribes the given current user' do + resource.subscriptions.create(user: user_1, project: project, subscribed: true) + expect(resource.subscribed?(user_1, project)).to be_truthy - resource.unsubscribe(user, project) + resource.unsubscribe(user_1, project) - expect(resource.subscribed?(user, project)).to be_falsey + expect(resource.subscribed?(user_1, project)).to be_falsey + end end end end diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb index ab674958387..9ab112bb2ee 100644 --- a/spec/models/subscription_spec.rb +++ b/spec/models/subscription_spec.rb @@ -8,7 +8,6 @@ describe Subscription, models: true do end describe 'validations' do - it { is_expected.to validate_presence_of(:project) } it { is_expected.to validate_presence_of(:subscribable) } it { is_expected.to validate_presence_of(:user) } diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 64e378d8328..8726c9eaa55 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -382,18 +382,21 @@ describe NotificationService, services: true do user_1 = create(:user) user_2 = create(:user) user_3 = create(:user) + user_4 = create(:user) label = create(:label, project: project, issues: [issue]) group_label = create(:group_label, group: group, issues: [issue]) issue.reload label.toggle_subscription(user_1, project) group_label.toggle_subscription(user_2, project) group_label.toggle_subscription(user_3, another_project) + group_label.toggle_subscription(user_4) notification.new_issue(issue, @u_disabled) should_email(user_1) should_email(user_2) should_not_email(user_3) + should_email(user_4) end context 'confidential issues' do @@ -569,7 +572,8 @@ describe NotificationService, services: true do let(:label_1) { create(:label, project: project, title: 'Label 1', issues: [issue]) } let(:label_2) { create(:label, project: project, title: 'Label 2') } let!(:subscriber_to_group_label_1) { create(:user) { |u| group_label_1.toggle_subscription(u, project) } } - let!(:subscriber_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_1_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_2_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u) } } let!(:subscriber_to_group_label_2_on_another_project) { create(:user) { |u| group_label_2.toggle_subscription(u, another_project) } } let!(:subscriber_to_label_1) { create(:user) { |u| label_1.toggle_subscription(u, project) } } let!(:subscriber_to_label_2) { create(:user) { |u| label_2.toggle_subscription(u, project) } } @@ -580,7 +584,8 @@ describe NotificationService, services: true do should_not_email(subscriber_to_label_1) should_not_email(subscriber_to_group_label_1) should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_to_group_label_2) + should_email(subscriber_1_to_group_label_2) + should_email(subscriber_2_to_group_label_2) should_email(subscriber_to_label_2) end @@ -599,7 +604,8 @@ describe NotificationService, services: true do should_not_email(subscriber_to_label_1) should_not_email(subscriber_to_group_label_1) should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_to_group_label_2) + should_email(subscriber_1_to_group_label_2) + should_email(subscriber_2_to_group_label_2) should_email(subscriber_to_label_2) end @@ -784,17 +790,20 @@ describe NotificationService, services: true do user_1 = create(:user) user_2 = create(:user) user_3 = create(:user) + user_4 = create(:user) label = create(:label, project: project, merge_requests: [merge_request]) group_label = create(:group_label, group: group, merge_requests: [merge_request]) label.toggle_subscription(user_1, project) group_label.toggle_subscription(user_2, project) group_label.toggle_subscription(user_3, another_project) + group_label.toggle_subscription(user_4) notification.new_merge_request(merge_request, @u_disabled) should_email(user_1) should_email(user_2) should_not_email(user_3) + should_email(user_4) end context 'participating' do @@ -893,7 +902,8 @@ describe NotificationService, services: true do let(:label_1) { create(:label, project: project, title: 'Label 1', merge_requests: [merge_request]) } let(:label_2) { create(:label, project: project, title: 'Label 2') } let!(:subscriber_to_group_label_1) { create(:user) { |u| group_label_1.toggle_subscription(u, project) } } - let!(:subscriber_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_1_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u, project) } } + let!(:subscriber_2_to_group_label_2) { create(:user) { |u| group_label_2.toggle_subscription(u) } } let!(:subscriber_to_group_label_2_on_another_project) { create(:user) { |u| group_label_2.toggle_subscription(u, another_project) } } let!(:subscriber_to_label_1) { create(:user) { |u| label_1.toggle_subscription(u, project) } } let!(:subscriber_to_label_2) { create(:user) { |u| label_2.toggle_subscription(u, project) } } @@ -904,7 +914,8 @@ describe NotificationService, services: true do should_not_email(subscriber_to_label_1) should_not_email(subscriber_to_group_label_1) should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_to_group_label_2) + should_email(subscriber_1_to_group_label_2) + should_email(subscriber_2_to_group_label_2) should_email(subscriber_to_label_2) end @@ -923,7 +934,8 @@ describe NotificationService, services: true do should_not_email(subscriber_to_label_1) should_not_email(subscriber_to_group_label_1) should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_to_group_label_2) + should_email(subscriber_1_to_group_label_2) + should_email(subscriber_2_to_group_label_2) should_email(subscriber_to_label_2) end end -- cgit v1.2.1 From 198fe1bfc281ed465b94bb0b0a077f607d3d9fc7 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 14 Nov 2016 20:42:44 -0200 Subject: Add toggle_subscription action to Groups::LabelsController --- spec/controllers/groups/labels_controller_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 spec/controllers/groups/labels_controller_spec.rb (limited to 'spec') diff --git a/spec/controllers/groups/labels_controller_spec.rb b/spec/controllers/groups/labels_controller_spec.rb new file mode 100644 index 00000000000..899d8ebd12b --- /dev/null +++ b/spec/controllers/groups/labels_controller_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Groups::LabelsController do + let(:group) { create(:group) } + let(:user) { create(:user) } + + before do + group.add_owner(user) + + sign_in(user) + end + + describe 'POST #toggle_subscription' do + it 'allows user to toggle subscription on group labels' do + label = create(:group_label, group: group) + + post :toggle_subscription, group_id: group.to_param, id: label.to_param + + expect(response).to have_http_status(200) + end + end +end -- cgit v1.2.1 From 23f45e842cbe366c1992b7cf1472a4039b9a69ea Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Nov 2016 18:23:15 -0200 Subject: Add feature spec for labels subscription --- spec/features/projects/labels/subscription_spec.rb | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 spec/features/projects/labels/subscription_spec.rb (limited to 'spec') diff --git a/spec/features/projects/labels/subscription_spec.rb b/spec/features/projects/labels/subscription_spec.rb new file mode 100644 index 00000000000..3130d87fba5 --- /dev/null +++ b/spec/features/projects/labels/subscription_spec.rb @@ -0,0 +1,74 @@ +require 'spec_helper' + +feature 'Labels subscription', feature: true do + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:project) { create(:empty_project, :public, namespace: group) } + let!(:bug) { create(:label, project: project, title: 'bug') } + let!(:feature) { create(:group_label, group: group, title: 'feature') } + + context 'when signed in' do + before do + project.team << [user, :developer] + login_as user + end + + scenario 'users can subscribe/unsubscribe to labels', js: true do + visit namespace_project_labels_path(project.namespace, project) + + expect(page).to have_content('bug') + expect(page).to have_content('feature') + + within "#project_label_#{bug.id}" do + expect(page).not_to have_button 'Unsubscribe' + + click_button 'Subscribe' + + expect(page).not_to have_button 'Subscribe' + expect(page).to have_button 'Unsubscribe' + + click_button 'Unsubscribe' + + expect(page).to have_button 'Subscribe' + expect(page).not_to have_button 'Unsubscribe' + end + + within "#group_label_#{feature.id}" do + expect(page).not_to have_button 'Unsubscribe' + + click_link_on_dropdown('Group level') + + expect(page).not_to have_selector('.dropdown-group-label') + expect(page).to have_button 'Unsubscribe' + + click_button 'Unsubscribe' + + expect(page).to have_selector('.dropdown-group-label') + + click_link_on_dropdown('Project level') + + expect(page).not_to have_selector('.dropdown-group-label') + expect(page).to have_button 'Unsubscribe' + end + end + end + + context 'when not signed in' do + it 'users can not subscribe/unsubscribe to labels' do + visit namespace_project_labels_path(project.namespace, project) + + expect(page).to have_content 'bug' + expect(page).to have_content 'feature' + expect(page).not_to have_button('Subscribe') + expect(page).not_to have_selector('.dropdown-group-label') + end + end + + def click_link_on_dropdown(text) + find('.dropdown-group-label').click + + page.within('.dropdown-group-label') do + find('a.js-subscribe-button', text: text).click + end + end +end -- cgit v1.2.1 From 79122896318ae50c835418888f7f781fa2e463f4 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 17 Nov 2016 12:41:48 +0000 Subject: Allow sorting groups in API Allow `order_by` and `sort` parameters to `/api/v3/groups.json`. At present, only ordering by name and path is supported, and the default sort is name ascending (alphabetical order). --- spec/requests/api/groups_spec.rb | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index d79b204a24e..d9fdafde05e 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -57,13 +57,48 @@ describe API::API, api: true do end context "when using all_available in request" do + let(:response_groups) { json_response.map { |group| group['name'] } } + it "returns all groups you have access to" do public_group = create :group, :public get api("/groups", user1), all_available: true expect(response).to have_http_status(200) expect(json_response).to be_an Array - expect(json_response.first['name']).to eq(public_group.name) + expect(response_groups).to contain_exactly(public_group.name, group1.name) + end + end + + context "when using sorting" do + let(:group3) { create(:group, name: "a#{group1.name}", path: "z#{group1.path}") } + let(:response_groups) { json_response.map { |group| group['name'] } } + + before do + group3.add_owner(user1) + end + + it "sorts by name ascending by default" do + get api("/groups", user1) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(response_groups).to eq([group3.name, group1.name]) + end + + it "sorts in descending order when passed" do + get api("/groups", user1), sort: "desc" + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(response_groups).to eq([group1.name, group3.name]) + end + + it "sorts by the order_by param" do + get api("/groups", user1), order_by: "path" + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(response_groups).to eq([group1.name, group3.name]) end end end -- cgit v1.2.1 From 67c833e90fa39b4a648828b884bb14454ccc7c9b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 17 Nov 2016 20:19:57 +0100 Subject: Fix Rubocop offense for lines in environment specs --- spec/features/environment_spec.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'spec') diff --git a/spec/features/environment_spec.rb b/spec/features/environment_spec.rb index 51bd1d4bdfc..0c1939fd885 100644 --- a/spec/features/environment_spec.rb +++ b/spec/features/environment_spec.rb @@ -64,7 +64,6 @@ feature 'Environment', :feature do given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') } scenario 'does show a play button' do - expect(page).to have_link(manual.name.humanize) end -- cgit v1.2.1 From 9ed7171a6a8c98858949891b298789a97c4f3fba Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Thu, 17 Nov 2016 13:33:53 -0600 Subject: Fix builds/show spec; use iid instead of id --- spec/views/projects/builds/show.html.haml_spec.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index 3b9a9c95daa..e0c77201116 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -40,6 +40,10 @@ describe 'projects/builds/show', :view do create(:ci_build, :success, environment: 'staging', pipeline: pipeline) end + let(:second_build) do + create(:ci_build, :success, environment: 'staging', pipeline: pipeline) + end + let(:environment) do create(:environment, name: 'staging', project: project) end @@ -49,12 +53,12 @@ describe 'projects/builds/show', :view do end let!(:second_deployment) do - create(:deployment, environment: environment, deployable: build) + create(:deployment, environment: environment, deployable: second_build) end it 'shows deployment message' do expected_text = 'This build is an out-of-date deployment ' \ - "to staging.\nView the most recent deployment ##{second_deployment.id}." + "to staging.\nView the most recent deployment ##{second_deployment.iid}." render expect(rendered).to have_css('.environment-information', text: expected_text) @@ -71,7 +75,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'The deployment of this build to staging did not complete.' + expected_text = 'The deployment of this build to staging did not succeed.' render expect(rendered).to have_css( @@ -107,7 +111,7 @@ describe 'projects/builds/show', :view do end it 'shows deployment message' do - expected_text = 'The deployment of this build to staging did not complete' + expected_text = 'The deployment of this build to staging did not succeed' render expect(rendered).to have_css( -- cgit v1.2.1 From bb988fd21498102e203f49c0968153d5ea83d03f Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 16 Nov 2016 14:56:30 +0100 Subject: Add most of specs for chat names --- spec/factories/chat_names.rb | 16 +++++++++ spec/lib/gitlab/chat_name_token_spec.rb | 39 ++++++++++++++++++++++ spec/models/chat_name_spec.rb | 16 +++++++++ spec/models/user_spec.rb | 1 + .../chat_names/authorize_user_service_spec.rb | 27 +++++++++++++++ spec/services/chat_names/find_user_service_spec.rb | 36 ++++++++++++++++++++ 6 files changed, 135 insertions(+) create mode 100644 spec/factories/chat_names.rb create mode 100644 spec/lib/gitlab/chat_name_token_spec.rb create mode 100644 spec/models/chat_name_spec.rb create mode 100644 spec/services/chat_names/authorize_user_service_spec.rb create mode 100644 spec/services/chat_names/find_user_service_spec.rb (limited to 'spec') diff --git a/spec/factories/chat_names.rb b/spec/factories/chat_names.rb new file mode 100644 index 00000000000..24225468d55 --- /dev/null +++ b/spec/factories/chat_names.rb @@ -0,0 +1,16 @@ +FactoryGirl.define do + factory :chat_name, class: ChatName do + user factory: :user + service factory: :service + + team_id 'T0001' + team_domain 'Awesome Team' + + sequence :chat_id do |n| + "U#{n}" + end + sequence :chat_name do |n| + "user#{n}" + end + end +end diff --git a/spec/lib/gitlab/chat_name_token_spec.rb b/spec/lib/gitlab/chat_name_token_spec.rb new file mode 100644 index 00000000000..8d7e7a99059 --- /dev/null +++ b/spec/lib/gitlab/chat_name_token_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe Gitlab::ChatNameToken, lib: true do + context 'when using unknown token' do + let(:token) { } + + subject { described_class.new(token).get } + + it 'returns empty data' do + is_expected.to be_nil + end + end + + context 'when storing data' do + let(:data) { + { key: 'value' } + } + + subject { described_class.new(@token) } + + before do + @token = described_class.new.store!(data) + end + + it 'returns stored data' do + expect(subject.get).to eq(data) + end + + context 'and after deleting them' do + before do + subject.delete + end + + it 'data are removed' do + expect(subject.get).to be_nil + end + end + end +end diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb new file mode 100644 index 00000000000..b02971cab82 --- /dev/null +++ b/spec/models/chat_name_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe ChatName, models: true do + subject { create(:chat_name) } + + it { is_expected.to belong_to(:service) } + it { is_expected.to belong_to(:user) } + + it { is_expected.to validate_presence_of(:user) } + it { is_expected.to validate_presence_of(:service) } + it { is_expected.to validate_presence_of(:team_id) } + it { is_expected.to validate_presence_of(:chat_id) } + + it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:service_id) } + it { is_expected.to validate_uniqueness_of(:chat_id).scoped_to(:service_id, :team_id) } +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 3159243553b..36619de13f8 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -33,6 +33,7 @@ describe User, models: true do it { is_expected.to have_many(:award_emoji).dependent(:destroy) } it { is_expected.to have_many(:builds).dependent(:nullify) } it { is_expected.to have_many(:pipelines).dependent(:nullify) } + it { is_expected.to have_many(:chat_names).dependent(:destroy) } describe '#group_members' do it 'does not include group memberships for which user is a requester' do diff --git a/spec/services/chat_names/authorize_user_service_spec.rb b/spec/services/chat_names/authorize_user_service_spec.rb new file mode 100644 index 00000000000..f8c26e51bfc --- /dev/null +++ b/spec/services/chat_names/authorize_user_service_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe ChatNames::AuthorizeUserService, services: true do + describe '#execute' do + let(:service) { create(:service) } + + subject { described_class.new(service, params).execute } + + context 'when all parameters are valid' do + let(:params) { { team_id: 'T0001', team_domain: 'myteam', user_id: 'U0001', user_name: 'user' } } + + it 'requests a new token' do + is_expected.to include('http') + is_expected.to include('://') + is_expected.to include('token=') + end + end + + context 'when there are missing parameters' do + let(:params) { { } } + + it 'does not request a new token' do + is_expected.to be_nil + end + end + end +end diff --git a/spec/services/chat_names/find_user_service_spec.rb b/spec/services/chat_names/find_user_service_spec.rb new file mode 100644 index 00000000000..cf5844069f9 --- /dev/null +++ b/spec/services/chat_names/find_user_service_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe ChatNames::FindUserService, services: true do + describe '#execute' do + let(:service) { create(:service) } + + subject { described_class.new(service, params).execute } + + context 'find user mapping' do + let(:user) { create(:user) } + let!(:chat_name) { create(:chat_name, user: user, service: service) } + + context 'when existing user is requested' do + let(:params) { { team_id: chat_name.team_id, user_id: chat_name.chat_id } } + + it 'returns existing user' do + is_expected.to eq(user) + end + + it 'updates when last time chat name was used' do + subject + + expect(chat_name.reload.used_at).to be_like_time(Time.now) + end + end + + context 'when different user is requested' do + let(:params) { { team_id: chat_name.team_id, user_id: 'non-existing-user' } } + + it 'returns existing user' do + is_expected.to be_nil + end + end + end + end +end -- cgit v1.2.1 From 9d8ca60d221a1500e31ef05ecf8c4db56adde3c0 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Sat, 12 Nov 2016 11:17:24 +0100 Subject: issue and mergerequest slash command for mattermost This commit includes a couple of thing: - A chatops controller - Mattermost::CommandService - Mattermost::Commands::(IssueService|MergeRequestService) The controller is the point where mattermost, and later slack will have to fire their payload to. This in turn will execute the CommandService. Thats where the authentication and authorization should happen. So far this is not yet implemented. This should happen in later commits. Per subcommand, in case of `/gitlab issue show 123` issue whould be the subcommand, there is a service to parse the data, and fetch the resource. The resource is passed back to the CommandService which structures the data. --- spec/controllers/chat_ops_controller_spec.rb | 11 ++++ spec/services/mattermost/command_service_spec.rb | 55 +++++++++++++++++ .../mattermost/commands/issue_service_spec.rb | 70 ++++++++++++++++++++++ .../commands/merge_request_service_spec.rb | 68 +++++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 spec/controllers/chat_ops_controller_spec.rb create mode 100644 spec/services/mattermost/command_service_spec.rb create mode 100644 spec/services/mattermost/commands/issue_service_spec.rb create mode 100644 spec/services/mattermost/commands/merge_request_service_spec.rb (limited to 'spec') diff --git a/spec/controllers/chat_ops_controller_spec.rb b/spec/controllers/chat_ops_controller_spec.rb new file mode 100644 index 00000000000..7303c981ba2 --- /dev/null +++ b/spec/controllers/chat_ops_controller_spec.rb @@ -0,0 +1,11 @@ +require 'rails_helper' + +RSpec.describe ChatOpsController, type: :controller do + describe "POST #trigger" do + it "returns http success" do + post :trigger + + expect(response).to have_http_status(:success) + end + end +end diff --git a/spec/services/mattermost/command_service_spec.rb b/spec/services/mattermost/command_service_spec.rb new file mode 100644 index 00000000000..35051c09f8d --- /dev/null +++ b/spec/services/mattermost/command_service_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Mattermost::CommandService, service: true do + let(:project) { build(:project) } + let(:user) { build(:user) } + let(:params) { { text: 'issue show 1' } } + + subject { described_class.new(project, user, params).execute } + + describe '#execute' do + context 'no user could be found' do + let(:user) { nil } + + it 'asks the user to introduce him/herself' do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with 'Hi there!' + end + end + + context 'no project could be found' do + it 'shows a 404 not found message' do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + + context 'the user has access to the project' do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + end + + context 'no command service is triggered' do + let(:params) { { text: 'unknown_command' } } + + it 'shows the help messages' do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with 'Sadly, the used command' + end + end + + context 'a valid command is executed' do + let(:issue) { create(:issue, project: project) } + let(:params) { { text: "issue show #{issue.iid}" } } + + it 'a resource is presented to the user' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match issue.title + end + end + end + end +end diff --git a/spec/services/mattermost/commands/issue_service_spec.rb b/spec/services/mattermost/commands/issue_service_spec.rb new file mode 100644 index 00000000000..67629d26bc0 --- /dev/null +++ b/spec/services/mattermost/commands/issue_service_spec.rb @@ -0,0 +1,70 @@ +require 'spec_helper' + +describe Mattermost::Commands::IssueService do + let(:project) { create(:project) } + let(:issue ) { create(:issue, :confidential, title: 'Bird is the word', project: project) } + let(:user) { issue.author } + + subject { described_class.new(project, user, params).execute } + + before do + project.team << [user, :developer] + end + + describe '#execute' do + context 'show as subcommand' do + context 'issue can be found' do + let(:params) { { text: "issue show #{issue.iid}" } } + + it 'returns the merge request' do + expect(subject).to eq issue + end + + context 'the user has no access' do + let(:non_member) { create(:user) } + subject { described_class.new(project, non_member, params).execute } + + it 'returns nil' do + expect(subject).to eq nil + end + end + end + + context 'issue can not be found' do + let(:params) { { text: 'issue show 12345' } } + + it 'returns nil' do + expect(subject).to eq nil + end + end + end + + context 'search as a subcommand' do + context 'with results' do + let(:params) { { text: "issue search is the word" } } + + it 'returns the issue' do + expect(subject).to eq [issue] + end + end + + context 'without results' do + let(:params) { { text: 'issue search mepmep' } } + + it 'returns an empty collection' do + expect(subject).to eq [] + end + end + end + end + + describe 'help_message' do + context 'issues are disabled' do + it 'returns nil' do + allow(described_class).to receive(:available?).and_return false + + expect(described_class.help_message(project)).to eq nil + end + end + end +end diff --git a/spec/services/mattermost/commands/merge_request_service_spec.rb b/spec/services/mattermost/commands/merge_request_service_spec.rb new file mode 100644 index 00000000000..39381520a99 --- /dev/null +++ b/spec/services/mattermost/commands/merge_request_service_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe Mattermost::Commands::MergeRequestService do + let(:project) { create(:project, :private) } + let(:merge_request) { create(:merge_request, title: 'Bird is the word', source_project: project) } + let(:user) { merge_request.author } + + subject { described_class.new(project, user, params).execute } + + before do + project.team << [user, :developer] + end + + context 'show as subcommand' do + context 'merge request can be found' do + let(:params) { { text: "mergerequest show #{merge_request.iid}" } } + + it 'returns the merge request' do + expect(subject).to eq merge_request + end + + context 'the user has no access' do + let(:non_member) { create(:user) } + subject { described_class.new(project, non_member, params).execute } + + it 'returns nil' do + expect(subject).to eq nil + end + end + end + + context 'merge request can not be found' do + let(:params) { { text: 'mergerequest show 12345' } } + + it 'returns nil' do + expect(subject).to eq nil + end + end + end + + context 'search as a subcommand' do + context 'with results' do + let(:params) { { text: "mergerequest search is the word" } } + + it 'returns the merge_request' do + expect(subject).to eq [merge_request] + end + end + + context 'without results' do + let(:params) { { text: 'mergerequest search mepmep' } } + + it 'returns an empty collection' do + expect(subject).to eq [] + end + end + end + + describe 'help_message' do + context 'issues are disabled' do + it 'returns nil' do + allow(described_class).to receive(:available?).and_return false + + expect(described_class.help_message(project)).to eq nil + end + end + end +end -- cgit v1.2.1 From 242e291e8999705cb517b8c2dfa2c29704d4ace9 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Sat, 12 Nov 2016 14:25:40 +0100 Subject: Add issue create subcommand --- spec/services/mattermost/commands/issue_service_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'spec') diff --git a/spec/services/mattermost/commands/issue_service_spec.rb b/spec/services/mattermost/commands/issue_service_spec.rb index 67629d26bc0..5ef363274ad 100644 --- a/spec/services/mattermost/commands/issue_service_spec.rb +++ b/spec/services/mattermost/commands/issue_service_spec.rb @@ -56,6 +56,19 @@ describe Mattermost::Commands::IssueService do end end end + + context 'create as subcommand' do + let(:title) { 'my new issue' } + let(:params) { { text: "issue create #{title}" } } + + it 'return the new issue' do + expect(subject).to be_a Issue + end + + it 'creates a new issue' do + expect { subject }.to change { Issue.count }.by(1) + end + end end describe 'help_message' do -- cgit v1.2.1 From 4762198959fbc2bc22981749313955b65c6d6026 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 14 Nov 2016 12:41:14 +0100 Subject: Remove duplication of implementations --- spec/controllers/chat_ops_controller_spec.rb | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 spec/controllers/chat_ops_controller_spec.rb (limited to 'spec') diff --git a/spec/controllers/chat_ops_controller_spec.rb b/spec/controllers/chat_ops_controller_spec.rb deleted file mode 100644 index 7303c981ba2..00000000000 --- a/spec/controllers/chat_ops_controller_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'rails_helper' - -RSpec.describe ChatOpsController, type: :controller do - describe "POST #trigger" do - it "returns http success" do - post :trigger - - expect(response).to have_http_status(:success) - end - end -end -- cgit v1.2.1 From 106b1e39c0d00f25e34dda0eba962c8cf1d43f1b Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 15 Nov 2016 09:55:56 +0100 Subject: First steps on refactoring Mattermost Slash commands Now, each subcommand has its own service, plus I've introduced presenters to be able to delegate the generation of the views. --- spec/services/mattermost/command_service_spec.rb | 55 ---------------------- .../mattermost/slash_command_service_spec.rb | 30 ++++++++++++ 2 files changed, 30 insertions(+), 55 deletions(-) delete mode 100644 spec/services/mattermost/command_service_spec.rb create mode 100644 spec/services/mattermost/slash_command_service_spec.rb (limited to 'spec') diff --git a/spec/services/mattermost/command_service_spec.rb b/spec/services/mattermost/command_service_spec.rb deleted file mode 100644 index 35051c09f8d..00000000000 --- a/spec/services/mattermost/command_service_spec.rb +++ /dev/null @@ -1,55 +0,0 @@ -require 'spec_helper' - -describe Mattermost::CommandService, service: true do - let(:project) { build(:project) } - let(:user) { build(:user) } - let(:params) { { text: 'issue show 1' } } - - subject { described_class.new(project, user, params).execute } - - describe '#execute' do - context 'no user could be found' do - let(:user) { nil } - - it 'asks the user to introduce him/herself' do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with 'Hi there!' - end - end - - context 'no project could be found' do - it 'shows a 404 not found message' do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - - context 'the user has access to the project' do - let(:project) { create(:project) } - let(:user) { create(:user) } - - before do - project.team << [user, :master] - end - - context 'no command service is triggered' do - let(:params) { { text: 'unknown_command' } } - - it 'shows the help messages' do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with 'Sadly, the used command' - end - end - - context 'a valid command is executed' do - let(:issue) { create(:issue, project: project) } - let(:params) { { text: "issue show #{issue.iid}" } } - - it 'a resource is presented to the user' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match issue.title - end - end - end - end -end diff --git a/spec/services/mattermost/slash_command_service_spec.rb b/spec/services/mattermost/slash_command_service_spec.rb new file mode 100644 index 00000000000..e1bfd073ef4 --- /dev/null +++ b/spec/services/mattermost/slash_command_service_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Mattermost::SlashCommandService, service: true do + let(:project) { build(:project) } + let(:user) { build(:user) } + let(:params) { { text: 'issue show 1' } } + + subject { described_class.new(project, user, params).execute } + + describe '#execute' do + context 'no command service is triggered' do + let(:params) { { text: 'unknown_command' } } + + it 'shows the help messages' do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with 'Sadly, the used command' + end + end + + context 'a valid command is executed' do + let(:issue) { create(:issue, project: project) } + let(:params) { { text: "issue show #{issue.iid}" } } + + it 'a resource is presented to the user' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match issue.title + end + end + end +end -- cgit v1.2.1 From 8c8bc07d32f1103bb7996b499ead6ad6eb5bd337 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 15 Nov 2016 21:50:27 +0100 Subject: Refactor and test Slash commands This is the structure Kamil proposed, which leaves us with a bunch of smaller classes. This commits deletes outdated files and tests everything from the SlashCommandService and down (child classes and subcommands) --- .../commands/issue_create_service_spec.rb | 35 +++++++++ .../commands/issue_search_service_spec.rb | 39 ++++++++++ .../mattermost/commands/issue_service_spec.rb | 83 ---------------------- .../mattermost/commands/issue_show_service_spec.rb | 31 ++++++++ .../commands/merge_request_search_service_spec.rb | 30 ++++++++ .../commands/merge_request_service_spec.rb | 68 ------------------ .../commands/merge_request_show_service_spec.rb | 30 ++++++++ .../mattermost/slash_command_service_spec.rb | 21 ++---- 8 files changed, 170 insertions(+), 167 deletions(-) create mode 100644 spec/services/mattermost/commands/issue_create_service_spec.rb create mode 100644 spec/services/mattermost/commands/issue_search_service_spec.rb delete mode 100644 spec/services/mattermost/commands/issue_service_spec.rb create mode 100644 spec/services/mattermost/commands/issue_show_service_spec.rb create mode 100644 spec/services/mattermost/commands/merge_request_search_service_spec.rb delete mode 100644 spec/services/mattermost/commands/merge_request_service_spec.rb create mode 100644 spec/services/mattermost/commands/merge_request_show_service_spec.rb (limited to 'spec') diff --git a/spec/services/mattermost/commands/issue_create_service_spec.rb b/spec/services/mattermost/commands/issue_create_service_spec.rb new file mode 100644 index 00000000000..5ed86606b8f --- /dev/null +++ b/spec/services/mattermost/commands/issue_create_service_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Mattermost::Commands::IssueCreateService, service: true do + describe '#execute' do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:params) { { text: "issue create bird is the word" } } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user, params).execute } + + context 'without description' do + it 'creates the issue' do + expect do + subject # this trigger the execution + end.to change { project.issues.count }.by(1) + + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match 'bird is the word' + end + end + + context 'with description' do + let(:description) { "Surfin bird" } + let(:params) { { text: "issue create The bird is the word\n#{description}" } } + + before { subject } + + it 'creates the issue with description' do + expect(Issue.last.description).to eq description + end + end + end +end diff --git a/spec/services/mattermost/commands/issue_search_service_spec.rb b/spec/services/mattermost/commands/issue_search_service_spec.rb new file mode 100644 index 00000000000..21934dfcdd0 --- /dev/null +++ b/spec/services/mattermost/commands/issue_search_service_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe Mattermost::Commands::IssueSearchService, service: true do + describe '#execute' do + let!(:issue) { create(:issue, title: 'The bird is the word') } + let(:project) { issue.project } + let(:user) { issue.author } + let(:params) { { text: "issue search bird is the" } } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user, params).execute } + + context 'without results' do + let(:params) { { text: "issue search no results for this one" } } + + it "returns nil" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + + context 'with 1 result' do + it 'returns the issue' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match issue.title + end + end + + context 'with 2 or more results' do + let!(:issue2) { create(:issue, project: project, title: 'bird is the word!') } + + it 'returns multiple resources' do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with 'Multiple results were found' + end + end + end +end diff --git a/spec/services/mattermost/commands/issue_service_spec.rb b/spec/services/mattermost/commands/issue_service_spec.rb deleted file mode 100644 index 5ef363274ad..00000000000 --- a/spec/services/mattermost/commands/issue_service_spec.rb +++ /dev/null @@ -1,83 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::IssueService do - let(:project) { create(:project) } - let(:issue ) { create(:issue, :confidential, title: 'Bird is the word', project: project) } - let(:user) { issue.author } - - subject { described_class.new(project, user, params).execute } - - before do - project.team << [user, :developer] - end - - describe '#execute' do - context 'show as subcommand' do - context 'issue can be found' do - let(:params) { { text: "issue show #{issue.iid}" } } - - it 'returns the merge request' do - expect(subject).to eq issue - end - - context 'the user has no access' do - let(:non_member) { create(:user) } - subject { described_class.new(project, non_member, params).execute } - - it 'returns nil' do - expect(subject).to eq nil - end - end - end - - context 'issue can not be found' do - let(:params) { { text: 'issue show 12345' } } - - it 'returns nil' do - expect(subject).to eq nil - end - end - end - - context 'search as a subcommand' do - context 'with results' do - let(:params) { { text: "issue search is the word" } } - - it 'returns the issue' do - expect(subject).to eq [issue] - end - end - - context 'without results' do - let(:params) { { text: 'issue search mepmep' } } - - it 'returns an empty collection' do - expect(subject).to eq [] - end - end - end - - context 'create as subcommand' do - let(:title) { 'my new issue' } - let(:params) { { text: "issue create #{title}" } } - - it 'return the new issue' do - expect(subject).to be_a Issue - end - - it 'creates a new issue' do - expect { subject }.to change { Issue.count }.by(1) - end - end - end - - describe 'help_message' do - context 'issues are disabled' do - it 'returns nil' do - allow(described_class).to receive(:available?).and_return false - - expect(described_class.help_message(project)).to eq nil - end - end - end -end diff --git a/spec/services/mattermost/commands/issue_show_service_spec.rb b/spec/services/mattermost/commands/issue_show_service_spec.rb new file mode 100644 index 00000000000..7578cd3a22c --- /dev/null +++ b/spec/services/mattermost/commands/issue_show_service_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe Mattermost::Commands::IssueShowService, service: true do + describe '#execute' do + let(:issue) { create(:issue) } + let(:project) { issue.project } + let(:user) { issue.author } + let(:params) { { text: "issue show #{issue.iid}" } } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user, params).execute } + + context 'the issue exists' do + it 'returns the issue' do + + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match issue.title + end + end + + context 'the issue does not exist' do + let(:params) { { text: "issue show 12345" } } + + it "returns nil" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + end +end diff --git a/spec/services/mattermost/commands/merge_request_search_service_spec.rb b/spec/services/mattermost/commands/merge_request_search_service_spec.rb new file mode 100644 index 00000000000..5212dc206a6 --- /dev/null +++ b/spec/services/mattermost/commands/merge_request_search_service_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Mattermost::Commands::MergeRequestSearchService, service: true do + describe '#execute' do + let!(:merge_request) { create(:merge_request, title: 'The bird is the word') } + let(:project) { merge_request.source_project } + let(:user) { merge_request.author } + let(:params) { { text: "mergerequest search #{merge_request.title}" } } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user, params).execute } + + context 'the merge request exists' do + it 'returns the merge request' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match merge_request.title + end + end + + context 'no results can be found' do + let(:params) { { text: "mergerequest search 12345" } } + + it "returns a 404 message" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + end +end diff --git a/spec/services/mattermost/commands/merge_request_service_spec.rb b/spec/services/mattermost/commands/merge_request_service_spec.rb deleted file mode 100644 index 39381520a99..00000000000 --- a/spec/services/mattermost/commands/merge_request_service_spec.rb +++ /dev/null @@ -1,68 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::MergeRequestService do - let(:project) { create(:project, :private) } - let(:merge_request) { create(:merge_request, title: 'Bird is the word', source_project: project) } - let(:user) { merge_request.author } - - subject { described_class.new(project, user, params).execute } - - before do - project.team << [user, :developer] - end - - context 'show as subcommand' do - context 'merge request can be found' do - let(:params) { { text: "mergerequest show #{merge_request.iid}" } } - - it 'returns the merge request' do - expect(subject).to eq merge_request - end - - context 'the user has no access' do - let(:non_member) { create(:user) } - subject { described_class.new(project, non_member, params).execute } - - it 'returns nil' do - expect(subject).to eq nil - end - end - end - - context 'merge request can not be found' do - let(:params) { { text: 'mergerequest show 12345' } } - - it 'returns nil' do - expect(subject).to eq nil - end - end - end - - context 'search as a subcommand' do - context 'with results' do - let(:params) { { text: "mergerequest search is the word" } } - - it 'returns the merge_request' do - expect(subject).to eq [merge_request] - end - end - - context 'without results' do - let(:params) { { text: 'mergerequest search mepmep' } } - - it 'returns an empty collection' do - expect(subject).to eq [] - end - end - end - - describe 'help_message' do - context 'issues are disabled' do - it 'returns nil' do - allow(described_class).to receive(:available?).and_return false - - expect(described_class.help_message(project)).to eq nil - end - end - end -end diff --git a/spec/services/mattermost/commands/merge_request_show_service_spec.rb b/spec/services/mattermost/commands/merge_request_show_service_spec.rb new file mode 100644 index 00000000000..688737df0f5 --- /dev/null +++ b/spec/services/mattermost/commands/merge_request_show_service_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Mattermost::Commands::MergeRequestShowService, service: true do + describe '#execute' do + let!(:merge_request) { create(:merge_request) } + let(:project) { merge_request.source_project } + let(:user) { merge_request.author } + let(:params) { { text: "mergerequest show #{merge_request.iid}" } } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user, params).execute } + + context 'the merge request exists' do + it 'returns the merge request' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match merge_request.title + end + end + + context 'the merge request does not exist' do + let(:params) { { text: "mergerequest show 12345" } } + + it "returns nil" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + end +end diff --git a/spec/services/mattermost/slash_command_service_spec.rb b/spec/services/mattermost/slash_command_service_spec.rb index e1bfd073ef4..14c2d9b7c37 100644 --- a/spec/services/mattermost/slash_command_service_spec.rb +++ b/spec/services/mattermost/slash_command_service_spec.rb @@ -7,23 +7,12 @@ describe Mattermost::SlashCommandService, service: true do subject { described_class.new(project, user, params).execute } - describe '#execute' do - context 'no command service is triggered' do - let(:params) { { text: 'unknown_command' } } + xdescribe '#execute' do + context 'when issue show is triggered' do + it 'calls IssueShowService' do + expect_any_instance_of(Mattermost::Commands::IssueShowService).to receive(:new).with(project, user, params) - it 'shows the help messages' do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with 'Sadly, the used command' - end - end - - context 'a valid command is executed' do - let(:issue) { create(:issue, project: project) } - let(:params) { { text: "issue show #{issue.iid}" } } - - it 'a resource is presented to the user' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match issue.title + subject end end end -- cgit v1.2.1 From 1b4fdb9893af28606b7594ee656438c7ef21e9d8 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 16 Nov 2016 18:28:38 +0100 Subject: Rename from service, and move to lib/gitlab --- spec/lib/gitlab/chat_commands/command_spec.rb | 19 +++++++++++ spec/lib/gitlab/chat_commands/issue_create_spec.rb | 35 +++++++++++++++++++ spec/lib/gitlab/chat_commands/issue_search_spec.rb | 39 ++++++++++++++++++++++ spec/lib/gitlab/chat_commands/issue_show_spec.rb | 30 +++++++++++++++++ .../chat_commands/merge_request_search_spec.rb | 36 ++++++++++++++++++++ .../chat_commands/merge_request_show_spec.rb | 37 ++++++++++++++++++++ .../commands/issue_create_service_spec.rb | 35 ------------------- .../commands/issue_search_service_spec.rb | 39 ---------------------- .../mattermost/commands/issue_show_service_spec.rb | 31 ----------------- .../commands/merge_request_search_service_spec.rb | 30 ----------------- .../commands/merge_request_show_service_spec.rb | 30 ----------------- .../mattermost/slash_command_service_spec.rb | 19 ----------- 12 files changed, 196 insertions(+), 184 deletions(-) create mode 100644 spec/lib/gitlab/chat_commands/command_spec.rb create mode 100644 spec/lib/gitlab/chat_commands/issue_create_spec.rb create mode 100644 spec/lib/gitlab/chat_commands/issue_search_spec.rb create mode 100644 spec/lib/gitlab/chat_commands/issue_show_spec.rb create mode 100644 spec/lib/gitlab/chat_commands/merge_request_search_spec.rb create mode 100644 spec/lib/gitlab/chat_commands/merge_request_show_spec.rb delete mode 100644 spec/services/mattermost/commands/issue_create_service_spec.rb delete mode 100644 spec/services/mattermost/commands/issue_search_service_spec.rb delete mode 100644 spec/services/mattermost/commands/issue_show_service_spec.rb delete mode 100644 spec/services/mattermost/commands/merge_request_search_service_spec.rb delete mode 100644 spec/services/mattermost/commands/merge_request_show_service_spec.rb delete mode 100644 spec/services/mattermost/slash_command_service_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb new file mode 100644 index 00000000000..d28349ff1d8 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Command, service: true do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:params) { { text: 'issue show 1' } } + + subject { described_class.new(project, user, params).execute } + + xdescribe '#execute' do + context 'when issue show is triggered' do + it 'calls IssueShowService' do + expect_any_instance_of(Mattermost::Commands::IssueShowService).to receive(:new).with(project, user, params) + + subject + end + end + end +end diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_create_spec.rb new file mode 100644 index 00000000000..184c09708a4 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/issue_create_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::IssueCreate, service: true do + describe '#execute' do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:regex_match) { described_class.match("issue create bird is the word") } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user).execute(regex_match) } + + context 'without description' do + it 'creates the issue' do + expect do + subject # this trigger the execution + end.to change { project.issues.count }.by(1) + + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match 'bird is the word' + end + end + + context 'with description' do + let(:description) { "Surfin bird" } + let(:regex_match) { described_class.match("issue create bird is the word\n#{description}") } + + before { subject } + + it 'creates the issue with description' do + expect(Issue.last.description).to eq description + end + end + end +end diff --git a/spec/lib/gitlab/chat_commands/issue_search_spec.rb b/spec/lib/gitlab/chat_commands/issue_search_spec.rb new file mode 100644 index 00000000000..3e54333528a --- /dev/null +++ b/spec/lib/gitlab/chat_commands/issue_search_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::IssueSearch, service: true do + describe '#execute' do + let!(:issue) { create(:issue, title: 'The bird is the word') } + let(:project) { issue.project } + let(:user) { issue.author } + let(:regex_match) { described_class.match("issue search bird is the") } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user).execute(regex_match) } + + context 'without results' do + let(:regex_match) { described_class.match("issue search no results for this one") } + + it "returns nil" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + + context 'with 1 result' do + it 'returns the issue' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match issue.title + end + end + + context 'with 2 or more results' do + let!(:issue2) { create(:issue, project: project, title: 'bird is the word!') } + + it 'returns multiple resources' do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with 'Multiple results were found' + end + 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 new file mode 100644 index 00000000000..ddf7fc87c36 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/issue_show_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::IssueShow, service: true do + describe '#execute' do + let(:issue) { create(:issue) } + let(:project) { issue.project } + let(:user) { issue.author } + let(:regex_match) { described_class.match("issue show #{issue.iid}") } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user).execute(regex_match) } + + context 'the issue exists' do + it 'returns the issue' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match issue.title + end + end + + context 'the issue does not exist' do + let(:regex_match) { described_class.match("issue show 1234") } + + it "returns nil" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + end +end diff --git a/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb b/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb new file mode 100644 index 00000000000..4cb4563e589 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::MergeRequestSearch, service: true do + describe '#execute' do + let!(:merge_request) { create(:merge_request, title: 'The bird is the word') } + let(:project) { merge_request.source_project } + let(:user) { merge_request.author } + let(:regex_match) { described_class.match("mergerequest search #{merge_request.title}") } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user, {}).execute(regex_match) } + + context 'the merge request exists' do + it 'returns the merge request' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match merge_request.title + end + end + + context 'no results can be found' do + let(:regex_match) { described_class.match("mergerequest search 12334") } + + it "returns a 404 message" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + end + + describe 'self.match' do + it 'matches a valid query' do + expect(described_class.match("mergerequest search my title here")).to be_truthy + end + end +end diff --git a/spec/lib/gitlab/chat_commands/merge_request_show_spec.rb b/spec/lib/gitlab/chat_commands/merge_request_show_spec.rb new file mode 100644 index 00000000000..ed63ffa5f85 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/merge_request_show_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::MergeRequestShow, service: true do + describe '#execute' do + let!(:merge_request) { create(:merge_request) } + let(:project) { merge_request.source_project } + let(:user) { merge_request.author } + let(:regex_match) { described_class.match("mergerequest show #{merge_request.iid}") } + + before { project.team << [user, :master] } + + subject { described_class.new(project, user).execute(regex_match) } + + context 'the merge request exists' do + it 'returns the merge request' do + expect(subject[:response_type]).to be :in_channel + expect(subject[:text]).to match merge_request.title + end + end + + context 'the merge request does not exist' do + let(:regex_match) { described_class.match("mergerequest show 12345") } + + it "returns nil" do + expect(subject[:response_type]).to be :ephemeral + expect(subject[:text]).to start_with '404 not found!' + end + end + end + + describe "self.match" do + it 'matches valid strings' do + expect(described_class.match("mergerequest show 123")).to be_truthy + expect(described_class.match("mergerequest show sdf23")).to be_falsy + end + end +end diff --git a/spec/services/mattermost/commands/issue_create_service_spec.rb b/spec/services/mattermost/commands/issue_create_service_spec.rb deleted file mode 100644 index 5ed86606b8f..00000000000 --- a/spec/services/mattermost/commands/issue_create_service_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::IssueCreateService, service: true do - describe '#execute' do - let(:project) { create(:empty_project) } - let(:user) { create(:user) } - let(:params) { { text: "issue create bird is the word" } } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user, params).execute } - - context 'without description' do - it 'creates the issue' do - expect do - subject # this trigger the execution - end.to change { project.issues.count }.by(1) - - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match 'bird is the word' - end - end - - context 'with description' do - let(:description) { "Surfin bird" } - let(:params) { { text: "issue create The bird is the word\n#{description}" } } - - before { subject } - - it 'creates the issue with description' do - expect(Issue.last.description).to eq description - end - end - end -end diff --git a/spec/services/mattermost/commands/issue_search_service_spec.rb b/spec/services/mattermost/commands/issue_search_service_spec.rb deleted file mode 100644 index 21934dfcdd0..00000000000 --- a/spec/services/mattermost/commands/issue_search_service_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::IssueSearchService, service: true do - describe '#execute' do - let!(:issue) { create(:issue, title: 'The bird is the word') } - let(:project) { issue.project } - let(:user) { issue.author } - let(:params) { { text: "issue search bird is the" } } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user, params).execute } - - context 'without results' do - let(:params) { { text: "issue search no results for this one" } } - - it "returns nil" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - - context 'with 1 result' do - it 'returns the issue' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match issue.title - end - end - - context 'with 2 or more results' do - let!(:issue2) { create(:issue, project: project, title: 'bird is the word!') } - - it 'returns multiple resources' do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with 'Multiple results were found' - end - end - end -end diff --git a/spec/services/mattermost/commands/issue_show_service_spec.rb b/spec/services/mattermost/commands/issue_show_service_spec.rb deleted file mode 100644 index 7578cd3a22c..00000000000 --- a/spec/services/mattermost/commands/issue_show_service_spec.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::IssueShowService, service: true do - describe '#execute' do - let(:issue) { create(:issue) } - let(:project) { issue.project } - let(:user) { issue.author } - let(:params) { { text: "issue show #{issue.iid}" } } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user, params).execute } - - context 'the issue exists' do - it 'returns the issue' do - - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match issue.title - end - end - - context 'the issue does not exist' do - let(:params) { { text: "issue show 12345" } } - - it "returns nil" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - end -end diff --git a/spec/services/mattermost/commands/merge_request_search_service_spec.rb b/spec/services/mattermost/commands/merge_request_search_service_spec.rb deleted file mode 100644 index 5212dc206a6..00000000000 --- a/spec/services/mattermost/commands/merge_request_search_service_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::MergeRequestSearchService, service: true do - describe '#execute' do - let!(:merge_request) { create(:merge_request, title: 'The bird is the word') } - let(:project) { merge_request.source_project } - let(:user) { merge_request.author } - let(:params) { { text: "mergerequest search #{merge_request.title}" } } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user, params).execute } - - context 'the merge request exists' do - it 'returns the merge request' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match merge_request.title - end - end - - context 'no results can be found' do - let(:params) { { text: "mergerequest search 12345" } } - - it "returns a 404 message" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - end -end diff --git a/spec/services/mattermost/commands/merge_request_show_service_spec.rb b/spec/services/mattermost/commands/merge_request_show_service_spec.rb deleted file mode 100644 index 688737df0f5..00000000000 --- a/spec/services/mattermost/commands/merge_request_show_service_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'spec_helper' - -describe Mattermost::Commands::MergeRequestShowService, service: true do - describe '#execute' do - let!(:merge_request) { create(:merge_request) } - let(:project) { merge_request.source_project } - let(:user) { merge_request.author } - let(:params) { { text: "mergerequest show #{merge_request.iid}" } } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user, params).execute } - - context 'the merge request exists' do - it 'returns the merge request' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match merge_request.title - end - end - - context 'the merge request does not exist' do - let(:params) { { text: "mergerequest show 12345" } } - - it "returns nil" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - end -end diff --git a/spec/services/mattermost/slash_command_service_spec.rb b/spec/services/mattermost/slash_command_service_spec.rb deleted file mode 100644 index 14c2d9b7c37..00000000000 --- a/spec/services/mattermost/slash_command_service_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'spec_helper' - -describe Mattermost::SlashCommandService, service: true do - let(:project) { build(:project) } - let(:user) { build(:user) } - let(:params) { { text: 'issue show 1' } } - - subject { described_class.new(project, user, params).execute } - - xdescribe '#execute' do - context 'when issue show is triggered' do - it 'calls IssueShowService' do - expect_any_instance_of(Mattermost::Commands::IssueShowService).to receive(:new).with(project, user, params) - - subject - end - end - end -end -- cgit v1.2.1 From d4def9cbcd664b7067e7f9f4ea8be54463bd1d50 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 17 Nov 2016 12:06:45 +0100 Subject: Incorporate feedback, improve presenter class [ci skip] --- spec/lib/gitlab/chat_commands/issue_create_spec.rb | 32 ++++++++++++++++++---- spec/lib/gitlab/chat_commands/issue_show_spec.rb | 30 ++++++++++++++------ .../chat_commands/merge_request_search_spec.rb | 16 +++++++---- 3 files changed, 58 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_create_spec.rb index 184c09708a4..5f5cc706c96 100644 --- a/spec/lib/gitlab/chat_commands/issue_create_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_create_spec.rb @@ -6,9 +6,13 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do let(:user) { create(:user) } let(:regex_match) { described_class.match("issue create bird is the word") } - before { project.team << [user, :master] } + before do + project.team << [user, :master] + end - subject { described_class.new(project, user).execute(regex_match) } + subject do + described_class.new(project, user).execute(regex_match) + end context 'without description' do it 'creates the issue' do @@ -17,7 +21,7 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do end.to change { project.issues.count }.by(1) expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match 'bird is the word' + expect(subject[:text]).to match('bird is the word') end end @@ -25,11 +29,29 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do let(:description) { "Surfin bird" } let(:regex_match) { described_class.match("issue create bird is the word\n#{description}") } - before { subject } + before do + subject + end it 'creates the issue with description' do - expect(Issue.last.description).to eq description + expect(Issue.last.description).to eq(description) end end end + + describe 'self.match' do + it 'matches the title without description' do + match = described_class.match("issue create my title") + + expect(match[:title]).to eq('my title') + expect(match[:description]).to eq("") + end + + it 'matches the title with description' do + match = described_class.match("issue create my title\n\ndescription") + + expect(match[:title]).to eq('my title') + expect(match[:description]).to eq('description') + 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 ddf7fc87c36..d7824dd6bf5 100644 --- a/spec/lib/gitlab/chat_commands/issue_show_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_show_spec.rb @@ -2,19 +2,23 @@ require 'spec_helper' describe Gitlab::ChatCommands::IssueShow, service: true do describe '#execute' do - let(:issue) { create(:issue) } - let(:project) { issue.project } - let(:user) { issue.author } + let(:issue) { create(:issue) } + let(:project) { issue.project } + let(:user) { issue.author } let(:regex_match) { described_class.match("issue show #{issue.iid}") } - before { project.team << [user, :master] } + before do + project.team << [user, :master] + end - subject { described_class.new(project, user).execute(regex_match) } + subject do + described_class.new(project, user).execute(regex_match) + end context 'the issue exists' do it 'returns the issue' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match issue.title + expect(subject[:response_type]).to be(:in_channel) + expect(subject[:text]).to match(issue.title) end end @@ -22,9 +26,17 @@ describe Gitlab::ChatCommands::IssueShow, service: true do let(:regex_match) { described_class.match("issue show 1234") } it "returns nil" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to start_with('404 not found!') end end end + + describe 'self.match' do + it 'matches the iid' do + match = described_class.match("issue show 123") + + expect(match[:iid]).to eq("123") + end + end end diff --git a/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb b/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb index 4cb4563e589..4033358ab2e 100644 --- a/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb +++ b/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb @@ -7,14 +7,18 @@ describe Gitlab::ChatCommands::MergeRequestSearch, service: true do let(:user) { merge_request.author } let(:regex_match) { described_class.match("mergerequest search #{merge_request.title}") } - before { project.team << [user, :master] } + before do + project.team << [user, :master] + end - subject { described_class.new(project, user, {}).execute(regex_match) } + subject do + described_class.new(project, user).execute(regex_match) + end context 'the merge request exists' do it 'returns the merge request' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match merge_request.title + expect(subject[:response_type]).to be(:in_channel) + expect(subject[:text]).to match(merge_request.title) end end @@ -22,8 +26,8 @@ describe Gitlab::ChatCommands::MergeRequestSearch, service: true do let(:regex_match) { described_class.match("mergerequest search 12334") } it "returns a 404 message" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to start_with('404 not found!') end end end -- cgit v1.2.1 From 6737ada0c8d980ed1bd8f425e885fa1b89930616 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 17 Nov 2016 12:57:27 +0100 Subject: Remove some commands for now --- spec/lib/gitlab/chat_commands/command_spec.rb | 20 ++++++++--- spec/lib/gitlab/chat_commands/issue_search_spec.rb | 39 --------------------- .../chat_commands/merge_request_search_spec.rb | 40 ---------------------- .../chat_commands/merge_request_show_spec.rb | 37 -------------------- 4 files changed, 15 insertions(+), 121 deletions(-) delete mode 100644 spec/lib/gitlab/chat_commands/issue_search_spec.rb delete mode 100644 spec/lib/gitlab/chat_commands/merge_request_search_spec.rb delete mode 100644 spec/lib/gitlab/chat_commands/merge_request_show_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index d28349ff1d8..bbd47f45761 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -7,12 +7,22 @@ describe Gitlab::ChatCommands::Command, service: true do subject { described_class.new(project, user, params).execute } - xdescribe '#execute' do - context 'when issue show is triggered' do - it 'calls IssueShowService' do - expect_any_instance_of(Mattermost::Commands::IssueShowService).to receive(:new).with(project, user, params) + describe '#execute' do + context 'when the command is not available' do + let(:project) { create(:project, has_external_issue_tracker: true) } - subject + it 'displays the help message' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to start_with('Available commands') + end + end + + context 'when an unknown command is triggered' do + let(:params) { { text: "unknown command 123" } } + + it 'displays the help message' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to start_with('Available commands') end end end diff --git a/spec/lib/gitlab/chat_commands/issue_search_spec.rb b/spec/lib/gitlab/chat_commands/issue_search_spec.rb deleted file mode 100644 index 3e54333528a..00000000000 --- a/spec/lib/gitlab/chat_commands/issue_search_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'spec_helper' - -describe Gitlab::ChatCommands::IssueSearch, service: true do - describe '#execute' do - let!(:issue) { create(:issue, title: 'The bird is the word') } - let(:project) { issue.project } - let(:user) { issue.author } - let(:regex_match) { described_class.match("issue search bird is the") } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user).execute(regex_match) } - - context 'without results' do - let(:regex_match) { described_class.match("issue search no results for this one") } - - it "returns nil" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - - context 'with 1 result' do - it 'returns the issue' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match issue.title - end - end - - context 'with 2 or more results' do - let!(:issue2) { create(:issue, project: project, title: 'bird is the word!') } - - it 'returns multiple resources' do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with 'Multiple results were found' - end - end - end -end diff --git a/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb b/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb deleted file mode 100644 index 4033358ab2e..00000000000 --- a/spec/lib/gitlab/chat_commands/merge_request_search_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'spec_helper' - -describe Gitlab::ChatCommands::MergeRequestSearch, service: true do - describe '#execute' do - let!(:merge_request) { create(:merge_request, title: 'The bird is the word') } - let(:project) { merge_request.source_project } - let(:user) { merge_request.author } - let(:regex_match) { described_class.match("mergerequest search #{merge_request.title}") } - - before do - project.team << [user, :master] - end - - subject do - described_class.new(project, user).execute(regex_match) - end - - context 'the merge request exists' do - it 'returns the merge request' do - expect(subject[:response_type]).to be(:in_channel) - expect(subject[:text]).to match(merge_request.title) - end - end - - context 'no results can be found' do - let(:regex_match) { described_class.match("mergerequest search 12334") } - - it "returns a 404 message" do - expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to start_with('404 not found!') - end - end - end - - describe 'self.match' do - it 'matches a valid query' do - expect(described_class.match("mergerequest search my title here")).to be_truthy - end - end -end diff --git a/spec/lib/gitlab/chat_commands/merge_request_show_spec.rb b/spec/lib/gitlab/chat_commands/merge_request_show_spec.rb deleted file mode 100644 index ed63ffa5f85..00000000000 --- a/spec/lib/gitlab/chat_commands/merge_request_show_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'spec_helper' - -describe Gitlab::ChatCommands::MergeRequestShow, service: true do - describe '#execute' do - let!(:merge_request) { create(:merge_request) } - let(:project) { merge_request.source_project } - let(:user) { merge_request.author } - let(:regex_match) { described_class.match("mergerequest show #{merge_request.iid}") } - - before { project.team << [user, :master] } - - subject { described_class.new(project, user).execute(regex_match) } - - context 'the merge request exists' do - it 'returns the merge request' do - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match merge_request.title - end - end - - context 'the merge request does not exist' do - let(:regex_match) { described_class.match("mergerequest show 12345") } - - it "returns nil" do - expect(subject[:response_type]).to be :ephemeral - expect(subject[:text]).to start_with '404 not found!' - end - end - end - - describe "self.match" do - it 'matches valid strings' do - expect(described_class.match("mergerequest show 123")).to be_truthy - expect(described_class.match("mergerequest show sdf23")).to be_falsy - end - end -end -- cgit v1.2.1 From 1607efa40081702488e22e560db2c1e30cd80093 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 17 Nov 2016 15:30:04 +0100 Subject: Add tests for increased converage --- spec/lib/gitlab/chat_commands/command_spec.rb | 22 +++++++++++++++++----- spec/lib/gitlab/chat_commands/issue_create_spec.rb | 15 +++++---------- spec/lib/gitlab/chat_commands/issue_show_spec.rb | 8 +++----- 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index bbd47f45761..328187b5048 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -1,19 +1,19 @@ require 'spec_helper' describe Gitlab::ChatCommands::Command, service: true do - let(:project) { create(:project) } - let(:user) { create(:user) } - let(:params) { { text: 'issue show 1' } } + let(:project) { create(:project) } + let(:user) { create(:user) } subject { described_class.new(project, user, params).execute } describe '#execute' do - context 'when the command is not available' do + context 'when no command is not available' do + let(:params) { { text: 'issue show 1' } } let(:project) { create(:project, has_external_issue_tracker: true) } 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('404 not found') end end @@ -25,5 +25,17 @@ describe Gitlab::ChatCommands::Command, service: true do expect(subject[:text]).to start_with('Available commands') end end + + context 'issue is succesfully 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 + end end end diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_create_spec.rb index 5f5cc706c96..4831f24efed 100644 --- a/spec/lib/gitlab/chat_commands/issue_create_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_create_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe Gitlab::ChatCommands::IssueCreate, service: true do describe '#execute' do - let(:project) { create(:empty_project) } - let(:user) { create(:user) } + let(:project) { create(:empty_project) } + let(:user) { create(:user) } let(:regex_match) { described_class.match("issue create bird is the word") } before do @@ -16,12 +16,9 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do context 'without description' do it 'creates the issue' do - expect do - subject # this trigger the execution - end.to change { project.issues.count }.by(1) + expect { subject }.to change { project.issues.count }.by(1) - expect(subject[:response_type]).to be :in_channel - expect(subject[:text]).to match('bird is the word') + expect(subject.title).to eq('bird is the word') end end @@ -29,11 +26,9 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do let(:description) { "Surfin bird" } let(:regex_match) { described_class.match("issue create bird is the word\n#{description}") } - before do + it 'creates the issue with description' do subject - end - it 'creates the issue with description' do expect(Issue.last.description).to eq(description) 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 d7824dd6bf5..331a4604e9b 100644 --- a/spec/lib/gitlab/chat_commands/issue_show_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_show_spec.rb @@ -17,17 +17,15 @@ describe Gitlab::ChatCommands::IssueShow, service: true do context 'the issue exists' do it 'returns the issue' do - expect(subject[:response_type]).to be(:in_channel) - expect(subject[:text]).to match(issue.title) + expect(subject.iid).to be issue.iid end end context 'the issue does not exist' do - let(:regex_match) { described_class.match("issue show 1234") } + let(:regex_match) { described_class.match("issue show 2343242") } it "returns nil" do - expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to start_with('404 not found!') + expect(subject).to be_nil end end end -- cgit v1.2.1 From 166ee0965bacc20e2ad1187321654499a9b0f825 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 17 Nov 2016 21:27:12 +0100 Subject: More refactoring, push present to base command --- spec/lib/gitlab/chat_commands/command_spec.rb | 9 +++++++++ spec/lib/gitlab/chat_name_token_spec.rb | 4 ++-- spec/models/project_spec.rb | 1 + spec/services/chat_names/authorize_user_service_spec.rb | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index 328187b5048..528e690d234 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -26,6 +26,15 @@ describe Gitlab::ChatCommands::Command, service: true do end end + context 'the user can not create an issue' do + let(:params) { { text: "issue create my new issue" } } + + 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 succesfully created' do let(:params) { { text: "issue create my new issue" } } diff --git a/spec/lib/gitlab/chat_name_token_spec.rb b/spec/lib/gitlab/chat_name_token_spec.rb index 8d7e7a99059..10153682973 100644 --- a/spec/lib/gitlab/chat_name_token_spec.rb +++ b/spec/lib/gitlab/chat_name_token_spec.rb @@ -12,9 +12,9 @@ describe Gitlab::ChatNameToken, lib: true do end context 'when storing data' do - let(:data) { + let(:data) do { key: 'value' } - } + end subject { described_class.new(@token) } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index c74d9c282cf..d89a83cfc71 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -35,6 +35,7 @@ describe Project, models: true do it { is_expected.to have_one(:hipchat_service).dependent(:destroy) } it { is_expected.to have_one(:flowdock_service).dependent(:destroy) } it { is_expected.to have_one(:assembla_service).dependent(:destroy) } + it { is_expected.to have_one(:mattermost_command_service).dependent(:destroy) } it { is_expected.to have_one(:gemnasium_service).dependent(:destroy) } it { is_expected.to have_one(:buildkite_service).dependent(:destroy) } it { is_expected.to have_one(:bamboo_service).dependent(:destroy) } diff --git a/spec/services/chat_names/authorize_user_service_spec.rb b/spec/services/chat_names/authorize_user_service_spec.rb index f8c26e51bfc..d5178176526 100644 --- a/spec/services/chat_names/authorize_user_service_spec.rb +++ b/spec/services/chat_names/authorize_user_service_spec.rb @@ -17,7 +17,7 @@ describe ChatNames::AuthorizeUserService, services: true do end context 'when there are missing parameters' do - let(:params) { { } } + let(:params) { {} } it 'does not request a new token' do is_expected.to be_nil -- cgit v1.2.1 From 8bd3f52667f4682ebfefa62024b901cabc928ed1 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 17 Nov 2016 20:58:38 +0000 Subject: Swaps url for paths in mock data --- spec/javascripts/environments/mock_data.js.es6 | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6 index 1142ace5846..9e16bc3e6a5 100644 --- a/spec/javascripts/environments/mock_data.js.es6 +++ b/spec/javascripts/environments/mock_data.js.es6 @@ -40,18 +40,18 @@ const environmentsList = [ avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', web_url: 'http://localhost:3000/root', }, - commit_url: 'http://localhost:3000/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', }, deployable: { id: 1278, name: 'build', - build_url: 'http://localhost:3000/root/ci-folders/builds/1278', - retry_url: 'http://localhost:3000/root/ci-folders/builds/1278/retry', + build_path: '/root/ci-folders/builds/1278', + retry_path: '/root/ci-folders/builds/1278/retry', }, manual_actions: [], }, 'stoppable?': true, - environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + environment_path: '/root/ci-folders/environments/31', created_at: '2016-11-07T11:11:16.525Z', updated_at: '2016-11-07T11:11:16.525Z', }, @@ -95,18 +95,18 @@ const environmentsList = [ avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', web_url: 'http://localhost:3000/root', }, - commit_url: 'http://localhost:3000/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', }, deployable: { id: 1278, name: 'build', - build_url: 'http://localhost:3000/root/ci-folders/builds/1278', - retry_url: 'http://localhost:3000/root/ci-folders/builds/1278/retry', + build_path: '/root/ci-folders/builds/1278', + retry_path: '/root/ci-folders/builds/1278/retry', }, manual_actions: [], }, 'stoppable?': false, - environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + environment_path: '/root/ci-folders/environments/31', created_at: '2016-11-07T11:11:16.525Z', updated_at: '2016-11-07T11:11:16.525Z', }, @@ -117,7 +117,7 @@ const environmentsList = [ environment_type: 'review', last_deployment: null, 'stoppable?': true, - environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + environment_path: '/root/ci-folders/environments/31', created_at: '2016-11-07T11:11:16.525Z', updated_at: '2016-11-07T11:11:16.525Z', }, @@ -128,9 +128,8 @@ const environmentsList = [ environment_type: 'review', last_deployment: null, 'stoppable?': true, - environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + environment_path: '/root/ci-folders/environments/31', created_at: '2016-11-07T11:11:16.525Z', updated_at: '2016-11-07T11:11:16.525Z', }, ]; - -- cgit v1.2.1 From 3228798b37cc98f6c7b92371cbf6d1800d1c280b Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Wed, 2 Nov 2016 21:38:43 +1000 Subject: Refactor github import to reduce number of API calls Ref #24073 --- spec/lib/gitlab/github_import/importer_spec.rb | 3 --- spec/lib/gitlab/github_import/issue_formatter_spec.rb | 10 +++++----- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/importer_spec.rb b/spec/lib/gitlab/github_import/importer_spec.rb index 7478f86bd28..000b9aa6f83 100644 --- a/spec/lib/gitlab/github_import/importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer_spec.rb @@ -101,7 +101,6 @@ describe Gitlab::GithubImport::Importer, lib: true do closed_at: nil, merged_at: nil, url: 'https://api.github.com/repos/octocat/Hello-World/pulls/1347', - labels: [double(name: 'Label #3')], ) end @@ -157,8 +156,6 @@ describe Gitlab::GithubImport::Importer, lib: true do errors: [ { type: :label, url: "https://api.github.com/repos/octocat/Hello-World/labels/bug", errors: "Validation failed: Title can't be blank, Title is invalid" }, { type: :issue, url: "https://api.github.com/repos/octocat/Hello-World/issues/1348", errors: "Validation failed: Title can't be blank, Title is too short (minimum is 0 characters)" }, - { type: :pull_request, url: "https://api.github.com/repos/octocat/Hello-World/pulls/1347", errors: "Invalid Repository. Use user/repo format." }, - { type: :pull_request, url: "https://api.github.com/repos/octocat/Hello-World/pulls/1347", errors: "Invalid Repository. Use user/repo format." }, { type: :wiki, errors: "Gitlab::Shell::Error" }, { type: :release, url: 'https://api.github.com/repos/octocat/Hello-World/releases/2', errors: "Validation failed: Description can't be blank" } ] diff --git a/spec/lib/gitlab/github_import/issue_formatter_spec.rb b/spec/lib/gitlab/github_import/issue_formatter_spec.rb index c2f1f6b91a1..95339e2f128 100644 --- a/spec/lib/gitlab/github_import/issue_formatter_spec.rb +++ b/spec/lib/gitlab/github_import/issue_formatter_spec.rb @@ -144,20 +144,20 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do end end - describe '#valid?' do + describe '#pull_request?' do context 'when mention a pull request' do let(:raw_data) { double(base_data.merge(pull_request: double)) } - it 'returns false' do - expect(issue.valid?).to eq false + it 'returns true' do + expect(issue.pull_request?).to eq true end end context 'when does not mention a pull request' do let(:raw_data) { double(base_data.merge(pull_request: nil)) } - it 'returns true' do - expect(issue.valid?).to eq true + it 'returns false' do + expect(issue.pull_request?).to eq false end end end -- cgit v1.2.1 From a08fba63be60dd011f4d1a639d4df8fbacb09d14 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Sat, 5 Nov 2016 17:28:29 +0000 Subject: Added empty state svg and set up blank conditional Added new spec step Added empty state to dashboard Split empty and filtered empty states Moved empty_state icons into their own folder and DRY up empty state html Fixed failing spec Added to groups page Review changes --- spec/features/issues/filter_issues_spec.rb | 10 +++++----- spec/features/issues_spec.rb | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb index 2798db92f0f..0d19563d628 100644 --- a/spec/features/issues/filter_issues_spec.rb +++ b/spec/features/issues/filter_issues_spec.rb @@ -3,8 +3,8 @@ require 'rails_helper' describe 'Filter issues', feature: true do include WaitForAjax - let!(:project) { create(:project) } let!(:group) { create(:group) } + let!(:project) { create(:project, group: group) } let!(:user) { create(:user)} let!(:milestone) { create(:milestone, project: project) } let!(:label) { create(:label, project: project) } @@ -127,7 +127,7 @@ describe 'Filter issues', feature: true do expect(page).to have_content wontfix.title end - find('body').click + find('.dropdown-menu-close-icon').click expect(find('.filtered-labels')).to have_content(wontfix.title) @@ -135,7 +135,7 @@ describe 'Filter issues', feature: true do wait_for_ajax find('.dropdown-menu-labels a', text: label.title).click - find('body').click + find('.dropdown-menu-close-icon').click expect(find('.filtered-labels')).to have_content(wontfix.title) expect(find('.filtered-labels')).to have_content(label.title) @@ -150,8 +150,8 @@ describe 'Filter issues', feature: true do it "selects and unselects `won't fix`" do find('.dropdown-menu-labels a', text: wontfix.title).click find('.dropdown-menu-labels a', text: wontfix.title).click - # Close label dropdown to load - find('body').click + + find('.dropdown-menu-close-icon').click expect(page).not_to have_css('.filtered-labels') end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index cdd02a8c8e3..5c958455604 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -371,10 +371,12 @@ describe 'Issues', feature: true do describe 'when I want to reset my incoming email token' do let(:project1) { create(:project, namespace: @user.namespace) } + let(:issue) { create(:issue, project: project1) } before do allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true) project1.team << [@user, :master] + project1.issues << issue visit namespace_project_issues_path(@user.namespace, project1) end @@ -576,7 +578,10 @@ describe 'Issues', feature: true do describe 'new issue by email' do shared_examples 'show the email in the modal' do + let(:issue) { create(:issue, project: project) } + before do + project.issues << issue stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") visit namespace_project_issues_path(project.namespace, project) -- cgit v1.2.1 From 8dd9a8b6e00cbd91f8455218397c8da716fc9b00 Mon Sep 17 00:00:00 2001 From: Oren Kanner Date: Thu, 17 Nov 2016 23:21:02 -0500 Subject: Allow admins to stop impersonating users without e-mail addresses Resolves #24576 Modify the guard clause of the `ApplicationController#require_email` before action to skip requests where an admin is impersonating the current user. --- .../admin/impersonations_controller_spec.rb | 28 ++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/controllers/admin/impersonations_controller_spec.rb b/spec/controllers/admin/impersonations_controller_spec.rb index 8be662974a0..8f1f0ba89ff 100644 --- a/spec/controllers/admin/impersonations_controller_spec.rb +++ b/spec/controllers/admin/impersonations_controller_spec.rb @@ -76,18 +76,32 @@ describe Admin::ImpersonationsController do end context "when the impersonator is not blocked" do - it "redirects to the impersonated user's page" do - expect(Gitlab::AppLogger).to receive(:info).with("User #{impersonator.username} has stopped impersonating #{user.username}").and_call_original + shared_examples_for "successfully stops impersonating" do + it "redirects to the impersonated user's page" do + expect(Gitlab::AppLogger).to receive(:info).with("User #{impersonator.username} has stopped impersonating #{user.username}").and_call_original - delete :destroy + delete :destroy + + expect(response).to redirect_to(admin_user_path(user)) + end + + it "signs us in as the impersonator" do + delete :destroy - expect(response).to redirect_to(admin_user_path(user)) + expect(warden.user).to eq(impersonator) + end end - it "signs us in as the impersonator" do - delete :destroy + # base case + it_behaves_like "successfully stops impersonating" + + context "and the user has a temporary oauth e-mail address" do + before do + allow(user).to receive(:temp_oauth_email?).and_return(true) + allow(controller).to receive(:current_user).and_return(user) + end - expect(warden.user).to eq(impersonator) + it_behaves_like "successfully stops impersonating" end end end -- cgit v1.2.1 From 78b6d6624be3a6d59710bf766e7253c2e6787f5a Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Wed, 16 Nov 2016 17:54:43 +0530 Subject: Allow registering users where the username contains dots (.). Javascript does not support the negative lookbehind assertion (? Date: Fri, 18 Nov 2016 08:13:34 +0100 Subject: fix spec failures --- spec/lib/gitlab/cycle_analytics/code_event_spec.rb | 8 ++--- .../lib/gitlab/cycle_analytics/issue_event_spec.rb | 8 ++--- spec/lib/gitlab/cycle_analytics/plan_event_spec.rb | 8 ++--- .../cycle_analytics/production_event_spec.rb | 2 +- .../gitlab/cycle_analytics/review_event_spec.rb | 2 +- .../gitlab/cycle_analytics/shared_event_spec.rb | 10 ++++--- .../gitlab/cycle_analytics/staging_event_spec.rb | 8 ++--- spec/lib/gitlab/cycle_analytics/test_event_spec.rb | 8 ++--- .../analytics_generic_serializer_spec.rb | 33 --------------------- .../serializers/analytics_issue_serializer_spec.rb | 33 +++++++++++++++++++++ .../analytics_merge_request_serializer_spec.rb | 34 ++++++++++++++++++++++ 11 files changed, 95 insertions(+), 59 deletions(-) delete mode 100644 spec/serializers/analytics_generic_serializer_spec.rb create mode 100644 spec/serializers/analytics_issue_serializer_spec.rb create mode 100644 spec/serializers/analytics_merge_request_serializer_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/code_event_spec.rb b/spec/lib/gitlab/cycle_analytics/code_event_spec.rb index 7b854d7fea1..43f42d1bde8 100644 --- a/spec/lib/gitlab/cycle_analytics/code_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/code_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::CodeEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).not_to eq(described_class.start_time_attrs) + it_behaves_like 'default query config' do + it 'does not have the default order' do + expect(event.order).not_to eq(event.start_time_attrs) + end end end diff --git a/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb index 2d7e7b1e0a5..1c5c308da7d 100644 --- a/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/issue_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::IssueEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) + it_behaves_like 'default query config' do + it 'has the default order' do + expect(event.order).to eq(event.start_time_attrs) + end end end diff --git a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb index 3452c146584..d76a255acf5 100644 --- a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::PlanEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) + it_behaves_like 'default query config' do + it 'has the default order' do + expect(event.order).to eq(event.start_time_attrs) + end end end diff --git a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb index 069c84efa09..6ee54f246a7 100644 --- a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb @@ -5,6 +5,6 @@ describe Gitlab::CycleAnalytics::ProductionEvent do it_behaves_like 'default query config' it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) + expect(event.order).to eq(event.start_time_attrs) end end diff --git a/spec/lib/gitlab/cycle_analytics/review_event_spec.rb b/spec/lib/gitlab/cycle_analytics/review_event_spec.rb index e9aca82ecc9..890e3ab3078 100644 --- a/spec/lib/gitlab/cycle_analytics/review_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/review_event_spec.rb @@ -5,6 +5,6 @@ describe Gitlab::CycleAnalytics::ReviewEvent do it_behaves_like 'default query config' it 'has the default order' do - expect(described_class.order).to eq(described_class.start_time_attrs) + expect(event.order).to eq(event.start_time_attrs) end end diff --git a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb index 1e76edce633..7019e4c3351 100644 --- a/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/shared_event_spec.rb @@ -1,19 +1,21 @@ require 'spec_helper' shared_examples 'default query config' do + let(:event) { described_class.new(project: double, options: {}) } + it 'has the start attributes' do - expect(described_class.start_time_attrs).not_to be_nil + expect(event.start_time_attrs).not_to be_nil end it 'has the stage attribute' do - expect(described_class.stage).not_to be_nil + expect(event.stage).not_to be_nil end it 'has the end attributes' do - expect(described_class.end_time_attrs).not_to be_nil + expect(event.end_time_attrs).not_to be_nil end it 'has the projection attributes' do - expect(described_class.projections).not_to be_nil + expect(event.projections).not_to be_nil end end diff --git a/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb index 9c1bec3edb1..4862d4765f2 100644 --- a/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/staging_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::StagingEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).not_to eq(described_class.start_time_attrs) + it_behaves_like 'default query config' do + it 'does not have the default order' do + expect(event.order).not_to eq(event.start_time_attrs) + end end end diff --git a/spec/lib/gitlab/cycle_analytics/test_event_spec.rb b/spec/lib/gitlab/cycle_analytics/test_event_spec.rb index 7238b9a34b3..e249db69fc6 100644 --- a/spec/lib/gitlab/cycle_analytics/test_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/test_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::TestEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(described_class.order).not_to eq(described_class.start_time_attrs) + it_behaves_like 'default query config' do + it 'does not have the default order' do + expect(event.order).not_to eq(event.start_time_attrs) + end end end diff --git a/spec/serializers/analytics_generic_serializer_spec.rb b/spec/serializers/analytics_generic_serializer_spec.rb deleted file mode 100644 index 99f2254d22c..00000000000 --- a/spec/serializers/analytics_generic_serializer_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'spec_helper' - -describe AnalyticsGenericSerializer do - let(:serializer) do - described_class - .new(project: project, entity: :merge_request) - .represent(resource) - end - - let(:user) { create(:user) } - let(:json) { serializer.as_json } - let(:project) { create(:project) } - let(:resource) do - { - total_time: "172802.724419", - title: "Eos voluptatem inventore in sed.", - iid: "1", - id: "1", - created_at: "2016-11-12 15:04:02.948604", - author: user, - } - end - - context 'when there is a single object provided' do - it 'it generates payload for single object' do - expect(json).to be_an_instance_of Hash - end - - it 'contains important elements of analyticsBuild' do - expect(json).to include(:title, :iid, :created_at, :total_time, :url, :author) - end - end -end diff --git a/spec/serializers/analytics_issue_serializer_spec.rb b/spec/serializers/analytics_issue_serializer_spec.rb new file mode 100644 index 00000000000..2842e1ba52f --- /dev/null +++ b/spec/serializers/analytics_issue_serializer_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe AnalyticsIssueSerializer do + let(:serializer) do + described_class + .new(project: project, entity: :merge_request) + .represent(resource) + end + + let(:user) { create(:user) } + let(:json) { serializer.as_json } + let(:project) { create(:project) } + let(:resource) do + { + total_time: "172802.724419", + title: "Eos voluptatem inventore in sed.", + iid: "1", + id: "1", + created_at: "2016-11-12 15:04:02.948604", + author: user, + } + end + + context 'when there is a single object provided' do + it 'it generates payload for single object' do + expect(json).to be_an_instance_of Hash + end + + it 'contains important elements of the issue' do + expect(json).to include(:title, :iid, :created_at, :total_time, :url, :author) + end + end +end diff --git a/spec/serializers/analytics_merge_request_serializer_spec.rb b/spec/serializers/analytics_merge_request_serializer_spec.rb new file mode 100644 index 00000000000..564207984df --- /dev/null +++ b/spec/serializers/analytics_merge_request_serializer_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe AnalyticsMergeRequestSerializer do + let(:serializer) do + described_class + .new(project: project, entity: :merge_request) + .represent(resource) + end + + let(:user) { create(:user) } + let(:json) { serializer.as_json } + let(:project) { create(:project) } + let(:resource) do + { + total_time: "172802.724419", + title: "Eos voluptatem inventore in sed.", + iid: "1", + id: "1", + state: 'open', + created_at: "2016-11-12 15:04:02.948604", + author: user + } + end + + context 'when there is a single object provided' do + it 'it generates payload for single object' do + expect(json).to be_an_instance_of Hash + end + + it 'contains important elements of the merge request' do + expect(json).to include(:title, :iid, :created_at, :total_time, :url, :author, :state) + end + end +end -- cgit v1.2.1 From f95fa7145b41dbeb0cbaea1e9677fb7dd65a2f04 Mon Sep 17 00:00:00 2001 From: Timothy Andrew Date: Thu, 17 Nov 2016 19:23:42 +0530 Subject: Write a spec covering the race condition during group deletion. - Use multiple threads / database connections to: 1. Escape the transaction the spec seems to be running in (`config.use_transactional_fixtures` is off, but `ActiveRecord::Base.connection.open_transactions` is not empty at the beginning of the spec. 2. Simulate a Sidekiq worker performing the hard delete outside of the soft-delete transaction. - The spec is a little clunky, but it was the smallest thing I could get working - and even this took a couple of hours. Let me know if you have any suggestions to improve it! --- spec/services/destroy_group_service_spec.rb | 40 +++++++++++++++++++++++++++++ spec/support/database_connection_helpers.rb | 9 +++++++ 2 files changed, 49 insertions(+) create mode 100644 spec/support/database_connection_helpers.rb (limited to 'spec') diff --git a/spec/services/destroy_group_service_spec.rb b/spec/services/destroy_group_service_spec.rb index da724643604..538e85cdc89 100644 --- a/spec/services/destroy_group_service_spec.rb +++ b/spec/services/destroy_group_service_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe DestroyGroupService, services: true do + include DatabaseConnectionHelpers + let!(:user) { create(:user) } let!(:group) { create(:group) } let!(:project) { create(:project, namespace: group) } @@ -50,6 +52,44 @@ describe DestroyGroupService, services: true do describe 'asynchronous delete' do it_behaves_like 'group destruction', true + + context 'potential race conditions' do + context "when the `GroupDestroyWorker` task runs immediately" do + it "deletes the group" do + # Commit the contents of this spec's transaction so far + # so subsequent db connections can see it. + # + # DO NOT REMOVE THIS LINE, even if you see a WARNING with "No + # transaction is currently in progress". Without this, this + # spec will always be green, since the group created in setup + # cannot be seen by any other connections / threads in this spec. + Group.connection.commit_db_transaction + + group_record = run_with_new_database_connection do |conn| + conn.execute("SELECT * FROM namespaces WHERE id = #{group.id}").first + end + + expect(group_record).not_to be_nil + + # Execute the contents of `GroupDestroyWorker` in a separate thread, to + # simulate data manipulation by the Sidekiq worker (different database + # connection / transaction). + expect(GroupDestroyWorker).to receive(:perform_async).and_wrap_original do |m, group_id, user_id| + Thread.new { m[group_id, user_id] }.join(5) + end + + # Kick off the initial group destroy in a new thread, so that + # it doesn't share this spec's database transaction. + Thread.new { DestroyGroupService.new(group, user).async_execute }.join(5) + + group_record = run_with_new_database_connection do |conn| + conn.execute("SELECT * FROM namespaces WHERE id = #{group.id}").first + end + + expect(group_record).to be_nil + end + end + end end describe 'synchronous delete' do diff --git a/spec/support/database_connection_helpers.rb b/spec/support/database_connection_helpers.rb new file mode 100644 index 00000000000..763329499f0 --- /dev/null +++ b/spec/support/database_connection_helpers.rb @@ -0,0 +1,9 @@ +module DatabaseConnectionHelpers + def run_with_new_database_connection + pool = ActiveRecord::Base.connection_pool + conn = pool.checkout + yield conn + ensure + pool.checkin(conn) + end +end -- cgit v1.2.1 From 0d04724fa1cd670124b8ad9a3860bfa476c50f99 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 18 Nov 2016 10:00:40 +0100 Subject: More coverage on service level --- spec/lib/gitlab/chat_commands/command_spec.rb | 2 +- spec/models/project_services/chat_service_spec.rb | 15 ++++ .../mattermost_command_service_spec.rb | 99 ++++++++++++++++++++++ spec/requests/api/services_spec.rb | 46 ++++++++++ spec/services/chat_names/find_user_service_spec.rb | 2 +- 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 spec/models/project_services/chat_service_spec.rb create mode 100644 spec/models/project_services/mattermost_command_service_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index 528e690d234..11b607a6843 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::ChatCommands::Command, service: true do - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:user) { create(:user) } subject { described_class.new(project, user, params).execute } diff --git a/spec/models/project_services/chat_service_spec.rb b/spec/models/project_services/chat_service_spec.rb new file mode 100644 index 00000000000..c6a45a3e1be --- /dev/null +++ b/spec/models/project_services/chat_service_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe ChatService, models: true do + describe "Associations" do + it { is_expected.to have_many :chat_names } + end + + describe '#valid_token?' do + subject { described_class.new } + + it 'is false as it has no token' do + expect(subject.valid_token?('wer')).to be_falsey + end + end +end diff --git a/spec/models/project_services/mattermost_command_service_spec.rb b/spec/models/project_services/mattermost_command_service_spec.rb new file mode 100644 index 00000000000..757ad687bc4 --- /dev/null +++ b/spec/models/project_services/mattermost_command_service_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + +describe MattermostCommandService, models: true do + describe "Associations" do + it { is_expected.to respond_to :token } + end + + describe '#valid_token?' do + subject { described_class.new } + + context 'when the token is empty' do + it 'is false' do + expect(subject.valid_token?('wer')).to be_falsey + end + end + + context 'when there is a token' do + before do + subject.token = '123' + end + + it 'accepts equal tokens' do + expect(subject.valid_token?('123')).to be_truthy + end + end + end + + describe '#trigger' do + subject { described_class.new } + + context 'no token is passed' do + let(:params) { Hash.new } + + it 'returns nil' do + expect(subject.trigger(params)).to be_nil + end + end + + context 'with a token passed' do + let(:project) { create(:empty_project) } + let(:params) { { token: 'token' } } + + before do + allow(subject).to receive(:token).and_return('token') + end + + context 'no user can be found' do + context 'when no url can be generated' do + it 'responds with the authorize url' do + response = subject.trigger(params) + + expect(response[:response_type]).to eq :ephemeral + expect(response[:text]).to start_with ":sweat_smile: Couldn't identify you" + end + end + + context 'when an auth url can be generated' do + let(:params) do + { + team_domain: 'http://domain.tld', + team_id: 'T3423423', + user_id: 'U234234', + user_name: 'mepmep', + token: 'token' + } + end + + let(:service) do + project.create_mattermost_command_service( + properties: { token: 'token' } + ) + end + + it 'generates the url' do + response = service.trigger(params) + + expect(response[:text]).to start_with(':wave: Hi there!') + end + end + end + + context 'when the user is authenticated' do + let!(:chat_name) { create(:chat_name, service: service) } + let(:service) do + project.create_mattermost_command_service( + properties: { token: 'token' } + ) + end + let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } } + + it 'triggers the command' do + expect_any_instance_of(Gitlab::ChatCommands::Command).to receive(:execute) + + service.trigger(params) + end + end + end + end +end diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 2aadab3cbe1..fb234ab8ed1 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -88,4 +88,50 @@ describe API::API, api: true do end end end + + describe 'POST /projects/:id/services/:slug/trigger' do + let!(:project) { create(:empty_project) } + let(:service_name) { 'mattermost_command' } + + context 'no service is available' do + it 'returns a not found message' do + post api("/projects/#{project.id}/services/mattermost_command/trigger") + + expect(response).to have_http_status(404) + end + end + + context 'the service exists' do + context 'the service is not active' do + let!(:inactive_service) do + project.create_mattermost_command_service( + active: false, + properties: { token: 'token' } + ) + end + + it 'when the service is inactive' do + post api("/projects/#{project.id}/services/mattermost_command/trigger") + + expect(response).to have_http_status(404) + end + end + + context 'the service is active' do + let!(:active_service) do + project.create_mattermost_command_service( + active: true, + properties: { token: 'token' } + ) + end + let(:params) { { token: 'token' } } + + it 'retusn status 200' do + post api("/projects/#{project.id}/services/mattermost_command/trigger"), params + + expect(response).to have_http_status(200) + end + end + end + end end diff --git a/spec/services/chat_names/find_user_service_spec.rb b/spec/services/chat_names/find_user_service_spec.rb index 5b885b2c657..51441e8f3be 100644 --- a/spec/services/chat_names/find_user_service_spec.rb +++ b/spec/services/chat_names/find_user_service_spec.rb @@ -13,7 +13,7 @@ describe ChatNames::FindUserService, services: true do context 'when existing user is requested' do let(:params) { { team_id: chat_name.team_id, user_id: chat_name.chat_id } } - it 'returns existing user' do + it 'returns the existing user' do is_expected.to eq(user) end -- cgit v1.2.1 From b8607576c1bb25fe2cbb575b48becdf7bd4aaa8c Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 18 Nov 2016 10:10:41 +0100 Subject: Projects have chat services --- spec/models/project_spec.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 45e0d783885..08eb3bc9cd4 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -20,6 +20,7 @@ describe Project, models: true do it { is_expected.to have_many(:deploy_keys) } it { is_expected.to have_many(:hooks).dependent(:destroy) } it { is_expected.to have_many(:protected_branches).dependent(:destroy) } + it { is_expected.to have_many(:chat_services).dependent(:destroy) } it { is_expected.to have_one(:forked_project_link).dependent(:destroy) } it { is_expected.to have_one(:slack_service).dependent(:destroy) } it { is_expected.to have_one(:pushover_service).dependent(:destroy) } -- cgit v1.2.1 From cd222357ade5f47f8d52f22dea66965c580a5843 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 18 Nov 2016 10:13:42 +0100 Subject: refactor events --- spec/lib/gitlab/cycle_analytics/production_event_spec.rb | 10 +++++----- spec/lib/gitlab/cycle_analytics/review_event_spec.rb | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb index 6ee54f246a7..5d12365c430 100644 --- a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::ProductionEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(event.order).to eq(event.start_time_attrs) + it_behaves_like 'default query config' do + it 'has the default order' do + expect(event.order).to eq(event.start_time_attrs) + end end -end +end \ No newline at end of file diff --git a/spec/lib/gitlab/cycle_analytics/review_event_spec.rb b/spec/lib/gitlab/cycle_analytics/review_event_spec.rb index 890e3ab3078..1ff53aa0227 100644 --- a/spec/lib/gitlab/cycle_analytics/review_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/review_event_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' require 'lib/gitlab/cycle_analytics/shared_event_spec' describe Gitlab::CycleAnalytics::ReviewEvent do - it_behaves_like 'default query config' - - it 'has the default order' do - expect(event.order).to eq(event.start_time_attrs) + it_behaves_like 'default query config' do + it 'has the default order' do + expect(event.order).to eq(event.start_time_attrs) + end end end -- cgit v1.2.1 From c76ef847817ac6346b2f367be63f482ee2df382a Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 18 Nov 2016 10:50:47 +0100 Subject: run pipeline worker in cycle analytics dev setup --- spec/lib/gitlab/cycle_analytics/production_event_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb index 5d12365c430..ac17e3b4287 100644 --- a/spec/lib/gitlab/cycle_analytics/production_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/production_event_spec.rb @@ -7,4 +7,4 @@ describe Gitlab::CycleAnalytics::ProductionEvent do expect(event.order).to eq(event.start_time_attrs) end end -end \ No newline at end of file +end -- cgit v1.2.1 From f749fb7fe0574d07eeb38561b9af62754e518281 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 18 Nov 2016 11:38:54 +0100 Subject: Improve style, add more tests --- spec/lib/gitlab/chat_commands/command_spec.rb | 6 +++++- spec/lib/gitlab/chat_commands/issue_create_spec.rb | 2 +- spec/lib/gitlab/import_export/all_models.yml | 4 +++- .../project_services/mattermost_command_service_spec.rb | 10 +++++----- spec/requests/api/services_spec.rb | 12 +++++++++++- 5 files changed, 25 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index 11b607a6843..f44c848479e 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -7,7 +7,7 @@ describe Gitlab::ChatCommands::Command, service: true do subject { described_class.new(project, user, params).execute } describe '#execute' do - context 'when no command is not available' do + context 'when no command is available' do let(:params) { { text: 'issue show 1' } } let(:project) { create(:project, has_external_issue_tracker: true) } @@ -45,6 +45,10 @@ describe Gitlab::ChatCommands::Command, service: true do 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 end end diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_create_spec.rb index 4831f24efed..df0c317ccea 100644 --- a/spec/lib/gitlab/chat_commands/issue_create_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_create_spec.rb @@ -34,7 +34,7 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do end end - describe 'self.match' do + describe '.match' do it 'matches the title without description' do match = described_class.match("issue create my title") diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 02b11bd999a..bc837299b9e 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -116,6 +116,7 @@ project: - base_tags - tag_taggings - tags +- chat_services - creator - group - namespace @@ -127,6 +128,7 @@ project: - emails_on_push_service - builds_email_service - pipelines_email_service +- mattermost_command_service - irker_service - pivotaltracker_service - hipchat_service @@ -188,4 +190,4 @@ award_emoji: - awardable - user priorities: -- label \ No newline at end of file +- label diff --git a/spec/models/project_services/mattermost_command_service_spec.rb b/spec/models/project_services/mattermost_command_service_spec.rb index 757ad687bc4..21bf1d35e3f 100644 --- a/spec/models/project_services/mattermost_command_service_spec.rb +++ b/spec/models/project_services/mattermost_command_service_spec.rb @@ -55,11 +55,11 @@ describe MattermostCommandService, models: true do end context 'when an auth url can be generated' do - let(:params) do + let(:params) do { - team_domain: 'http://domain.tld', - team_id: 'T3423423', - user_id: 'U234234', + team_domain: 'http://domain.tld', + team_id: 'T3423423', + user_id: 'U234234', user_name: 'mepmep', token: 'token' } @@ -72,7 +72,7 @@ describe MattermostCommandService, models: true do end it 'generates the url' do - response = service.trigger(params) + response = service.trigger(params) expect(response[:text]).to start_with(':wave: Hi there!') end diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index fb234ab8ed1..765d662e52b 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -102,6 +102,8 @@ describe API::API, api: true do end context 'the service exists' do + let(:params) { { token: 'token' } } + context 'the service is not active' do let!(:inactive_service) do project.create_mattermost_command_service( @@ -124,7 +126,6 @@ describe API::API, api: true do properties: { token: 'token' } ) end - let(:params) { { token: 'token' } } it 'retusn status 200' do post api("/projects/#{project.id}/services/mattermost_command/trigger"), params @@ -132,6 +133,15 @@ describe API::API, api: true do expect(response).to have_http_status(200) end end + + context 'when the project can not be found' do + it 'returns a generic 404' do + post api("/projects/404/services/mattermost_command/trigger"), params + + expect(response).to have_http_status(404) + expect(json_response["message"]).to eq '404 Not Found' + end + end end end end -- cgit v1.2.1 From 2fb862ccc6687273ada997743392d9dab7b31d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 18 Nov 2016 12:02:45 +0100 Subject: Rely on Gitlab::Shell public API, not reading internal files it may use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It ensures we rely on `Gitlab::Shell`'s public API and not on its internal. Since `Gitlab::Shell` is caching the value of its token, the only way to get the correct token is to call `Gitlab::Shell.secret_token`, not to read the `Gitlab.config.gitlab_shell.secret_file` file! Signed-off-by: Rémy Coutable --- spec/requests/api/internal_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 8f1a1f9e827..03796f20e36 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -5,7 +5,7 @@ describe API::API, api: true do let(:user) { create(:user) } let(:key) { create(:key, user: user) } let(:project) { create(:project) } - let(:secret_token) { File.read Gitlab.config.gitlab_shell.secret_file } + let(:secret_token) { Gitlab::Shell.secret_token } describe "GET /internal/check", no_db: true do it do -- cgit v1.2.1 From cb353d655bd8802c14a1e12e0fe78a1f7cc2e4ed Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 18 Nov 2016 12:05:29 +0100 Subject: added new build updater, specs and refactored allowed_ids --- spec/lib/gitlab/cycle_analytics/author_updater_spec.rb | 12 ++++++++++++ spec/lib/gitlab/cycle_analytics/build_updater_spec.rb | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 spec/lib/gitlab/cycle_analytics/author_updater_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/build_updater_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb new file mode 100644 index 00000000000..f9e4d1714e6 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe Gitlab::CycleAnalytics::AuthorUpdater do + let(:user) { create(:user) } + let(:events) { [{ 'author_id' => user.id }] } + + it 'maps the correct user' do + described_class.update!(events) + + expect(events.first['author']).to eq(user) + end +end diff --git a/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb new file mode 100644 index 00000000000..8e461f6c6ea --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe Gitlab::CycleAnalytics::BuildUpdater do + let(:build) { create(:ci_build) } + let(:events) { [{ 'id' => build.id }] } + + it 'maps the correct user' do + described_class.update!(events) + + expect(events.first['build']).to eq(build) + end +end -- cgit v1.2.1 From 0aa477884c6ac3298f79f62e08e63294d81735a3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 18 Nov 2016 12:09:36 +0100 Subject: fix small typo --- spec/lib/gitlab/cycle_analytics/build_updater_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb index 8e461f6c6ea..70886d7b453 100644 --- a/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb @@ -4,7 +4,7 @@ describe Gitlab::CycleAnalytics::BuildUpdater do let(:build) { create(:ci_build) } let(:events) { [{ 'id' => build.id }] } - it 'maps the correct user' do + it 'maps the correct build' do described_class.update!(events) expect(events.first['build']).to eq(build) -- cgit v1.2.1 From dd826a5f20837f33263c658e41a4def0fc932069 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 18 Nov 2016 12:08:30 +0100 Subject: Return a consistent not found message This prevents leakage of project names on an endpoint which is unauthenticated and thus open to the world. --- spec/models/project_spec.rb | 2 +- spec/requests/api/services_spec.rb | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 08eb3bc9cd4..1972a8bb3f4 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -20,7 +20,7 @@ describe Project, models: true do it { is_expected.to have_many(:deploy_keys) } it { is_expected.to have_many(:hooks).dependent(:destroy) } it { is_expected.to have_many(:protected_branches).dependent(:destroy) } - it { is_expected.to have_many(:chat_services).dependent(:destroy) } + it { is_expected.to have_many(:chat_services) } it { is_expected.to have_one(:forked_project_link).dependent(:destroy) } it { is_expected.to have_one(:slack_service).dependent(:destroy) } it { is_expected.to have_one(:pushover_service).dependent(:destroy) } diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 765d662e52b..782d76db318 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -95,9 +95,10 @@ describe API::API, api: true do context 'no service is available' do it 'returns a not found message' do - post api("/projects/#{project.id}/services/mattermost_command/trigger") + post api("/projects/#{project.id}/services/idonotexist/trigger") expect(response).to have_http_status(404) + expect(json_response["message"]).to eq("404 Service Not Found") end end @@ -139,7 +140,7 @@ describe API::API, api: true do post api("/projects/404/services/mattermost_command/trigger"), params expect(response).to have_http_status(404) - expect(json_response["message"]).to eq '404 Not Found' + expect(json_response["message"]).to eq("404 Service Not Found") end end end -- cgit v1.2.1 From 6b5aa83354b3dff903eb099bf03da733c36958fc Mon Sep 17 00:00:00 2001 From: jacopo-beschi-intersail Date: Mon, 14 Nov 2016 14:11:55 +0100 Subject: Fix Admin Links to new Group does not respect Default Visibility Settings This is done by passing a visibility_level option to the group edit _form. The visibility_level is set to @group.visibility_level in edit ation and to default_group_visibility in the new action. --- spec/features/admin/admin_groups_spec.rb | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 spec/features/admin/admin_groups_spec.rb (limited to 'spec') diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb new file mode 100644 index 00000000000..f6d625fa7f6 --- /dev/null +++ b/spec/features/admin/admin_groups_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +feature 'Admin Groups', feature: true do + let(:internal) { Gitlab::VisibilityLevel::INTERNAL } + + before do + login_as(:admin) + + stub_application_setting(default_group_visibility: internal) + end + + describe 'create a group' do + scenario 'shows the visibility level radio populated with the default value' do + visit new_admin_group_path + + expect_selected_visibility(internal) + end + end + + describe 'group edit' do + scenario 'shows the visibility level radio populated with the group visibility_level value' do + group = create(:group, :private) + + visit edit_admin_group_path(group) + + expect_selected_visibility(group.visibility_level) + end + end + + def expect_selected_visibility(level) + selector = "#group_visibility_level_#{level}[checked=checked]" + + expect(page).to have_selector(selector, count: 1) + end +end -- cgit v1.2.1 From 2a085e5edddbeb7927d8f8d4413bed8a1ff74f49 Mon Sep 17 00:00:00 2001 From: winniehell Date: Fri, 18 Nov 2016 12:32:52 +0100 Subject: Add missing require statements to build_spec --- spec/javascripts/build_spec.js.es6 | 2 ++ 1 file changed, 2 insertions(+) (limited to 'spec') diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index 370944b6a8c..b329ad8062a 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -1,5 +1,7 @@ /* global Build */ /* eslint-disable no-new */ +//= require lib/utils/timeago +//= require lib/utils/datetime_utility //= require build //= require breakpoints //= require jquery.nicescroll -- cgit v1.2.1 From f5b792e22eb7bd4ecafcd2ad3bc7a388abb36ffc Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 18 Nov 2016 13:00:38 +0100 Subject: refactored updater and updated specs --- .../gitlab/cycle_analytics/author_updater_spec.rb | 12 ----------- .../gitlab/cycle_analytics/build_updater_spec.rb | 12 ----------- spec/lib/gitlab/cycle_analytics/updater_spec.rb | 25 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 24 deletions(-) delete mode 100644 spec/lib/gitlab/cycle_analytics/author_updater_spec.rb delete mode 100644 spec/lib/gitlab/cycle_analytics/build_updater_spec.rb create mode 100644 spec/lib/gitlab/cycle_analytics/updater_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb deleted file mode 100644 index f9e4d1714e6..00000000000 --- a/spec/lib/gitlab/cycle_analytics/author_updater_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe Gitlab::CycleAnalytics::AuthorUpdater do - let(:user) { create(:user) } - let(:events) { [{ 'author_id' => user.id }] } - - it 'maps the correct user' do - described_class.update!(events) - - expect(events.first['author']).to eq(user) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb b/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb deleted file mode 100644 index 70886d7b453..00000000000 --- a/spec/lib/gitlab/cycle_analytics/build_updater_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe Gitlab::CycleAnalytics::BuildUpdater do - let(:build) { create(:ci_build) } - let(:events) { [{ 'id' => build.id }] } - - it 'maps the correct build' do - described_class.update!(events) - - expect(events.first['build']).to eq(build) - end -end diff --git a/spec/lib/gitlab/cycle_analytics/updater_spec.rb b/spec/lib/gitlab/cycle_analytics/updater_spec.rb new file mode 100644 index 00000000000..eff54cd3692 --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/updater_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Gitlab::CycleAnalytics::Updater do + describe 'updates authors' do + let(:user) { create(:user) } + let(:events) { [{ 'author_id' => user.id }] } + + it 'maps the correct user' do + described_class.update!(events, from: 'author_id', to: 'author', klass: User) + + expect(events.first['author']).to eq(user) + end + end + + describe 'updates builds' do + let(:build) { create(:ci_build) } + let(:events) { [{ 'id' => build.id }] } + + it 'maps the correct build' do + described_class.update!(events, from: 'id', to: 'build', klass: ::Ci::Build) + + expect(events.first['build']).to eq(build) + end + end +end -- cgit v1.2.1 From 85dd05b5b3afb27743998b4f3f9f042b5b5bfa81 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 9 Nov 2016 19:55:21 -0200 Subject: Add JIRA remotelinks and prevent duplicated closing messages --- spec/models/project_services/jira_service_spec.rb | 44 +++++++++++++++++++++ spec/services/git_push_service_spec.rb | 10 +++++ spec/services/merge_requests/merge_service_spec.rb | 6 ++- spec/services/system_note_service_spec.rb | 45 +++++++++++++++++++++- spec/support/jira_service_helper.rb | 5 +++ 5 files changed, 106 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 05ee4a08391..699cd9a5bb2 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -85,17 +85,30 @@ describe JiraService, models: true do project_key: 'GitLabProject' ) + # These stubs are needed to test JiraService#close_issue. + # We close the issue then do another request to API to check if it got closed. + # Here is stubbed the API return with a closed and an opened issues. + open_issue = JIRA::Resource::Issue.new(@jira_service.client, attrs: { "id" => "JIRA-123" }) + closed_issue = open_issue.dup + allow(open_issue).to receive(:resolution).and_return(false) + allow(closed_issue).to receive(:resolution).and_return(true) + allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue) + + allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return("JIRA-123") + @jira_service.save project_issues_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123' @project_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/project/GitLabProject' @transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions' @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment' + @remote_link_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/remotelink' WebMock.stub_request(:get, @project_url) WebMock.stub_request(:get, project_issues_url) WebMock.stub_request(:post, @transitions_url) WebMock.stub_request(:post, @comment_url) + WebMock.stub_request(:post, @remote_link_url) end it "calls JIRA API" do @@ -106,6 +119,37 @@ describe JiraService, models: true do ).once end + # Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links + # for more information + it "creates Remote Link reference in JIRA for comment" do + @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) + + # Creates comment + expect(WebMock).to have_requested(:post, @comment_url) + + # Creates Remote Link in JIRA issue fields + expect(WebMock).to have_requested(:post, @remote_link_url).with( + body: hash_including( + GlobalID: "GitLab", + object: { + url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/#{merge_request.diff_head_sha}", + title: "GitLab: Solved by commit #{merge_request.diff_head_sha}.", + icon: { title: "GitLab", url16x16: "https://gitlab.com/favicon.ico" }, + status: { resolved: true, icon: { url16x16: "http://www.openwebgraphics.com/resources/data/1768/16x16_apply.png", title: "Closed" } } + } + ) + ).once + end + + it "does not send comment or remote links to issues already closed" do + allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true) + + @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) + + expect(WebMock).not_to have_requested(:post, @comment_url) + expect(WebMock).not_to have_requested(:post, @remote_link_url) + end + it "references the GitLab commit/merge request" do @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index cea7e6429f9..a67e071341f 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -492,6 +492,16 @@ describe GitPushService, services: true do let(:message) { "this is some work.\n\ncloses JIRA-1" } let(:comment_body) { { body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." }.to_json } + before do + open_issue = JIRA::Resource::Issue.new(jira_tracker.client, attrs: { "id" => "JIRA-1" }) + closed_issue = open_issue.dup + allow(open_issue).to receive(:resolution).and_return(false) + allow(closed_issue).to receive(:resolution).and_return(true) + allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue) + + allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return("JIRA-1") + end + context "using right markdown" do it "initiates one api call to jira server to close the issue" do execute_service(project, commit_author, @oldrev, @newrev, @ref ) diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index f93d7732a9a..1fd9f5a4910 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -67,17 +67,19 @@ describe MergeRequests::MergeService, services: true do it 'closes issues on JIRA issue tracker' do jira_issue = ExternalIssue.new('JIRA-123', project) + stub_jira_urls(jira_issue) commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}") allow(merge_request).to receive(:commits).and_return([commit]) - expect_any_instance_of(JiraService).to receive(:close_issue).with(merge_request, jira_issue).once + expect_any_instance_of(JiraService).to receive(:close_issue).with(merge_request, an_instance_of(JIRA::Resource::Issue)).once service.execute(merge_request) end context "wrong issue markdown" do it 'does not close issues on JIRA issue tracker' do - jira_issue = ExternalIssue.new('#123', project) + jira_issue = ExternalIssue.new('#JIRA-123', project) + stub_jira_urls(jira_issue) commit = double('commit', safe_message: "Fixes #{jira_issue.to_reference}") allow(merge_request).to receive(:commits).and_return([commit]) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 5bb107fdd85..56d39e9a005 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe SystemNoteService, services: true do + include Gitlab::Routing.url_helpers + let(:project) { create(:project) } let(:author) { create(:user) } let(:noteable) { create(:issue, project: project) } @@ -543,23 +545,55 @@ describe SystemNoteService, services: true do before { stub_jira_urls(jira_issue.id) } - context 'in JIRA issue tracker' do + context 'in issue' do before { jira_service_settings } describe "new reference" do subject { described_class.cross_reference(jira_issue, commit, author) } it { is_expected.to eq(success_message) } + + it "creates remote link" do + subject + + expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with( + body: hash_including( + GlobalID: "GitLab", + object: { + url: namespace_project_commit_url(project.namespace, project, commit), + title: "GitLab: Mentioned on commit - #{commit.title}", + icon: { title: "GitLab", url16x16: "https://gitlab.com/favicon.ico" }, + status: { resolved: false } + } + ) + ).once + end end end - context 'issue from an issue' do + context 'in commit' do context 'in JIRA issue tracker' do before { jira_service_settings } subject { described_class.cross_reference(jira_issue, issue, author) } it { is_expected.to eq(success_message) } + + it "creates remote link" do + subject + + expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with( + body: hash_including( + GlobalID: "GitLab", + object: { + url: namespace_project_issue_url(project.namespace, project, issue), + title: "GitLab: Mentioned on issue - #{issue.title}", + icon: { title: "GitLab", url16x16: "https://gitlab.com/favicon.ico" }, + status: { resolved: false } + } + ) + ).once + end end end @@ -572,6 +606,13 @@ describe SystemNoteService, services: true do subject { described_class.cross_reference(jira_issue, commit, author) } it { is_expected.not_to eq(success_message) } + + it 'does not try to create comment and remote link' do + subject + + expect(WebMock).not_to have_requested(:post, jira_api_comment_url(jira_issue)) + expect(WebMock).not_to have_requested(:post, jira_api_remote_link_url(jira_issue)) + end end end end diff --git a/spec/support/jira_service_helper.rb b/spec/support/jira_service_helper.rb index 96e0dad6b55..7437ba2688d 100644 --- a/spec/support/jira_service_helper.rb +++ b/spec/support/jira_service_helper.rb @@ -57,6 +57,10 @@ module JiraServiceHelper JIRA_API + "/issue/#{issue_id}/comment" end + def jira_api_remote_link_url(issue_id) + JIRA_API + "/issue/#{issue_id}/remotelink" + end + def jira_api_transition_url(issue_id) JIRA_API + "/issue/#{issue_id}/transitions" end @@ -75,6 +79,7 @@ module JiraServiceHelper WebMock.stub_request(:get, jira_issue_url(issue_id)) WebMock.stub_request(:get, jira_api_test_url) WebMock.stub_request(:post, jira_api_comment_url(issue_id)) + WebMock.stub_request(:post, jira_api_remote_link_url(issue_id)) WebMock.stub_request(:post, jira_api_transition_url(issue_id)) end end -- cgit v1.2.1 From 9c4e0d64451bd76b829e1bb66afab892e19926da Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 18 Nov 2016 20:17:10 +0800 Subject: Use `Gitlab.config.gitlab.host` over `'localhost'` This would fix long standing failures running tests on my development machine, which set `Gitlab.config.gitlab.host` to another host because it's not my local computer. Now I finally cannot withstand it and decided to fix them once and for all. --- spec/helpers/application_helper_spec.rb | 4 ++-- spec/helpers/gitlab_markdown_helper_spec.rb | 2 +- spec/lib/gitlab/middleware/go_spec.rb | 2 +- spec/mailers/emails/profile_spec.rb | 2 +- spec/models/key_spec.rb | 2 +- spec/models/project_services/gitlab_issue_tracker_service_spec.rb | 6 +++--- spec/models/project_spec.rb | 4 ++-- spec/requests/api/internal_spec.rb | 2 +- spec/services/git_push_service_spec.rb | 2 +- spec/services/merge_requests/get_urls_service_spec.rb | 6 +++--- 10 files changed, 16 insertions(+), 16 deletions(-) (limited to 'spec') diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index c706e418d26..15863d444f8 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -57,7 +57,7 @@ describe ApplicationHelper do it 'returns an url for the avatar' do project = create(:project, avatar: File.open(avatar_file_path)) - avatar_url = "http://localhost/uploads/project/avatar/#{project.id}/banana_sample.gif" + avatar_url = "http://#{Gitlab.config.gitlab.host}/uploads/project/avatar/#{project.id}/banana_sample.gif" expect(helper.project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s). to eq "\"Banana" end @@ -67,7 +67,7 @@ describe ApplicationHelper do allow_any_instance_of(Project).to receive(:avatar_in_git).and_return(true) - avatar_url = 'http://localhost' + namespace_project_avatar_path(project.namespace, project) + avatar_url = "http://#{Gitlab.config.gitlab.host}#{namespace_project_avatar_path(project.namespace, project)}" expect(helper.project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).to match( image_tag(avatar_url)) end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 5368e5fab06..1d494edcd3b 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -113,7 +113,7 @@ describe GitlabMarkdownHelper do it 'replaces commit message with emoji to link' do actual = link_to_gfm(':book:Book', '/foo') expect(actual). - to eq %Q(:book:Book) + to eq %Q(:book:Book) end end diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb index 117a15264da..fd3769d75b5 100644 --- a/spec/lib/gitlab/middleware/go_spec.rb +++ b/spec/lib/gitlab/middleware/go_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::Middleware::Go, lib: true do resp = middleware.call(env) expect(resp[0]).to eq(200) expect(resp[1]['Content-Type']).to eq('text/html') - expected_body = "\n" + expected_body = "\n" expect(resp[2].body).to eq([expected_body]) end end diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb index 14bc062ef12..e1877d5fde0 100644 --- a/spec/mailers/emails/profile_spec.rb +++ b/spec/mailers/emails/profile_spec.rb @@ -25,7 +25,7 @@ describe Notify do it 'includes a link for user to set password' do params = "reset_password_token=#{token}" is_expected.to have_body_text( - %r{http://localhost(:\d+)?/users/password/edit\?#{params}} + %r{http://#{Gitlab.config.gitlab.host}(:\d+)?/users/password/edit\?#{params}} ) end diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 1a26cee9f3d..90731f55470 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -19,7 +19,7 @@ describe Key, models: true do describe "#publishable_keys" do it 'replaces SSH key comment with simple identifier of username + hostname' do - expect(build(:key, user: user).publishable_key).to include("#{user.name} (localhost)") + expect(build(:key, user: user).publishable_key).to include("#{user.name} (#{Gitlab.config.gitlab.host})") end end end diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index 652804fb444..9b80f0e7296 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -35,9 +35,9 @@ describe GitlabIssueTrackerService, models: true do end it 'gives the correct path' do - expect(@service.project_url).to eq("http://localhost/gitlab/root/#{project.path_with_namespace}/issues") - expect(@service.new_issue_url).to eq("http://localhost/gitlab/root/#{project.path_with_namespace}/issues/new") - expect(@service.issue_url(432)).to eq("http://localhost/gitlab/root/#{project.path_with_namespace}/issues/432") + expect(@service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues") + expect(@service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new") + expect(@service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432") end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 46fa00a79c4..42aa617cb1e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -700,7 +700,7 @@ describe Project, models: true do "/uploads/project/avatar/#{project.id}/uploads/avatar.png" end - it { should eq "http://localhost#{avatar_path}" } + it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" } end context 'When avatar file in git' do @@ -712,7 +712,7 @@ describe Project, models: true do "/#{project.namespace.name}/#{project.path}/avatar" end - it { should eq "http://localhost#{avatar_path}" } + it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" } end context 'when git repo is empty' do diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 8f1a1f9e827..d91628807ef 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -406,7 +406,7 @@ describe API::API, api: true do it 'returns link to create new merge request' do expect(json_response).to match [{ "branch_name" => "new_branch", - "url" => "http://localhost/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch", + "url" => "http://#{Gitlab.config.gitlab.host}/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch", "new_merge_request" => true }] end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index cea7e6429f9..6358f1fed71 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -490,7 +490,7 @@ describe GitPushService, services: true do context "closing an issue" do let(:message) { "this is some work.\n\ncloses JIRA-1" } - let(:comment_body) { { body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." }.to_json } + let(:comment_body) { { body: "Issue solved with [#{closing_commit.id}|http://#{Gitlab.config.gitlab.host}/#{project.path_with_namespace}/commit/#{closing_commit.id}]." }.to_json } context "using right markdown" do it "initiates one api call to jira server to close the issue" do diff --git a/spec/services/merge_requests/get_urls_service_spec.rb b/spec/services/merge_requests/get_urls_service_spec.rb index 3a71776e81f..08829e4be70 100644 --- a/spec/services/merge_requests/get_urls_service_spec.rb +++ b/spec/services/merge_requests/get_urls_service_spec.rb @@ -4,8 +4,8 @@ describe MergeRequests::GetUrlsService do let(:project) { create(:project, :public) } let(:service) { MergeRequests::GetUrlsService.new(project) } let(:source_branch) { "my_branch" } - let(:new_merge_request_url) { "http://localhost/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=#{source_branch}" } - let(:show_merge_request_url) { "http://localhost/#{project.namespace.name}/#{project.path}/merge_requests/#{merge_request.iid}" } + let(:new_merge_request_url) { "http://#{Gitlab.config.gitlab.host}/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=#{source_branch}" } + let(:show_merge_request_url) { "http://#{Gitlab.config.gitlab.host}/#{project.namespace.name}/#{project.path}/merge_requests/#{merge_request.iid}" } let(:new_branch_changes) { "#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{source_branch}" } let(:deleted_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 #{Gitlab::Git::BLANK_SHA} refs/heads/#{source_branch}" } let(:existing_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/#{source_branch}" } @@ -115,7 +115,7 @@ describe MergeRequests::GetUrlsService do let(:new_branch_changes) { "#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new_branch" } let(:existing_branch_changes) { "d14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/existing_branch" } let(:changes) { "#{new_branch_changes}\n#{existing_branch_changes}" } - let(:new_merge_request_url) { "http://localhost/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch" } + let(:new_merge_request_url) { "http://#{Gitlab.config.gitlab.host}/#{project.namespace.name}/#{project.path}/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch" } it 'returns 2 urls for both creating new and showing merge request' do result = service.execute(changes) -- cgit v1.2.1 From eef360912320ecfcb427684edf35672b643a87c0 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 18 Nov 2016 14:52:39 +0200 Subject: Add shortcuts for adding users to a project team with a specific role This also updates _some_ specs to use these new methods, just to serve as an example for others going forward, but by no means is this exhaustive. Original implementations at !5992 and !6012. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/20944 --- spec/controllers/autocomplete_controller_spec.rb | 30 ++++++------ spec/models/project_spec.rb | 7 +++ spec/models/project_team_spec.rb | 34 +++++++------- spec/services/notification_service_spec.rb | 60 ++++++++++++------------ 4 files changed, 69 insertions(+), 62 deletions(-) (limited to 'spec') diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index a121cb2fc97..d9a86346c81 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -11,7 +11,7 @@ describe AutocompleteController do context 'project members' do before do sign_in(user) - project.team << [user, :master] + project.add_master(user) end describe 'GET #users with project ID' do @@ -69,7 +69,7 @@ describe AutocompleteController do before do sign_in(non_member) - project.team << [user, :master] + project.add_master(user) end let(:body) { JSON.parse(response.body) } @@ -103,7 +103,7 @@ describe AutocompleteController do describe 'GET #users with public project' do before do - public_project.team << [user, :guest] + public_project.add_guest(user) get(:users, project_id: public_project.id) end @@ -129,7 +129,7 @@ describe AutocompleteController do describe 'GET #users with inaccessible group' do before do - project.team << [user, :guest] + project.add_guest(user) get(:users, group_id: user.namespace.id) end @@ -186,12 +186,12 @@ describe AutocompleteController do before do sign_in(user) - project.team << [user, :master] + project.add_master(user) end context 'authorized projects' do before do - authorized_project.team << [user, :master] + authorized_project.add_master(user) end describe 'GET #projects with project ID' do @@ -216,8 +216,8 @@ describe AutocompleteController do context 'authorized projects and search' do before do - authorized_project.team << [user, :master] - authorized_search_project.team << [user, :master] + authorized_project.add_master(user) + authorized_search_project.add_master(user) end describe 'GET #projects with project ID and search' do @@ -242,9 +242,9 @@ describe AutocompleteController do authorized_project2 = create(:project) authorized_project3 = create(:project) - authorized_project.team << [user, :master] - authorized_project2.team << [user, :master] - authorized_project3.team << [user, :master] + authorized_project.add_master(user) + authorized_project2.add_master(user) + authorized_project3.add_master(user) stub_const 'MoveToProjectFinder::PAGE_SIZE', 2 end @@ -268,9 +268,9 @@ describe AutocompleteController do authorized_project2 = create(:project) authorized_project3 = create(:project) - authorized_project.team << [user, :master] - authorized_project2.team << [user, :master] - authorized_project3.team << [user, :master] + authorized_project.add_master(user) + authorized_project2.add_master(user) + authorized_project3.add_master(user) end describe 'GET #projects with project ID and offset_id' do @@ -289,7 +289,7 @@ describe AutocompleteController do context 'authorized projects without admin_issue ability' do before(:each) do - authorized_project.team << [user, :guest] + authorized_project.add_guest(user) expect(user.can?(:admin_issue, authorized_project)).to eq(false) end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 46fa00a79c4..2fae3dde58c 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -241,6 +241,13 @@ describe Project, models: true do it { is_expected.to respond_to(:path_with_namespace) } end + describe 'delegation' do + it { is_expected.to delegate_method(:add_guest).to(:team) } + it { is_expected.to delegate_method(:add_reporter).to(:team) } + it { is_expected.to delegate_method(:add_developer).to(:team) } + it { is_expected.to delegate_method(:add_master).to(:team) } + end + describe '#name_with_namespace' do let(:project) { build_stubbed(:empty_project) } diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 12228425579..eb6b009c7cf 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -10,9 +10,9 @@ describe ProjectTeam, models: true do let(:project) { create(:empty_project) } before do - project.team << [master, :master] - project.team << [reporter, :reporter] - project.team << [guest, :guest] + project.add_master(master) + project.add_reporter(reporter) + project.add_guest(guest) end describe 'members collection' do @@ -47,8 +47,8 @@ describe ProjectTeam, models: true do # If user is a group and a project member - GitLab uses highest permission # So we add group guest as master and add group master as guest # to this project to test highest access - project.team << [guest, :master] - project.team << [master, :guest] + project.add_master(guest) + project.add_guest(master) end describe 'members collection' do @@ -79,14 +79,14 @@ describe ProjectTeam, models: true do it 'returns project members' do user = create(:user) - project.team << [user, :guest] + project.add_guest(user) expect(project.team.members).to contain_exactly(user) end it 'returns project members of a specified level' do user = create(:user) - project.team << [user, :reporter] + project.add_reporter(user) expect(project.team.guests).to be_empty expect(project.team.reporters).to contain_exactly(user) @@ -141,9 +141,9 @@ describe ProjectTeam, models: true do let(:requester) { create(:user) } before do - project.team << [master, :master] - project.team << [reporter, :reporter] - project.team << [guest, :guest] + project.add_master(master) + project.add_reporter(reporter) + project.add_guest(guest) project.request_access(requester) end @@ -204,9 +204,9 @@ describe ProjectTeam, models: true do context 'when project is not shared with group' do before do - project.team << [master, :master] - project.team << [reporter, :reporter] - project.team << [guest, :guest] + project.add_master(master) + project.add_reporter(reporter) + project.add_guest(guest) project.request_access(requester) end @@ -281,10 +281,10 @@ describe ProjectTeam, models: true do guest = create(:user) project = create(:project) - project.team << [master, :master] - project.team << [reporter, :reporter] - project.team << [promoted_guest, :guest] - project.team << [guest, :guest] + project.add_master(master) + project.add_reporter(reporter) + project.add_guest(promoted_guest) + project.add_guest(guest) group = create(:group) group_developer = create(:user) diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 8726c9eaa55..08ae61708a5 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -64,9 +64,9 @@ describe NotificationService, services: true do before do build_team(note.project) - project.team << [issue.author, :master] - project.team << [issue.assignee, :master] - project.team << [note.author, :master] + project.add_master(issue.author) + project.add_master(issue.assignee) + project.add_master(note.author) create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@subscribed_participant cc this guy') update_custom_notification(:new_note, @u_guest_custom, project) update_custom_notification(:new_note, @u_custom_global) @@ -168,8 +168,8 @@ describe NotificationService, services: true do let(:guest_watcher) { create_user_with_notification(:watch, "guest-watcher-confidential") } it 'filters out users that can not read the issue' do - project.team << [member, :developer] - project.team << [guest, :guest] + project.add_developer(member) + project.add_guest(guest) expect(SentNotification).to receive(:record).with(confidential_issue, any_args).exactly(4).times @@ -195,7 +195,7 @@ describe NotificationService, services: true do before do build_team(note.project) - note.project.team << [note.author, :master] + note.project.add_master(note.author) reset_delivered_emails! end @@ -237,7 +237,7 @@ describe NotificationService, services: true do before do build_team(note.project) - note.project.team << [note.author, :master] + note.project.add_master(note.author) reset_delivered_emails! end @@ -324,8 +324,8 @@ describe NotificationService, services: true do before do build_team(note.project) - project.team << [merge_request.author, :master] - project.team << [merge_request.assignee, :master] + project.add_master(merge_request.author) + project.add_master(merge_request.assignee) end describe '#new_note' do @@ -409,8 +409,8 @@ describe NotificationService, services: true do let(:confidential_issue) { create(:issue, :confidential, project: project, title: 'Confidential issue', author: author, assignee: assignee) } it "emails subscribers of the issue's labels that can read the issue" do - project.team << [member, :developer] - project.team << [guest, :guest] + project.add_developer(member) + project.add_guest(guest) label = create(:label, project: project, issues: [confidential_issue]) confidential_issue.reload @@ -621,8 +621,8 @@ describe NotificationService, services: true do let!(:label_2) { create(:label, project: project) } it "emails subscribers of the issue's labels that can read the issue" do - project.team << [member, :developer] - project.team << [guest, :guest] + project.add_developer(member) + project.add_guest(guest) label_2.toggle_subscription(non_member, project) label_2.toggle_subscription(author, project) @@ -1210,7 +1210,7 @@ describe NotificationService, services: true do let(:member) { create(:user) } before(:each) do - project.team << [member, :developer, project.owner] + project.add_developer(member, current_user: project.owner) end it do @@ -1233,9 +1233,9 @@ describe NotificationService, services: true do let(:note) { create(:note, noteable: merge_request, project: private_project) } before do - private_project.team << [assignee, :developer] - private_project.team << [developer, :developer] - private_project.team << [guest, :guest] + private_project.add_developer(assignee) + private_project.add_developer(developer) + private_project.add_guest(guest) ActionMailer::Base.deliveries.clear end @@ -1297,15 +1297,15 @@ describe NotificationService, services: true do @u_guest_watcher = create_user_with_notification(:watch, 'guest_watching') @u_guest_custom = create_user_with_notification(:custom, 'guest_custom') - project.team << [@u_watcher, :master] - project.team << [@u_participating, :master] - project.team << [@u_participant_mentioned, :master] - project.team << [@u_disabled, :master] - project.team << [@u_mentioned, :master] - project.team << [@u_committer, :master] - project.team << [@u_not_mentioned, :master] - project.team << [@u_lazy_participant, :master] - project.team << [@u_custom_global, :master] + project.add_master(@u_watcher) + project.add_master(@u_participating) + project.add_master(@u_participant_mentioned) + project.add_master(@u_disabled) + project.add_master(@u_mentioned) + project.add_master(@u_committer) + project.add_master(@u_not_mentioned) + project.add_master(@u_lazy_participant) + project.add_master(@u_custom_global) end def create_global_setting_for(user, level) @@ -1339,10 +1339,10 @@ describe NotificationService, services: true do @subscribed_participant = create_global_setting_for(create(:user, username: 'subscribed_participant'), :participating) @watcher_and_subscriber = create_global_setting_for(create(:user), :watch) - project.team << [@subscribed_participant, :master] - project.team << [@subscriber, :master] - project.team << [@unsubscriber, :master] - project.team << [@watcher_and_subscriber, :master] + project.add_master(@subscribed_participant) + project.add_master(@subscriber) + project.add_master(@unsubscriber) + project.add_master(@watcher_and_subscriber) issuable.subscriptions.create(user: @subscriber, project: project, subscribed: true) issuable.subscriptions.create(user: @subscribed_participant, project: project, subscribed: true) -- cgit v1.2.1 From 65724301e6129440d0fba9cf9779297bc702c95b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 18 Nov 2016 14:14:41 +0100 Subject: Make CI job script a required configuration entry --- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 4 ++-- spec/lib/gitlab/ci/config/entry/job_spec.rb | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 84f21631719..ff5dcc06ab3 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -1124,8 +1124,8 @@ EOT end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:extra config should be a hash") end - it "returns errors if there are unknown parameters that are hashes, but doesn't have a script" do - config = YAML.dump({ extra: { services: "test" } }) + it "returns errors if services configuration is not correct" do + config = YAML.dump({ extra: { script: 'rspec', services: "test" } }) expect do GitlabCiYamlProcessor.new(config, path) end.to raise_error(GitlabCiYamlProcessor::ValidationError, "jobs:extra:services config should be an array of strings") diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index c05711b6338..fc9b8b86dc4 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -19,8 +19,7 @@ describe Gitlab::Ci::Config::Entry::Job do let(:entry) { described_class.new(config, name: ''.to_sym) } it 'reports error' do - expect(entry.errors) - .to include "job name can't be blank" + expect(entry.errors).to include "job name can't be blank" end end end @@ -56,6 +55,15 @@ describe Gitlab::Ci::Config::Entry::Job do end end end + + context 'when script is not provided' do + let(:config) { { stage: 'test' } } + + it 'returns error about missing script entry' do + expect(entry).not_to be_valid + expect(entry.errors).to include "job script can't be blank" + end + end end end @@ -78,7 +86,7 @@ describe Gitlab::Ci::Config::Entry::Job do before { entry.compose!(deps) } let(:config) do - { image: 'some_image', cache: { key: 'test' } } + { script: 'rspec', image: 'some_image', cache: { key: 'test' } } end it 'overrides global config' do -- cgit v1.2.1 From c72c76fde3882b7c2f778bf85132cd2c80f01f5b Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 18 Nov 2016 13:29:47 +0100 Subject: Fix typos --- spec/lib/gitlab/chat_commands/command_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index f44c848479e..8cedbb0240f 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -11,18 +11,19 @@ describe Gitlab::ChatCommands::Command, service: true do let(:params) { { text: 'issue show 1' } } let(:project) { create(:project, has_external_issue_tracker: true) } - it 'displays the help message' do + it 'displays 404 messages' do expect(subject[:response_type]).to be(:ephemeral) expect(subject[:text]).to start_with('404 not found') end end context 'when an unknown command is triggered' do - let(:params) { { text: "unknown command 123" } } + let(:params) { { command: '/gitlab', text: "unknown command 123" } } 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 match('/gitlab issue show') end end @@ -35,7 +36,7 @@ describe Gitlab::ChatCommands::Command, service: true do end end - context 'issue is succesfully created' do + context 'issue is successfully created' do let(:params) { { text: "issue create my new issue" } } before do -- cgit v1.2.1 From bf25b5f69d8343b1d1a39a49815c9c888896a758 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 18 Nov 2016 14:30:27 +0100 Subject: Remove CI config helper with same name as an entry --- spec/lib/gitlab/ci/config/entry/global_spec.rb | 58 +++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index c7726adfd27..5e5c5dcc385 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -60,9 +60,9 @@ describe Gitlab::Ci::Config::Entry::Global do end context 'when not composed' do - describe '#before_script' do + describe '#before_script_value' do it 'returns nil' do - expect(global.before_script).to be nil + expect(global.before_script_value).to be nil end end @@ -82,40 +82,40 @@ describe Gitlab::Ci::Config::Entry::Global do end end - describe '#before_script' do + describe '#before_script_value' do it 'returns correct script' do - expect(global.before_script).to eq ['ls', 'pwd'] + expect(global.before_script_value).to eq ['ls', 'pwd'] end end - describe '#image' do + describe '#image_value' do it 'returns valid image' do - expect(global.image).to eq 'ruby:2.2' + expect(global.image_value).to eq 'ruby:2.2' end end - describe '#services' do + describe '#services_value' do it 'returns array of services' do - expect(global.services).to eq ['postgres:9.1', 'mysql:5.5'] + expect(global.services_value).to eq ['postgres:9.1', 'mysql:5.5'] end end - describe '#after_script' do + describe '#after_script_value' do it 'returns after script' do - expect(global.after_script).to eq ['make clean'] + expect(global.after_script_value).to eq ['make clean'] end end - describe '#variables' do + describe '#variables_value' do it 'returns variables' do - expect(global.variables).to eq(VAR: 'value') + expect(global.variables_value).to eq(VAR: 'value') end end - describe '#stages' do + describe '#stages_value' do context 'when stages key defined' do it 'returns array of stages' do - expect(global.stages).to eq %w[build pages] + expect(global.stages_value).to eq %w[build pages] end end @@ -126,21 +126,21 @@ describe Gitlab::Ci::Config::Entry::Global do end it 'returns array of types as stages' do - expect(global.stages).to eq %w[test deploy] + expect(global.stages_value).to eq %w[test deploy] end end end - describe '#cache' do + describe '#cache_value' do it 'returns cache configuration' do - expect(global.cache) + expect(global.cache_value) .to eq(key: 'k', untracked: true, paths: ['public/']) end end - describe '#jobs' do + describe '#jobs_value' do it 'returns jobs configuration' do - expect(global.jobs).to eq( + expect(global.jobs_value).to eq( rspec: { name: :rspec, script: %w[rspec ls], before_script: ['ls', 'pwd'], @@ -185,21 +185,21 @@ describe Gitlab::Ci::Config::Entry::Global do end end - describe '#variables' do + describe '#variables_value' do it 'returns default value for variables' do - expect(global.variables).to eq({}) + expect(global.variables_value).to eq({}) end end - describe '#stages' do + describe '#stages_value' do it 'returns an array of default stages' do - expect(global.stages).to eq %w[build test deploy] + expect(global.stages_value).to eq %w[build test deploy] end end - describe '#cache' do + describe '#cache_value' do it 'returns correct cache definition' do - expect(global.cache).to eq(key: 'a') + expect(global.cache_value).to eq(key: 'a') end end end @@ -217,9 +217,9 @@ describe Gitlab::Ci::Config::Entry::Global do { variables: nil, rspec: { script: 'rspec' } } end - describe '#variables' do + describe '#variables_value' do it 'undefined entry returns a default value' do - expect(global.variables).to eq({}) + expect(global.variables_value).to eq({}) end end end @@ -245,9 +245,9 @@ describe Gitlab::Ci::Config::Entry::Global do end end - describe '#before_script' do + describe '#before_script_value' do it 'returns nil' do - expect(global.before_script).to be_nil + expect(global.before_script_value).to be_nil end end end -- cgit v1.2.1 From ae51774bc45d2e15ccc61b01a30d1b588f179f85 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Fri, 18 Nov 2016 15:20:48 +0100 Subject: Pass correct tag target to post-receive hook when creating tag via UI We need to handle annotated tags that are created via GitLab UI. Annotated tags have their own SHA. We have to pass this SHA to post-receive hook to mirror what happens when someone creates an annotated tag in their local repository and pushes it via command line. In order to obtain tag SHA we first have to create it. This is a bit confusing because we create the tag before executing pre-hooks, but there is no way to create a tag outside the repository. If pre-hooks fail we have to clean up after ourselves. --- spec/models/repository_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 2470d504c68..72ac41f3472 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1354,6 +1354,28 @@ describe Repository, models: true do repository.add_tag(user, '8.5', 'master', 'foo') end + it 'does not create a tag when a pre-hook fails' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) + + expect do + repository.add_tag(user, '8.5', 'master', 'foo') + end.to raise_error(GitHooksService::PreReceiveError) + + repository.expire_tags_cache + expect(repository.find_tag('8.5')).to be_nil + end + + it 'passes tag SHA to hooks' do + spy = GitHooksService.new + allow(GitHooksService).to receive(:new).and_return(spy) + allow(spy).to receive(:execute).and_call_original + + tag = repository.add_tag(user, '8.5', 'master', 'foo') + + expect(spy).to have_received(:execute). + with(anything, anything, anything, tag.target, anything) + end + it 'returns a Gitlab::Git::Tag object' do tag = repository.add_tag(user, '8.5', 'master', 'foo') -- cgit v1.2.1 From 9c67b320a7adacc3a777bf7dc2fabd0b9a31caa8 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 18 Nov 2016 16:49:40 +0100 Subject: Backport SmartInterval, PrettyTime, SubbableResource from EE. --- spec/javascripts/pretty_time_spec.js.es6 | 134 +++++++++++++++++++++ spec/javascripts/smart_interval_spec.js.es6 | 159 +++++++++++++++++++++++++ spec/javascripts/subbable_resource_spec.js.es6 | 65 ++++++++++ 3 files changed, 358 insertions(+) create mode 100644 spec/javascripts/pretty_time_spec.js.es6 create mode 100644 spec/javascripts/smart_interval_spec.js.es6 create mode 100644 spec/javascripts/subbable_resource_spec.js.es6 (limited to 'spec') diff --git a/spec/javascripts/pretty_time_spec.js.es6 b/spec/javascripts/pretty_time_spec.js.es6 new file mode 100644 index 00000000000..2e12d45f7a7 --- /dev/null +++ b/spec/javascripts/pretty_time_spec.js.es6 @@ -0,0 +1,134 @@ +//= require lib/utils/pretty_time + +(() => { + const PrettyTime = gl.PrettyTime; + + describe('PrettyTime methods', function () { + describe('parseSeconds', function () { + it('should correctly parse a negative value', function () { + const parser = PrettyTime.parseSeconds; + + const zeroSeconds = parser(-1000); + + expect(zeroSeconds.minutes).toBe(16); + expect(zeroSeconds.hours).toBe(0); + expect(zeroSeconds.days).toBe(0); + expect(zeroSeconds.weeks).toBe(0); + }); + + it('should correctly parse a zero value', function () { + const parser = PrettyTime.parseSeconds; + + const zeroSeconds = parser(0); + + expect(zeroSeconds.minutes).toBe(0); + expect(zeroSeconds.hours).toBe(0); + expect(zeroSeconds.days).toBe(0); + expect(zeroSeconds.weeks).toBe(0); + }); + + it('should correctly parse a small non-zero second values', function () { + const parser = PrettyTime.parseSeconds; + + const subOneMinute = parser(10); + + expect(subOneMinute.minutes).toBe(0); + expect(subOneMinute.hours).toBe(0); + expect(subOneMinute.days).toBe(0); + expect(subOneMinute.weeks).toBe(0); + + const aboveOneMinute = parser(100); + + expect(aboveOneMinute.minutes).toBe(1); + expect(aboveOneMinute.hours).toBe(0); + expect(aboveOneMinute.days).toBe(0); + expect(aboveOneMinute.weeks).toBe(0); + + const manyMinutes = parser(1000); + + expect(manyMinutes.minutes).toBe(16); + expect(manyMinutes.hours).toBe(0); + expect(manyMinutes.days).toBe(0); + expect(manyMinutes.weeks).toBe(0); + }); + + it('should correctly parse large second values', function () { + const parser = PrettyTime.parseSeconds; + + const aboveOneHour = parser(4800); + + expect(aboveOneHour.minutes).toBe(20); + expect(aboveOneHour.hours).toBe(1); + expect(aboveOneHour.days).toBe(0); + expect(aboveOneHour.weeks).toBe(0); + + const aboveOneDay = parser(110000); + + expect(aboveOneDay.minutes).toBe(33); + expect(aboveOneDay.hours).toBe(6); + expect(aboveOneDay.days).toBe(3); + expect(aboveOneDay.weeks).toBe(0); + + const aboveOneWeek = parser(25000000); + + expect(aboveOneWeek.minutes).toBe(26); + expect(aboveOneWeek.hours).toBe(0); + expect(aboveOneWeek.days).toBe(3); + expect(aboveOneWeek.weeks).toBe(173); + }); + }); + + describe('stringifyTime', function () { + it('should stringify values with all non-zero units', function () { + const timeObject = { + weeks: 1, + days: 4, + hours: 7, + minutes: 20, + }; + + const timeString = PrettyTime.stringifyTime(timeObject); + + expect(timeString).toBe('1w 4d 7h 20m'); + }); + + it('should stringify values with some non-zero units', function () { + const timeObject = { + weeks: 0, + days: 4, + hours: 0, + minutes: 20, + }; + + const timeString = PrettyTime.stringifyTime(timeObject); + + expect(timeString).toBe('4d 20m'); + }); + + it('should stringify values with no non-zero units', function () { + const timeObject = { + weeks: 0, + days: 0, + hours: 0, + minutes: 0, + }; + + const timeString = PrettyTime.stringifyTime(timeObject); + + expect(timeString).toBe('0m'); + }); + }); + + describe('abbreviateTime', function () { + it('should abbreviate stringified times for weeks', function () { + const fullTimeString = '1w 3d 4h 5m'; + expect(PrettyTime.abbreviateTime(fullTimeString)).toBe('1w'); + }); + + it('should abbreviate stringified times for non-weeks', function () { + const fullTimeString = '0w 3d 4h 5m'; + expect(PrettyTime.abbreviateTime(fullTimeString)).toBe('3d'); + }); + }); + }); +})(window.gl || (window.gl = {})); diff --git a/spec/javascripts/smart_interval_spec.js.es6 b/spec/javascripts/smart_interval_spec.js.es6 new file mode 100644 index 00000000000..651d1f0f975 --- /dev/null +++ b/spec/javascripts/smart_interval_spec.js.es6 @@ -0,0 +1,159 @@ +//= require jquery +//= require smart_interval + +(() => { + const DEFAULT_MAX_INTERVAL = 100; + const DEFAULT_STARTING_INTERVAL = 5; + const DEFAULT_SHORT_TIMEOUT = 75; + const DEFAULT_LONG_TIMEOUT = 1000; + const DEFAULT_INCREMENT_FACTOR = 2; + + function createDefaultSmartInterval(config) { + const defaultParams = { + callback: () => {}, + startingInterval: DEFAULT_STARTING_INTERVAL, + maxInterval: DEFAULT_MAX_INTERVAL, + incrementByFactorOf: DEFAULT_INCREMENT_FACTOR, + delayStartBy: 0, + lazyStart: false, + }; + + if (config) { + _.extend(defaultParams, config); + } + + return new gl.SmartInterval(defaultParams); + } + + describe('SmartInterval', function () { + describe('Increment Interval', function () { + beforeEach(function () { + this.smartInterval = createDefaultSmartInterval(); + }); + + it('should increment the interval delay', function (done) { + const interval = this.smartInterval; + setTimeout(() => { + const intervalConfig = this.smartInterval.cfg; + const iterationCount = 4; + const maxIntervalAfterIterations = intervalConfig.startingInterval * + Math.pow(intervalConfig.incrementByFactorOf, (iterationCount - 1)); // 40 + const currentInterval = interval.getCurrentInterval(); + + // Provide some flexibility for performance of testing environment + expect(currentInterval).toBeGreaterThan(intervalConfig.startingInterval); + expect(currentInterval <= maxIntervalAfterIterations).toBeTruthy(); + + done(); + }, DEFAULT_SHORT_TIMEOUT); // 4 iterations, increment by 2x = (5 + 10 + 20 + 40) + }); + + it('should not increment past maxInterval', function (done) { + const interval = this.smartInterval; + + setTimeout(() => { + const currentInterval = interval.getCurrentInterval(); + expect(currentInterval).toBe(interval.cfg.maxInterval); + + done(); + }, DEFAULT_LONG_TIMEOUT); + }); + }); + + describe('Public methods', function () { + beforeEach(function () { + this.smartInterval = createDefaultSmartInterval(); + }); + + it('should cancel an interval', function (done) { + const interval = this.smartInterval; + + setTimeout(() => { + interval.cancel(); + + const intervalId = interval.state.intervalId; + const currentInterval = interval.getCurrentInterval(); + const intervalLowerLimit = interval.cfg.startingInterval; + + expect(intervalId).toBeUndefined(); + expect(currentInterval).toBe(intervalLowerLimit); + + done(); + }, DEFAULT_SHORT_TIMEOUT); + }); + + it('should resume an interval', function (done) { + const interval = this.smartInterval; + + setTimeout(() => { + interval.cancel(); + + interval.resume(); + + const intervalId = interval.state.intervalId; + + expect(intervalId).toBeTruthy(); + + done(); + }, DEFAULT_SHORT_TIMEOUT); + }); + }); + + describe('DOM Events', function () { + beforeEach(function () { + // This ensures DOM and DOM events are initialized for these specs. + fixture.set('
    '); + + this.smartInterval = createDefaultSmartInterval(); + }); + + it('should pause when page is not visible', function (done) { + const interval = this.smartInterval; + + setTimeout(() => { + expect(interval.state.intervalId).toBeTruthy(); + + // simulates triggering of visibilitychange event + interval.state.pageVisibility = 'hidden'; + interval.handleVisibilityChange(); + + expect(interval.state.intervalId).toBeUndefined(); + done(); + }, DEFAULT_SHORT_TIMEOUT); + }); + + it('should resume when page is becomes visible at the previous interval', function (done) { + const interval = this.smartInterval; + + setTimeout(() => { + expect(interval.state.intervalId).toBeTruthy(); + + // simulates triggering of visibilitychange event + interval.state.pageVisibility = 'hidden'; + interval.handleVisibilityChange(); + + expect(interval.state.intervalId).toBeUndefined(); + + // simulates triggering of visibilitychange event + interval.state.pageVisibility = 'visible'; + interval.handleVisibilityChange(); + + expect(interval.state.intervalId).toBeTruthy(); + + done(); + }, DEFAULT_SHORT_TIMEOUT); + }); + + it('should cancel on page unload', function (done) { + const interval = this.smartInterval; + + setTimeout(() => { + $(document).trigger('page:before-unload'); + expect(interval.state.intervalId).toBeUndefined(); + expect(interval.getCurrentInterval()).toBe(interval.cfg.startingInterval); + done(); + }, DEFAULT_SHORT_TIMEOUT); + }); + }); + }); +})(window.gl || (window.gl = {})); diff --git a/spec/javascripts/subbable_resource_spec.js.es6 b/spec/javascripts/subbable_resource_spec.js.es6 new file mode 100644 index 00000000000..df395296791 --- /dev/null +++ b/spec/javascripts/subbable_resource_spec.js.es6 @@ -0,0 +1,65 @@ +/* eslint-disable */ +//= vue +//= vue-resource +//= require jquery +//= require subbable_resource + +/* +* Test that each rest verb calls the publish and subscribe function and passes the correct value back +* +* +* */ +((global) => { + describe('Subbable Resource', function () { + describe('PubSub', function () { + beforeEach(function () { + this.MockResource = new global.SubbableResource('https://example.com'); + }); + it('should successfully add a single subscriber', function () { + const callback = () => {}; + this.MockResource.subscribe(callback); + + expect(this.MockResource.subscribers.length).toBe(1); + expect(this.MockResource.subscribers[0]).toBe(callback); + }); + + it('should successfully add multiple subscribers', function () { + const callbackOne = () => {}; + const callbackTwo = () => {}; + const callbackThree = () => {}; + + this.MockResource.subscribe(callbackOne); + this.MockResource.subscribe(callbackTwo); + this.MockResource.subscribe(callbackThree); + + expect(this.MockResource.subscribers.length).toBe(3); + }); + + it('should successfully publish an update to a single subscriber', function () { + const state = { myprop: 1 }; + + const callbacks = { + one: (data) => expect(data.myprop).toBe(2), + two: (data) => expect(data.myprop).toBe(2), + three: (data) => expect(data.myprop).toBe(2) + }; + + const spyOne = spyOn(callbacks, 'one'); + const spyTwo = spyOn(callbacks, 'two'); + const spyThree = spyOn(callbacks, 'three'); + + this.MockResource.subscribe(callbacks.one); + this.MockResource.subscribe(callbacks.two); + this.MockResource.subscribe(callbacks.three); + + state.myprop++; + + this.MockResource.publish(state); + + expect(spyOne).toHaveBeenCalled(); + expect(spyTwo).toHaveBeenCalled(); + expect(spyThree).toHaveBeenCalled(); + }); + }); + }); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 1db1896ed2375481d53f74f7900d259fe068ef64 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 18 Nov 2016 16:16:45 +0100 Subject: Rename mattermost_command to mattermost_slash_commands --- spec/lib/gitlab/import_export/all_models.yml | 2 +- .../mattermost_command_service_spec.rb | 99 ---------------------- .../mattermost_slash_commands_service_spec.rb | 99 ++++++++++++++++++++++ spec/models/project_spec.rb | 2 +- spec/requests/api/services_spec.rb | 12 +-- 5 files changed, 107 insertions(+), 107 deletions(-) delete mode 100644 spec/models/project_services/mattermost_command_service_spec.rb create mode 100644 spec/models/project_services/mattermost_slash_commands_service_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index bc837299b9e..fe3c39e38db 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -128,7 +128,7 @@ project: - emails_on_push_service - builds_email_service - pipelines_email_service -- mattermost_command_service +- mattermost_slash_commands_service - irker_service - pivotaltracker_service - hipchat_service diff --git a/spec/models/project_services/mattermost_command_service_spec.rb b/spec/models/project_services/mattermost_command_service_spec.rb deleted file mode 100644 index 21bf1d35e3f..00000000000 --- a/spec/models/project_services/mattermost_command_service_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -require 'spec_helper' - -describe MattermostCommandService, models: true do - describe "Associations" do - it { is_expected.to respond_to :token } - end - - describe '#valid_token?' do - subject { described_class.new } - - context 'when the token is empty' do - it 'is false' do - expect(subject.valid_token?('wer')).to be_falsey - end - end - - context 'when there is a token' do - before do - subject.token = '123' - end - - it 'accepts equal tokens' do - expect(subject.valid_token?('123')).to be_truthy - end - end - end - - describe '#trigger' do - subject { described_class.new } - - context 'no token is passed' do - let(:params) { Hash.new } - - it 'returns nil' do - expect(subject.trigger(params)).to be_nil - end - end - - context 'with a token passed' do - let(:project) { create(:empty_project) } - let(:params) { { token: 'token' } } - - before do - allow(subject).to receive(:token).and_return('token') - end - - context 'no user can be found' do - context 'when no url can be generated' do - it 'responds with the authorize url' do - response = subject.trigger(params) - - expect(response[:response_type]).to eq :ephemeral - expect(response[:text]).to start_with ":sweat_smile: Couldn't identify you" - end - end - - context 'when an auth url can be generated' do - let(:params) do - { - team_domain: 'http://domain.tld', - team_id: 'T3423423', - user_id: 'U234234', - user_name: 'mepmep', - token: 'token' - } - end - - let(:service) do - project.create_mattermost_command_service( - properties: { token: 'token' } - ) - end - - it 'generates the url' do - response = service.trigger(params) - - expect(response[:text]).to start_with(':wave: Hi there!') - end - end - end - - context 'when the user is authenticated' do - let!(:chat_name) { create(:chat_name, service: service) } - let(:service) do - project.create_mattermost_command_service( - properties: { token: 'token' } - ) - end - let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } } - - it 'triggers the command' do - expect_any_instance_of(Gitlab::ChatCommands::Command).to receive(:execute) - - service.trigger(params) - end - end - end - end -end diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb new file mode 100644 index 00000000000..4a1037e950b --- /dev/null +++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + +describe MattermostSlashCommandsService, models: true do + describe "Associations" do + it { is_expected.to respond_to :token } + end + + describe '#valid_token?' do + subject { described_class.new } + + context 'when the token is empty' do + it 'is false' do + expect(subject.valid_token?('wer')).to be_falsey + end + end + + context 'when there is a token' do + before do + subject.token = '123' + end + + it 'accepts equal tokens' do + expect(subject.valid_token?('123')).to be_truthy + end + end + end + + describe '#trigger' do + subject { described_class.new } + + context 'no token is passed' do + let(:params) { Hash.new } + + it 'returns nil' do + expect(subject.trigger(params)).to be_nil + end + end + + context 'with a token passed' do + let(:project) { create(:empty_project) } + let(:params) { { token: 'token' } } + + before do + allow(subject).to receive(:token).and_return('token') + end + + context 'no user can be found' do + context 'when no url can be generated' do + it 'responds with the authorize url' do + response = subject.trigger(params) + + expect(response[:response_type]).to eq :ephemeral + expect(response[:text]).to start_with ":sweat_smile: Couldn't identify you" + end + end + + context 'when an auth url can be generated' do + let(:params) do + { + team_domain: 'http://domain.tld', + team_id: 'T3423423', + user_id: 'U234234', + user_name: 'mepmep', + token: 'token' + } + end + + let(:service) do + project.create_mattermost_slash_commands_service( + properties: { token: 'token' } + ) + end + + it 'generates the url' do + response = service.trigger(params) + + expect(response[:text]).to start_with(':wave: Hi there!') + end + end + end + + context 'when the user is authenticated' do + let!(:chat_name) { create(:chat_name, service: service) } + let(:service) do + project.create_mattermost_slash_commands_service( + properties: { token: 'token' } + ) + end + let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } } + + it 'triggers the command' do + expect_any_instance_of(Gitlab::ChatCommands::Command).to receive(:execute) + + service.trigger(params) + end + end + end + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 1972a8bb3f4..42589858ab1 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -36,7 +36,7 @@ describe Project, models: true do it { is_expected.to have_one(:hipchat_service).dependent(:destroy) } it { is_expected.to have_one(:flowdock_service).dependent(:destroy) } it { is_expected.to have_one(:assembla_service).dependent(:destroy) } - it { is_expected.to have_one(:mattermost_command_service).dependent(:destroy) } + it { is_expected.to have_one(:mattermost_slash_commands_service).dependent(:destroy) } it { is_expected.to have_one(:gemnasium_service).dependent(:destroy) } it { is_expected.to have_one(:buildkite_service).dependent(:destroy) } it { is_expected.to have_one(:bamboo_service).dependent(:destroy) } diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 782d76db318..ce9c96ace21 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -91,7 +91,7 @@ describe API::API, api: true do describe 'POST /projects/:id/services/:slug/trigger' do let!(:project) { create(:empty_project) } - let(:service_name) { 'mattermost_command' } + let(:service_name) { 'mattermost_slash_commands' } context 'no service is available' do it 'returns a not found message' do @@ -107,14 +107,14 @@ describe API::API, api: true do context 'the service is not active' do let!(:inactive_service) do - project.create_mattermost_command_service( + project.create_mattermost_slash_commands_service( active: false, properties: { token: 'token' } ) end it 'when the service is inactive' do - post api("/projects/#{project.id}/services/mattermost_command/trigger") + post api("/projects/#{project.id}/services/mattermost_slash_commands/trigger") expect(response).to have_http_status(404) end @@ -122,14 +122,14 @@ describe API::API, api: true do context 'the service is active' do let!(:active_service) do - project.create_mattermost_command_service( + project.create_mattermost_slash_commands_service( active: true, properties: { token: 'token' } ) end it 'retusn status 200' do - post api("/projects/#{project.id}/services/mattermost_command/trigger"), params + post api("/projects/#{project.id}/services/mattermost_slash_commands/trigger"), params expect(response).to have_http_status(200) end @@ -137,7 +137,7 @@ describe API::API, api: true do context 'when the project can not be found' do it 'returns a generic 404' do - post api("/projects/404/services/mattermost_command/trigger"), params + post api("/projects/404/services/mattermost_slash_commands/trigger"), params expect(response).to have_http_status(404) expect(json_response["message"]).to eq("404 Service Not Found") -- cgit v1.2.1 From d399e1ae2b92bc399962a286fddc59eaa09670a7 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 14 Nov 2016 19:30:01 -0200 Subject: Allow enabling and disabling commit and MR events for JIRA --- .../gitlab/import_export/safe_model_attributes.yml | 3 ++- spec/models/project_services/jira_service_spec.rb | 6 ++--- spec/services/merge_requests/merge_service_spec.rb | 16 +++++++++++++ spec/services/system_note_service_spec.rb | 28 ++++++++++++++++++++-- spec/support/jira_service_helper.rb | 3 ++- 5 files changed, 49 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 07a2c316899..d6807941b31 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -258,6 +258,7 @@ Service: - template - push_events - issues_events +- commit_events - merge_requests_events - tag_push_events - note_events @@ -339,4 +340,4 @@ LabelPriority: - label_id - priority - created_at -- updated_at \ No newline at end of file +- updated_at diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index d8c47322220..f5da967cd14 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -83,7 +83,8 @@ describe JiraService, models: true do url: 'http://jira.example.com', username: 'gitlab_jira_username', password: 'gitlab_jira_password', - project_key: 'GitLabProject' + project_key: 'GitLabProject', + jira_issue_transition_id: "custom-id" ) # These stubs are needed to test JiraService#close_issue. @@ -177,11 +178,10 @@ describe JiraService, models: true do end it "calls the api with jira_issue_transition_id" do - @jira_service.jira_issue_transition_id = 'this-is-a-custom-id' @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project)) expect(WebMock).to have_requested(:post, @transitions_url).with( - body: /this-is-a-custom-id/ + body: /custom-id/ ).once end diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 1fd9f5a4910..7db32a33c93 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -59,10 +59,14 @@ describe MergeRequests::MergeService, services: true do include JiraServiceHelper let(:jira_tracker) { project.create_jira_service } + let(:jira_issue) { ExternalIssue.new('JIRA-123', project) } + let(:commit) { double('commit', safe_message: "Fixes #{jira_issue.to_reference}") } before do project.update_attributes!(has_external_issue_tracker: true) jira_service_settings + stub_jira_urls(jira_issue.id) + allow(merge_request).to receive(:commits).and_return([commit]) end it 'closes issues on JIRA issue tracker' do @@ -76,6 +80,18 @@ describe MergeRequests::MergeService, services: true do service.execute(merge_request) end + context "when jira_issue_transition_id is not present" do + before { allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(nil) } + + it "does not close issue" do + allow(jira_tracker).to receive_messages(jira_issue_transition_id: nil) + + expect_any_instance_of(JiraService).not_to receive(:transition_issue) + + service.execute(merge_request) + end + end + context "wrong issue markdown" do it 'does not close issues on JIRA issue tracker' do jira_issue = ExternalIssue.new('#JIRA-123', project) diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 56d39e9a005..150e21574a1 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -536,7 +536,7 @@ describe SystemNoteService, services: true do let(:project) { create(:jira_project) } let(:author) { create(:user) } let(:issue) { create(:issue, project: project) } - let(:mergereq) { create(:merge_request, :simple, target_project: project, source_project: project) } + let(:merge_request) { create(:merge_request, :simple, target_project: project, source_project: project) } let(:jira_issue) { ExternalIssue.new("JIRA-1", project)} let(:jira_tracker) { project.jira_service } let(:commit) { project.commit } @@ -545,7 +545,31 @@ describe SystemNoteService, services: true do before { stub_jira_urls(jira_issue.id) } - context 'in issue' do + noteable_types = ["merge_requests", "commit"] + + noteable_types.each do |type| + context "when noteable is a #{type}" do + it "blocks cross reference when #{type.underscore}_events is false" do + jira_tracker.update("#{type}_events" => false) + + noteable = type == "commit" ? commit : merge_request + result = described_class.cross_reference(jira_issue, noteable, author) + + expect(result).to eq("Events for #{noteable.class.to_s.underscore.humanize.pluralize.downcase} are disabled.") + end + + it "blocks cross reference when #{type.underscore}_events is true" do + jira_tracker.update("#{type}_events" => true) + + noteable = type == "commit" ? commit : merge_request + result = described_class.cross_reference(jira_issue, noteable, author) + + expect(result).to eq(success_message) + end + end + end + + context 'in JIRA issue tracker' do before { jira_service_settings } describe "new reference" do diff --git a/spec/support/jira_service_helper.rb b/spec/support/jira_service_helper.rb index 7437ba2688d..929fc0c5182 100644 --- a/spec/support/jira_service_helper.rb +++ b/spec/support/jira_service_helper.rb @@ -6,7 +6,8 @@ module JiraServiceHelper properties = { title: "JIRA tracker", url: JIRA_URL, - project_key: "JIRA" + project_key: "JIRA", + jira_issue_transition_id: '1' } jira_tracker.update_attributes(properties: properties, active: true) -- cgit v1.2.1 From 49e726ec331e2f765fae184e8e9dff42a94d5227 Mon Sep 17 00:00:00 2001 From: winniehell Date: Fri, 18 Nov 2016 13:18:49 +0100 Subject: Add failing test for #24614 --- spec/javascripts/build_spec.js.es6 | 13 +++++++++++++ spec/javascripts/fixtures/build.html.haml | 5 +++++ 2 files changed, 18 insertions(+) (limited to 'spec') diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index b329ad8062a..e21e5844a26 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -26,7 +26,15 @@ }); describe('setup', function () { + const removeDate = new Date(); + removeDate.setUTCFullYear(removeDate.getUTCFullYear() + 1); + // give the test three days to run + removeDate.setTime(removeDate.getTime() + (3 * 24 * 60 * 60 * 1000)); + beforeEach(function () { + const removeDateElement = document.querySelector('.js-artifacts-remove'); + removeDateElement.innerText = removeDate.toString(); + this.build = new Build(); }); @@ -56,6 +64,11 @@ expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false); expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); }); + + it('displays the remove date correctly', function () { + const removeDateElement = document.querySelector('.js-artifacts-remove'); + expect(removeDateElement.innerText.trim()).toBe('1 year'); + }); }); describe('initial build trace', function () { diff --git a/spec/javascripts/fixtures/build.html.haml b/spec/javascripts/fixtures/build.html.haml index a2bc81c6be7..27136beb14c 100644 --- a/spec/javascripts/fixtures/build.html.haml +++ b/spec/javascripts/fixtures/build.html.haml @@ -55,3 +55,8 @@ build_status: 'passed', build_stage: 'test', state1: 'buildstate' }} + +%p.build-detail-row + The artifacts will be removed in + %span.js-artifacts-remove + 2016-12-19 09:02:12 UTC -- cgit v1.2.1 From fd05e26618dd0c123ca476b6f5a3d85f1cfe397a Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Tue, 11 Oct 2016 14:25:17 +0200 Subject: Precalculate user's authorized projects in database Closes #23150 --- spec/finders/group_projects_finder_spec.rb | 5 +- spec/models/member_spec.rb | 22 +++++++ spec/models/project_group_link_spec.rb | 16 ++++++ spec/models/project_spec.rb | 6 +- spec/models/user_spec.rb | 76 ++++++++++++++++++++++++- spec/services/projects/create_service_spec.rb | 3 + spec/support/db_cleaner.rb | 4 ++ spec/workers/authorized_projects_worker_spec.rb | 22 +++++++ 8 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 spec/workers/authorized_projects_worker_spec.rb (limited to 'spec') diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb index fbe09b28b3c..00eec3f3f4c 100644 --- a/spec/finders/group_projects_finder_spec.rb +++ b/spec/finders/group_projects_finder_spec.rb @@ -38,7 +38,10 @@ describe GroupProjectsFinder do end describe 'without group member current_user' do - before { shared_project_2.team << [current_user, Gitlab::Access::MASTER] } + before do + shared_project_2.team << [current_user, Gitlab::Access::MASTER] + current_user.reload + end context "only shared" do context "without external user" do diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 12419d6fd5a..4f7c8a36cb5 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -443,6 +443,16 @@ describe Member, models: true do member.accept_invite!(user) end + + it "refreshes user's authorized projects", truncate: true do + project = member.source + + expect(user.authorized_projects).not_to include(project) + + member.accept_invite!(user) + + expect(user.authorized_projects.reload).to include(project) + end end describe "#decline_invite!" do @@ -468,4 +478,16 @@ describe Member, models: true do expect { member.generate_invite_token }.to change { member.invite_token} end end + + describe "destroying a record", truncate: true do + it "refreshes user's authorized projects" do + project = create(:project, :private) + user = create(:user) + member = project.team << [user, :reporter] + + member.destroy + + expect(user.authorized_projects).not_to include(project) + end + end end diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb index c5ff1941378..47397a822c1 100644 --- a/spec/models/project_group_link_spec.rb +++ b/spec/models/project_group_link_spec.rb @@ -14,4 +14,20 @@ describe ProjectGroupLink do it { should validate_presence_of(:group) } it { should validate_presence_of(:group_access) } end + + describe "destroying a record", truncate: true do + it "refreshes group users' authorized projects" do + project = create(:project, :private) + group = create(:group) + reporter = create(:user) + group_users = group.users + + group.add_reporter(reporter) + project.project_group_links.create(group: group) + group_users.each { |user| expect(user.authorized_projects).to include(project) } + + project.project_group_links.destroy_all + group_users.each { |user| expect(user.authorized_projects).not_to include(project) } + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 46fa00a79c4..e637c464b18 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1514,7 +1514,7 @@ describe Project, models: true do members_project.team << [developer, :developer] members_project.team << [master, :master] - create(:project_group_link, project: shared_project, group: group) + create(:project_group_link, project: shared_project, group: group, group_access: Gitlab::Access::DEVELOPER) end it 'returns false for no user' do @@ -1543,7 +1543,9 @@ describe Project, models: true do expect(members_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false) expect(members_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(true) expect(shared_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false) - expect(shared_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(true) + expect(shared_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(false) + expect(shared_project.authorized_for_user?(developer, Gitlab::Access::DEVELOPER)).to be(true) + expect(shared_project.authorized_for_user?(master, Gitlab::Access::DEVELOPER)).to be(true) end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 580ce4a9e0a..10528693024 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1072,7 +1072,7 @@ describe User, models: true do it { is_expected.to eq([private_group]) } end - describe '#authorized_projects' do + describe '#authorized_projects', truncate: true do context 'with a minimum access level' do it 'includes projects for which the user is an owner' do user = create(:user) @@ -1092,6 +1092,80 @@ describe User, models: true do .to contain_exactly(project) end end + + it "includes user's personal projects" do + user = create(:user) + project = create(:project, :private, namespace: user.namespace) + + expect(user.authorized_projects).to include(project) + end + + it "includes personal projects user has been given access to" do + user1 = create(:user) + user2 = create(:user) + project = create(:project, :private, namespace: user1.namespace) + + project.team << [user2, Gitlab::Access::DEVELOPER] + + expect(user2.authorized_projects).to include(project) + end + + it "includes projects of groups user has been added to" do + group = create(:group) + project = create(:project, group: group) + user = create(:user) + + group.add_developer(user) + + expect(user.authorized_projects).to include(project) + end + + it "does not include projects of groups user has been removed from" do + group = create(:group) + project = create(:project, group: group) + user = create(:user) + + member = group.add_developer(user) + expect(user.authorized_projects).to include(project) + + member.destroy + expect(user.authorized_projects).not_to include(project) + end + + it "includes projects shared with user's group" do + user = create(:user) + project = create(:project, :private) + group = create(:group) + + group.add_reporter(user) + project.project_group_links.create(group: group) + + expect(user.authorized_projects).to include(project) + end + + it "does not include destroyed projects user had access to" do + user1 = create(:user) + user2 = create(:user) + project = create(:project, :private, namespace: user1.namespace) + + project.team << [user2, Gitlab::Access::DEVELOPER] + expect(user2.authorized_projects).to include(project) + + project.destroy + expect(user2.authorized_projects).not_to include(project) + end + + it "does not include projects of destroyed groups user had access to" do + group = create(:group) + project = create(:project, namespace: group) + user = create(:user) + + group.add_developer(user) + expect(user.authorized_projects).to include(project) + + group.destroy + expect(user.authorized_projects).not_to include(project) + end end describe '#projects_where_can_admin_issues' do diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 2cf9883113c..fbd22560d6e 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -34,6 +34,8 @@ describe Projects::CreateService, services: true do @group = create :group @group.add_owner(@user) + @user.refresh_authorized_projects # Ensure cache is warm + @opts.merge!(namespace_id: @group.id) @project = create_project(@user, @opts) end @@ -41,6 +43,7 @@ describe Projects::CreateService, services: true do it { expect(@project).to be_valid } it { expect(@project.owner).to eq(@group) } it { expect(@project.namespace).to eq(@group) } + it { expect(@user.authorized_projects).to include(@project) } end context 'error handling' do diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index ac38e31b77e..247f0954221 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -11,6 +11,10 @@ RSpec.configure do |config| DatabaseCleaner.strategy = :truncation end + config.before(:each, truncate: true) do + DatabaseCleaner.strategy = :truncation + end + config.before(:each) do DatabaseCleaner.start end diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb new file mode 100644 index 00000000000..18a1aab766c --- /dev/null +++ b/spec/workers/authorized_projects_worker_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe AuthorizedProjectsWorker do + describe '#perform' do + it "refreshes user's authorized projects" do + user = create(:user) + + expect(User).to receive(:find_by).with(id: user.id).and_return(user) + expect(user).to receive(:refresh_authorized_projects) + + described_class.new.perform(user.id) + end + + context "when user is not found" do + it "does nothing" do + expect_any_instance_of(User).not_to receive(:refresh_authorized_projects) + + described_class.new.perform(999_999) + end + end + end +end -- cgit v1.2.1 From 43898f8efbe4981ad2ca67e7804db2c73fe2f3e2 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 18 Nov 2016 19:40:47 +0000 Subject: Fix broken tests --- .../environments/environment_actions_spec.js.es6 | 6 +++--- .../environments/environment_item_spec.js.es6 | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_actions_spec.js.es6 b/spec/javascripts/environments/environment_actions_spec.js.es6 index 1097582a8e9..c9ac7a73fd0 100644 --- a/spec/javascripts/environments/environment_actions_spec.js.es6 +++ b/spec/javascripts/environments/environment_actions_spec.js.es6 @@ -12,11 +12,11 @@ describe('Actions Component', () => { const actionsMock = [ { name: 'bar', - play_url: 'https://gitlab.com/play', + play_path: 'https://gitlab.com/play', }, { name: 'foo', - play_url: '#', + play_path: '#', }, ]; @@ -32,6 +32,6 @@ describe('Actions Component', () => { ).toEqual(actionsMock.length); expect( component.$el.querySelector('.dropdown-menu li a').getAttribute('href') - ).toEqual(actionsMock[0].play_url); + ).toEqual(actionsMock[0].play_path); }); }); diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js.es6 index 7559258426b..54c93367b17 100644 --- a/spec/javascripts/environments/environment_item_spec.js.es6 +++ b/spec/javascripts/environments/environment_item_spec.js.es6 @@ -74,7 +74,7 @@ describe('Environment item', () => { sha: '500aabcb17c97bdcf2d0c410b70cb8556f0362dd', ref: { name: 'master', - ref_url: 'http://localhost:3000/root/ci-folders/tree/master', + ref_path: 'root/ci-folders/tree/master', }, tag: true, 'last?': true, @@ -102,23 +102,23 @@ describe('Environment item', () => { avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', web_url: 'http://localhost:3000/root', }, - commit_url: 'http://localhost:3000/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', + commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd', }, deployable: { id: 1279, name: 'deploy', - build_url: 'http://localhost:3000/root/ci-folders/builds/1279', - retry_url: 'http://localhost:3000/root/ci-folders/builds/1279/retry', + build_path: '/root/ci-folders/builds/1279', + retry_path: '/root/ci-folders/builds/1279/retry', }, manual_actions: [ { name: 'action', - play_url: 'http://localhost:3000/play', + play_path: '/play', }, ], }, 'stoppable?': true, - environment_url: 'http://localhost:3000/root/ci-folders/environments/31', + environment_path: 'root/ci-folders/environments/31', created_at: '2016-11-07T11:11:16.525Z', updated_at: '2016-11-10T15:55:58.778Z', }; @@ -161,13 +161,13 @@ describe('Environment item', () => { it('Should link to build url provided', () => { expect( component.$el.querySelector('.build-link').getAttribute('href') - ).toEqual(environment.last_deployment.deployable.build_url); + ).toEqual(environment.last_deployment.deployable.build_path); }); it('Should render deployable name and id', () => { expect( component.$el.querySelector('.build-link').getAttribute('href') - ).toEqual(environment.last_deployment.deployable.build_url); + ).toEqual(environment.last_deployment.deployable.build_path); }); }); -- cgit v1.2.1 From fbfc7523cb0119ac3a0d02cd04dc12e453ad3ad6 Mon Sep 17 00:00:00 2001 From: Ido Leibovich Date: Mon, 31 Oct 2016 22:38:24 +0200 Subject: Add api endpoint for creating a pipeline Add a new endpoint in the new API for creating a new pipeline, and return the details of that pipeline. --- spec/requests/api/pipelines_spec.rb | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index 7011bdc9ec0..d83f7883c78 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -41,6 +41,52 @@ describe API::API, api: true do end end + describe 'POST /projects/:id/pipeline ' do + context 'authorized user' do + context 'with gitlab-ci.yml' do + before { stub_ci_pipeline_to_return_yaml_file } + + it 'creates and returns a new pipeline' do + expect do + post api("/projects/#{project.id}/pipeline", user), ref: project.default_branch + end.to change { Ci::Pipeline.count }.by(1) + + expect(response).to have_http_status(201) + expect(json_response).to be_a Hash + expect(json_response['sha']).to eq project.commit.id + end + + it 'fails when using an invalid ref' do + post api("/projects/#{project.id}/pipeline", user), ref: 'invalid_ref' + + expect(response).to have_http_status(400) + expect(json_response['message']['base'].first).to eq 'Reference not found' + expect(json_response).not_to be_an Array + end + end + + context 'without gitlab-ci.yml' do + it 'fails to create pipeline' do + post api("/projects/#{project.id}/pipeline", user), ref: project.default_branch + + expect(response).to have_http_status(400) + expect(json_response['message']['base'].first).to eq 'Missing .gitlab-ci.yml file' + expect(json_response).not_to be_an Array + end + end + end + + context 'unauthorized user' do + it 'does not create pipeline' do + post api("/projects/#{project.id}/pipeline", non_member), ref: project.default_branch + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq '404 Project Not Found' + expect(json_response).not_to be_an Array + end + end + end + describe 'GET /projects/:id/pipelines/:pipeline_id' do context 'authorized user' do it 'returns project pipelines' do -- cgit v1.2.1 From b1f5af40598528fbc1326946376a595d41793537 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 18 Nov 2016 22:31:26 +0100 Subject: Bring back the `commit_url` as it's used by CycleAnalytics --- spec/serializers/commit_entity_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spec') diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb index a44a23ef619..15f11ac3df9 100644 --- a/spec/serializers/commit_entity_spec.rb +++ b/spec/serializers/commit_entity_spec.rb @@ -35,6 +35,10 @@ describe CommitEntity do expect(subject).to include(:commit_path) end + it 'contains URL to commit' do + expect(subject).to include(:commit_url) + end + it 'needs to receive project in the request' do expect(request).to receive(:project) .and_return(project) -- cgit v1.2.1 From d2007ee6ddaf665170bac0ed63fc1a3ab92b04db Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 18 Nov 2016 23:02:09 +0100 Subject: Try to fix tests --- spec/javascripts/environments/environment_stop_spec.js.es6 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js.es6 index 20eb8c92322..d3eff278292 100644 --- a/spec/javascripts/environments/environment_stop_spec.js.es6 +++ b/spec/javascripts/environments/environment_stop_spec.js.es6 @@ -7,14 +7,14 @@ describe('Stop Component', () => { }); it('should link to the provided URL', () => { - const stopURL = 'https://gitlab.com/stop'; + const stopURL = '/stop'; const component = new window.gl.environmentsList.StopComponent({ el: document.querySelector('.test-dom-element'), propsData: { stop_url: stopURL, }, }); - expect(component.$el.getAttribute('href')).toEqual(`${stopURL}/stop`); + expect(component.$el.getAttribute('href')).toEqual(stopURL); }); describe('When clicked', () => { @@ -26,9 +26,10 @@ describe('Stop Component', () => { }, }); - const spy = spyOn(window, 'confirm'); + var confirm = spyOn(window, 'confirm'); + confirm.and.returnValue(false); component.$el.click(); - expect(spy).toHaveBeenCalled(); + expect(confirm).toHaveBeenCalled(); }); }); }); -- cgit v1.2.1 From cad3ad266a3fa28de9ae8e5025d1f7a984892b4e Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Sat, 19 Nov 2016 03:22:02 +0500 Subject: Use build instead create in BroadcastMessage model spec --- spec/models/broadcast_message_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index 02d6263094a..219db365a91 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe BroadcastMessage, models: true do - subject { create(:broadcast_message) } + subject { build(:broadcast_message) } it { is_expected.to be_valid } -- cgit v1.2.1 From 34eec88c6cfc288bfb18e51d4876905f1337c6e6 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Fri, 18 Nov 2016 22:47:10 -0600 Subject: Fix spec --- spec/javascripts/merge_request_widget_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 8c5afc2ff3c..575b87e6f17 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -35,9 +35,9 @@ external_url_formatted: 'test-url.com' }]; - spyOn(jQuery, 'getJSON').and.callFake((req, cb) => { + spyOn(jQuery, 'getJSON').and.callFake(function(req, cb) { cb(this.ciEnvironmentsStatusData); - }); + }.bind(this)); }); it('should call renderEnvironments when the environments property is set', function() { -- cgit v1.2.1 From f9a662c38fc8bbcee66ab08db53f86bdad146784 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Sat, 19 Nov 2016 12:37:54 +0000 Subject: Changes for stop url to path --- .../environments/environment_stop_spec.js.es6 | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js.es6 index d3eff278292..37fba925e16 100644 --- a/spec/javascripts/environments/environment_stop_spec.js.es6 +++ b/spec/javascripts/environments/environment_stop_spec.js.es6 @@ -16,20 +16,4 @@ describe('Stop Component', () => { }); expect(component.$el.getAttribute('href')).toEqual(stopURL); }); - - describe('When clicked', () => { - it('Should open popup with confirmation warning', () => { - const component = new window.gl.environmentsList.StopComponent({ - el: document.querySelector('.test-dom-element'), - propsData: { - stop_url: '#', - }, - }); - - var confirm = spyOn(window, 'confirm'); - confirm.and.returnValue(false); - component.$el.click(); - expect(confirm).toHaveBeenCalled(); - }); - }); }); -- cgit v1.2.1 From 6e5a1ea02ad929b5c7d5f4c69405281428a26a11 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Sat, 19 Nov 2016 13:07:13 +0000 Subject: Fix broken test --- .../environments/environment_stop_spec.js.es6 | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js.es6 index 37fba925e16..3502914dbd6 100644 --- a/spec/javascripts/environments/environment_stop_spec.js.es6 +++ b/spec/javascripts/environments/environment_stop_spec.js.es6 @@ -16,4 +16,24 @@ describe('Stop Component', () => { }); expect(component.$el.getAttribute('href')).toEqual(stopURL); }); + + describe('When clicked', () => { + it('Should open popup with confirmation warning', () => { + const component = new window.gl.environmentsList.StopComponent({ + el: document.querySelector('.test-dom-element'), + propsData: { + stop_url: '#', + }, + }); + + let opened = false; + + spyOn(window, 'confirm').and.callFake(function () { + opened = true; + expect(opened).toEqual(true); + return false; + }); + component.$el.click(); + }); + }); }); -- cgit v1.2.1 From 531d4e564b8417db672b096755a54f909ee7af76 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Sat, 19 Nov 2016 13:29:48 +0000 Subject: Fix test --- .../environments/environment_stop_spec.js.es6 | 33 ++++++++-------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_stop_spec.js.es6 b/spec/javascripts/environments/environment_stop_spec.js.es6 index 3502914dbd6..b842be4da61 100644 --- a/spec/javascripts/environments/environment_stop_spec.js.es6 +++ b/spec/javascripts/environments/environment_stop_spec.js.es6 @@ -2,38 +2,27 @@ //= require environments/components/environment_stop describe('Stop Component', () => { fixture.preload('environments/element.html'); + + let stopURL; + let component; + beforeEach(() => { fixture.load('environments/element.html'); - }); - it('should link to the provided URL', () => { - const stopURL = '/stop'; - const component = new window.gl.environmentsList.StopComponent({ + stopURL = '/stop'; + component = new window.gl.environmentsList.StopComponent({ el: document.querySelector('.test-dom-element'), propsData: { stop_url: stopURL, }, }); - expect(component.$el.getAttribute('href')).toEqual(stopURL); }); - describe('When clicked', () => { - it('Should open popup with confirmation warning', () => { - const component = new window.gl.environmentsList.StopComponent({ - el: document.querySelector('.test-dom-element'), - propsData: { - stop_url: '#', - }, - }); - - let opened = false; + it('should link to the provided URL', () => { + expect(component.$el.getAttribute('href')).toEqual(stopURL); + }); - spyOn(window, 'confirm').and.callFake(function () { - opened = true; - expect(opened).toEqual(true); - return false; - }); - component.$el.click(); - }); + it('should have a data-confirm attribute', () => { + expect(component.$el.getAttribute('data-confirm')).toEqual('Are you sure you want to stop this environment?'); }); }); -- cgit v1.2.1 From 16a8d6442928b6909e4421430f4bfc9b725c1bc9 Mon Sep 17 00:00:00 2001 From: Alex Sanford Date: Sat, 19 Nov 2016 11:28:56 -0400 Subject: Fix regression in Merge request form Merge request !7163 caused an error message to appear on the Merge Request form when it was first loaded by the user. This commit fixes that regression bug. --- spec/features/merge_requests/create_new_mr_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'spec') diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb index 584574cc91a..702869b6e8b 100644 --- a/spec/features/merge_requests/create_new_mr_spec.rb +++ b/spec/features/merge_requests/create_new_mr_spec.rb @@ -77,4 +77,11 @@ feature 'Create New Merge Request', feature: true, js: true do expect(page).to have_content "6049019_460s.jpg" end end + + # Isolates a regression (see #24627) + it 'does not show error messages on initial form' do + visit new_namespace_project_merge_request_path(project.namespace, project) + expect(page).not_to have_selector('#error_explanation') + expect(page).not_to have_content('The form contains the following error') + end end -- cgit v1.2.1 From c5205046105cb908df1fb753ca31d8e4fa4f60a2 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 17 Nov 2016 14:41:35 -0600 Subject: Fix timeago rendering for environment timeago --- spec/javascripts/merge_request_widget_spec.js | 54 ++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index 575b87e6f17..f38e9cb8ef5 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, indent, quote-props, no-var, padded-blocks, max-len */ /*= require merge_request_widget */ -/*= require lib/utils/timeago.js */ +/*= require lib/utils/timeago */ +/*= require lib/utils/datetime_utility */ (function() { describe('MergeRequestWidget', function() { @@ -54,6 +55,57 @@ }); }); + describe('renderEnvironments', function() { + describe('should render correct timeago', function() { + beforeEach(function() { + this.environments = [{ + id: 'test-environment-id', + url: 'testurl', + deployed_at: new Date().toISOString(), + deployed_at_formatted: true + }]; + }); + + function getTimeagoText(template) { + var el = document.createElement('html'); + el.innerHTML = template; + return el.querySelector('.js-environment-timeago').innerText.trim(); + } + + it('should render less than a minute ago text', function() { + spyOn(this.class.$widgetBody, 'before').and.callFake(function(template) { + expect(getTimeagoText(template)).toBe('less than a minute ago.'); + }); + + this.class.renderEnvironments(this.environments); + }); + + it('should render about an hour ago text', function() { + var oneHourAgo = new Date(); + oneHourAgo.setHours(oneHourAgo.getHours() - 1); + + this.environments[0].deployed_at = oneHourAgo.toISOString(); + spyOn(this.class.$widgetBody, 'before').and.callFake(function(template) { + expect(getTimeagoText(template)).toBe('about an hour ago.'); + }); + + this.class.renderEnvironments(this.environments); + }); + + it('should render about 2 hours ago text', function() { + var twoHoursAgo = new Date(); + twoHoursAgo.setHours(twoHoursAgo.getHours() - 2); + + this.environments[0].deployed_at = twoHoursAgo.toISOString(); + spyOn(this.class.$widgetBody, 'before').and.callFake(function(template) { + expect(getTimeagoText(template)).toBe('about 2 hours ago.'); + }); + + this.class.renderEnvironments(this.environments); + }); + }); + }); + return describe('getCIStatus', function() { beforeEach(function() { this.ciStatusData = { -- cgit v1.2.1 From ed88515d56f72ba9f77cac2a4dca121fd34f622f Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sat, 19 Nov 2016 23:52:53 -0600 Subject: convert activities.js to es6 class syntax --- spec/javascripts/activities_spec.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/activities_spec.js.es6 b/spec/javascripts/activities_spec.js.es6 index 9d855ef1060..8640cd44085 100644 --- a/spec/javascripts/activities_spec.js.es6 +++ b/spec/javascripts/activities_spec.js.es6 @@ -35,7 +35,7 @@ describe('Activities', () => { beforeEach(() => { fixture.load(fixtureTemplate); - new Activities(); + new gl.Activities(); }); for(let i = 0; i < filters.length; i++) { -- cgit v1.2.1 From 0fd397bba1a36136c3737165c9057bc59dcbca77 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 21 Nov 2016 10:48:07 +0100 Subject: Added permissions per stage to cycle analytics endpoint --- .../lib/gitlab/cycle_analytics/permissions_spec.rb | 127 +++++++++++++++++++++ spec/models/cycle_analytics/code_spec.rb | 2 +- spec/models/cycle_analytics/issue_spec.rb | 2 +- spec/models/cycle_analytics/plan_spec.rb | 2 +- spec/models/cycle_analytics/production_spec.rb | 2 +- spec/models/cycle_analytics/review_spec.rb | 2 +- spec/models/cycle_analytics/staging_spec.rb | 2 +- spec/models/cycle_analytics/summary_spec.rb | 2 +- spec/models/cycle_analytics/test_spec.rb | 2 +- 9 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 spec/lib/gitlab/cycle_analytics/permissions_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/permissions_spec.rb b/spec/lib/gitlab/cycle_analytics/permissions_spec.rb new file mode 100644 index 00000000000..dc4f7dc69db --- /dev/null +++ b/spec/lib/gitlab/cycle_analytics/permissions_spec.rb @@ -0,0 +1,127 @@ +require 'spec_helper' + +describe Gitlab::CycleAnalytics::Permissions do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + + subject { described_class.get(user: user, project: project) } + + context 'user with no relation to the project' do + it 'has no permissions to issue stage' do + expect(subject[:issue]).to eq(false) + end + + it 'has no permissions to test stage' do + expect(subject[:test]).to eq(false) + end + + it 'has no permissions to staging stage' do + expect(subject[:staging]).to eq(false) + end + + it 'has no permissions to production stage' do + expect(subject[:production]).to eq(false) + end + + it 'has no permissions to code stage' do + expect(subject[:code]).to eq(false) + end + + it 'has no permissions to review stage' do + expect(subject[:review]).to eq(false) + end + + it 'has no permissions to plan stage' do + expect(subject[:plan]).to eq(false) + end + end + + context 'user is master' do + before do + project.team << [user, :master] + end + + it 'has permissions to issue stage' do + expect(subject[:issue]).to eq(true) + end + + it 'has permissions to test stage' do + expect(subject[:test]).to eq(true) + end + + it 'has permissions to staging stage' do + expect(subject[:staging]).to eq(true) + end + + it 'has permissions to production stage' do + expect(subject[:production]).to eq(true) + end + + it 'has permissions to code stage' do + expect(subject[:code]).to eq(true) + end + + it 'has permissions to review stage' do + expect(subject[:review]).to eq(true) + end + + it 'has permissions to plan stage' do + expect(subject[:plan]).to eq(true) + end + end + + context 'user has no build permissions' do + before do + project.team << [user, :guest] + end + + it 'has permissions to issue stage' do + expect(subject[:issue]).to eq(true) + end + + it 'has no permissions to test stage' do + expect(subject[:test]).to eq(false) + end + + it 'has no permissions to staging stage' do + expect(subject[:staging]).to eq(false) + end + end + + context 'user has no merge request permissions' do + before do + project.team << [user, :guest] + end + + it 'has permissions to issue stage' do + expect(subject[:issue]).to eq(true) + end + + it 'has no permissions to code stage' do + expect(subject[:code]).to eq(false) + end + + it 'has no permissions to review stage' do + expect(subject[:review]).to eq(false) + end + end + + context 'user has no issue permissions' do + before do + project.team << [user, :developer] + project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) + end + + it 'has permissions to code stage' do + expect(subject[:code]).to eq(true) + end + + it 'has no permissions to issue stage' do + expect(subject[:issue]).to eq(false) + end + + it 'has no permissions to production stage' do + expect(subject[:production]).to eq(false) + end + end +end diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 7691d690db0..7e5941c39a6 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#code', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } context 'with deployment' do generate_cycle_analytics_spec( diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index f649b44d367..ff5c95c08cb 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } generate_cycle_analytics_spec( phase: :issue, diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 2cdefbeef21..16db10e4a1e 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#plan', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } generate_cycle_analytics_spec( phase: :plan, diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 1f5e5cab92d..8d5460c1e5a 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#production', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } generate_cycle_analytics_spec( phase: :production, diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 0ed080a42b1..9f3cb06c2df 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#review', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } generate_cycle_analytics_spec( phase: :review, diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index af1c4477ddb..1feb6326c31 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#staging', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } generate_cycle_analytics_spec( phase: :staging, diff --git a/spec/models/cycle_analytics/summary_spec.rb b/spec/models/cycle_analytics/summary_spec.rb index 9d67bc82cba..dfbd9a553bc 100644 --- a/spec/models/cycle_analytics/summary_spec.rb +++ b/spec/models/cycle_analytics/summary_spec.rb @@ -4,7 +4,7 @@ describe CycleAnalytics::Summary, models: true do let(:project) { create(:project) } let(:from) { Time.now } let(:user) { create(:user, :admin) } - subject { described_class.new(project, from: from) } + subject { described_class.new(project, from: from, user: user) } describe "#new_issues" do it "finds the number of issues created after the 'from date'" do diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index 02ddfeed9c1..ff7f03ca5fb 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#test', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, from: from_date, user: user) } generate_cycle_analytics_spec( phase: :test, -- cgit v1.2.1 From 4cb3c0b404f256be8bc80430eaf25b468e30ee44 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Thu, 27 Oct 2016 10:20:06 +0200 Subject: Grapify the users API --- spec/requests/api/users_spec.rb | 76 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 27 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 34d1f557e4b..1a6e7716b2f 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -108,7 +108,7 @@ describe API::API, api: true do it "returns a 404 error if user id not found" do get api("/users/9999", user) expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('404 User Not Found') end it "returns a 404 for invalid ID" do @@ -359,7 +359,7 @@ describe API::API, api: true do it "returns 404 for non-existing user" do put api("/users/999999", admin), { bio: 'update should fail' } expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('404 User Not Found') end it "returns a 404 if invalid ID" do @@ -387,6 +387,18 @@ describe API::API, api: true do to eq([Gitlab::Regex.namespace_regex_message]) end + it 'returns 400 if provider is missing for identity update' do + put api("/users/#{omniauth_user.id}", admin), extern_uid: '654321' + + expect(response).to have_http_status(400) + end + + it 'returns 400 if external UID is missing for identity update' do + put api("/users/#{omniauth_user.id}", admin), provider: 'ldap' + + expect(response).to have_http_status(400) + end + context "with existing user" do before do post api("/users", admin), { email: 'test@example.com', password: 'password', username: 'test', name: 'test' } @@ -414,14 +426,16 @@ describe API::API, api: true do it "does not create invalid ssh key" do post api("/users/#{user.id}/keys", admin), { title: "invalid key" } + expect(response).to have_http_status(400) - expect(json_response['message']).to eq('400 (Bad request) "key" not given') + expect(json_response['error']).to eq('key is missing') end it 'does not create key without title' do post api("/users/#{user.id}/keys", admin), key: 'some key' + expect(response).to have_http_status(400) - expect(json_response['message']).to eq('400 (Bad request) "title" not given') + expect(json_response['error']).to eq('title is missing') end it "creates ssh key" do @@ -437,7 +451,7 @@ describe API::API, api: true do end end - describe 'GET /user/:uid/keys' do + describe 'GET /user/:id/keys' do before { admin } context 'when unauthenticated' do @@ -465,7 +479,7 @@ describe API::API, api: true do end end - describe 'DELETE /user/:uid/keys/:id' do + describe 'DELETE /user/:id/keys/:key_id' do before { admin } context 'when unauthenticated' do @@ -506,8 +520,9 @@ describe API::API, api: true do it "does not create invalid email" do post api("/users/#{user.id}/emails", admin), {} + expect(response).to have_http_status(400) - expect(json_response['message']).to eq('400 (Bad request) "email" not given') + expect(json_response['error']).to eq('email is missing') end it "creates email" do @@ -524,7 +539,7 @@ describe API::API, api: true do end end - describe 'GET /user/:uid/emails' do + describe 'GET /user/:id/emails' do before { admin } context 'when unauthenticated' do @@ -558,7 +573,7 @@ describe API::API, api: true do end end - describe 'DELETE /user/:uid/emails/:id' do + describe 'DELETE /user/:id/emails/:email_id' do before { admin } context 'when unauthenticated' do @@ -673,7 +688,7 @@ describe API::API, api: true do end end - describe "GET /user/keys/:id" do + describe "GET /user/keys/:key_id" do it "returns single key" do user.keys << key user.save @@ -686,7 +701,7 @@ describe API::API, api: true do get api("/user/keys/42", user) expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('404 Key Not Found') end it "returns 404 error if admin accesses user's ssh key" do @@ -695,7 +710,7 @@ describe API::API, api: true do admin get api("/user/keys/#{key.id}", admin) expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('404 Key Not Found') end it "returns 404 for invalid ID" do @@ -721,14 +736,16 @@ describe API::API, api: true do it "does not create ssh key without key" do post api("/user/keys", user), title: 'title' + expect(response).to have_http_status(400) - expect(json_response['message']).to eq('400 (Bad request) "key" not given') + expect(json_response['error']).to eq('key is missing') end it 'does not create ssh key without title' do post api('/user/keys', user), key: 'some key' + expect(response).to have_http_status(400) - expect(json_response['message']).to eq('400 (Bad request) "title" not given') + expect(json_response['error']).to eq('title is missing') end it "does not create ssh key without title" do @@ -737,7 +754,7 @@ describe API::API, api: true do end end - describe "DELETE /user/keys/:id" do + describe "DELETE /user/keys/:key_id" do it "deletes existed key" do user.keys << key user.save @@ -747,9 +764,11 @@ describe API::API, api: true do expect(response).to have_http_status(200) end - it "returns success if key ID not found" do + it "returns 404 if key ID not found" do delete api("/user/keys/42", user) - expect(response).to have_http_status(200) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 Key Not Found') end it "returns 401 error if unauthorized" do @@ -786,7 +805,7 @@ describe API::API, api: true do end end - describe "GET /user/emails/:id" do + describe "GET /user/emails/:email_id" do it "returns single email" do user.emails << email user.save @@ -798,7 +817,7 @@ describe API::API, api: true do it "returns 404 Not Found within invalid ID" do get api("/user/emails/42", user) expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('404 Email Not Found') end it "returns 404 error if admin accesses user's email" do @@ -807,7 +826,7 @@ describe API::API, api: true do admin get api("/user/emails/#{email.id}", admin) expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Not found') + expect(json_response['message']).to eq('404 Email Not Found') end it "returns 404 for invalid ID" do @@ -833,12 +852,13 @@ describe API::API, api: true do it "does not create email with invalid email" do post api("/user/emails", user), {} + expect(response).to have_http_status(400) - expect(json_response['message']).to eq('400 (Bad request) "email" not given') + expect(json_response['error']).to eq('email is missing') end end - describe "DELETE /user/emails/:id" do + describe "DELETE /user/emails/:email_id" do it "deletes existed email" do user.emails << email user.save @@ -848,9 +868,11 @@ describe API::API, api: true do expect(response).to have_http_status(200) end - it "returns success if email ID not found" do + it "returns 404 if email ID not found" do delete api("/user/emails/42", user) - expect(response).to have_http_status(200) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 Email Not Found') end it "returns 401 error if unauthorized" do @@ -860,10 +882,10 @@ describe API::API, api: true do expect(response).to have_http_status(401) end - it "returns a 404 for invalid ID" do - delete api("/users/emails/ASDF", admin) + it "returns 400 for invalid ID" do + delete api("/user/emails/ASDF", admin) - expect(response).to have_http_status(404) + expect(response).to have_http_status(400) end end -- cgit v1.2.1 From beb638ca0379472eb15f840249321cdaca7bf5be Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 21 Nov 2016 12:41:44 +0200 Subject: Fix 404 on some group pages when name contains dot Signed-off-by: Dmitriy Zaporozhets --- spec/routing/routing_spec.rb | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 61dca5d5a62..7aba4f08088 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -261,20 +261,28 @@ describe "Authentication", "routing" do end describe "Groups", "routing" do + let(:name) { 'complex.group-name' } + it "to #show" do - expect(get("/groups/1")).to route_to('groups#show', id: '1') + expect(get("/groups/#{name}")).to route_to('groups#show', id: name) end it "also display group#show on the short path" do allow(Group).to receive(:find_by).and_return(true) - expect(get('/1')).to route_to('groups#show', id: '1') + expect(get("/#{name}")).to route_to('groups#show', id: name) end - it "also display group#show with dot in the path" do - allow(Group).to receive(:find_by).and_return(true) + it "to #activity" do + expect(get("/groups/#{name}/activity")).to route_to('groups#activity', id: name) + end + + it "to #issues" do + expect(get("/groups/#{name}/issues")).to route_to('groups#issues', id: name) + end - expect(get('/group.with.dot')).to route_to('groups#show', id: 'group.with.dot') + it "to #members" do + expect(get("/groups/#{name}/group_members")).to route_to('groups/group_members#index', group_id: name) end end -- cgit v1.2.1 From d747c1c0f974034d71a25edc2c8e525d3657c774 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 21 Nov 2016 11:52:04 +0100 Subject: fix spec failure --- spec/models/cycle_analytics/summary_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/summary_spec.rb b/spec/models/cycle_analytics/summary_spec.rb index dfbd9a553bc..9d67bc82cba 100644 --- a/spec/models/cycle_analytics/summary_spec.rb +++ b/spec/models/cycle_analytics/summary_spec.rb @@ -4,7 +4,7 @@ describe CycleAnalytics::Summary, models: true do let(:project) { create(:project) } let(:from) { Time.now } let(:user) { create(:user, :admin) } - subject { described_class.new(project, from: from, user: user) } + subject { described_class.new(project, from: from) } describe "#new_issues" do it "finds the number of issues created after the 'from date'" do -- cgit v1.2.1 From 903c81327f3e443a84ba24cfc68be635a3904722 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 21 Nov 2016 11:45:22 +0000 Subject: Remove v-html --- spec/javascripts/environments/environment_item_spec.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js.es6 index 54c93367b17..3c15e3b7719 100644 --- a/spec/javascripts/environments/environment_item_spec.js.es6 +++ b/spec/javascripts/environments/environment_item_spec.js.es6 @@ -135,7 +135,7 @@ describe('Environment item', () => { }); it('should render environment name', () => { - expect(component.$el.querySelector('.environment-name').textContent).toEqual(environment.name); + expect(component.$el.querySelector('.environment-name').textContent).toContain(environment.name); }); describe('With deployment', () => { -- cgit v1.2.1 From df5548e19e8c988b709e66a7e35ddc097344913e Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 8 Nov 2016 16:42:28 +0100 Subject: Unify detecting of special repository files This moves the logic of detecting special repository files (e.g. a README or a Koding configuration file) to a single class: Gitlab::FileDetector. Moving this logic into a single place allows this to be re-used more easily. This commit also changes Repository#gitlab_ci_yaml so that its cached similar to other data (e.g. the Koding configuration file). --- spec/lib/gitlab/file_detector_spec.rb | 59 ++++++++++++++++++++++ spec/models/repository_spec.rb | 94 +++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 spec/lib/gitlab/file_detector_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb new file mode 100644 index 00000000000..e5ba13bbaf8 --- /dev/null +++ b/spec/lib/gitlab/file_detector_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe Gitlab::FileDetector do + describe '.types_in_paths' do + it 'returns the file types for the given paths' do + expect(described_class.types_in_paths(%w(README.md CHANGELOG VERSION VERSION))). + to eq(%i{readme changelog version}) + end + + it 'does not include unrecognized file paths' do + expect(described_class.types_in_paths(%w(README.md foo.txt))). + to eq(%i{readme}) + end + end + + describe '.type_of' do + it 'returns the type of a README file' do + expect(described_class.type_of('README.md')).to eq(:readme) + end + + it 'returns the type of a changelog file' do + %w(CHANGELOG HISTORY CHANGES NEWS).each do |file| + expect(described_class.type_of(file)).to eq(:changelog) + end + end + + it 'returns the type of a license file' do + %w(LICENSE LICENCE COPYING).each do |file| + expect(described_class.type_of(file)).to eq(:license) + end + end + + it 'returns the type of a version file' do + expect(described_class.type_of('VERSION')).to eq(:version) + end + + it 'returns the type of a .gitignore file' do + expect(described_class.type_of('.gitignore')).to eq(:gitignore) + end + + it 'returns the type of a Koding config file' do + expect(described_class.type_of('.koding.yml')).to eq(:koding) + end + + it 'returns the type of a GitLab CI config file' do + expect(described_class.type_of('.gitlab-ci.yml')).to eq(:gitlab_ci) + end + + it 'returns the type of an avatar' do + %w(logo.gif logo.png logo.jpg).each do |file| + expect(described_class.type_of(file)).to eq(:avatar) + end + end + + it 'returns nil for an unknown file' do + expect(described_class.type_of('foo.txt')).to be_nil + end + end +end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 72ac41f3472..5e8a7bb08a1 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1578,4 +1578,98 @@ describe Repository, models: true do end.to raise_error(Repository::CommitError) end end + + describe '#contribution_guide', caching: true do + it 'returns and caches the output' do + expect(repository).to receive(:file_on_head). + with(:contributing). + and_return(Gitlab::Git::Tree.new(path: 'CONTRIBUTING.md')). + once + + 2.times do + expect(repository.contribution_guide). + to be_an_instance_of(Gitlab::Git::Tree) + end + end + end + + describe '#changelog', caching: true do + it 'returns and caches the output' do + expect(repository).to receive(:file_on_head). + with(:changelog). + and_return(Gitlab::Git::Tree.new(path: 'CHANGELOG')). + once + + 2.times do + expect(repository.changelog).to be_an_instance_of(Gitlab::Git::Tree) + end + end + end + + describe '#license_blob', caching: true do + it 'returns and caches the output' do + expect(repository).to receive(:file_on_head). + with(:license). + and_return(Gitlab::Git::Tree.new(path: 'LICENSE')). + once + + 2.times do + expect(repository.license_blob).to be_an_instance_of(Gitlab::Git::Tree) + end + end + end + + describe '#license_key', caching: true do + it 'returns and caches the output' do + license = double(key: 'mit') + + expect(Licensee).to receive(:license). + with(repository.path). + and_return(license). + once + + 2.times do + expect(repository.license_key).to eq('mit') + end + end + end + + describe '#gitignore', caching: true do + it 'returns and caches the output' do + expect(repository).to receive(:file_on_head). + with(:gitignore). + and_return(Gitlab::Git::Tree.new(path: '.gitignore')). + once + + 2.times do + expect(repository.gitignore).to be_an_instance_of(Gitlab::Git::Tree) + end + end + end + + describe '#koding_yml', caching: true do + it 'returns and caches the output' do + expect(repository).to receive(:file_on_head). + with(:koding). + and_return(Gitlab::Git::Tree.new(path: '.koding.yml')). + once + + 2.times do + expect(repository.koding_yml).to be_an_instance_of(Gitlab::Git::Tree) + end + end + end + + describe '#gitlab_ci_yml', caching: true do + it 'returns and caches the output' do + expect(repository).to receive(:file_on_head). + with(:gitlab_ci). + and_return(Gitlab::Git::Tree.new(path: '.gitlab-ci.yml')). + once + + 2.times do + expect(repository.gitlab_ci_yml).to be_an_instance_of(Gitlab::Git::Tree) + end + end + end end -- cgit v1.2.1 From 6f393877e555c9e87017747cd70d3577bb70a03e Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 8 Nov 2016 18:42:13 +0100 Subject: Use File.exist? to check if a repository exists Initializing Rugged objects is way too expensive just to check if a repository exists. Even though we cache this data once in a while we have to refresh this. On GitLab.com we have seen Repository#exists? taking up to _1 minute_ to complete in the absolute worst case, though usually it sits around a second or so. Using File.exist? to instead check if $GIT_DIR/refs exists is a much faster way of checking if a repository was initialized properly. --- spec/models/repository_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 5e8a7bb08a1..635130cf797 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -811,8 +811,7 @@ describe Repository, models: true do end it 'returns false when a repository does not exist' do - expect(repository.raw_repository).to receive(:rugged). - and_raise(Gitlab::Git::Repository::NoRepository) + allow(repository).to receive(:refs_directory_exists?).and_return(false) expect(repository.exists?).to eq(false) end -- cgit v1.2.1 From 9e9965ba5ce5a2acca97325412c63eed398ef80b Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Fri, 18 Nov 2016 11:14:44 +0100 Subject: Revert "Do not create a MergeRequestDiff record when source branch is deleted" This reverts commit f913170e2f76ef44800f0272cb7fb40b9d6709ee. --- spec/services/merge_requests/refresh_service_spec.rb | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 0220f7e1db2..e515bc9f89c 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -227,16 +227,6 @@ describe MergeRequests::RefreshService, services: true do end end - context 'when the source branch is deleted' do - it 'does not create a MergeRequestDiff record' do - refresh_service = service.new(@project, @user) - - expect do - refresh_service.execute(@oldrev, Gitlab::Git::BLANK_SHA, 'refs/heads/master') - end.not_to change { MergeRequestDiff.count } - end - end - def reload_mrs @merge_request.reload @fork_merge_request.reload -- cgit v1.2.1 From e22514fd4c54ec05e3272afdba5cba27d5b70516 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Fri, 18 Nov 2016 14:33:42 +0100 Subject: Hide empty merge request diffs when comparing versions --- spec/features/merge_requests/merge_request_versions_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/merge_request_versions_spec.rb b/spec/features/merge_requests/merge_request_versions_spec.rb index 23cee891bac..09451f41de4 100644 --- a/spec/features/merge_requests/merge_request_versions_spec.rb +++ b/spec/features/merge_requests/merge_request_versions_spec.rb @@ -3,11 +3,12 @@ require 'spec_helper' feature 'Merge Request versions', js: true, feature: true do let(:merge_request) { create(:merge_request, importing: true) } let(:project) { merge_request.source_project } + let!(:merge_request_diff1) { merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } + let!(:merge_request_diff2) { merge_request.merge_request_diffs.create(head_commit_sha: nil) } + let!(:merge_request_diff3) { merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') } before do login_as :admin - merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') - merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) end @@ -53,7 +54,7 @@ feature 'Merge Request versions', js: true, feature: true do project.namespace, project, merge_request.iid, - diff_id: 2, + diff_id: merge_request_diff3.id, start_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' ) end -- cgit v1.2.1 From fa936c68083810043b8c84fcbcad9fb3ce717eb6 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 21 Nov 2016 20:29:34 +0800 Subject: External jobs do not have show page nor traces Fixes #24677 --- spec/models/ci/pipeline_spec.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 71b7628ef10..ea5e0e28c5c 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -571,7 +571,13 @@ describe Ci::Pipeline, models: true do context 'with failed pipeline' do before do perform_enqueued_jobs do - pipeline.drop + create(:ci_build, :created, pipeline: pipeline) + create(:generic_commit_status, :created, pipeline: pipeline) + + pipeline.statuses.count.times do |offset| + # workaround race conditions + pipeline.statuses.offset(offset).first.drop + end end end -- cgit v1.2.1 From f0d5ef963fb591beaec768262476677c8c48c734 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 21 Nov 2016 13:30:24 +0100 Subject: Do not create TODO when build is allowed to fail --- .../add_todo_when_build_fails_service_spec.rb | 33 ++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb index dd656c3bbb7..a44312dd363 100644 --- a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb +++ b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb @@ -1,13 +1,22 @@ require 'spec_helper' -# Write specs in this file. describe MergeRequests::AddTodoWhenBuildFailsService do let(:user) { create(:user) } let(:merge_request) { create(:merge_request) } let(:project) { create(:project) } let(:sha) { '1234567890abcdef1234567890abcdef12345678' } - let(:pipeline) { create(:ci_pipeline_with_one_job, ref: merge_request.source_branch, project: project, sha: sha) } - let(:service) { MergeRequests::AddTodoWhenBuildFailsService.new(project, user, commit_message: 'Awesome message') } + let(:ref) { merge_request.source_branch } + + let(:pipeline) do + create(:ci_pipeline_with_one_job, ref: ref, + project: project, + sha: sha) + end + + let(:service) do + described_class.new(project, user, commit_message: 'Awesome message') + end + let(:todo_service) { TodoService.new } let(:merge_request) do @@ -23,7 +32,9 @@ describe MergeRequests::AddTodoWhenBuildFailsService do describe '#execute' do context 'commit status with ref' do - let(:commit_status) { create(:generic_commit_status, ref: merge_request.source_branch, pipeline: pipeline) } + let(:commit_status) do + create(:generic_commit_status, ref: ref, pipeline: pipeline) + end it 'notifies the todo service' do expect(todo_service).to receive(:merge_request_build_failed).with(merge_request) @@ -32,7 +43,7 @@ describe MergeRequests::AddTodoWhenBuildFailsService do end context 'commit status with non-HEAD ref' do - let(:commit_status) { create(:generic_commit_status, ref: merge_request.source_branch) } + let(:commit_status) { create(:generic_commit_status, ref: ref) } it 'does not notify the todo service' do expect(todo_service).not_to receive(:merge_request_build_failed) @@ -48,6 +59,18 @@ describe MergeRequests::AddTodoWhenBuildFailsService do service.execute(commit_status) end end + + context 'when commit status is a build allowed to fail' do + let(:commit_status) do + create(:ci_build, :allowed_to_fail, ref: ref, pipeline: pipeline) + end + + it 'does not create todo' do + expect(todo_service).not_to receive(:merge_request_build_failed) + + service.execute(commit_status) + end + end end describe '#close' do -- cgit v1.2.1 From 9b691688583ad46d5608320ec64873dd2eb9a647 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 21 Nov 2016 14:09:26 +0100 Subject: refactored a couple of things based on feedback --- spec/models/cycle_analytics/code_spec.rb | 2 +- spec/models/cycle_analytics/issue_spec.rb | 2 +- spec/models/cycle_analytics/plan_spec.rb | 2 +- spec/models/cycle_analytics/production_spec.rb | 2 +- spec/models/cycle_analytics/review_spec.rb | 2 +- spec/models/cycle_analytics/staging_spec.rb | 2 +- spec/models/cycle_analytics/test_spec.rb | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 7e5941c39a6..7691d690db0 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#code', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } context 'with deployment' do generate_cycle_analytics_spec( diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index ff5c95c08cb..f649b44d367 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec( phase: :issue, diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 16db10e4a1e..2cdefbeef21 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#plan', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec( phase: :plan, diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 8d5460c1e5a..1f5e5cab92d 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#production', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec( phase: :production, diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 9f3cb06c2df..0ed080a42b1 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#review', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec( phase: :review, diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index 1feb6326c31..af1c4477ddb 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#staging', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec( phase: :staging, diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index ff7f03ca5fb..02ddfeed9c1 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#test', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date, user: user) } + subject { CycleAnalytics.new(project, from: from_date) } generate_cycle_analytics_spec( phase: :test, -- cgit v1.2.1 From 1a5eedf3fedb09a3f6a7210ce435c95812c55013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 18 Nov 2016 18:30:07 +0100 Subject: Fix a wrong "The build for this merge request failed" message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also allow merge request to be merged with skipped pipeline and the "only allow merge when pipeline is green" feature enabled Signed-off-by: Rémy Coutable --- ...eck_if_mergeable_with_unresolved_discussions.rb | 69 ----------- ...f_mergeable_with_unresolved_discussions_spec.rb | 69 +++++++++++ .../only_allow_merge_if_build_succeeds.rb | 105 ---------------- .../only_allow_merge_if_build_succeeds_spec.rb | 132 +++++++++++++++++++++ .../merge_requests/toggle_whitespace_changes.rb | 22 ---- .../toggle_whitespace_changes_spec.rb | 22 ++++ spec/models/merge_request_spec.rb | 20 +++- 7 files changed, 242 insertions(+), 197 deletions(-) delete mode 100644 spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb create mode 100644 spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb delete mode 100644 spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb create mode 100644 spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb delete mode 100644 spec/features/merge_requests/toggle_whitespace_changes.rb create mode 100644 spec/features/merge_requests/toggle_whitespace_changes_spec.rb (limited to 'spec') diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb deleted file mode 100644 index 7f11db3c417..00000000000 --- a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'spec_helper' - -feature 'Check if mergeable with unresolved discussions', js: true, feature: true do - let(:user) { create(:user) } - let(:project) { create(:project) } - let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } - - before do - login_as user - project.team << [user, :master] - end - - context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do - before do - project.update_column(:only_allow_merge_if_all_discussions_are_resolved, true) - end - - context 'with unresolved discussions' do - it 'does not allow to merge' do - visit_merge_request(merge_request) - - expect(page).not_to have_button 'Accept Merge Request' - expect(page).to have_content('This merge request has unresolved discussions') - end - end - - context 'with all discussions resolved' do - before do - merge_request.discussions.each { |d| d.resolve!(user) } - end - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - end - - context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do - before do - project.update_column(:only_allow_merge_if_all_discussions_are_resolved, false) - end - - context 'with unresolved discussions' do - it 'does not allow to merge' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - - context 'with all discussions resolved' do - before do - merge_request.discussions.each { |d| d.resolve!(user) } - end - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - end - - def visit_merge_request(merge_request) - visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) - end -end diff --git a/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb new file mode 100644 index 00000000000..7f11db3c417 --- /dev/null +++ b/spec/features/merge_requests/check_if_mergeable_with_unresolved_discussions_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +feature 'Check if mergeable with unresolved discussions', js: true, feature: true do + let(:user) { create(:user) } + let(:project) { create(:project) } + let!(:merge_request) { create(:merge_request_with_diff_notes, source_project: project, author: user) } + + before do + login_as user + project.team << [user, :master] + end + + context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, true) + end + + context 'with unresolved discussions' do + it 'does not allow to merge' do + visit_merge_request(merge_request) + + expect(page).not_to have_button 'Accept Merge Request' + expect(page).to have_content('This merge request has unresolved discussions') + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + end + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + end + + context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do + before do + project.update_column(:only_allow_merge_if_all_discussions_are_resolved, false) + end + + context 'with unresolved discussions' do + it 'does not allow to merge' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'with all discussions resolved' do + before do + merge_request.discussions.each { |d| d.resolve!(user) } + end + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + end + + def visit_merge_request(merge_request) + visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + end +end diff --git a/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb b/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb deleted file mode 100644 index 80e8b8fc642..00000000000 --- a/spec/features/merge_requests/only_allow_merge_if_build_succeeds.rb +++ /dev/null @@ -1,105 +0,0 @@ -require 'spec_helper' - -feature 'Only allow merge requests to be merged if the build succeeds', feature: true do - let(:project) { create(:project, :public) } - let(:merge_request) { create(:merge_request_with_diffs, source_project: project) } - - before do - login_as merge_request.author - - project.team << [merge_request.author, :master] - end - - context 'project does not have CI enabled' do - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - - context 'when project has CI enabled' do - let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: merge_request.diff_head_sha, ref: merge_request.source_branch) } - - context 'when merge requests can only be merged if the build succeeds' do - before do - project.update_attribute(:only_allow_merge_if_build_succeeds, true) - end - - context 'when CI is running' do - before { pipeline.update_column(:status, :running) } - - it 'does not allow to merge immediately' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Merge When Build Succeeds' - expect(page).not_to have_button 'Select Merge Moment' - end - end - - context 'when CI failed' do - before { pipeline.update_column(:status, :failed) } - - it 'does not allow MR to be merged' do - 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.') - end - end - - context 'when CI succeeded' do - before { pipeline.update_column(:status, :success) } - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - end - - context 'when merge requests can be merged when the build failed' do - before do - project.update_attribute(:only_allow_merge_if_build_succeeds, false) - end - - context 'when CI is running' do - before { pipeline.update_column(:status, :running) } - - it 'allows MR to be merged immediately', js: true do - visit_merge_request(merge_request) - - expect(page).to have_button 'Merge When Build Succeeds' - - click_button 'Select Merge Moment' - expect(page).to have_content 'Merge Immediately' - end - end - - context 'when CI failed' do - before { pipeline.update_column(:status, :failed) } - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - - context 'when CI succeeded' do - before { pipeline.update_column(:status, :success) } - - it 'allows MR to be merged' do - visit_merge_request(merge_request) - - expect(page).to have_button 'Accept Merge Request' - end - end - end - end - - def visit_merge_request(merge_request) - visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) - 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 new file mode 100644 index 00000000000..1ec3103feef --- /dev/null +++ b/spec/features/merge_requests/only_allow_merge_if_build_succeeds_spec.rb @@ -0,0 +1,132 @@ +require 'spec_helper' + +feature 'Only allow merge requests to be merged if the build succeeds', feature: true do + let(:merge_request) { create(:merge_request_with_diffs) } + let(:project) { merge_request.target_project } + + before do + login_as merge_request.author + + project.team << [merge_request.author, :master] + end + + context 'project does not have CI enabled' do + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'when project has CI enabled' do + given!(:pipeline) do + create(:ci_empty_pipeline, + project: project, + sha: merge_request.diff_head_sha, + ref: merge_request.source_branch, + status: status) + end + + context 'when merge requests can only be merged if the build succeeds' do + before do + project.update_attribute(:only_allow_merge_if_build_succeeds, true) + end + + context 'when CI is running' do + given(:status) { :running } + + it 'does not allow to merge immediately' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Merge When Build Succeeds' + expect(page).not_to have_button 'Select Merge Moment' + end + end + + context 'when CI failed' do + given(:status) { :failed } + + it 'does not allow MR to be merged' do + 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.') + end + end + + context 'when CI canceled' do + given(:status) { :canceled } + + it 'does not allow MR to be merged' do + 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.') + end + end + + context 'when CI succeeded' do + given(:status) { :success } + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'when CI skipped' do + given(:status) { :skipped } + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + end + + context 'when merge requests can be merged when the build failed' do + before do + project.update_attribute(:only_allow_merge_if_build_succeeds, false) + end + + context 'when CI is running' do + given(:status) { :running } + + it 'allows MR to be merged immediately', js: true do + visit_merge_request(merge_request) + + expect(page).to have_button 'Merge When Build Succeeds' + + click_button 'Select Merge Moment' + expect(page).to have_content 'Merge Immediately' + end + end + + context 'when CI failed' do + given(:status) { :failed } + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + + context 'when CI succeeded' do + given(:status) { :success } + + it 'allows MR to be merged' do + visit_merge_request(merge_request) + + expect(page).to have_button 'Accept Merge Request' + end + end + end + end + + def visit_merge_request(merge_request) + visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request) + end +end diff --git a/spec/features/merge_requests/toggle_whitespace_changes.rb b/spec/features/merge_requests/toggle_whitespace_changes.rb deleted file mode 100644 index 0f98737b700..00000000000 --- a/spec/features/merge_requests/toggle_whitespace_changes.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec_helper' - -feature 'Toggle Whitespace Changes', js: true, feature: true do - before do - login_as :admin - merge_request = create(:merge_request) - project = merge_request.source_project - visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) - end - - it 'has a button to toggle whitespace changes' do - expect(page).to have_content 'Hide whitespace changes' - end - - describe 'clicking "Hide whitespace changes" button' do - it 'toggles the "Hide whitespace changes" button' do - click_link 'Hide whitespace changes' - - expect(page).to have_content 'Show whitespace changes' - end - end -end diff --git a/spec/features/merge_requests/toggle_whitespace_changes_spec.rb b/spec/features/merge_requests/toggle_whitespace_changes_spec.rb new file mode 100644 index 00000000000..0f98737b700 --- /dev/null +++ b/spec/features/merge_requests/toggle_whitespace_changes_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +feature 'Toggle Whitespace Changes', js: true, feature: true do + before do + login_as :admin + merge_request = create(:merge_request) + project = merge_request.source_project + visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + it 'has a button to toggle whitespace changes' do + expect(page).to have_content 'Hide whitespace changes' + end + + describe 'clicking "Hide whitespace changes" button' do + it 'toggles the "Hide whitespace changes" button' do + click_link 'Hide whitespace changes' + + expect(page).to have_content 'Show whitespace changes' + end + end +end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index fb032a89d50..0b4277b1edd 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -856,13 +856,31 @@ describe MergeRequest, models: true do context 'when it is only allowed to merge when build is green' do context 'and a failed pipeline is associated' do before do - pipeline.statuses << create(:commit_status, status: 'failed', project: project) + pipeline.update(status: 'failed') allow(subject).to receive(:pipeline) { pipeline } end it { expect(subject.mergeable_ci_state?).to be_falsey } end + context 'and a successful pipeline is associated' do + before do + pipeline.update(status: 'success') + allow(subject).to receive(:pipeline) { pipeline } + end + + it { expect(subject.mergeable_ci_state?).to be_truthy } + end + + context 'and a skipped pipeline is associated' do + before do + pipeline.update(status: 'skipped') + allow(subject).to receive(:pipeline) { pipeline } + end + + it { expect(subject.mergeable_ci_state?).to be_truthy } + end + context 'when no pipeline is associated' do before do allow(subject).to receive(:pipeline) { nil } -- cgit v1.2.1 From e3fb0740228219433a4623dc0b9325785e23ae16 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Sun, 20 Nov 2016 20:43:50 +0100 Subject: Send credentials array with build data --- spec/requests/ci/api/builds_spec.rb | 40 +++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'spec') diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index bd4d3d61714..c5e498601e6 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -58,28 +58,38 @@ describe Ci::API::API do expect { register_builds }.to change { runner.reload.contacted_at } end - context 'when registry is enabled' do - before do - stub_container_registry_config(enabled: true, host_port: 'registry.example.com:5005') + context 'registry credentials' do + let(:registry_credentials) do + { 'type' => 'docker-registry', + 'url' => 'registry.example.com:5005', + 'username' => 'gitlab-ci-token', + 'password' => build.token } end - it 'sends registry_url key' do - register_builds info: { platform: :darwin } + context 'when registry is enabled' do + before do + stub_container_registry_config(enabled: true, host_port: 'registry.example.com:5005') + end - expect(json_response).to have_key('registry_url') - expect(json_response['registry_url']).to eq("registry.example.com:5005") - end - end + it 'sends registry credentials key' do + register_builds info: { platform: :darwin } - context 'when registry is disabled' do - before do - stub_container_registry_config(enabled: false, host_port: 'registry.example.com:5005') + expect(json_response).to have_key('credentials') + expect(json_response['credentials']).to include(registry_credentials) + end end - it 'does not send registry_url key' do - register_builds info: { platform: :darwin } + context 'when registry is disabled' do + before do + stub_container_registry_config(enabled: false, host_port: 'registry.example.com:5005') + end - expect(json_response).not_to have_key('registry_url') + it 'does not send registry credentials' do + register_builds info: { platform: :darwin } + + expect(json_response).to have_key('credentials') + expect(json_response['credentials']).not_to include(registry_credentials) + end end end end -- cgit v1.2.1 From ffb9b3ef18dee6f7e561ff53253da42a25854c6c Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 18 Nov 2016 14:04:18 +0100 Subject: Refactor cache refreshing/expiring This refactors repository caching so it's possible to selectively refresh certain caches, instead of just expiring and refreshing everything. To allow this the various methods that were cached (e.g. "tag_count" and "readme") use a similar pattern that makes expiring and refreshing their data much easier. In this new setup caches are refreshed as follows: 1. After a commit (but before running ProjectCacheWorker) we expire some basic caches such as the commit count and repository size. 2. ProjectCacheWorker will recalculate the commit count, repository size, then refresh a specific set of caches based on the list of files changed in a push payload. This requires a bunch of changes to the various methods that may be cached. For one, data should not be cached if a branch used or the entire repository does not exist. To prevent all these methods from handling this manually this is taken care of in Repository#cache_method_output. Some methods still manually check for the existence of a repository but this result is also cached. With selective flushing implemented ProjectCacheWorker no longer uses an exclusive lease for all of its work. Instead this worker only uses a lease to limit the number of times the repository size is updated as this is a fairly expensive operation. --- spec/models/project_spec.rb | 2 +- spec/models/repository_spec.rb | 484 +++++++++++++++-------------- spec/requests/api/branches_spec.rb | 2 +- spec/services/git_push_service_spec.rb | 104 ++++--- spec/services/git_tag_push_service_spec.rb | 8 +- spec/workers/project_cache_worker_spec.rb | 86 ++--- 6 files changed, 352 insertions(+), 334 deletions(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 25458e20618..e183fa88873 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1572,7 +1572,7 @@ describe Project, models: true do end it 'expires the avatar cache' do - expect(project.repository).to receive(:expire_avatar_cache).with(project.default_branch) + expect(project.repository).to receive(:expire_avatar_cache) project.change_head(project.default_branch) end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 635130cf797..04afb8ebc98 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -464,11 +464,7 @@ describe Repository, models: true do end end - describe "#changelog" do - before do - repository.send(:cache).expire(:changelog) - end - + describe "#changelog", caching: true do it 'accepts changelog' do expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('changelog')]) @@ -500,17 +496,16 @@ describe Repository, models: true do end end - describe "#license_blob" do + describe "#license_blob", caching: true do before do - repository.send(:cache).expire(:license_blob) repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'master') end it 'handles when HEAD points to non-existent ref' do repository.commit_file(user, 'LICENSE', 'Copyright!', 'Add LICENSE', 'master', false) - rugged = double('rugged') - expect(rugged).to receive(:head_unborn?).and_return(true) - expect(repository).to receive(:rugged).and_return(rugged) + + allow(repository).to receive(:file_on_head). + and_raise(Rugged::ReferenceError) expect(repository.license_blob).to be_nil end @@ -537,22 +532,18 @@ describe Repository, models: true do end end - describe '#license_key' do + describe '#license_key', caching: true do before do - repository.send(:cache).expire(:license_key) repository.remove_file(user, 'LICENSE', 'Remove LICENSE', 'master') end - it 'handles when HEAD points to non-existent ref' do - repository.commit_file(user, 'LICENSE', 'Copyright!', 'Add LICENSE', 'master', false) - rugged = double('rugged') - expect(rugged).to receive(:head_unborn?).and_return(true) - expect(repository).to receive(:rugged).and_return(rugged) - + it 'returns nil when no license is detected' do expect(repository.license_key).to be_nil end - it 'returns nil when no license is detected' do + it 'returns nil when the repository does not exist' do + expect(repository).to receive(:exists?).and_return(false) + expect(repository.license_key).to be_nil end @@ -569,7 +560,7 @@ describe Repository, models: true do end end - describe "#gitlab_ci_yml" do + describe "#gitlab_ci_yml", caching: true do it 'returns valid file' do files = [TestBlob.new('file'), TestBlob.new('.gitlab-ci.yml'), TestBlob.new('copying')] expect(repository.tree).to receive(:blobs).and_return(files) @@ -583,7 +574,7 @@ describe Repository, models: true do end it 'returns nil for empty repository' do - expect(repository).to receive(:empty?).and_return(true) + allow(repository).to receive(:file_on_head).and_raise(Rugged::ReferenceError) expect(repository.gitlab_ci_yml).to be_nil end end @@ -778,7 +769,6 @@ describe Repository, models: true do expect(repository).not_to receive(:expire_emptiness_caches) expect(repository).to receive(:expire_branches_cache) expect(repository).to receive(:expire_has_visible_content_cache) - expect(repository).to receive(:expire_branch_count_cache) repository.update_branch_with_hooks(user, 'new-feature') { new_rev } end @@ -797,7 +787,6 @@ describe Repository, models: true do expect(empty_repository).to receive(:expire_emptiness_caches) expect(empty_repository).to receive(:expire_branches_cache) expect(empty_repository).to receive(:expire_has_visible_content_cache) - expect(empty_repository).to receive(:expire_branch_count_cache) empty_repository.commit_file(user, 'CHANGELOG', 'Changelog!', 'Updates file content', 'master', false) @@ -915,34 +904,6 @@ describe Repository, models: true do end end - describe '#expire_cache' do - it 'expires all caches' do - expect(repository).to receive(:expire_branch_cache) - - repository.expire_cache - end - - it 'expires the caches for a specific branch' do - expect(repository).to receive(:expire_branch_cache).with('master') - - repository.expire_cache('master') - end - - it 'expires the emptiness caches for an empty repository' do - expect(repository).to receive(:empty?).and_return(true) - expect(repository).to receive(:expire_emptiness_caches) - - repository.expire_cache - end - - it 'does not expire the emptiness caches for a non-empty repository' do - expect(repository).to receive(:empty?).and_return(false) - expect(repository).not_to receive(:expire_emptiness_caches) - - repository.expire_cache - end - end - describe '#expire_root_ref_cache' do it 'expires the root reference cache' do repository.root_ref @@ -1002,12 +963,23 @@ describe Repository, models: true do describe '#expire_emptiness_caches' do let(:cache) { repository.send(:cache) } - it 'expires the caches' do + it 'expires the caches for an empty repository' do + allow(repository).to receive(:empty?).and_return(true) + expect(cache).to receive(:expire).with(:empty?) expect(repository).to receive(:expire_has_visible_content_cache) repository.expire_emptiness_caches end + + it 'does not expire the cache for a non-empty repository' do + allow(repository).to receive(:empty?).and_return(false) + + expect(cache).not_to receive(:expire).with(:empty?) + expect(repository).not_to receive(:expire_has_visible_content_cache) + + repository.expire_emptiness_caches + end end describe :skip_merged_commit do @@ -1119,24 +1091,12 @@ describe Repository, models: true do repository.before_delete end - it 'flushes the tag count cache' do - expect(repository).to receive(:expire_tag_count_cache) - - repository.before_delete - end - it 'flushes the branches cache' do expect(repository).to receive(:expire_branches_cache) repository.before_delete end - it 'flushes the branch count cache' do - expect(repository).to receive(:expire_branch_count_cache) - - repository.before_delete - end - it 'flushes the root ref cache' do expect(repository).to receive(:expire_root_ref_cache) @@ -1161,36 +1121,18 @@ describe Repository, models: true do allow(repository).to receive(:exists?).and_return(true) end - it 'flushes the caches that depend on repository data' do - expect(repository).to receive(:expire_cache) - - repository.before_delete - end - it 'flushes the tags cache' do expect(repository).to receive(:expire_tags_cache) repository.before_delete end - it 'flushes the tag count cache' do - expect(repository).to receive(:expire_tag_count_cache) - - repository.before_delete - end - it 'flushes the branches cache' do expect(repository).to receive(:expire_branches_cache) repository.before_delete end - it 'flushes the branch count cache' do - expect(repository).to receive(:expire_branch_count_cache) - - repository.before_delete - end - it 'flushes the root ref cache' do expect(repository).to receive(:expire_root_ref_cache) @@ -1221,8 +1163,9 @@ describe Repository, models: true do describe '#before_push_tag' do it 'flushes the cache' do - expect(repository).to receive(:expire_cache) - expect(repository).to receive(:expire_tag_count_cache) + expect(repository).to receive(:expire_statistics_caches) + expect(repository).to receive(:expire_emptiness_caches) + expect(repository).to receive(:expire_tags_cache) repository.before_push_tag end @@ -1239,17 +1182,23 @@ describe Repository, models: true do describe '#after_import' do it 'flushes and builds the cache' do expect(repository).to receive(:expire_content_cache) - expect(repository).to receive(:build_cache) + expect(repository).to receive(:expire_tags_cache) + expect(repository).to receive(:expire_branches_cache) repository.after_import end end describe '#after_push_commit' do - it 'flushes the cache' do - expect(repository).to receive(:expire_cache).with('master', '123') + it 'expires statistics caches' do + expect(repository).to receive(:expire_statistics_caches). + and_call_original + + expect(repository).to receive(:expire_branch_cache). + with('master'). + and_call_original - repository.after_push_commit('master', '123') + repository.after_push_commit('master') end end @@ -1301,7 +1250,8 @@ describe Repository, models: true do describe '#before_remove_tag' do it 'flushes the tag cache' do - expect(repository).to receive(:expire_tag_count_cache) + expect(repository).to receive(:expire_tags_cache).and_call_original + expect(repository).to receive(:expire_statistics_caches).and_call_original repository.before_remove_tag end @@ -1319,23 +1269,23 @@ describe Repository, models: true do end end - describe '#expire_branch_count_cache' do - let(:cache) { repository.send(:cache) } - + describe '#expire_branches_cache' do it 'expires the cache' do - expect(cache).to receive(:expire).with(:branch_count) + expect(repository).to receive(:expire_method_caches). + with(%i(branch_names branch_count)). + and_call_original - repository.expire_branch_count_cache + repository.expire_branches_cache end end - describe '#expire_tag_count_cache' do - let(:cache) { repository.send(:cache) } - + describe '#expire_tags_cache' do it 'expires the cache' do - expect(cache).to receive(:expire).with(:tag_count) + expect(repository).to receive(:expire_method_caches). + with(%i(tag_names tag_count)). + and_call_original - repository.expire_tag_count_cache + repository.expire_tags_cache end end @@ -1411,84 +1361,27 @@ describe Repository, models: true do describe '#avatar' do it 'returns nil if repo does not exist' do - expect(repository).to receive(:exists?).and_return(false) + expect(repository).to receive(:file_on_head). + and_raise(Rugged::ReferenceError) expect(repository.avatar).to eq(nil) end it 'returns the first avatar file found in the repository' do - expect(repository).to receive(:blob_at_branch). - with('master', 'logo.png'). - and_return(true) + expect(repository).to receive(:file_on_head). + with(:avatar). + and_return(double(:tree, path: 'logo.png')) expect(repository.avatar).to eq('logo.png') end it 'caches the output' do - allow(repository).to receive(:blob_at_branch). - with('master', 'logo.png'). - and_return(true) - - expect(repository.avatar).to eq('logo.png') - - expect(repository).not_to receive(:blob_at_branch) - expect(repository.avatar).to eq('logo.png') - end - end - - describe '#expire_avatar_cache' do - let(:cache) { repository.send(:cache) } - - before do - allow(repository).to receive(:cache).and_return(cache) - end - - context 'without a branch or revision' do - it 'flushes the cache' do - expect(cache).to receive(:expire).with(:avatar) - - repository.expire_avatar_cache - end - end - - context 'with a branch' do - it 'does not flush the cache if the branch is not the default branch' do - expect(cache).not_to receive(:expire) - - repository.expire_avatar_cache('cats') - end - - it 'flushes the cache if the branch equals the default branch' do - expect(cache).to receive(:expire).with(:avatar) - - repository.expire_avatar_cache(repository.root_ref) - end - end - - context 'with a branch and revision' do - let(:commit) { double(:commit) } - - before do - allow(repository).to receive(:commit).and_return(commit) - end - - it 'does not flush the cache if the commit does not change any logos' do - diff = double(:diff, new_path: 'test.txt') - - expect(commit).to receive(:raw_diffs).and_return([diff]) - expect(cache).not_to receive(:expire) - - repository.expire_avatar_cache(repository.root_ref, '123') - end - - it 'flushes the cache if the commit changes any of the logos' do - diff = double(:diff, new_path: Repository::AVATAR_FILES[0]) - - expect(commit).to receive(:raw_diffs).and_return([diff]) - expect(cache).to receive(:expire).with(:avatar) + expect(repository).to receive(:file_on_head). + with(:avatar). + once. + and_return(double(:tree, path: 'logo.png')) - repository.expire_avatar_cache(repository.root_ref, '123') - end + 2.times { expect(repository.avatar).to eq('logo.png') } end end @@ -1502,40 +1395,6 @@ describe Repository, models: true do end end - describe '#build_cache' do - let(:cache) { repository.send(:cache) } - - it 'builds the caches if they do not already exist' do - cache_keys = repository.cache_keys + repository.cache_keys_for_branches_and_tags - - expect(cache).to receive(:exist?). - exactly(cache_keys.length). - times. - and_return(false) - - cache_keys.each do |key| - expect(repository).to receive(key) - end - - repository.build_cache - end - - it 'does not build any caches that already exist' do - cache_keys = repository.cache_keys + repository.cache_keys_for_branches_and_tags - - expect(cache).to receive(:exist?). - exactly(cache_keys.length). - times. - and_return(true) - - cache_keys.each do |key| - expect(repository).not_to receive(key) - end - - repository.build_cache - end - end - describe "#keep_around" do it "does not fail if we attempt to reference bad commit" do expect(repository.kept_around?('abc1234')).to be_falsey @@ -1592,83 +1451,226 @@ describe Repository, models: true do end end - describe '#changelog', caching: true do + describe '#gitignore', caching: true do it 'returns and caches the output' do expect(repository).to receive(:file_on_head). - with(:changelog). - and_return(Gitlab::Git::Tree.new(path: 'CHANGELOG')). + with(:gitignore). + and_return(Gitlab::Git::Tree.new(path: '.gitignore')). once 2.times do - expect(repository.changelog).to be_an_instance_of(Gitlab::Git::Tree) + expect(repository.gitignore).to be_an_instance_of(Gitlab::Git::Tree) end end end - describe '#license_blob', caching: true do + describe '#koding_yml', caching: true do it 'returns and caches the output' do expect(repository).to receive(:file_on_head). - with(:license). - and_return(Gitlab::Git::Tree.new(path: 'LICENSE')). + with(:koding). + and_return(Gitlab::Git::Tree.new(path: '.koding.yml')). once 2.times do - expect(repository.license_blob).to be_an_instance_of(Gitlab::Git::Tree) + expect(repository.koding_yml).to be_an_instance_of(Gitlab::Git::Tree) end end end - describe '#license_key', caching: true do - it 'returns and caches the output' do - license = double(key: 'mit') + describe '#readme', caching: true do + context 'with a non-existing repository' do + it 'returns nil' do + expect(repository).to receive(:tree).with(:head).and_return(nil) - expect(Licensee).to receive(:license). - with(repository.path). - and_return(license). - once + expect(repository.readme).to be_nil + end + end - 2.times do - expect(repository.license_key).to eq('mit') + context 'with an existing repository' do + it 'returns the README' do + expect(repository.readme).to be_an_instance_of(Gitlab::Git::Blob) end end end - describe '#gitignore', caching: true do - it 'returns and caches the output' do - expect(repository).to receive(:file_on_head). - with(:gitignore). - and_return(Gitlab::Git::Tree.new(path: '.gitignore')). - once + describe '#expire_statistics_caches' do + it 'expires the caches' do + expect(repository).to receive(:expire_method_caches). + with(%i(size commit_count)) - 2.times do - expect(repository.gitignore).to be_an_instance_of(Gitlab::Git::Tree) + repository.expire_statistics_caches + end + end + + describe '#expire_method_caches' do + it 'expires the caches of the given methods' do + expect_any_instance_of(RepositoryCache).to receive(:expire).with(:readme) + expect_any_instance_of(RepositoryCache).to receive(:expire).with(:gitignore) + + repository.expire_method_caches(%i(readme gitignore)) + end + end + + describe '#expire_all_method_caches' do + it 'expires the caches of all methods' do + expect(repository).to receive(:expire_method_caches). + with(Repository::CACHED_METHODS) + + repository.expire_all_method_caches + end + end + + describe '#expire_avatar_cache' do + it 'expires the cache' do + expect(repository).to receive(:expire_method_caches).with(%i(avatar)) + + repository.expire_avatar_cache + end + end + + describe '#file_on_head' do + context 'with a non-existing repository' do + it 'returns nil' do + expect(repository).to receive(:tree).with(:head).and_return(nil) + + expect(repository.file_on_head(:readme)).to be_nil + end + end + + context 'with a repository that has no blobs' do + it 'returns nil' do + expect_any_instance_of(Tree).to receive(:blobs).and_return([]) + + expect(repository.file_on_head(:readme)).to be_nil + end + end + + context 'with an existing repository' do + it 'returns a Gitlab::Git::Tree' do + expect(repository.file_on_head(:readme)). + to be_an_instance_of(Gitlab::Git::Tree) end end end - describe '#koding_yml', caching: true do - it 'returns and caches the output' do - expect(repository).to receive(:file_on_head). - with(:koding). - and_return(Gitlab::Git::Tree.new(path: '.koding.yml')). - once + describe '#head_tree' do + context 'with an existing repository' do + it 'returns a Tree' do + expect(repository.head_tree).to be_an_instance_of(Tree) + end + end - 2.times do - expect(repository.koding_yml).to be_an_instance_of(Gitlab::Git::Tree) + context 'with a non-existing repository' do + it 'returns nil' do + expect(repository).to receive(:head_commit).and_return(nil) + + expect(repository.head_tree).to be_nil end end end - describe '#gitlab_ci_yml', caching: true do - it 'returns and caches the output' do - expect(repository).to receive(:file_on_head). - with(:gitlab_ci). - and_return(Gitlab::Git::Tree.new(path: '.gitlab-ci.yml')). - once + describe '#tree' do + context 'using a non-existing repository' do + before do + allow(repository).to receive(:head_commit).and_return(nil) + end - 2.times do - expect(repository.gitlab_ci_yml).to be_an_instance_of(Gitlab::Git::Tree) + it 'returns nil' do + expect(repository.tree(:head)).to be_nil + end + + it 'returns nil when using a path' do + expect(repository.tree(:head, 'README.md')).to be_nil + end + end + + context 'using an existing repository' do + it 'returns a Tree' do + expect(repository.tree(:head)).to be_an_instance_of(Tree) + end + end + end + + describe '#size' do + context 'with a non-existing repository' do + it 'returns 0' do + expect(repository).to receive(:exists?).and_return(false) + + expect(repository.size).to eq(0.0) + end + end + + context 'with an existing repository' do + it 'returns the repository size as a Float' do + expect(repository.size).to be_an_instance_of(Float) + end + end + end + + describe '#commit_count' do + context 'with a non-existing repository' do + it 'returns 0' do + expect(repository).to receive(:root_ref).and_return(nil) + + expect(repository.commit_count).to eq(0) + end + end + + context 'with an existing repository' do + it 'returns the commit count' do + expect(repository.commit_count).to be_an_instance_of(Fixnum) + end + end + end + + describe '#cache_method_output', caching: true do + context 'with a non-existing repository' do + let(:value) do + repository.cache_method_output(:cats, fallback: 10) do + raise Rugged::ReferenceError + end + end + + it 'returns a fallback value' do + expect(value).to eq(10) + end + + it 'does not cache the data' do + value + + expect(repository.instance_variable_defined?(:@cats)).to eq(false) + expect(repository.send(:cache).exist?(:cats)).to eq(false) end end + + context 'with an existing repository' do + it 'caches the output' do + object = double + + expect(object).to receive(:number).once.and_return(10) + + 2.times do + val = repository.cache_method_output(:cats) { object.number } + + expect(val).to eq(10) + end + + expect(repository.send(:cache).exist?(:cats)).to eq(true) + expect(repository.instance_variable_get(:@cats)).to eq(10) + end + end + end + + describe '#refresh_method_caches' do + it 'refreshes the caches of the given types' do + expect(repository).to receive(:expire_method_caches). + with(%i(readme license_blob license_key)) + + expect(repository).to receive(:readme) + expect(repository).to receive(:license_blob) + expect(repository).to receive(:license_key) + + repository.refresh_method_caches(%i(readme license)) + end end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index 8f605757186..fe6b875b997 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -14,7 +14,7 @@ describe API::API, api: true do describe "GET /projects/:id/repository/branches" do it "returns an array of project branches" do - project.repository.expire_cache + project.repository.expire_all_method_caches get api("/projects/#{project.id}/repository/branches", user) expect(response).to have_http_status(200) diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 62f9982e840..9d7702f5c96 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -27,27 +27,14 @@ describe GitPushService, services: true do it { is_expected.to be_truthy } - it 'flushes general cached data' do - expect(project.repository).to receive(:expire_cache). - with('master', newrev) + it 'calls the after_push_commit hook' do + expect(project.repository).to receive(:after_push_commit).with('master') subject end - it 'flushes the visible content cache' do - expect(project.repository).to receive(:expire_has_visible_content_cache) - - subject - end - - it 'flushes the branches cache' do - expect(project.repository).to receive(:expire_branches_cache) - - subject - end - - it 'flushes the branch count cache' do - expect(project.repository).to receive(:expire_branch_count_cache) + it 'calls the after_create_branch hook' do + expect(project.repository).to receive(:after_create_branch) subject end @@ -56,21 +43,8 @@ describe GitPushService, services: true do context 'existing branch' do it { is_expected.to be_truthy } - it 'flushes general cached data' do - expect(project.repository).to receive(:expire_cache). - with('master', newrev) - - subject - end - - it 'does not flush the branches cache' do - expect(project.repository).not_to receive(:expire_branches_cache) - - subject - end - - it 'does not flush the branch count cache' do - expect(project.repository).not_to receive(:expire_branch_count_cache) + it 'calls the after_push_commit hook' do + expect(project.repository).to receive(:after_push_commit).with('master') subject end @@ -81,27 +55,14 @@ describe GitPushService, services: true do it { is_expected.to be_truthy } - it 'flushes the visible content cache' do - expect(project.repository).to receive(:expire_has_visible_content_cache) - - subject - end - - it 'flushes the branches cache' do - expect(project.repository).to receive(:expire_branches_cache) - - subject - end - - it 'flushes the branch count cache' do - expect(project.repository).to receive(:expire_branch_count_cache) + it 'calls the after_push_commit hook' do + expect(project.repository).to receive(:after_push_commit).with('master') subject end - it 'flushes general cached data' do - expect(project.repository).to receive(:expire_cache). - with('master', newrev) + it 'calls the after_remove_branch hook' do + expect(project.repository).to receive(:after_remove_branch) subject end @@ -598,6 +559,51 @@ describe GitPushService, services: true do end end + describe '#update_caches' do + let(:service) do + described_class.new(project, + user, + oldrev: sample_commit.parent_id, + newrev: sample_commit.id, + ref: 'refs/heads/master') + end + + context 'on the default branch' do + before do + allow(service).to receive(:is_default_branch?).and_return(true) + end + + it 'flushes the caches of any special files that have been changed' do + commit = double(:commit) + diff = double(:diff, new_path: 'README.md') + + expect(commit).to receive(:raw_diffs).with(deltas_only: true). + and_return([diff]) + + service.push_commits = [commit] + + expect(ProjectCacheWorker).to receive(:perform_async). + with(project.id, %i(readme)) + + service.update_caches + end + end + + context 'on a non-default branch' do + before do + allow(service).to receive(:is_default_branch?).and_return(false) + end + + it 'does not flush any conditional caches' do + expect(ProjectCacheWorker).to receive(:perform_async). + with(project.id, []). + and_call_original + + service.update_caches + end + end + end + def execute_service(project, user, oldrev, newrev, ref) service = described_class.new(project, user, oldrev: oldrev, newrev: newrev, ref: ref ) service.execute diff --git a/spec/services/git_tag_push_service_spec.rb b/spec/services/git_tag_push_service_spec.rb index 0879e3ab4c8..bd074b9bd71 100644 --- a/spec/services/git_tag_push_service_spec.rb +++ b/spec/services/git_tag_push_service_spec.rb @@ -18,7 +18,7 @@ describe GitTagPushService, services: true do end it 'flushes general cached data' do - expect(project.repository).to receive(:expire_cache) + expect(project.repository).to receive(:before_push_tag) subject end @@ -28,12 +28,6 @@ describe GitTagPushService, services: true do subject end - - it 'flushes the tag count cache' do - expect(project.repository).to receive(:expire_tag_count_cache) - - subject - end end describe "Git Tag Push Data" do diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index bfa8c0ff2c6..855c28b584e 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -2,62 +2,78 @@ require 'spec_helper' describe ProjectCacheWorker do let(:project) { create(:project) } + let(:worker) { described_class.new } - subject { described_class.new } - - describe '.perform_async' do - it 'schedules the job when no lease exists' do - allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:exists?). - and_return(false) + describe '#perform' do + before do + allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain). + and_return(true) + end - expect_any_instance_of(described_class).to receive(:perform) + context 'with a non-existing project' do + it 'does nothing' do + expect(worker).not_to receive(:update_repository_size) - described_class.perform_async(project.id) + worker.perform(-1) + end end - it 'does not schedule the job when a lease exists' do - allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:exists?). - and_return(true) + context 'with an existing project without a repository' do + it 'does nothing' do + allow_any_instance_of(Repository).to receive(:exists?).and_return(false) - expect_any_instance_of(described_class).not_to receive(:perform) + expect(worker).not_to receive(:update_repository_size) - described_class.perform_async(project.id) + worker.perform(project.id) + end end - end - describe '#perform' do - context 'when an exclusive lease can be obtained' do - before do - allow(subject).to receive(:try_obtain_lease_for).with(project.id). - and_return(true) - end + context 'with an existing project' do + it 'updates the repository size' do + expect(worker).to receive(:update_repository_size).and_call_original - it 'updates project cache data' do - expect_any_instance_of(Repository).to receive(:size) - expect_any_instance_of(Repository).to receive(:commit_count) + worker.perform(project.id) + end - expect_any_instance_of(Project).to receive(:update_repository_size) - expect_any_instance_of(Project).to receive(:update_commit_count) + it 'updates the commit count' do + expect_any_instance_of(Project).to receive(:update_commit_count). + and_call_original - subject.perform(project.id) + worker.perform(project.id) end - it 'handles missing repository data' do - expect_any_instance_of(Repository).to receive(:exists?).and_return(false) - expect_any_instance_of(Repository).not_to receive(:size) + it 'refreshes the method caches' do + expect_any_instance_of(Repository).to receive(:refresh_method_caches). + with(%i(readme)). + and_call_original - subject.perform(project.id) + worker.perform(project.id, %i(readme)) end end + end - context 'when an exclusive lease can not be obtained' do - it 'does nothing' do - allow(subject).to receive(:try_obtain_lease_for).with(project.id). + describe '#update_repository_size' do + context 'when a lease could not be obtained' do + it 'does not update the repository size' do + allow(worker).to receive(:try_obtain_lease_for). + with(project.id, :update_repository_size). and_return(false) - expect(subject).not_to receive(:update_caches) + expect(project).not_to receive(:update_repository_size) + + worker.update_repository_size(project) + end + end + + context 'when a lease could be obtained' do + it 'updates the repository size' do + allow(worker).to receive(:try_obtain_lease_for). + with(project.id, :update_repository_size). + and_return(true) + + expect(project).to receive(:update_repository_size).and_call_original - subject.perform(project.id) + worker.update_repository_size(project) end end end -- cgit v1.2.1 From 9c740133a3bb4e992ccd7e3801402e4eab537e29 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 17 Nov 2016 18:46:31 -0200 Subject: Allow JIRA references for project snippets --- spec/services/system_note_service_spec.rb | 65 +++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 17 deletions(-) (limited to 'spec') diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 150e21574a1..2a5709c6322 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -543,7 +543,10 @@ describe SystemNoteService, services: true do let(:comment_url) { jira_api_comment_url(jira_issue.id) } let(:success_message) { "JiraService SUCCESS: Successfully posted to http://jira.example.net." } - before { stub_jira_urls(jira_issue.id) } + before do + stub_jira_urls(jira_issue.id) + jira_service_settings + end noteable_types = ["merge_requests", "commit"] @@ -569,16 +572,16 @@ describe SystemNoteService, services: true do end end - context 'in JIRA issue tracker' do - before { jira_service_settings } - - describe "new reference" do - subject { described_class.cross_reference(jira_issue, commit, author) } + describe "new reference" do + context 'for commits' do + it "creates comment" do + result = described_class.cross_reference(jira_issue, commit, author) - it { is_expected.to eq(success_message) } + expect(result).to eq(success_message) + end it "creates remote link" do - subject + described_class.cross_reference(jira_issue, commit, author) expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with( body: hash_including( @@ -593,18 +596,18 @@ describe SystemNoteService, services: true do ).once end end - end - context 'in commit' do - context 'in JIRA issue tracker' do - before { jira_service_settings } + context 'for issues' do + let(:issue) { create(:issue, project: project) } - subject { described_class.cross_reference(jira_issue, issue, author) } + it "creates comment" do + result = described_class.cross_reference(jira_issue, issue, author) - it { is_expected.to eq(success_message) } + expect(result).to eq(success_message) + end it "creates remote link" do - subject + described_class.cross_reference(jira_issue, issue, author) expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with( body: hash_including( @@ -619,6 +622,32 @@ describe SystemNoteService, services: true do ).once end end + + context 'for snippets' do + let(:snippet) { create(:snippet, project: project) } + + it "creates comment" do + result = described_class.cross_reference(jira_issue, snippet, author) + + expect(result).to eq(success_message) + end + + it "creates remote link" do + described_class.cross_reference(jira_issue, snippet, author) + + expect(WebMock).to have_requested(:post, jira_api_remote_link_url(jira_issue)).with( + body: hash_including( + GlobalID: "GitLab", + object: { + url: namespace_project_snippet_url(project.namespace, project, snippet), + title: "GitLab: Mentioned on snippet - #{snippet.title}", + icon: { title: "GitLab", url16x16: "https://gitlab.com/favicon.ico" }, + status: { resolved: false } + } + ) + ).once + end + end end describe "existing reference" do @@ -627,9 +656,11 @@ describe SystemNoteService, services: true do allow_any_instance_of(JIRA::Resource::Issue).to receive(:comments).and_return([OpenStruct.new(body: message)]) end - subject { described_class.cross_reference(jira_issue, commit, author) } + it "does not return success message" do + result = described_class.cross_reference(jira_issue, commit, author) - it { is_expected.not_to eq(success_message) } + expect(result).not_to eq(success_message) + end it 'does not try to create comment and remote link' do subject -- cgit v1.2.1 From dde8fba524aa071d08121818a1e2c3d635664819 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 21 Nov 2016 15:39:43 +0100 Subject: Adds a flag to reflect whether or not there is data in cycle analytics --- .../projects/cycle_analytics_controller_spec.rb | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 spec/controllers/projects/cycle_analytics_controller_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb new file mode 100644 index 00000000000..9131014a05d --- /dev/null +++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe Projects::CycleAnalyticsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + sign_in(user) + project.team << [user, :master] + end + + describe 'cycle analytics not set up flag' do + context 'with no data' do + it 'is true' do + get(:show, + namespace_id: project.namespace.to_param, + project_id: project.to_param) + + expect(response).to be_success + expect(assigns(:cycle_analytics_not_set_up)).to eq(true) + end + end + + context 'with data' do + before do + issue = create(:issue, project: project, created_at: 4.days.ago) + milestone = create(:milestone, project: project, created_at: 5.days.ago) + issue.update(milestone: milestone) + + create_merge_request_closing_issue(issue) + end + + it 'is false' do + get(:show, + namespace_id: project.namespace.to_param, + project_id: project.to_param) + + expect(response).to be_success + expect(assigns(:cycle_analytics_not_set_up)).to eq(false) + end + end + end +end -- cgit v1.2.1 From b7bf1f3a9d8c406024a212e6098f049334cda8e3 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Mon, 21 Nov 2016 15:06:32 +0100 Subject: Grapify the projects snippet API --- spec/requests/api/project_snippets_spec.rb | 64 +++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 14 deletions(-) (limited to 'spec') diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index 01148f0a05e..1c25fd04339 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -3,10 +3,12 @@ require 'rails_helper' describe API::API, api: true do include ApiHelpers + let(:project) { create(:empty_project, :public) } + let(:admin) { create(:admin) } + describe 'GET /projects/:project_id/snippets/:id' do # TODO (rspeicher): Deprecated; remove in 9.0 it 'always exposes expires_at as nil' do - admin = create(:admin) snippet = create(:project_snippet, author: admin) get api("/projects/#{snippet.project.id}/snippets/#{snippet.id}", admin) @@ -17,9 +19,9 @@ describe API::API, api: true do end describe 'GET /projects/:project_id/snippets/' do + let(:user) { create(:user) } + it 'returns all snippets available to team member' do - project = create(:project, :public) - user = create(:user) project.team << [user, :developer] public_snippet = create(:project_snippet, :public, project: project) internal_snippet = create(:project_snippet, :internal, project: project) @@ -34,8 +36,6 @@ describe API::API, api: true do end it 'hides private snippets from regular user' do - project = create(:project, :public) - user = create(:user) create(:project_snippet, :private, project: project) get api("/projects/#{project.id}/snippets/", user) @@ -45,16 +45,16 @@ describe API::API, api: true do end describe 'POST /projects/:project_id/snippets/' do - it 'creates a new snippet' do - admin = create(:admin) - project = create(:project) - params = { + let(:params) do + { title: 'Test Title', file_name: 'test.rb', code: 'puts "hello world"', visibility_level: Gitlab::VisibilityLevel::PUBLIC } + end + it 'creates a new snippet' do post api("/projects/#{project.id}/snippets/", admin), params expect(response).to have_http_status(201) @@ -64,12 +64,20 @@ describe API::API, api: true do expect(snippet.file_name).to eq(params[:file_name]) expect(snippet.visibility_level).to eq(params[:visibility_level]) end + + it 'returns 400 for missing parameters' do + params.delete(:title) + + post api("/projects/#{project.id}/snippets/", admin), params + + expect(response).to have_http_status(400) + end end describe 'PUT /projects/:project_id/snippets/:id/' do + let(:snippet) { create(:project_snippet, author: admin) } + it 'updates snippet' do - admin = create(:admin) - snippet = create(:project_snippet, author: admin) new_content = 'New content' put api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin), code: new_content @@ -78,9 +86,24 @@ describe API::API, api: true do snippet.reload expect(snippet.content).to eq(new_content) end + + it 'returns 404 for invalid snippet id' do + put api("/projects/#{snippet.project.id}/snippets/1234", admin), title: 'foo' + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 Snippet Not Found') + end + + it 'returns 400 for missing parameters' do + put api("/projects/#{project.id}/snippets/1234", admin) + + expect(response).to have_http_status(400) + end end describe 'DELETE /projects/:project_id/snippets/:id/' do + let(:snippet) { create(:project_snippet, author: admin) } + it 'deletes snippet' do admin = create(:admin) snippet = create(:project_snippet, author: admin) @@ -89,18 +112,31 @@ describe API::API, api: true do expect(response).to have_http_status(200) end + + it 'returns 404 for invalid snippet id' do + delete api("/projects/#{snippet.project.id}/snippets/1234", admin) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 Snippet Not Found') + end end describe 'GET /projects/:project_id/snippets/:id/raw' do - it 'returns raw text' do - admin = create(:admin) - snippet = create(:project_snippet, author: admin) + let(:snippet) { create(:project_snippet, author: admin) } + it 'returns raw text' do get api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/raw", admin) expect(response).to have_http_status(200) expect(response.content_type).to eq 'text/plain' expect(response.body).to eq(snippet.content) end + + it 'returns 404 for invalid snippet id' do + delete api("/projects/#{snippet.project.id}/snippets/1234", admin) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 Snippet Not Found') + end end end -- cgit v1.2.1 From a36d556137116385e84eca592ec62e46ecb97e03 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 21 Nov 2016 17:26:35 +0100 Subject: Introduce deploy command that allows to start deployment from one environment to second one --- spec/factories/ci/builds.rb | 6 +++ spec/lib/gitlab/chat_commands/command_spec.rb | 43 ++++++++++++++- spec/lib/gitlab/chat_commands/deploy_spec.rb | 75 +++++++++++++++++++++++++++ spec/models/environment_spec.rb | 12 +++++ 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 spec/lib/gitlab/chat_commands/deploy_spec.rb (limited to 'spec') diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 0c93bbdfe26..eb20bd7dd58 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -55,6 +55,12 @@ FactoryGirl.define do self.when 'manual' end + trait :teardown_environment do + options do + { environment: { action: 'stop' } } + end + end + trait :allowed_to_fail do allow_failure true end diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index 8cedbb0240f..924b4b7b101 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -4,9 +4,9 @@ describe Gitlab::ChatCommands::Command, service: true do let(:project) { create(:empty_project) } let(:user) { create(:user) } - subject { described_class.new(project, user, params).execute } - describe '#execute' do + subject { described_class.new(project, user, params).execute } + context 'when no command is available' do let(:params) { { text: 'issue show 1' } } let(:project) { create(:project, has_external_issue_tracker: true) } @@ -51,5 +51,44 @@ describe Gitlab::ChatCommands::Command, service: true do expect(subject[:text]).to match(/\/issues\/\d+/) end end + + context 'when trying to do deployment' do + let(:params) { { text: 'deploy staging to production' } } + let!(:build) { create(:ci_build, project: project) } + let!(:staging) { create(:environment, name: 'staging', project: project) } + let!(:deployment) { create(:deployment, environment: staging, deployable: build) } + let!(:manual) do + create(:ci_build, :manual, project: project, pipeline: build.pipeline, name: 'first', environment: 'production') + end + + 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') + end + end + + context 'and user does have deployment permission' do + before do + project.team << [user, :developer] + end + + it 'returns action' do + expect(subject[:text]).to include(manual.name) + expect(subject[:response_type]).to be(:in_channel) + end + + context 'when duplicate action exists' do + let!(:manual2) do + create(:ci_build, :manual, project: project, pipeline: build.pipeline, name: 'second', environment: 'production') + end + + it 'returns error' do + expect(subject[:response_type]).to be(:ephemeral) + expect(subject[:text]).to include('Too many actions defined') + end + end + end + end end end diff --git a/spec/lib/gitlab/chat_commands/deploy_spec.rb b/spec/lib/gitlab/chat_commands/deploy_spec.rb new file mode 100644 index 00000000000..bdbaa41dd14 --- /dev/null +++ b/spec/lib/gitlab/chat_commands/deploy_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::Deploy, service: true do + describe '#execute' do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + let(:regex_match) { described_class.match('deploy staging to production') } + + before do + project.team << [user, :master] + end + + subject do + described_class.new(project, user).execute(regex_match) + end + + context 'if no environment is defined' do + it 'returns nil' do + expect(subject).to be_nil + end + end + + context 'with environment' do + let!(:staging) { create(:environment, name: 'staging', project: project) } + let!(:build) { create(:ci_build, project: project) } + let!(:deployment) { create(:deployment, environment: staging, deployable: build) } + + context 'without actions' do + it 'returns nil' do + expect(subject).to be_nil + end + end + + context 'with action' do + let!(:manual1) do + create(:ci_build, :manual, project: project, pipeline: build.pipeline, name: 'first', environment: 'production') + end + + it 'returns action' do + expect(subject).to eq(manual1) + end + + context 'when duplicate action exists' do + let!(:manual2) do + create(:ci_build, :manual, project: project, pipeline: build.pipeline, name: 'second', environment: 'production') + end + + it 'returns error' do + expect(subject.message).to eq('Too many actions defined') + end + end + + context 'when teardown action exists' do + let!(:teardown) do + create(:ci_build, :manual, :teardown_environment, project: project, pipeline: build.pipeline, + name: 'teardown', environment: 'production') + end + + it 'returns error' do + expect(subject).to eq(action) + end + end + end + end + end + + describe 'self.match' do + it 'matches the environment' do + match = described_class.match('deploy staging to production') + + expect(match[:from]).to eq('staging') + expect(match[:to]).to eq('production') + end + end +end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 60bbe3fcd72..d06665197db 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -9,6 +9,7 @@ describe Environment, models: true do it { is_expected.to delegate_method(:last_deployment).to(:deployments).as(:last) } it { is_expected.to delegate_method(:stop_action).to(:last_deployment) } + it { is_expected.to delegate_method(:manual_actions).to(:last_deployment) } it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) } @@ -187,4 +188,15 @@ describe Environment, models: true do it { is_expected.to be false } end end + + describe '#actions_for' do + let(:deployment) { create(:deployment, environment: environment) } + let(:pipeline) { deployment.deployable.pipeline } + let!(:review_action) { create(:ci_build, :manual, name: 'review-apps', pipeline: pipeline, environment: 'review/$CI_BUILD_REF_NAME' )} + let!(:production_action) { create(:ci_build, :manual, name: 'production', pipeline: pipeline, environment: 'production' )} + + it 'returns a list of actions with matching environment' do + expect(environment.actions_for('review/master')).to contain_exactly(review_action) + end + end end -- cgit v1.2.1 From a3331eee91fdd2170865c37641a88af2b47f9839 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Mon, 21 Nov 2016 17:29:07 +0100 Subject: Updated code based on feedback --- spec/controllers/projects/cycle_analytics_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/cycle_analytics_controller_spec.rb b/spec/controllers/projects/cycle_analytics_controller_spec.rb index 9131014a05d..a971adf0539 100644 --- a/spec/controllers/projects/cycle_analytics_controller_spec.rb +++ b/spec/controllers/projects/cycle_analytics_controller_spec.rb @@ -17,7 +17,7 @@ describe Projects::CycleAnalyticsController do project_id: project.to_param) expect(response).to be_success - expect(assigns(:cycle_analytics_not_set_up)).to eq(true) + expect(assigns(:cycle_analytics_no_data)).to eq(true) end end @@ -36,7 +36,7 @@ describe Projects::CycleAnalyticsController do project_id: project.to_param) expect(response).to be_success - expect(assigns(:cycle_analytics_not_set_up)).to eq(false) + expect(assigns(:cycle_analytics_no_data)).to eq(false) end end end -- cgit v1.2.1 From 67fde38806bd843c8008766edf49023e4c63df81 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 21 Nov 2016 13:43:31 +0100 Subject: Improve the mattermost help box Also added tests, and moved the slack test to a better location. --- .../services/mattermost_slash_command_spec.rb | 48 ++++++++++++++++++++++ .../projects/services/slack_service_spec.rb | 26 ++++++++++++ .../projects/slack_service/slack_service_spec.rb | 26 ------------ 3 files changed, 74 insertions(+), 26 deletions(-) create mode 100644 spec/features/projects/services/mattermost_slash_command_spec.rb create mode 100644 spec/features/projects/services/slack_service_spec.rb delete mode 100644 spec/features/projects/slack_service/slack_service_spec.rb (limited to 'spec') diff --git a/spec/features/projects/services/mattermost_slash_command_spec.rb b/spec/features/projects/services/mattermost_slash_command_spec.rb new file mode 100644 index 00000000000..f474e7e891b --- /dev/null +++ b/spec/features/projects/services/mattermost_slash_command_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +feature 'Setup Mattermost slash commands', feature: true do + include WaitForAjax + + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:service) { project.create_mattermost_slash_commands_service } + + before do + project.team << [user, :master] + login_as(user) + end + + describe 'user visites the mattermost slash command config page', js: true do + it 'shows a help message' do + visit edit_namespace_project_service_path(project.namespace, project, service) + + wait_for_ajax + + expect(page).to have_content("This service allows GitLab users to perform common") + end + end + + describe 'saving a token' do + let(:token) { ('a'..'z').to_a.join } + + it 'shows the token after saving' do + visit edit_namespace_project_service_path(project.namespace, project, service) + + fill_in 'service_token', with: token + click_on 'Save' + + value = find_field('service_token').value + + expect(value).to eq(token) + end + end + + describe 'the trigger url' do + it 'shows the correct url' do + visit edit_namespace_project_service_path(project.namespace, project, service) + + value = find_field('request_url').value + expect(value).to match("api/v3/projects/#{project.id}/services/mattermost_slash_commands/trigger") + end + end +end diff --git a/spec/features/projects/services/slack_service_spec.rb b/spec/features/projects/services/slack_service_spec.rb new file mode 100644 index 00000000000..16541f51d98 --- /dev/null +++ b/spec/features/projects/services/slack_service_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +feature 'Projects > Slack service > Setup events', feature: true do + let(:user) { create(:user) } + let(:service) { SlackService.new } + let(:project) { create(:project, slack_service: service) } + + background do + service.fields + service.update_attributes(push_channel: 1, issue_channel: 2, merge_request_channel: 3, note_channel: 4, tag_push_channel: 5, build_channel: 6, wiki_page_channel: 7) + project.team << [user, :master] + login_as(user) + end + + scenario 'user can filter events by channel' do + visit edit_namespace_project_service_path(project.namespace, project, service) + + expect(page.find_field("service_push_channel").value).to have_content '1' + expect(page.find_field("service_issue_channel").value).to have_content '2' + expect(page.find_field("service_merge_request_channel").value).to have_content '3' + expect(page.find_field("service_note_channel").value).to have_content '4' + expect(page.find_field("service_tag_push_channel").value).to have_content '5' + expect(page.find_field("service_build_channel").value).to have_content '6' + expect(page.find_field("service_wiki_page_channel").value).to have_content '7' + end +end diff --git a/spec/features/projects/slack_service/slack_service_spec.rb b/spec/features/projects/slack_service/slack_service_spec.rb deleted file mode 100644 index 16541f51d98..00000000000 --- a/spec/features/projects/slack_service/slack_service_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'spec_helper' - -feature 'Projects > Slack service > Setup events', feature: true do - let(:user) { create(:user) } - let(:service) { SlackService.new } - let(:project) { create(:project, slack_service: service) } - - background do - service.fields - service.update_attributes(push_channel: 1, issue_channel: 2, merge_request_channel: 3, note_channel: 4, tag_push_channel: 5, build_channel: 6, wiki_page_channel: 7) - project.team << [user, :master] - login_as(user) - end - - scenario 'user can filter events by channel' do - visit edit_namespace_project_service_path(project.namespace, project, service) - - expect(page.find_field("service_push_channel").value).to have_content '1' - expect(page.find_field("service_issue_channel").value).to have_content '2' - expect(page.find_field("service_merge_request_channel").value).to have_content '3' - expect(page.find_field("service_note_channel").value).to have_content '4' - expect(page.find_field("service_tag_push_channel").value).to have_content '5' - expect(page.find_field("service_build_channel").value).to have_content '6' - expect(page.find_field("service_wiki_page_channel").value).to have_content '7' - end -end -- cgit v1.2.1 From 6bfa3c93ed49d65783de824e4e99fec79adedf4e Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Mon, 21 Nov 2016 15:16:57 +0100 Subject: Warn that branch does not exist instead of saying that there is nothing to merge in merge request page --- .../merge_requests/deleted_source_branch_spec.rb | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 spec/features/merge_requests/deleted_source_branch_spec.rb (limited to 'spec') diff --git a/spec/features/merge_requests/deleted_source_branch_spec.rb b/spec/features/merge_requests/deleted_source_branch_spec.rb new file mode 100644 index 00000000000..778b3a90cf3 --- /dev/null +++ b/spec/features/merge_requests/deleted_source_branch_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe 'Deleted source branch', feature: true, js: true do + let(:user) { create(:user) } + let(:merge_request) { create(:merge_request) } + + before do + login_as user + merge_request.project.team << [user, :master] + merge_request.update!(source_branch: 'this-branch-does-not-exist') + visit namespace_project_merge_request_path( + merge_request.project.namespace, + merge_request.project, merge_request + ) + end + + it 'shows a message about missing source branch' do + expect(page).to have_content( + 'Source branch this-branch-does-not-exist does not exist' + ) + end + + it 'hides Discussion, Commits and Changes tabs' do + within '.merge-request-details' do + expect(page).to have_no_content('Discussion') + expect(page).to have_no_content('Commits') + expect(page).to have_no_content('Changes') + end + end +end -- cgit v1.2.1 From d375e3f15b6f0340addb9a20e0c03a1f1fca413a Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 21 Nov 2016 18:22:03 +0100 Subject: Fix specs and improve code readability --- spec/lib/gitlab/chat_commands/deploy_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/deploy_spec.rb b/spec/lib/gitlab/chat_commands/deploy_spec.rb index bdbaa41dd14..26741367e63 100644 --- a/spec/lib/gitlab/chat_commands/deploy_spec.rb +++ b/spec/lib/gitlab/chat_commands/deploy_spec.rb @@ -52,12 +52,13 @@ describe Gitlab::ChatCommands::Deploy, service: true do context 'when teardown action exists' do let!(:teardown) do - create(:ci_build, :manual, :teardown_environment, project: project, pipeline: build.pipeline, + create(:ci_build, :manual, :teardown_environment, + project: project, pipeline: build.pipeline, name: 'teardown', environment: 'production') end it 'returns error' do - expect(subject).to eq(action) + expect(subject).to eq(manual1) end end end -- cgit v1.2.1 From 461195665b22291d5e57287efc0567b89a9ee262 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Mon, 21 Nov 2016 16:02:08 +0100 Subject: Add Gitlab::Ci::Build::Credentials module with build credentials abstraction --- .../gitlab/ci/build/credentials/factory_spec.rb | 38 ++++++++++++++++++++ .../gitlab/ci/build/credentials/registry_spec.rb | 41 ++++++++++++++++++++++ spec/requests/ci/api/builds_spec.rb | 2 +- 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 spec/lib/gitlab/ci/build/credentials/factory_spec.rb create mode 100644 spec/lib/gitlab/ci/build/credentials/registry_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/ci/build/credentials/factory_spec.rb b/spec/lib/gitlab/ci/build/credentials/factory_spec.rb new file mode 100644 index 00000000000..10b4b7a8826 --- /dev/null +++ b/spec/lib/gitlab/ci/build/credentials/factory_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Gitlab::Ci::Build::Credentials::Factory do + let(:build) { create(:ci_build, name: 'spinach', stage: 'test', stage_idx: 0) } + + subject { Gitlab::Ci::Build::Credentials::Factory.new(build).create! } + + class TestProvider + def initialize(build); end + end + + before do + allow_any_instance_of(Gitlab::Ci::Build::Credentials::Factory).to receive(:providers).and_return([TestProvider]) + end + + context 'when provider is valid' do + before do + allow_any_instance_of(TestProvider).to receive(:valid?).and_return(true) + end + + it 'generates an array of credentials objects' do + is_expected.to be_kind_of(Array) + is_expected.not_to be_empty + expect(subject.first).to be_kind_of(TestProvider) + end + end + + context 'when provider is not valid' do + before do + allow_any_instance_of(TestProvider).to receive(:valid?).and_return(false) + end + + it 'generates an array without specific credential object' do + is_expected.to be_kind_of(Array) + is_expected.to be_empty + end + end +end diff --git a/spec/lib/gitlab/ci/build/credentials/registry_spec.rb b/spec/lib/gitlab/ci/build/credentials/registry_spec.rb new file mode 100644 index 00000000000..84e44dd53e2 --- /dev/null +++ b/spec/lib/gitlab/ci/build/credentials/registry_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe Gitlab::Ci::Build::Credentials::Registry do + let(:build) { create(:ci_build, name: 'spinach', stage: 'test', stage_idx: 0) } + let(:registry_url) { 'registry.example.com:5005' } + + subject { Gitlab::Ci::Build::Credentials::Registry.new(build) } + + before do + stub_container_registry_config(host_port: registry_url) + end + + it 'contains valid DockerRegistry credentials' do + expect(subject).to be_kind_of(Gitlab::Ci::Build::Credentials::Registry) + + expect(subject.username).to eq 'gitlab-ci-token' + expect(subject.password).to eq build.token + expect(subject.url).to eq registry_url + expect(subject.type).to eq 'registry' + end + + describe '.valid?' do + subject { Gitlab::Ci::Build::Credentials::Registry.new(build).valid? } + + context 'when registry is enabled' do + before do + stub_container_registry_config(enabled: true) + end + + it { is_expected.to be_truthy } + end + + context 'when registry is disabled' do + before do + stub_container_registry_config(enabled: false) + end + + it { is_expected.to be_falsey } + end + end +end diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index c5e498601e6..48b31c740c8 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -60,7 +60,7 @@ describe Ci::API::API do context 'registry credentials' do let(:registry_credentials) do - { 'type' => 'docker-registry', + { 'type' => 'registry', 'url' => 'registry.example.com:5005', 'username' => 'gitlab-ci-token', 'password' => build.token } -- cgit v1.2.1 From 5949f398f71d9cb540e42988c19fac2768c92eb8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 21 Nov 2016 21:03:18 +0200 Subject: Fix 500 error when group name ends with git Signed-off-by: Dmitriy Zaporozhets --- spec/routing/routing_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 7aba4f08088..f15c45cbaac 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -261,7 +261,7 @@ describe "Authentication", "routing" do end describe "Groups", "routing" do - let(:name) { 'complex.group-name' } + let(:name) { 'complex.group-namegit' } it "to #show" do expect(get("/groups/#{name}")).to route_to('groups#show', id: name) -- cgit v1.2.1 From 41aa605d4ed3d0d302c70ecd01052115f818f949 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 21 Nov 2016 19:40:04 +0100 Subject: Improve deploy command message --- spec/lib/gitlab/chat_commands/command_spec.rb | 2 +- spec/lib/gitlab/chat_commands/deploy_spec.rb | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/command_spec.rb b/spec/lib/gitlab/chat_commands/command_spec.rb index 924b4b7b101..bfc6818ac08 100644 --- a/spec/lib/gitlab/chat_commands/command_spec.rb +++ b/spec/lib/gitlab/chat_commands/command_spec.rb @@ -74,7 +74,7 @@ describe Gitlab::ChatCommands::Command, service: true do end it 'returns action' do - expect(subject[:text]).to include(manual.name) + expect(subject[:text]).to include('Deployment from staging to production started') expect(subject[:response_type]).to be(:in_channel) end diff --git a/spec/lib/gitlab/chat_commands/deploy_spec.rb b/spec/lib/gitlab/chat_commands/deploy_spec.rb index 26741367e63..bd8099c92da 100644 --- a/spec/lib/gitlab/chat_commands/deploy_spec.rb +++ b/spec/lib/gitlab/chat_commands/deploy_spec.rb @@ -36,8 +36,9 @@ describe Gitlab::ChatCommands::Deploy, service: true do create(:ci_build, :manual, project: project, pipeline: build.pipeline, name: 'first', environment: 'production') end - it 'returns action' do - expect(subject).to eq(manual1) + it 'returns success result' do + expect(subject.type).to eq(:success) + expect(subject.message).to include('Deployment from staging to production started') end context 'when duplicate action exists' do @@ -46,7 +47,8 @@ describe Gitlab::ChatCommands::Deploy, service: true do end it 'returns error' do - expect(subject.message).to eq('Too many actions defined') + expect(subject.type).to eq(:error) + expect(subject.message).to include('Too many actions defined') end end @@ -57,8 +59,9 @@ describe Gitlab::ChatCommands::Deploy, service: true do name: 'teardown', environment: 'production') end - it 'returns error' do - expect(subject).to eq(manual1) + it 'returns success result' do + expect(subject.type).to eq(:success) + expect(subject.message).to include('Deployment from staging to production started') end end end -- cgit v1.2.1 From d20c0682ac4a91f9cdea1d71f9eb515755955c7a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 22 Nov 2016 13:41:39 +0800 Subject: Just create failed builds rather than calling events Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7617#note_18763033 --- spec/models/ci/pipeline_spec.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index ea5e0e28c5c..ea022e03608 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -571,13 +571,10 @@ describe Ci::Pipeline, models: true do context 'with failed pipeline' do before do perform_enqueued_jobs do - create(:ci_build, :created, pipeline: pipeline) - create(:generic_commit_status, :created, pipeline: pipeline) + create(:ci_build, :failed, pipeline: pipeline) + create(:generic_commit_status, :failed, pipeline: pipeline) - pipeline.statuses.count.times do |offset| - # workaround race conditions - pipeline.statuses.offset(offset).first.drop - end + pipeline.drop end end -- cgit v1.2.1 From cb11d3521ce99a5ce796e2fdf9e6d96a3e36791d Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 22 Nov 2016 08:23:43 +0100 Subject: Fix IID filter for merge requests and milestones --- spec/requests/api/merge_requests_spec.rb | 10 ++++++++++ spec/requests/api/milestones_spec.rb | 9 +++++++++ 2 files changed, 19 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 7b3d1460c90..37fcb2bc3a9 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -169,6 +169,16 @@ describe API::API, api: true do expect(json_response.first['id']).to eq merge_request.id end + it 'returns merge_request by iid array' do + get api("/projects/#{project.id}/merge_requests", user), iid: [merge_request.iid, merge_request_closed.iid] + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + expect(json_response.first['title']).to eq merge_request_closed.title + expect(json_response.first['id']).to eq merge_request_closed.id + end + it "returns a 404 error if merge_request_id not found" do get api("/projects/#{project.id}/merge_requests/999", user) expect(response).to have_http_status(404) diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index 62327f64e50..5d7b39e71b8 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -61,6 +61,15 @@ describe API::API, api: true do expect(json_response.first['id']).to eq closed_milestone.id end + it 'returns a project milestone by iid array' do + get api("/projects/#{project.id}/milestones", user), iid: [milestone.iid, closed_milestone.iid] + + expect(response).to have_http_status(200) + expect(json_response.size).to eq(2) + expect(json_response.first['title']).to eq milestone.title + expect(json_response.first['id']).to eq milestone.id + end + it 'returns 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones/#{milestone.id}") -- cgit v1.2.1 From 3ff0575669ecda15c5e72bd2987715a998f97d82 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 21 Nov 2016 20:48:18 +0100 Subject: Issue creation now accepts trailing whitespace --- spec/lib/gitlab/chat_commands/issue_create_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/chat_commands/issue_create_spec.rb b/spec/lib/gitlab/chat_commands/issue_create_spec.rb index df0c317ccea..dd07cff9243 100644 --- a/spec/lib/gitlab/chat_commands/issue_create_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_create_spec.rb @@ -32,6 +32,15 @@ describe Gitlab::ChatCommands::IssueCreate, service: true do expect(Issue.last.description).to eq(description) end end + + context "with more newlines between the title and the description" do + let(:description) { "Surfin bird" } + let(:regex_match) { described_class.match("issue create bird is the word\n\n#{description}\n") } + + it 'creates the issue' do + expect { subject }.to change { project.issues.count }.by(1) + end + end end describe '.match' do -- cgit v1.2.1 From 4c34b4e5171596bd09b621b66d9c2765f042483c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 09:05:16 +0100 Subject: Extend specs for global ci configuration entry --- spec/lib/gitlab/ci/config/entry/global_spec.rb | 49 ++++++++++++++++---------- 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index 5e5c5dcc385..5683d875dd6 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -13,7 +13,7 @@ describe Gitlab::Ci::Config::Entry::Global do end end - context 'when hash is valid' do + context 'when configuration is valid' do context 'when some entries defined' do let(:hash) do { before_script: ['ls', 'pwd'], @@ -225,29 +225,42 @@ describe Gitlab::Ci::Config::Entry::Global do end end - context 'when hash is not valid' do + context 'when configuration is not valid' do before { global.compose! } - let(:hash) do - { before_script: 'ls' } - end + context 'when before script is not an array' do + let(:hash) do + { before_script: 'ls' } + end - describe '#valid?' do - it 'is not valid' do - expect(global).not_to be_valid + describe '#valid?' do + it 'is not valid' do + expect(global).not_to be_valid + end end - end - describe '#errors' do - it 'reports errors from child nodes' do - expect(global.errors) - .to include 'before_script config should be an array of strings' + describe '#errors' do + it 'reports errors from child nodes' do + expect(global.errors) + .to include 'before_script config should be an array of strings' + end + end + + describe '#before_script_value' do + it 'returns nil' do + expect(global.before_script_value).to be_nil + end end end - describe '#before_script_value' do - it 'returns nil' do - expect(global.before_script_value).to be_nil + context 'when job does not have commands' do + let(:hash) { { rspec: { stage: 'test' } } } + + describe '#errors' do + it 'reports errors about missing script' do + expect(global.errors) + .to include "jobs:rspec script can't be blank" + end end end end @@ -281,7 +294,7 @@ describe Gitlab::Ci::Config::Entry::Global do { cache: { key: 'a' }, rspec: { script: 'ls' } } end - context 'when node exists' do + context 'when entry exists' do it 'returns correct entry' do expect(global[:cache]) .to be_an_instance_of Gitlab::Ci::Config::Entry::Cache @@ -289,7 +302,7 @@ describe Gitlab::Ci::Config::Entry::Global do end end - context 'when node does not exist' do + context 'when entry does not exist' do it 'always return unspecified node' do expect(global[:some][:unknown][:node]) .not_to be_specified -- cgit v1.2.1 From c048d5d2d964292bddb567bbad6caffd8b275bfa Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 09:09:38 +0100 Subject: Fix entry lookup in CI config inheritance rules --- spec/lib/gitlab/ci/config/entry/global_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index 5683d875dd6..e64c8d46bd8 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -254,7 +254,9 @@ describe Gitlab::Ci::Config::Entry::Global do end context 'when job does not have commands' do - let(:hash) { { rspec: { stage: 'test' } } } + let(:hash) do + { before_script: ['echo 123'], rspec: { stage: 'test' } } + end describe '#errors' do it 'reports errors about missing script' do -- cgit v1.2.1 From 9d3186e44aa9690c0c6c3af6f979132baf34cb41 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 22 Nov 2016 10:25:09 +0000 Subject: Disabled award emoji button when user is not logged in Closes #24680 --- spec/features/issues/award_emoji_spec.rb | 93 ++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 41 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index ef00f209998..efb53026449 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -3,72 +3,83 @@ require 'rails_helper' describe 'Awards Emoji', feature: true do include WaitForAjax - let!(:project) { create(:project) } + let!(:project) { create(:project, :public) } let!(:user) { create(:user) } - - before do - project.team << [user, :master] - login_as(user) + let(:issue) do + create(:issue, + assignee: @user, + project: project) end - describe 'Click award emoji from issue#show' do - let!(:issue) do - create(:issue, - assignee: @user, - project: project) - end - - let!(:note) { create(:note_on_issue, noteable: issue, project: issue.project, note: "Hello world") } - + context 'authorized user' do before do - visit namespace_project_issue_path(project.namespace, project, issue) + project.team << [user, :master] + login_as(user) end - it 'increments the thumbsdown emoji', js: true do - find('[data-emoji="thumbsdown"]').click - wait_for_ajax - expect(thumbsdown_emoji).to have_text("1") - end + describe 'Click award emoji from issue#show' do + let!(:note) { create(:note_on_issue, noteable: issue, project: issue.project, note: "Hello world") } - context 'click the thumbsup emoji' do - it 'increments the thumbsup emoji', js: true do - find('[data-emoji="thumbsup"]').click - wait_for_ajax - expect(thumbsup_emoji).to have_text("1") + before do + visit namespace_project_issue_path(project.namespace, project, issue) end - it 'decrements the thumbsdown emoji', js: true do - expect(thumbsdown_emoji).to have_text("0") - end - end - - context 'click the thumbsdown emoji' do it 'increments the thumbsdown emoji', js: true do find('[data-emoji="thumbsdown"]').click wait_for_ajax expect(thumbsdown_emoji).to have_text("1") end - it 'decrements the thumbsup emoji', js: true do - expect(thumbsup_emoji).to have_text("0") + context 'click the thumbsup emoji' do + it 'increments the thumbsup emoji', js: true do + find('[data-emoji="thumbsup"]').click + wait_for_ajax + expect(thumbsup_emoji).to have_text("1") + end + + it 'decrements the thumbsdown emoji', js: true do + expect(thumbsdown_emoji).to have_text("0") + end end - end - it 'toggles the smiley emoji on a note', js: true do - toggle_smiley_emoji(true) + context 'click the thumbsdown emoji' do + it 'increments the thumbsdown emoji', js: true do + find('[data-emoji="thumbsdown"]').click + wait_for_ajax + expect(thumbsdown_emoji).to have_text("1") + end - within('.note-awards') do - expect(find(emoji_counter)).to have_text("1") + it 'decrements the thumbsup emoji', js: true do + expect(thumbsup_emoji).to have_text("0") + end end - toggle_smiley_emoji(false) + it 'toggles the smiley emoji on a note', js: true do + toggle_smiley_emoji(true) + + within('.note-awards') do + expect(find(emoji_counter)).to have_text("1") + end + + toggle_smiley_emoji(false) - within('.note-awards') do - expect(page).not_to have_selector(emoji_counter) + within('.note-awards') do + expect(page).not_to have_selector(emoji_counter) + end end end end + context 'unauthorized user', js: true do + before do + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'has disabled emoji button' do + expect(first('.award-control')[:disabled]).to be(true) + end + end + def thumbsup_emoji page.all(emoji_counter).first end -- cgit v1.2.1 From 1e19737ca20fe53327094196bbc9758e5c9e03fa Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 11:52:58 +0100 Subject: Refactor feature tests for project builds page --- spec/features/projects/builds_spec.rb | 159 ++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 75 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index a8022a5361f..eec1d337224 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -2,51 +2,56 @@ require 'spec_helper' require 'tempfile' describe "Builds" do - let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } + let(:artifacts_file) do + fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') + end + + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:pipeline) { create(:ci_pipeline, project: project) } + + let!(:build) { create(:ci_build, :trace, pipeline: pipeline) } + let!(:build2) { create(:ci_build) } before do - login_as(:user) - @commit = FactoryGirl.create :ci_pipeline - @build = FactoryGirl.create :ci_build, :trace, pipeline: @commit - @build2 = FactoryGirl.create :ci_build - @project = @commit.project - @project.team << [@user, :developer] + project.team << [user, :developer] + login_as(user) end describe "GET /:project/builds" do context "Pending scope" do before do - visit namespace_project_builds_path(@project.namespace, @project, scope: :pending) + visit namespace_project_builds_path(project.namespace, project, scope: :pending) end it "shows Pending tab builds" 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 - expect(page).to have_content @build.ref - expect(page).to have_content @build.name + expect(page).to have_content build.short_sha + expect(page).to have_content build.ref + expect(page).to have_content build.name end end context "Running scope" do before do - @build.run! - visit namespace_project_builds_path(@project.namespace, @project, scope: :running) + build.run! + visit namespace_project_builds_path(project.namespace, project, scope: :running) end it "shows Running tab builds" 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 - expect(page).to have_content @build.ref - expect(page).to have_content @build.name + expect(page).to have_content build.short_sha + expect(page).to have_content build.ref + expect(page).to have_content build.name end end context "Finished scope" do before do - @build.run! - visit namespace_project_builds_path(@project.namespace, @project, scope: :finished) + build.run! + visit namespace_project_builds_path(project.namespace, project, scope: :finished) end it "shows Finished tab builds" do @@ -58,15 +63,15 @@ describe "Builds" do context "All builds" do before do - @project.builds.running_or_pending.each(&:success) - visit namespace_project_builds_path(@project.namespace, @project) + project.builds.running_or_pending.each(&:success) + visit namespace_project_builds_path(project.namespace, project) end it "shows All tab builds" 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 - expect(page).to have_content @build.name + expect(page).to have_content build.short_sha + expect(page).to have_content build.ref + expect(page).to have_content build.name expect(page).not_to have_link 'Cancel running' end end @@ -74,17 +79,17 @@ describe "Builds" do describe "POST /:project/builds/:id/cancel_all" do before do - @build.run! - visit namespace_project_builds_path(@project.namespace, @project) + build.run! + visit namespace_project_builds_path(project.namespace, project) click_link "Cancel running" end it 'shows all necessary content' do expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_content 'canceled' - expect(page).to have_content @build.short_sha - expect(page).to have_content @build.ref - expect(page).to have_content @build.name + expect(page).to have_content build.short_sha + expect(page).to have_content build.ref + expect(page).to have_content build.name expect(page).not_to have_link 'Cancel running' end end @@ -92,20 +97,20 @@ describe "Builds" do describe "GET /:project/builds/:id" do context "Build from project" do before do - visit namespace_project_build_path(@project.namespace, @project, @build) + visit namespace_project_build_path(project.namespace, project, build) end it 'shows commit`s data' do expect(page.status_code).to eq(200) - expect(page).to have_content @commit.sha[0..7] - expect(page).to have_content @commit.git_commit_message - expect(page).to have_content @commit.git_author_name + expect(page).to have_content pipeline.sha[0..7] + expect(page).to have_content pipeline.git_commit_message + expect(page).to have_content pipeline.git_author_name end end context "Build from other project" do before do - visit namespace_project_build_path(@project.namespace, @project, @build2) + visit namespace_project_build_path(project.namespace, project, build2) end it { expect(page.status_code).to eq(404) } @@ -113,8 +118,8 @@ describe "Builds" do context "Download artifacts" do before do - @build.update_attributes(artifacts_file: artifacts_file) - visit namespace_project_build_path(@project.namespace, @project, @build) + build.update_attributes(artifacts_file: artifacts_file) + visit namespace_project_build_path(project.namespace, project, build) end it 'has button to download artifacts' do @@ -124,8 +129,8 @@ describe "Builds" do context 'Artifacts expire date' do before do - @build.update_attributes(artifacts_file: artifacts_file, artifacts_expire_at: expire_at) - visit namespace_project_build_path(@project.namespace, @project, @build) + build.update_attributes(artifacts_file: artifacts_file, artifacts_expire_at: expire_at) + visit namespace_project_build_path(project.namespace, project, build) end context 'no expire date defined' do @@ -160,8 +165,8 @@ describe "Builds" do context 'Build raw trace' do before do - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) end it do @@ -170,10 +175,14 @@ describe "Builds" do end describe 'Variables' do + let(:trigger_request) { create(:ci_trigger_request_with_variables) } + + let(:build) do + create :ci_build, pipeline: pipeline, trigger_request: trigger_request + end + before do - @trigger_request = create :ci_trigger_request_with_variables - @build = create :ci_build, pipeline: @commit, trigger_request: @trigger_request - visit namespace_project_build_path(@project.namespace, @project, @build) + visit namespace_project_build_path(project.namespace, project, build) end it 'shows variable key and value after click', js: true do @@ -193,8 +202,8 @@ describe "Builds" do describe "POST /:project/builds/:id/cancel" do context "Build from project" do before do - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) click_link "Cancel" end @@ -207,9 +216,9 @@ describe "Builds" do context "Build from other project" do before do - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) - page.driver.post(cancel_namespace_project_build_path(@project.namespace, @project, @build2)) + build.run! + visit namespace_project_build_path(project.namespace, project, build) + page.driver.post(cancel_namespace_project_build_path(project.namespace, project, build2)) end it { expect(page.status_code).to eq(404) } @@ -219,8 +228,8 @@ describe "Builds" do describe "POST /:project/builds/:id/retry" do context "Build from project" do before do - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) click_link 'Cancel' page.within('.build-header') do click_link 'Retry build' @@ -238,10 +247,10 @@ describe "Builds" do context "Build from other project" do before do - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) click_link 'Cancel' - page.driver.post(retry_namespace_project_build_path(@project.namespace, @project, @build2)) + page.driver.post(retry_namespace_project_build_path(project.namespace, project, build2)) end it { expect(page).to have_http_status(404) } @@ -249,13 +258,13 @@ describe "Builds" do context "Build that current user is not allowed to retry" do before do - @build.run! - @build.cancel! - @project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + build.run! + build.cancel! + project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) logout_direct login_with(create(:user)) - visit namespace_project_build_path(@project.namespace, @project, @build) + visit namespace_project_build_path(project.namespace, project, build) end it 'does not show the Retry button' do @@ -268,15 +277,15 @@ describe "Builds" do describe "GET /:project/builds/:id/download" do before do - @build.update_attributes(artifacts_file: artifacts_file) - visit namespace_project_build_path(@project.namespace, @project, @build) + build.update_attributes(artifacts_file: artifacts_file) + visit namespace_project_build_path(project.namespace, project, build) click_link 'Download' end context "Build from other project" do before do - @build2.update_attributes(artifacts_file: artifacts_file) - visit download_namespace_project_build_artifacts_path(@project.namespace, @project, @build2) + build2.update_attributes(artifacts_file: artifacts_file) + visit download_namespace_project_build_artifacts_path(project.namespace, project, build2) end it { expect(page.status_code).to eq(404) } @@ -288,23 +297,23 @@ describe "Builds" do context 'build from project' do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) page.within('.js-build-sidebar') { click_link 'Raw' } end it 'sends the right headers' do expect(page.status_code).to eq(200) expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8') - expect(page.response_headers['X-Sendfile']).to eq(@build.path_to_trace) + expect(page.response_headers['X-Sendfile']).to eq(build.path_to_trace) end end context 'build from other project' do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') - @build2.run! - visit raw_namespace_project_build_path(@project.namespace, @project, @build2) + build2.run! + visit raw_namespace_project_build_path(project.namespace, project, build2) end it 'sends the right headers' do @@ -325,8 +334,8 @@ describe "Builds" do context 'when build has trace in file' do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) allow_any_instance_of(Project).to receive(:ci_id).and_return(nil) allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(existing_file) @@ -345,8 +354,8 @@ describe "Builds" do context 'when build has trace in old file' do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) allow_any_instance_of(Project).to receive(:ci_id).and_return(999) allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(non_existing_file) @@ -365,8 +374,8 @@ describe "Builds" do context 'when build has trace in DB' do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') - @build.run! - visit namespace_project_build_path(@project.namespace, @project, @build) + build.run! + visit namespace_project_build_path(project.namespace, project, build) allow_any_instance_of(Project).to receive(:ci_id).and_return(nil) allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(non_existing_file) @@ -385,7 +394,7 @@ describe "Builds" do describe "GET /:project/builds/:id/trace.json" do context "Build from project" do before do - visit trace_namespace_project_build_path(@project.namespace, @project, @build, format: :json) + visit trace_namespace_project_build_path(project.namespace, project, build, format: :json) end it { expect(page.status_code).to eq(200) } @@ -393,7 +402,7 @@ describe "Builds" do context "Build from other project" do before do - visit trace_namespace_project_build_path(@project.namespace, @project, @build2, format: :json) + visit trace_namespace_project_build_path(project.namespace, project, build2, format: :json) end it { expect(page.status_code).to eq(404) } @@ -403,7 +412,7 @@ describe "Builds" do describe "GET /:project/builds/:id/status" do context "Build from project" do before do - visit status_namespace_project_build_path(@project.namespace, @project, @build) + visit status_namespace_project_build_path(project.namespace, project, build) end it { expect(page.status_code).to eq(200) } @@ -411,7 +420,7 @@ describe "Builds" do context "Build from other project" do before do - visit status_namespace_project_build_path(@project.namespace, @project, @build2) + visit status_namespace_project_build_path(project.namespace, project, build2) end it { expect(page.status_code).to eq(404) } -- cgit v1.2.1 From e249a35161401e9b2449346132f1130c6cd1b824 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 12:19:46 +0100 Subject: Add missing specs for loading build HTML trace --- spec/features/projects/builds_spec.rb | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index eec1d337224..f0ad936ca69 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -1,11 +1,7 @@ require 'spec_helper' require 'tempfile' -describe "Builds" do - let(:artifacts_file) do - fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') - end - +feature 'Builds', :feature do let(:user) { create(:user) } let(:project) { create(:project) } let(:pipeline) { create(:ci_pipeline, project: project) } @@ -13,6 +9,10 @@ describe "Builds" do let!(:build) { create(:ci_build, :trace, pipeline: pipeline) } let!(:build2) { create(:ci_build) } + let(:artifacts_file) do + fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') + end + before do project.team << [user, :developer] login_as(user) @@ -163,7 +163,7 @@ describe "Builds" do end end - context 'Build raw trace' do + feature 'Raw trace' do before do build.run! visit namespace_project_build_path(project.namespace, project, build) @@ -174,7 +174,23 @@ describe "Builds" do end end - describe 'Variables' do + feature 'HTML trace', :js do + before do + build.run! + + visit namespace_project_build_path(project.namespace, project, build) + end + + it 'loads build trace' do + expect(page).to have_content 'BUILD TRACE' + + build.append_trace(' and more trace', 11) + + expect(page).to have_content 'BUILD TRACE and more trace' + end + end + + feature 'Variables' do let(:trigger_request) { create(:ci_trigger_request_with_variables) } let(:build) do -- cgit v1.2.1 From 89e367f2e5c9e52e3b8f3e966b5e541d4e1cde72 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 13:15:10 +0100 Subject: Add missing feature tests for loading build trace See #24638 --- spec/features/projects/builds_spec.rb | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index f0ad936ca69..eb50d397b29 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -181,12 +181,24 @@ feature 'Builds', :feature do visit namespace_project_build_path(project.namespace, project, build) end - it 'loads build trace' do - expect(page).to have_content 'BUILD TRACE' + context 'when build has an initial trace' do + it 'loads build trace' do + expect(page).to have_content 'BUILD TRACE' - build.append_trace(' and more trace', 11) + build.append_trace(' and more trace', 11) - expect(page).to have_content 'BUILD TRACE and more trace' + expect(page).to have_content 'BUILD TRACE and more trace' + end + end + + context 'when build does not have an initial trace' do + let(:build) { create(:ci_build, pipeline: pipeline) } + + it 'loads new trace' do + build.append_trace('build trace', 0) + + expect(page).to have_content 'build trace' + end end end -- cgit v1.2.1 From 07ce4c28b3c854a912a1b98d0715d0ed3f8c937d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 13:35:18 +0100 Subject: Improve reproducibility of build trace test example --- spec/features/projects/builds_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index eb50d397b29..a0ccc472d11 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -6,8 +6,8 @@ feature 'Builds', :feature do let(:project) { create(:project) } let(:pipeline) { create(:ci_pipeline, project: project) } - let!(:build) { create(:ci_build, :trace, pipeline: pipeline) } - let!(:build2) { create(:ci_build) } + let(:build) { create(:ci_build, :trace, pipeline: pipeline) } + let(:build2) { create(:ci_build) } let(:artifacts_file) do fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') @@ -19,6 +19,8 @@ feature 'Builds', :feature do end describe "GET /:project/builds" do + let!(:build) { create(:ci_build, pipeline: pipeline) } + context "Pending scope" do before do visit namespace_project_builds_path(project.namespace, project, scope: :pending) -- cgit v1.2.1 From de24902852454a7805c30912eaca32903f491aa7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 22 Nov 2016 14:48:14 +0100 Subject: Improve name of build log state data attribute --- spec/javascripts/fixtures/build.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/fixtures/build.html.haml b/spec/javascripts/fixtures/build.html.haml index 27136beb14c..06b49516e5c 100644 --- a/spec/javascripts/fixtures/build.html.haml +++ b/spec/javascripts/fixtures/build.html.haml @@ -54,7 +54,7 @@ build_url: 'http://example.com/root/test-build/builds/2.json', build_status: 'passed', build_stage: 'test', - state1: 'buildstate' }} + log_state: 'buildstate' }} %p.build-detail-row The artifacts will be removed in -- cgit v1.2.1 From db62eb957157ffe14a474f5f858c753cade067b1 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 22 Nov 2016 15:05:37 +0100 Subject: fixed bug to do with calculating durations --- spec/serializers/analytics_build_entity_spec.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb index 9ac6f20fd3c..a802c0fa49d 100644 --- a/spec/serializers/analytics_build_entity_spec.rb +++ b/spec/serializers/analytics_build_entity_spec.rb @@ -7,7 +7,7 @@ describe AnalyticsBuildEntity do context 'build with an author' do let(:user) { create(:user) } - let(:build) { create(:ci_build, author: user) } + let(:build) { create(:ci_build, author: user, started_at: 2.hours.ago, finished_at: 1.hour.ago) } subject { entity.as_json } @@ -23,5 +23,13 @@ describe AnalyticsBuildEntity do expect(subject).not_to include(/token/) expect(subject).not_to include(/variables/) end + + it 'contains the right started at' do + expect(subject[:date]).to eq('about 2 hours ago') + end + + it 'contains the duration' do + expect(subject[:total_time]).to eq({ :hours => 1 }) + end end end -- cgit v1.2.1 From ed85fa7b10ed2214c849b7d0d0b3164414afaa16 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 22 Nov 2016 16:30:27 +0100 Subject: fix rubocop warning --- spec/serializers/analytics_build_entity_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb index a802c0fa49d..c0b7e86b17c 100644 --- a/spec/serializers/analytics_build_entity_spec.rb +++ b/spec/serializers/analytics_build_entity_spec.rb @@ -29,7 +29,7 @@ describe AnalyticsBuildEntity do end it 'contains the duration' do - expect(subject[:total_time]).to eq({ :hours => 1 }) + expect(subject[:total_time]).to eq(hours: 1 ) end end end -- cgit v1.2.1 From d6f98cc2de7db1aa27375d8bfbceca8099f64504 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Tue, 22 Nov 2016 21:27:16 +0500 Subject: Remove empty describe block in service spec --- spec/models/service_spec.rb | 3 --- 1 file changed, 3 deletions(-) (limited to 'spec') diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index b1615a95004..691511cd93f 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -6,9 +6,6 @@ describe Service, models: true do it { is_expected.to have_one :service_hook } end - describe "Mass assignment" do - end - describe "Test Button" do before do @service = Service.new -- cgit v1.2.1 From bd0017c6d4e008474fcd87e979b3b4e3f93e39b1 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 21 Nov 2016 17:19:51 -0600 Subject: clean up globals exemptions within .eslintrc --- spec/javascripts/.eslintrc | 4 ++++ spec/javascripts/build_spec.js.es6 | 4 +++- spec/javascripts/environments/environments_store_spec.js.es6 | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/.eslintrc b/spec/javascripts/.eslintrc index 90388929612..7792acffac2 100644 --- a/spec/javascripts/.eslintrc +++ b/spec/javascripts/.eslintrc @@ -7,5 +7,9 @@ "rules": { "prefer-arrow-callback": 0, "func-names": 0 + }, + "globals": { + "fixture": false, + "spyOnEvent": false } } diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index e21e5844a26..ee192c4f18a 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -1,5 +1,7 @@ -/* global Build */ /* eslint-disable no-new */ +/* global Build */ +/* global Turbolinks */ + //= require lib/utils/timeago //= require lib/utils/datetime_utility //= require build diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index 82d9599f372..9b0b3cb1c65 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -1,7 +1,9 @@ +/* global environmentsList */ + //= require vue //= require environments/stores/environments_store //= require ./mock_data -/* globals environmentsList */ + (() => { beforeEach(() => { gl.environmentsList.EnvironmentsStore.create(); -- cgit v1.2.1 From 40822b618576f06098f3f61cc5e11a29d656619e Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Tue, 22 Nov 2016 21:31:01 +1100 Subject: Fix sidekiq stats in admin area Added tests Added changelog entry Resolved all issues in code --- spec/helpers/sidekiq_helper_spec.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'spec') diff --git a/spec/helpers/sidekiq_helper_spec.rb b/spec/helpers/sidekiq_helper_spec.rb index d60839b78ec..f86e496740a 100644 --- a/spec/helpers/sidekiq_helper_spec.rb +++ b/spec/helpers/sidekiq_helper_spec.rb @@ -30,6 +30,29 @@ describe SidekiqHelper do expect(parts).to eq(['55137', '10.0', '2.1', 'S+', '2:30pm', 'sidekiq 4.1.4 gitlab [0 of 25 busy]']) end + it 'parses OSX output' do + line = ' 1641 1.5 3.8 S+ 4:04PM sidekiq 4.2.1 gitlab [0 of 25 busy]' + parts = helper.parse_sidekiq_ps(line) + + expect(parts).to eq(['1641', '1.5', '3.8', 'S+', '4:04PM', 'sidekiq 4.2.1 gitlab [0 of 25 busy]']) + end + + it 'parses Ubuntu output' do + # Ubuntu Linux 16.04 LTS / procps-3.3.10-4ubuntu2 + line = ' 938 1.4 2.5 Sl+ 21:23:21 sidekiq 4.2.1 gitlab [0 of 25 busy] ' + parts = helper.parse_sidekiq_ps(line) + + expect(parts).to eq(['938', '1.4', '2.5', 'Sl+', '21:23:21', 'sidekiq 4.2.1 gitlab [0 of 25 busy]']) + end + + it 'parses Debian output' do + # Debian Linux Wheezy/Jessie + line = '17725 1.0 12.1 Ssl 19:20:15 sidekiq 4.2.1 gitlab-rails [0 of 25 busy] ' + parts = helper.parse_sidekiq_ps(line) + + expect(parts).to eq(['17725', '1.0', '12.1', 'Ssl', '19:20:15', 'sidekiq 4.2.1 gitlab-rails [0 of 25 busy]']) + end + it 'does fail gracefully on line not matching the format' do line = '55137 10.0 2.1 S+ 2:30pm something' parts = helper.parse_sidekiq_ps(line) -- cgit v1.2.1 From 8ede8603b0f6910886219ab1594eff1c0bfa3252 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 22 Nov 2016 23:47:52 -0600 Subject: timeago should be a dependency of datetime_utility --- spec/javascripts/build_spec.js.es6 | 1 - spec/javascripts/merge_request_widget_spec.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index ee192c4f18a..4208e076e96 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -2,7 +2,6 @@ /* global Build */ /* global Turbolinks */ -//= require lib/utils/timeago //= require lib/utils/datetime_utility //= require build //= require breakpoints diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js index f38e9cb8ef5..62890f1ca96 100644 --- a/spec/javascripts/merge_request_widget_spec.js +++ b/spec/javascripts/merge_request_widget_spec.js @@ -1,6 +1,6 @@ /* eslint-disable space-before-function-paren, quotes, comma-dangle, dot-notation, indent, quote-props, no-var, padded-blocks, max-len */ + /*= require merge_request_widget */ -/*= require lib/utils/timeago */ /*= require lib/utils/datetime_utility */ (function() { -- cgit v1.2.1 From b938aa5cc83ffb51b516c7abfaaf6fe5e37031a6 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 23 Nov 2016 09:10:04 +0100 Subject: Fix and relevant spec for plan stage breaking with nil commits --- spec/lib/gitlab/cycle_analytics/plan_event_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'spec') diff --git a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb index d76a255acf5..4a5604115ec 100644 --- a/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/plan_event_spec.rb @@ -6,5 +6,13 @@ describe Gitlab::CycleAnalytics::PlanEvent do it 'has the default order' do expect(event.order).to eq(event.start_time_attrs) end + + context 'no commits' do + it 'does not blow up if there are no commits' do + allow_any_instance_of(Gitlab::CycleAnalytics::EventsQuery).to receive(:execute).and_return([{}]) + + expect { event.fetch }.not_to raise_error + end + end end end -- cgit v1.2.1 From 916332815e33c655f727a28457f655f6425306ae Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Fri, 18 Nov 2016 19:15:47 +0200 Subject: Drop Project#authorized_for_user? in favor of ProjectTeam#member? Closes #23938 --- spec/helpers/members_helper_spec.rb | 4 +-- spec/models/issue_spec.rb | 2 +- spec/models/project_spec.rb | 51 ------------------------------------- spec/models/project_team_spec.rb | 51 +++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 54 deletions(-) (limited to 'spec') diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb index ffca1c94da1..33934cdf8b1 100644 --- a/spec/helpers/members_helper_spec.rb +++ b/spec/helpers/members_helper_spec.rb @@ -10,7 +10,7 @@ describe MembersHelper do end describe '#remove_member_message' do - let(:requester) { build(:user) } + let(:requester) { create(:user) } let(:project) { create(:empty_project, :public, :access_requestable) } let(:project_member) { build(:project_member, project: project) } let(:project_member_invite) { build(:project_member, project: project).tap { |m| m.generate_invite_token! } } @@ -31,7 +31,7 @@ describe MembersHelper do end describe '#remove_member_title' do - let(:requester) { build(:user) } + let(:requester) { create(:user) } let(:project) { create(:empty_project, :public, :access_requestable) } let(:project_member) { build(:project_member, project: project) } let(:project_member_request) { project.request_access(requester) } diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 300425767ed..89e93dce8c5 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -331,7 +331,7 @@ describe Issue, models: true do end context 'with a user' do - let(:user) { build(:user) } + let(:user) { create(:user) } let(:issue) { build(:issue) } it 'returns true when the issue is readable' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 5ba741f40ec..da38254d1bc 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1507,57 +1507,6 @@ describe Project, models: true do end end - describe 'authorized_for_user' do - let(:group) { create(:group) } - let(:developer) { create(:user) } - let(:master) { create(:user) } - let(:personal_project) { create(:project, namespace: developer.namespace) } - let(:group_project) { create(:project, namespace: group) } - let(:members_project) { create(:project) } - let(:shared_project) { create(:project) } - - before do - group.add_master(master) - group.add_developer(developer) - - members_project.team << [developer, :developer] - members_project.team << [master, :master] - - create(:project_group_link, project: shared_project, group: group, group_access: Gitlab::Access::DEVELOPER) - end - - it 'returns false for no user' do - expect(personal_project.authorized_for_user?(nil)).to be(false) - end - - it 'returns true for personal projects of the user' do - expect(personal_project.authorized_for_user?(developer)).to be(true) - end - - it 'returns true for projects of groups the user is a member of' do - expect(group_project.authorized_for_user?(developer)).to be(true) - end - - it 'returns true for projects for which the user is a member of' do - expect(members_project.authorized_for_user?(developer)).to be(true) - end - - it 'returns true for projects shared on a group the user is a member of' do - expect(shared_project.authorized_for_user?(developer)).to be(true) - end - - it 'checks for the correct minimum level access' do - expect(group_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false) - expect(group_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(true) - expect(members_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false) - expect(members_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(true) - expect(shared_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false) - expect(shared_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(false) - expect(shared_project.authorized_for_user?(developer, Gitlab::Access::DEVELOPER)).to be(true) - expect(shared_project.authorized_for_user?(master, Gitlab::Access::DEVELOPER)).to be(true) - end - end - describe 'change_head' do let(:project) { create(:project) } diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index eb6b009c7cf..573da5e50d4 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -261,6 +261,57 @@ describe ProjectTeam, models: true do end end + describe '#member?' do + let(:group) { create(:group) } + let(:developer) { create(:user) } + let(:master) { create(:user) } + let(:personal_project) { create(:project, namespace: developer.namespace) } + let(:group_project) { create(:project, namespace: group) } + let(:members_project) { create(:project) } + let(:shared_project) { create(:project) } + + before do + group.add_master(master) + group.add_developer(developer) + + members_project.team << [developer, :developer] + members_project.team << [master, :master] + + create(:project_group_link, project: shared_project, group: group) + end + + it 'returns false for no user' do + expect(personal_project.team.member?(nil)).to be(false) + end + + it 'returns true for personal projects of the user' do + expect(personal_project.team.member?(developer)).to be(true) + end + + it 'returns true for projects of groups the user is a member of' do + expect(group_project.team.member?(developer)).to be(true) + end + + it 'returns true for projects for which the user is a member of' do + expect(members_project.team.member?(developer)).to be(true) + end + + it 'returns true for projects shared on a group the user is a member of' do + expect(shared_project.team.member?(developer)).to be(true) + end + + it 'checks for the correct minimum level access' do + expect(group_project.team.member?(developer, Gitlab::Access::MASTER)).to be(false) + expect(group_project.team.member?(master, Gitlab::Access::MASTER)).to be(true) + expect(members_project.team.member?(developer, Gitlab::Access::MASTER)).to be(false) + expect(members_project.team.member?(master, Gitlab::Access::MASTER)).to be(true) + expect(shared_project.team.member?(developer, Gitlab::Access::MASTER)).to be(false) + expect(shared_project.team.member?(master, Gitlab::Access::MASTER)).to be(false) + expect(shared_project.team.member?(developer, Gitlab::Access::DEVELOPER)).to be(true) + expect(shared_project.team.member?(master, Gitlab::Access::DEVELOPER)).to be(true) + end + end + shared_examples_for "#max_member_access_for_users" do |enable_request_store| describe "#max_member_access_for_users" do before do -- cgit v1.2.1 From 747959a832bddcdffba3e7c687b66904e8c6dbf9 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Mon, 21 Nov 2016 15:36:40 +0200 Subject: Update ProjectTeam#max_member_access_for_user_ids to use project authorizations --- spec/lib/gitlab/import_export/all_models.yml | 2 ++ spec/models/project_team_spec.rb | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index fe3c39e38db..7e00e214c6e 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -186,6 +186,8 @@ project: - environments - deployments - project_feature +- authorized_users +- project_authorizations award_emoji: - awardable - user diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 573da5e50d4..700776be931 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -37,7 +37,7 @@ describe ProjectTeam, models: true do context 'group project' do let(:group) { create(:group) } - let(:project) { create(:empty_project, group: group) } + let!(:project) { create(:empty_project, group: group) } before do group.add_master(master) @@ -178,9 +178,9 @@ describe ProjectTeam, models: true do it 'returns Master role' do user = create(:user) group = create(:group) - group.add_master(user) + project = create(:empty_project, namespace: group) - project = build_stubbed(:empty_project, namespace: group) + group.add_master(user) expect(project.team.human_max_access(user.id)).to eq 'Master' end @@ -188,9 +188,9 @@ describe ProjectTeam, models: true do it 'returns Owner role' do user = create(:user) group = create(:group) - group.add_owner(user) + project = create(:empty_project, namespace: group) - project = build_stubbed(:empty_project, namespace: group) + group.add_owner(user) expect(project.team.human_max_access(user.id)).to eq 'Owner' end @@ -244,7 +244,7 @@ describe ProjectTeam, models: true do context 'group project' do let(:group) { create(:group, :access_requestable) } - let(:project) { create(:empty_project, group: group) } + let!(:project) { create(:empty_project, group: group) } before do group.add_master(master) -- cgit v1.2.1 From 2ea5ef0ba4ee00b5551b88a6b9a68e045bf4b3f4 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Mon, 21 Nov 2016 16:26:12 +0200 Subject: Update ProjectTeam#fetch_members to use project authorizations --- spec/models/project_team_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index 700776be931..0475cecaa2d 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -118,7 +118,7 @@ describe ProjectTeam, models: true do context 'group project' do let(:group) { create(:group) } - let(:project) { create(:empty_project, group: group) } + let!(:project) { create(:empty_project, group: group) } it 'returns project members' do group_member = create(:group_member, group: group) -- cgit v1.2.1 From 3789cfe056c1d8a5fb91267cc2b1dd0f9f5902a9 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 15 Nov 2016 19:48:30 +0200 Subject: Add a starting date to milestones --- spec/features/milestone_spec.rb | 5 +++ spec/helpers/milestones_helper_spec.rb | 19 ++++++++++ .../gitlab/import_export/safe_model_attributes.yml | 1 + spec/models/concerns/milestoneish_spec.rb | 20 ++++++++++ spec/models/milestone_spec.rb | 43 +++++++++++++--------- spec/requests/api/milestones_spec.rb | 5 ++- 6 files changed, 74 insertions(+), 19 deletions(-) (limited to 'spec') diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index b8c838bf7ab..a2e40546588 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -14,12 +14,17 @@ feature 'Milestone', feature: true do feature 'Create a milestone' do scenario 'shows an informative message for a new milestone' do visit new_namespace_project_milestone_path(project.namespace, project) + page.within '.milestone-form' do fill_in "milestone_title", with: '8.7' + fill_in "milestone_start_date", with: '2016-11-16' + fill_in "milestone_due_date", with: '2016-12-16' end + find('input[name="commit"]').click expect(find('.alert-success')).to have_content('Assign some issues to this milestone.') + expect(page).to have_content('Nov 16, 2016 - Dec 16, 2016') end end diff --git a/spec/helpers/milestones_helper_spec.rb b/spec/helpers/milestones_helper_spec.rb index 28c2268f8d0..ea744dbb629 100644 --- a/spec/helpers/milestones_helper_spec.rb +++ b/spec/helpers/milestones_helper_spec.rb @@ -1,6 +1,25 @@ require 'spec_helper' describe MilestonesHelper do + describe "#milestone_date_range" do + def result_for(*args) + milestone_date_range(build(:milestone, *args)) + end + + let(:yesterday) { Date.yesterday } + let(:tomorrow) { yesterday + 2 } + let(:format) { '%b %-d, %Y' } + let(:yesterday_formatted) { yesterday.strftime(format) } + let(:tomorrow_formatted) { tomorrow.strftime(format) } + + it { expect(result_for(due_date: nil, start_date: nil)).to be_nil } + it { expect(result_for(due_date: tomorrow)).to eq("expires on #{tomorrow_formatted}") } + it { expect(result_for(due_date: yesterday)).to eq("expired on #{yesterday_formatted}") } + it { expect(result_for(start_date: tomorrow)).to eq("starts on #{tomorrow_formatted}") } + it { expect(result_for(start_date: yesterday)).to eq("started on #{yesterday_formatted}") } + it { expect(result_for(start_date: yesterday, due_date: tomorrow)).to eq("#{yesterday_formatted} - #{tomorrow_formatted}") } + end + describe '#milestone_counts' do let(:project) { FactoryGirl.create(:project) } let(:counts) { helper.milestone_counts(project.milestones) } diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index d6807941b31..78d6b2c5032 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -78,6 +78,7 @@ Milestone: - project_id - description - due_date +- start_date - created_at - updated_at - state diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb index b7e973798a3..0e097559b59 100644 --- a/spec/models/concerns/milestoneish_spec.rb +++ b/spec/models/concerns/milestoneish_spec.rb @@ -115,4 +115,24 @@ describe Milestone, 'Milestoneish' do expect(milestone.percent_complete(admin)).to eq 60 end end + + describe '#elapsed_days' do + it 'shows 0 if no start_date set' do + milestone = build(:milestone) + + expect(milestone.elapsed_days).to eq(0) + end + + it 'shows 0 if start_date is a future' do + milestone = build(:milestone, start_date: Time.now + 2.days) + + expect(milestone.elapsed_days).to eq(0) + end + + it 'shows correct amount of days' do + milestone = build(:milestone, start_date: Time.now - 2.days) + + expect(milestone.elapsed_days).to eq(2) + end + end end diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 33fe22dd98c..a4bfe851dfb 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -1,11 +1,6 @@ require 'spec_helper' describe Milestone, models: true do - describe "Associations" do - it { is_expected.to belong_to(:project) } - it { is_expected.to have_many(:issues) } - end - describe "Validation" do before do allow(subject).to receive(:set_iid).and_return(false) @@ -13,6 +8,20 @@ describe Milestone, models: true do it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_presence_of(:project) } + + describe 'start_date' do + it 'adds an error when start_date is greated then due_date' do + milestone = build(:milestone, start_date: Date.tomorrow, due_date: Date.yesterday) + + expect(milestone).not_to be_valid + expect(milestone.errors[:start_date]).to include("Can't be greater than due date") + end + end + end + + describe "Associations" do + it { is_expected.to belong_to(:project) } + it { is_expected.to have_many(:issues) } end let(:milestone) { create(:milestone) } @@ -58,18 +67,6 @@ describe Milestone, models: true do end end - describe "#expires_at" do - it "is nil when due_date is unset" do - milestone.update_attributes(due_date: nil) - expect(milestone.expires_at).to be_nil - end - - it "is not nil when due_date is set" do - milestone.update_attributes(due_date: Date.tomorrow) - expect(milestone.expires_at).to be_present - end - end - describe '#expired?' do context "expired" do before do @@ -88,6 +85,18 @@ describe Milestone, models: true do end end + describe '#upcoming?' do + it 'returns true' do + milestone = build(:milestone, start_date: Time.now + 1.month) + expect(milestone.upcoming?).to be_truthy + end + + it 'returns false' do + milestone = build(:milestone, start_date: Date.today.prev_year) + expect(milestone.upcoming?).to be_falsey + end + end + describe '#percent_complete' do before do allow(milestone).to receive_messages( diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index 5d7b39e71b8..b0946a838a1 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -92,13 +92,14 @@ describe API::API, api: true do expect(json_response['description']).to be_nil end - it 'creates a new project milestone with description and due date' do + it 'creates a new project milestone with description and dates' do post api("/projects/#{project.id}/milestones", user), - title: 'new milestone', description: 'release', due_date: '2013-03-02' + title: 'new milestone', description: 'release', due_date: '2013-03-02', start_date: '2013-02-02' expect(response).to have_http_status(201) expect(json_response['description']).to eq('release') expect(json_response['due_date']).to eq('2013-03-02') + expect(json_response['start_date']).to eq('2013-02-02') end it 'returns a 400 error if title is missing' do -- cgit v1.2.1 From eff1b05ab1d50895be668be12de8239def648d97 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Tue, 22 Nov 2016 11:23:41 +0100 Subject: API: Add endpoint to delete a group share --- spec/requests/api/projects_spec.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index f020d471422..e53ee2a4e76 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -908,6 +908,36 @@ describe API::API, api: true do end end + describe 'DELETE /projects/:id/share/:group_id' do + it 'returns 204 when deleting a group share' do + group = create(:group, :public) + create(:project_group_link, group: group, project: project) + + delete api("/projects/#{project.id}/share/#{group.id}", user) + + expect(response).to have_http_status(204) + expect(project.project_group_links).to be_empty + end + + it 'returns a 400 when group id is not an integer' do + delete api("/projects/#{project.id}/share/foo", user) + + expect(response).to have_http_status(400) + end + + it 'returns a 404 error when group link does not exist' do + delete api("/projects/#{project.id}/share/1234", user) + + expect(response).to have_http_status(404) + end + + it 'returns a 404 error when project does not exist' do + delete api("/projects/123/share/1234", user) + + expect(response).to have_http_status(404) + end + end + describe 'GET /projects/search/:query' do let!(:query) { 'query'} let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) } -- cgit v1.2.1 From f2a0c6f6bf768db8837283ad65fe6790b9105d26 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 23 Nov 2016 20:00:58 +0800 Subject: Correctly determine mergeability of MR with no discussions --- spec/models/merge_request_spec.rb | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'spec') diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 0b4277b1edd..58ccd056328 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -937,6 +937,16 @@ describe MergeRequest, models: true do expect(merge_request.mergeable_discussions_state?).to be_falsey end end + + context 'with no discussions' do + before do + merge_request.notes.destroy_all + end + + it 'returns true' do + expect(merge_request.mergeable_discussions_state?).to be_truthy + end + end end context 'when project.only_allow_merge_if_all_discussions_are_resolved == false' do @@ -1198,6 +1208,50 @@ describe MergeRequest, models: true do end end end + + describe "#discussions_to_be_resolved?" do + context "when discussions are not resolvable" do + before do + allow(subject).to receive(:discussions_resolvable?).and_return(false) + end + + it "returns false" do + expect(subject.discussions_to_be_resolved?).to be false + end + end + + context "when discussions are resolvable" do + before do + allow(subject).to receive(:discussions_resolvable?).and_return(true) + + allow(first_discussion).to receive(:resolvable?).and_return(true) + allow(second_discussion).to receive(:resolvable?).and_return(false) + allow(third_discussion).to receive(:resolvable?).and_return(true) + end + + context "when all resolvable discussions are resolved" do + before do + allow(first_discussion).to receive(:resolved?).and_return(true) + allow(third_discussion).to receive(:resolved?).and_return(true) + end + + it "returns false" do + expect(subject.discussions_to_be_resolved?).to be false + end + end + + context "when some resolvable discussions are not resolved" do + before do + allow(first_discussion).to receive(:resolved?).and_return(true) + allow(third_discussion).to receive(:resolved?).and_return(false) + end + + it "returns true" do + expect(subject.discussions_to_be_resolved?).to be true + end + end + end + end end describe '#conflicts_can_be_resolved_in_ui?' do -- cgit v1.2.1 From 6683fdcfb0ae4ceb368b6f5f63dde0a10a4a3e1b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 14 Nov 2016 16:55:31 +0200 Subject: Add nested groups support to the routing Signed-off-by: Dmitriy Zaporozhets --- spec/controllers/application_controller_spec.rb | 23 +- spec/lib/constraints/constrainer_helper_spec.rb | 20 - spec/lib/constraints/group_url_constrainer_spec.rb | 20 +- .../constraints/project_url_constrainer_spec.rb | 32 + spec/lib/constraints/user_url_constrainer_spec.rb | 21 +- spec/models/user_spec.rb | 11 + spec/routing/project_routing_spec.rb | 1034 ++++++++++---------- spec/routing/routing_spec.rb | 16 +- 8 files changed, 628 insertions(+), 549 deletions(-) delete mode 100644 spec/lib/constraints/constrainer_helper_spec.rb create mode 100644 spec/lib/constraints/project_url_constrainer_spec.rb (limited to 'spec') diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 98e912f000c..81cbccd5436 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' describe ApplicationController do + let(:user) { create(:user) } + describe '#check_password_expiration' do - let(:user) { create(:user) } let(:controller) { ApplicationController.new } it 'redirects if the user is over their password expiry' do @@ -39,8 +40,6 @@ describe ApplicationController do end end - let(:user) { create(:user) } - context "when the 'private_token' param is populated with the private token" do it "logs the user in" do get :index, private_token: user.private_token @@ -73,7 +72,6 @@ describe ApplicationController do end end - let(:user) { create(:user) } let(:personal_access_token) { create(:personal_access_token, user: user) } context "when the 'personal_access_token' param is populated with the personal access token" do @@ -100,4 +98,21 @@ describe ApplicationController do end end end + + describe '#route_not_found' do + let(:controller) { ApplicationController.new } + + it 'renders 404 if authenticated' do + allow(controller).to receive(:current_user).and_return(user) + expect(controller).to receive(:not_found) + controller.send(:route_not_found) + end + + it 'does redirect to login page if not authenticated' do + allow(controller).to receive(:current_user).and_return(nil) + expect(controller).to receive(:redirect_to) + expect(controller).to receive(:new_user_session_path) + controller.send(:route_not_found) + end + end end diff --git a/spec/lib/constraints/constrainer_helper_spec.rb b/spec/lib/constraints/constrainer_helper_spec.rb deleted file mode 100644 index 27c8d72aefc..00000000000 --- a/spec/lib/constraints/constrainer_helper_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' - -describe ConstrainerHelper, lib: true do - include ConstrainerHelper - - describe '#extract_resource_path' do - it { expect(extract_resource_path('/gitlab/')).to eq('gitlab') } - it { expect(extract_resource_path('///gitlab//')).to eq('gitlab') } - it { expect(extract_resource_path('/gitlab.atom')).to eq('gitlab') } - - context 'relative url' do - before do - allow(Gitlab::Application.config).to receive(:relative_url_root) { '/gitlab' } - end - - it { expect(extract_resource_path('/gitlab/foo')).to eq('foo') } - it { expect(extract_resource_path('/foo/bar')).to eq('foo/bar') } - end - end -end diff --git a/spec/lib/constraints/group_url_constrainer_spec.rb b/spec/lib/constraints/group_url_constrainer_spec.rb index 42299b17c2b..892554f2870 100644 --- a/spec/lib/constraints/group_url_constrainer_spec.rb +++ b/spec/lib/constraints/group_url_constrainer_spec.rb @@ -4,16 +4,20 @@ describe GroupUrlConstrainer, lib: true do let!(:group) { create(:group, path: 'gitlab') } describe '#matches?' do - context 'root group' do - it { expect(subject.matches?(request '/gitlab')).to be_truthy } - it { expect(subject.matches?(request '/gitlab.atom')).to be_truthy } - it { expect(subject.matches?(request '/gitlab/edit')).to be_falsey } - it { expect(subject.matches?(request '/gitlab-ce')).to be_falsey } - it { expect(subject.matches?(request '/.gitlab')).to be_falsey } + context 'valid request' do + let(:request) { build_request(group.path) } + + it { expect(subject.matches?(request)).to be_truthy } + end + + context 'invalid request' do + let(:request) { build_request('foo') } + + it { expect(subject.matches?(request)).to be_falsey } end end - def request(path) - double(:request, path: path) + def build_request(path) + double(:request, params: { id: path }) end end diff --git a/spec/lib/constraints/project_url_constrainer_spec.rb b/spec/lib/constraints/project_url_constrainer_spec.rb new file mode 100644 index 00000000000..94266f6653b --- /dev/null +++ b/spec/lib/constraints/project_url_constrainer_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe ProjectUrlConstrainer, lib: true do + let!(:project) { create(:project) } + let!(:namespace) { project.namespace } + + describe '#matches?' do + context 'valid request' do + let(:request) { build_request(namespace.path, project.path) } + + it { expect(subject.matches?(request)).to be_truthy } + end + + context 'invalid request' do + context "non-existing project" do + let(:request) { build_request('foo', 'bar') } + + it { expect(subject.matches?(request)).to be_falsey } + end + + context "project id ending with .git" do + let(:request) { build_request(namespace.path, project.path + '.git') } + + it { expect(subject.matches?(request)).to be_falsey } + end + end + end + + def build_request(namespace, project) + double(:request, params: { namespace_id: namespace, id: project }) + end +end diff --git a/spec/lib/constraints/user_url_constrainer_spec.rb b/spec/lib/constraints/user_url_constrainer_spec.rb index b3f8530c609..207b6fe6c9e 100644 --- a/spec/lib/constraints/user_url_constrainer_spec.rb +++ b/spec/lib/constraints/user_url_constrainer_spec.rb @@ -1,16 +1,23 @@ require 'spec_helper' describe UserUrlConstrainer, lib: true do - let!(:username) { create(:user, username: 'dz') } + let!(:user) { create(:user, username: 'dz') } describe '#matches?' do - it { expect(subject.matches?(request '/dz')).to be_truthy } - it { expect(subject.matches?(request '/dz.atom')).to be_truthy } - it { expect(subject.matches?(request '/dz/projects')).to be_falsey } - it { expect(subject.matches?(request '/gitlab')).to be_falsey } + context 'valid request' do + let(:request) { build_request(user.username) } + + it { expect(subject.matches?(request)).to be_truthy } + end + + context 'invalid request' do + let(:request) { build_request('foo') } + + it { expect(subject.matches?(request)).to be_falsey } + end end - def request(path) - double(:request, path: path) + def build_request(username) + double(:request, params: { username: username }) end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e84042f8063..91826e5884d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -752,6 +752,17 @@ describe User, models: true do end end + describe '.find_by_username' do + it 'returns nil if not found' do + expect(described_class.find_by_username('JohnDoe')).to be_nil + end + + it 'is case-insensitive' do + user = create(:user, username: 'JohnDoe') + expect(described_class.find_by_username('JOHNDOE')).to eq user + end + end + describe '.find_by_username!' do it 'raises RecordNotFound' do expect { described_class.find_by_username!('JohnDoe') }. diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 2322430d212..b6e7da841b1 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -1,511 +1,531 @@ require 'spec_helper' -# Shared examples for a resource inside a Project -# -# By default it tests all the default REST actions: index, create, new, edit, -# show, update, and destroy. You can remove actions by customizing the -# `actions` variable. -# -# It also expects a `controller` variable to be available which defines both -# the path to the resource as well as the controller name. -# -# Examples -# -# # Default behavior -# it_behaves_like 'RESTful project resources' do -# let(:controller) { 'issues' } -# end -# -# # Customizing actions -# it_behaves_like 'RESTful project resources' do -# let(:actions) { [:index] } -# let(:controller) { 'issues' } -# end -shared_examples 'RESTful project resources' do - let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] } - - it 'to #index' do - expect(get("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#index", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:index) - end - - it 'to #create' do - expect(post("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#create", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:create) - end - - it 'to #new' do - expect(get("/gitlab/gitlabhq/#{controller}/new")).to route_to("projects/#{controller}#new", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:new) - end - - it 'to #edit' do - expect(get("/gitlab/gitlabhq/#{controller}/1/edit")).to route_to("projects/#{controller}#edit", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:edit) - end - - it 'to #show' do - expect(get("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#show", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:show) - end - - it 'to #update' do - expect(put("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#update", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:update) - end - - it 'to #destroy' do - expect(delete("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#destroy", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:destroy) - end -end - -# projects POST /projects(.:format) projects#create -# new_project GET /projects/new(.:format) projects#new -# files_project GET /:id/files(.:format) projects#files -# edit_project GET /:id/edit(.:format) projects#edit -# project GET /:id(.:format) projects#show -# PUT /:id(.:format) projects#update -# DELETE /:id(.:format) projects#destroy -# preview_markdown_project POST /:id/preview_markdown(.:format) projects#preview_markdown -describe ProjectsController, 'routing' do - it 'to #create' do - expect(post('/projects')).to route_to('projects#create') - end - - it 'to #new' do - expect(get('/projects/new')).to route_to('projects#new') - end - - it 'to #edit' do - expect(get('/gitlab/gitlabhq/edit')).to route_to('projects#edit', namespace_id: 'gitlab', id: 'gitlabhq') - end - - it 'to #autocomplete_sources' do - expect(get('/gitlab/gitlabhq/autocomplete_sources')).to route_to('projects#autocomplete_sources', namespace_id: 'gitlab', id: 'gitlabhq') - end - - it 'to #show' do - expect(get('/gitlab/gitlabhq')).to route_to('projects#show', namespace_id: 'gitlab', id: 'gitlabhq') - expect(get('/gitlab/gitlabhq.keys')).to route_to('projects#show', namespace_id: 'gitlab', id: 'gitlabhq.keys') - end - - it 'to #update' do - expect(put('/gitlab/gitlabhq')).to route_to('projects#update', namespace_id: 'gitlab', id: 'gitlabhq') - end - - it 'to #destroy' do - expect(delete('/gitlab/gitlabhq')).to route_to('projects#destroy', namespace_id: 'gitlab', id: 'gitlabhq') - end - - it 'to #preview_markdown' do - expect(post('/gitlab/gitlabhq/preview_markdown')).to( - route_to('projects#preview_markdown', namespace_id: 'gitlab', id: 'gitlabhq') - ) - end -end - -# pages_project_wikis GET /:project_id/wikis/pages(.:format) projects/wikis#pages -# history_project_wiki GET /:project_id/wikis/:id/history(.:format) projects/wikis#history -# project_wikis POST /:project_id/wikis(.:format) projects/wikis#create -# edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) projects/wikis#edit -# project_wiki GET /:project_id/wikis/:id(.:format) projects/wikis#show -# DELETE /:project_id/wikis/:id(.:format) projects/wikis#destroy -describe Projects::WikisController, 'routing' do - it 'to #pages' do - expect(get('/gitlab/gitlabhq/wikis/pages')).to route_to('projects/wikis#pages', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #history' do - expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it_behaves_like 'RESTful project resources' do - let(:actions) { [:create, :edit, :show, :destroy] } - let(:controller) { 'wikis' } - end -end - -# branches_project_repository GET /:project_id/repository/branches(.:format) projects/repositories#branches -# tags_project_repository GET /:project_id/repository/tags(.:format) projects/repositories#tags -# archive_project_repository GET /:project_id/repository/archive(.:format) projects/repositories#archive -# edit_project_repository GET /:project_id/repository/edit(.:format) projects/repositories#edit -describe Projects::RepositoriesController, 'routing' do - it 'to #archive' do - expect(get('/gitlab/gitlabhq/repository/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #archive format:zip' do - expect(get('/gitlab/gitlabhq/repository/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip') - end - - it 'to #archive format:tar.bz2' do - expect(get('/gitlab/gitlabhq/repository/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2') - end -end - -describe Projects::BranchesController, 'routing' do - it 'to #branches' do - expect(get('/gitlab/gitlabhq/branches')).to route_to('projects/branches#index', namespace_id: 'gitlab', project_id: 'gitlabhq') - expect(delete('/gitlab/gitlabhq/branches/feature%2345')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') - expect(delete('/gitlab/gitlabhq/branches/feature%2B45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') - expect(delete('/gitlab/gitlabhq/branches/feature@45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') - expect(delete('/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz') - expect(delete('/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz') - expect(delete('/gitlab/gitlabhq/branches/feature@45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz') - end -end - -describe Projects::TagsController, 'routing' do - it 'to #tags' do - expect(get('/gitlab/gitlabhq/tags')).to route_to('projects/tags#index', namespace_id: 'gitlab', project_id: 'gitlabhq') - expect(delete('/gitlab/gitlabhq/tags/feature%2345')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') - expect(delete('/gitlab/gitlabhq/tags/feature%2B45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') - expect(delete('/gitlab/gitlabhq/tags/feature@45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') - expect(delete('/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz') - expect(delete('/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz') - expect(delete('/gitlab/gitlabhq/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz') - end -end - -# project_deploy_keys GET /:project_id/deploy_keys(.:format) deploy_keys#index -# POST /:project_id/deploy_keys(.:format) deploy_keys#create -# new_project_deploy_key GET /:project_id/deploy_keys/new(.:format) deploy_keys#new -# project_deploy_key GET /:project_id/deploy_keys/:id(.:format) deploy_keys#show -# DELETE /:project_id/deploy_keys/:id(.:format) deploy_keys#destroy -describe Projects::DeployKeysController, 'routing' do - it_behaves_like 'RESTful project resources' do - let(:actions) { [:index, :new, :create] } - let(:controller) { 'deploy_keys' } - end -end - -# project_protected_branches GET /:project_id/protected_branches(.:format) protected_branches#index -# POST /:project_id/protected_branches(.:format) protected_branches#create -# project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy -describe Projects::ProtectedBranchesController, 'routing' do - it_behaves_like 'RESTful project resources' do - let(:actions) { [:index, :create, :destroy] } - let(:controller) { 'protected_branches' } - end -end - -# switch_project_refs GET /:project_id/refs/switch(.:format) refs#switch -# logs_tree_project_ref GET /:project_id/refs/:id/logs_tree(.:format) refs#logs_tree -# logs_file_project_ref GET /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree -describe Projects::RefsController, 'routing' do - it 'to #switch' do - expect(get('/gitlab/gitlabhq/refs/switch')).to route_to('projects/refs#switch', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #logs_tree' do - expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable') - expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') - expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') - expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') - expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') - expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz') - expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz') - expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45', path: 'foo/bar/baz') - expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/files.scss')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'files.scss') - end -end - -# diffs_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/diffs(.:format) projects/merge_requests#diffs -# commits_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/commits(.:format) projects/merge_requests#commits -# merge_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/merge(.:format) projects/merge_requests#merge -# merge_check_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/merge_check(.:format) projects/merge_requests#merge_check -# ci_status_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/ci_status(.:format) projects/merge_requests#ci_status -# toggle_subscription_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/toggle_subscription(.:format) projects/merge_requests#toggle_subscription -# branch_from_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/branch_from(.:format) projects/merge_requests#branch_from -# branch_to_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/branch_to(.:format) projects/merge_requests#branch_to -# update_branches_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/update_branches(.:format) projects/merge_requests#update_branches -# namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests(.:format) projects/merge_requests#index -# POST /:namespace_id/:project_id/merge_requests(.:format) projects/merge_requests#create -# new_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/new(.:format) projects/merge_requests#new -# edit_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/edit(.:format) projects/merge_requests#edit -# namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id(.:format) projects/merge_requests#show -# PATCH /:namespace_id/:project_id/merge_requests/:id(.:format) projects/merge_requests#update -# PUT /:namespace_id/:project_id/merge_requests/:id(.:format) projects/merge_requests#update -describe Projects::MergeRequestsController, 'routing' do - it 'to #diffs' do - expect(get('/gitlab/gitlabhq/merge_requests/1/diffs')).to route_to('projects/merge_requests#diffs', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #commits' do - expect(get('/gitlab/gitlabhq/merge_requests/1/commits')).to route_to('projects/merge_requests#commits', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #merge' do - expect(post('/gitlab/gitlabhq/merge_requests/1/merge')).to route_to( - 'projects/merge_requests#merge', - namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1' - ) - end - - it 'to #merge_check' do - expect(get('/gitlab/gitlabhq/merge_requests/1/merge_check')).to route_to('projects/merge_requests#merge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #branch_from' do - expect(get('/gitlab/gitlabhq/merge_requests/branch_from')).to route_to('projects/merge_requests#branch_from', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #branch_to' do - expect(get('/gitlab/gitlabhq/merge_requests/branch_to')).to route_to('projects/merge_requests#branch_to', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #show' do - expect(get('/gitlab/gitlabhq/merge_requests/1.diff')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'diff') - expect(get('/gitlab/gitlabhq/merge_requests/1.patch')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'patch') - end - - it_behaves_like 'RESTful project resources' do - let(:controller) { 'merge_requests' } - let(:actions) { [:index, :create, :new, :edit, :show, :update] } - end -end - -# raw_project_snippet GET /:project_id/snippets/:id/raw(.:format) snippets#raw -# project_snippets GET /:project_id/snippets(.:format) snippets#index -# POST /:project_id/snippets(.:format) snippets#create -# new_project_snippet GET /:project_id/snippets/new(.:format) snippets#new -# edit_project_snippet GET /:project_id/snippets/:id/edit(.:format) snippets#edit -# project_snippet GET /:project_id/snippets/:id(.:format) snippets#show -# PUT /:project_id/snippets/:id(.:format) snippets#update -# DELETE /:project_id/snippets/:id(.:format) snippets#destroy -describe SnippetsController, 'routing' do - it 'to #raw' do - expect(get('/gitlab/gitlabhq/snippets/1/raw')).to route_to('projects/snippets#raw', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #index' do - expect(get('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#index', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #create' do - expect(post('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#create', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #new' do - expect(get('/gitlab/gitlabhq/snippets/new')).to route_to('projects/snippets#new', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #edit' do - expect(get('/gitlab/gitlabhq/snippets/1/edit')).to route_to('projects/snippets#edit', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #show' do - expect(get('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #update' do - expect(put('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#update', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it 'to #destroy' do - expect(delete('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end -end - -# test_project_hook GET /:project_id/hooks/:id/test(.:format) hooks#test -# project_hooks GET /:project_id/hooks(.:format) hooks#index -# POST /:project_id/hooks(.:format) hooks#create -# project_hook DELETE /:project_id/hooks/:id(.:format) hooks#destroy -describe Projects::HooksController, 'routing' do - it 'to #test' do - expect(get('/gitlab/gitlabhq/hooks/1/test')).to route_to('projects/hooks#test', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') - end - - it_behaves_like 'RESTful project resources' do - let(:actions) { [:index, :create, :destroy] } - let(:controller) { 'hooks' } - end -end - -# project_commit GET /:project_id/commit/:id(.:format) commit#show {id: /\h{7,40}/, project_id: /[^\/]+/} -describe Projects::CommitController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/commit/4246fbd')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd') - expect(get('/gitlab/gitlabhq/commit/4246fbd.diff')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd', format: 'diff') - expect(get('/gitlab/gitlabhq/commit/4246fbd.patch')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd', format: 'patch') - expect(get('/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5') - end -end - -# patch_project_commit GET /:project_id/commits/:id/patch(.:format) commits#patch -# project_commits GET /:project_id/commits(.:format) commits#index -# POST /:project_id/commits(.:format) commits#create -# project_commit GET /:project_id/commits/:id(.:format) commits#show -describe Projects::CommitsController, 'routing' do - it_behaves_like 'RESTful project resources' do - let(:actions) { [:show] } - let(:controller) { 'commits' } - end - - it 'to #show' do - expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom') - end -end - -# project_project_members GET /:project_id/project_members(.:format) project_members#index -# POST /:project_id/project_members(.:format) project_members#create -# PUT /:project_id/project_members/:id(.:format) project_members#update -# DELETE /:project_id/project_members/:id(.:format) project_members#destroy -describe Projects::ProjectMembersController, 'routing' do - it_behaves_like 'RESTful project resources' do - let(:actions) { [:index, :create, :update, :destroy] } - let(:controller) { 'project_members' } - end -end - -# project_milestones GET /:project_id/milestones(.:format) milestones#index -# POST /:project_id/milestones(.:format) milestones#create -# new_project_milestone GET /:project_id/milestones/new(.:format) milestones#new -# edit_project_milestone GET /:project_id/milestones/:id/edit(.:format) milestones#edit -# project_milestone GET /:project_id/milestones/:id(.:format) milestones#show -# PUT /:project_id/milestones/:id(.:format) milestones#update -# DELETE /:project_id/milestones/:id(.:format) milestones#destroy -describe Projects::MilestonesController, 'routing' do - it_behaves_like 'RESTful project resources' do - let(:controller) { 'milestones' } - let(:actions) { [:index, :create, :new, :edit, :show, :update] } - end -end - -# project_labels GET /:project_id/labels(.:format) labels#index -describe Projects::LabelsController, 'routing' do - it 'to #index' do - expect(get('/gitlab/gitlabhq/labels')).to route_to('projects/labels#index', namespace_id: 'gitlab', project_id: 'gitlabhq') - end -end - -# sort_project_issues POST /:project_id/issues/sort(.:format) issues#sort -# bulk_update_project_issues POST /:project_id/issues/bulk_update(.:format) issues#bulk_update -# search_project_issues GET /:project_id/issues/search(.:format) issues#search -# project_issues GET /:project_id/issues(.:format) issues#index -# POST /:project_id/issues(.:format) issues#create -# new_project_issue GET /:project_id/issues/new(.:format) issues#new -# edit_project_issue GET /:project_id/issues/:id/edit(.:format) issues#edit -# project_issue GET /:project_id/issues/:id(.:format) issues#show -# PUT /:project_id/issues/:id(.:format) issues#update -# DELETE /:project_id/issues/:id(.:format) issues#destroy -describe Projects::IssuesController, 'routing' do - it 'to #bulk_update' do - expect(post('/gitlab/gitlabhq/issues/bulk_update')).to route_to('projects/issues#bulk_update', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it_behaves_like 'RESTful project resources' do - let(:controller) { 'issues' } - let(:actions) { [:index, :create, :new, :edit, :show, :update] } - end -end - -# project_notes GET /:project_id/notes(.:format) notes#index -# POST /:project_id/notes(.:format) notes#create -# project_note DELETE /:project_id/notes/:id(.:format) notes#destroy -describe Projects::NotesController, 'routing' do - it_behaves_like 'RESTful project resources' do - let(:actions) { [:index, :create, :destroy] } - let(:controller) { 'notes' } - end -end - -# project_blame GET /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/} -describe Projects::BlameController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/blame/master/app/models/project.rb')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') - expect(get('/gitlab/gitlabhq/blame/master/files.scss')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') - end -end - -# project_blob GET /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/} -describe Projects::BlobController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') - expect(get('/gitlab/gitlabhq/blob/master/app/models/compare.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/compare.rb') - expect(get('/gitlab/gitlabhq/blob/master/app/models/diff.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/diff.js') - expect(get('/gitlab/gitlabhq/blob/master/files.scss')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') - end -end - -# project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/} -describe Projects::TreeController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') - expect(get('/gitlab/gitlabhq/tree/master/files.scss')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') - end -end - -# project_find_file GET /:namespace_id/:project_id/find_file/*id(.:format) projects/find_file#show {:id=>/.+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?/html/} -# project_files GET /:namespace_id/:project_id/files/*id(.:format) projects/find_file#list {:id=>/(?:[^.]|\.(?!json$))+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?/json/} -describe Projects::FindFileController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/find_file/master')).to route_to('projects/find_file#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') - end - - it 'to #list' do - expect(get('/gitlab/gitlabhq/files/master.json')).to route_to('projects/find_file#list', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') - end -end - -describe Projects::BlobController, 'routing' do - it 'to #edit' do - expect(get('/gitlab/gitlabhq/edit/master/app/models/project.rb')).to( - route_to('projects/blob#edit', - namespace_id: 'gitlab', project_id: 'gitlabhq', - id: 'master/app/models/project.rb')) - end - - it 'to #preview' do - expect(post('/gitlab/gitlabhq/preview/master/app/models/project.rb')).to( - route_to('projects/blob#preview', - namespace_id: 'gitlab', project_id: 'gitlabhq', - id: 'master/app/models/project.rb')) - end -end - -# project_compare_index GET /:project_id/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/} -# POST /:project_id/compare(.:format) compare#create {id: /[^\/]+/, project_id: /[^\/]+/} -# project_compare /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/} -describe Projects::CompareController, 'routing' do - it 'to #index' do - expect(get('/gitlab/gitlabhq/compare')).to route_to('projects/compare#index', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #compare' do - expect(post('/gitlab/gitlabhq/compare')).to route_to('projects/compare#create', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #show' do - expect(get('/gitlab/gitlabhq/compare/master...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'master', to: 'stable') - expect(get('/gitlab/gitlabhq/compare/issue/1234...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable') - end -end - -describe Projects::NetworkController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') - expect(get('/gitlab/gitlabhq/network/ends-with.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json') - expect(get('/gitlab/gitlabhq/network/master?format=json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') - end -end - -describe Projects::GraphsController, 'routing' do - it 'to #show' do - expect(get('/gitlab/gitlabhq/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') - expect(get('/gitlab/gitlabhq/graphs/ends-with.json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json') - expect(get('/gitlab/gitlabhq/graphs/master?format=json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') - end -end - -describe Projects::ForksController, 'routing' do - it 'to #new' do - expect(get('/gitlab/gitlabhq/forks/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq') - end - - it 'to #create' do - expect(post('/gitlab/gitlabhq/forks')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq') - end -end - -# project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy -describe Projects::AvatarsController, 'routing' do - it 'to #destroy' do - expect(delete('/gitlab/gitlabhq/avatar')).to route_to( - 'projects/avatars#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq') +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) + end + + # Shared examples for a resource inside a Project + # + # By default it tests all the default REST actions: index, create, new, edit, + # show, update, and destroy. You can remove actions by customizing the + # `actions` variable. + # + # It also expects a `controller` variable to be available which defines both + # the path to the resource as well as the controller name. + # + # Examples + # + # # Default behavior + # it_behaves_like 'RESTful project resources' do + # let(:controller) { 'issues' } + # end + # + # # Customizing actions + # it_behaves_like 'RESTful project resources' do + # let(:actions) { [:index] } + # let(:controller) { 'issues' } + # end + shared_examples 'RESTful project resources' do + let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] } + + it 'to #index' do + expect(get("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#index", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:index) + end + + it 'to #create' do + expect(post("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#create", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:create) + end + + it 'to #new' do + expect(get("/gitlab/gitlabhq/#{controller}/new")).to route_to("projects/#{controller}#new", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:new) + end + + it 'to #edit' do + expect(get("/gitlab/gitlabhq/#{controller}/1/edit")).to route_to("projects/#{controller}#edit", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:edit) + end + + it 'to #show' do + expect(get("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#show", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:show) + end + + it 'to #update' do + expect(put("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#update", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:update) + end + + it 'to #destroy' do + expect(delete("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#destroy", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:destroy) + end + end + + # projects POST /projects(.:format) projects#create + # new_project GET /projects/new(.:format) projects#new + # files_project GET /:id/files(.:format) projects#files + # edit_project GET /:id/edit(.:format) projects#edit + # project GET /:id(.:format) projects#show + # PUT /:id(.:format) projects#update + # DELETE /:id(.:format) projects#destroy + # preview_markdown_project POST /:id/preview_markdown(.:format) projects#preview_markdown + describe ProjectsController, 'routing' do + it 'to #create' do + expect(post('/projects')).to route_to('projects#create') + end + + it 'to #new' do + expect(get('/projects/new')).to route_to('projects#new') + end + + it 'to #edit' do + expect(get('/gitlab/gitlabhq/edit')).to route_to('projects#edit', namespace_id: 'gitlab', id: 'gitlabhq') + end + + it 'to #autocomplete_sources' do + expect(get('/gitlab/gitlabhq/autocomplete_sources')).to route_to('projects#autocomplete_sources', namespace_id: 'gitlab', id: 'gitlabhq') + end + + describe 'to #show' do + context 'regular name' do + it { expect(get('/gitlab/gitlabhq')).to route_to('projects#show', namespace_id: 'gitlab', id: 'gitlabhq') } + end + + context 'name with dot' do + before { allow(Project).to receive(:find_with_namespace).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) } + + it { expect(get('/gitlab/subgroup/gitlabhq')).to route_to('projects#show', namespace_id: 'gitlab/subgroup', id: 'gitlabhq') } + end + end + + it 'to #update' do + expect(put('/gitlab/gitlabhq')).to route_to('projects#update', namespace_id: 'gitlab', id: 'gitlabhq') + end + + it 'to #destroy' do + expect(delete('/gitlab/gitlabhq')).to route_to('projects#destroy', namespace_id: 'gitlab', id: 'gitlabhq') + end + + it 'to #preview_markdown' do + expect(post('/gitlab/gitlabhq/preview_markdown')).to( + route_to('projects#preview_markdown', namespace_id: 'gitlab', id: 'gitlabhq') + ) + end + end + + # pages_project_wikis GET /:project_id/wikis/pages(.:format) projects/wikis#pages + # history_project_wiki GET /:project_id/wikis/:id/history(.:format) projects/wikis#history + # project_wikis POST /:project_id/wikis(.:format) projects/wikis#create + # edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) projects/wikis#edit + # project_wiki GET /:project_id/wikis/:id(.:format) projects/wikis#show + # DELETE /:project_id/wikis/:id(.:format) projects/wikis#destroy + describe Projects::WikisController, 'routing' do + it 'to #pages' do + expect(get('/gitlab/gitlabhq/wikis/pages')).to route_to('projects/wikis#pages', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #history' do + expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it_behaves_like 'RESTful project resources' do + let(:actions) { [:create, :edit, :show, :destroy] } + let(:controller) { 'wikis' } + end + end + + # branches_project_repository GET /:project_id/repository/branches(.:format) projects/repositories#branches + # tags_project_repository GET /:project_id/repository/tags(.:format) projects/repositories#tags + # archive_project_repository GET /:project_id/repository/archive(.:format) projects/repositories#archive + # edit_project_repository GET /:project_id/repository/edit(.:format) projects/repositories#edit + describe Projects::RepositoriesController, 'routing' do + it 'to #archive' do + expect(get('/gitlab/gitlabhq/repository/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #archive format:zip' do + expect(get('/gitlab/gitlabhq/repository/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip') + end + + it 'to #archive format:tar.bz2' do + expect(get('/gitlab/gitlabhq/repository/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2') + end + end + + describe Projects::BranchesController, 'routing' do + it 'to #branches' do + expect(get('/gitlab/gitlabhq/branches')).to route_to('projects/branches#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + expect(delete('/gitlab/gitlabhq/branches/feature%2345')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') + expect(delete('/gitlab/gitlabhq/branches/feature%2B45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') + expect(delete('/gitlab/gitlabhq/branches/feature@45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') + expect(delete('/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/branches/feature@45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz') + end + end + + describe Projects::TagsController, 'routing' do + it 'to #tags' do + expect(get('/gitlab/gitlabhq/tags')).to route_to('projects/tags#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + expect(delete('/gitlab/gitlabhq/tags/feature%2345')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') + expect(delete('/gitlab/gitlabhq/tags/feature%2B45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') + expect(delete('/gitlab/gitlabhq/tags/feature@45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') + expect(delete('/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz') + end + end + + # project_deploy_keys GET /:project_id/deploy_keys(.:format) deploy_keys#index + # POST /:project_id/deploy_keys(.:format) deploy_keys#create + # new_project_deploy_key GET /:project_id/deploy_keys/new(.:format) deploy_keys#new + # project_deploy_key GET /:project_id/deploy_keys/:id(.:format) deploy_keys#show + # DELETE /:project_id/deploy_keys/:id(.:format) deploy_keys#destroy + describe Projects::DeployKeysController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:actions) { [:index, :new, :create] } + let(:controller) { 'deploy_keys' } + end + end + + # project_protected_branches GET /:project_id/protected_branches(.:format) protected_branches#index + # POST /:project_id/protected_branches(.:format) protected_branches#create + # project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy + describe Projects::ProtectedBranchesController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:actions) { [:index, :create, :destroy] } + let(:controller) { 'protected_branches' } + end + end + + # switch_project_refs GET /:project_id/refs/switch(.:format) refs#switch + # logs_tree_project_ref GET /:project_id/refs/:id/logs_tree(.:format) refs#logs_tree + # logs_file_project_ref GET /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree + describe Projects::RefsController, 'routing' do + it 'to #switch' do + expect(get('/gitlab/gitlabhq/refs/switch')).to route_to('projects/refs#switch', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #logs_tree' do + expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable') + expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') + expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') + expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') + expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/files.scss')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'files.scss') + end + end + + # diffs_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/diffs(.:format) projects/merge_requests#diffs + # commits_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/commits(.:format) projects/merge_requests#commits + # merge_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/merge(.:format) projects/merge_requests#merge + # merge_check_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/merge_check(.:format) projects/merge_requests#merge_check + # ci_status_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/ci_status(.:format) projects/merge_requests#ci_status + # toggle_subscription_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/toggle_subscription(.:format) projects/merge_requests#toggle_subscription + # branch_from_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/branch_from(.:format) projects/merge_requests#branch_from + # branch_to_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/branch_to(.:format) projects/merge_requests#branch_to + # update_branches_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/update_branches(.:format) projects/merge_requests#update_branches + # namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests(.:format) projects/merge_requests#index + # POST /:namespace_id/:project_id/merge_requests(.:format) projects/merge_requests#create + # new_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/new(.:format) projects/merge_requests#new + # edit_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/edit(.:format) projects/merge_requests#edit + # namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id(.:format) projects/merge_requests#show + # PATCH /:namespace_id/:project_id/merge_requests/:id(.:format) projects/merge_requests#update + # PUT /:namespace_id/:project_id/merge_requests/:id(.:format) projects/merge_requests#update + describe Projects::MergeRequestsController, 'routing' do + it 'to #diffs' do + expect(get('/gitlab/gitlabhq/merge_requests/1/diffs')).to route_to('projects/merge_requests#diffs', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #commits' do + expect(get('/gitlab/gitlabhq/merge_requests/1/commits')).to route_to('projects/merge_requests#commits', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #merge' do + expect(post('/gitlab/gitlabhq/merge_requests/1/merge')).to route_to( + 'projects/merge_requests#merge', + namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1' + ) + end + + it 'to #merge_check' do + expect(get('/gitlab/gitlabhq/merge_requests/1/merge_check')).to route_to('projects/merge_requests#merge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #branch_from' do + expect(get('/gitlab/gitlabhq/merge_requests/branch_from')).to route_to('projects/merge_requests#branch_from', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #branch_to' do + expect(get('/gitlab/gitlabhq/merge_requests/branch_to')).to route_to('projects/merge_requests#branch_to', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #show' do + expect(get('/gitlab/gitlabhq/merge_requests/1.diff')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'diff') + expect(get('/gitlab/gitlabhq/merge_requests/1.patch')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'patch') + end + + it_behaves_like 'RESTful project resources' do + let(:controller) { 'merge_requests' } + let(:actions) { [:index, :create, :new, :edit, :show, :update] } + end + end + + # raw_project_snippet GET /:project_id/snippets/:id/raw(.:format) snippets#raw + # project_snippets GET /:project_id/snippets(.:format) snippets#index + # POST /:project_id/snippets(.:format) snippets#create + # new_project_snippet GET /:project_id/snippets/new(.:format) snippets#new + # edit_project_snippet GET /:project_id/snippets/:id/edit(.:format) snippets#edit + # project_snippet GET /:project_id/snippets/:id(.:format) snippets#show + # PUT /:project_id/snippets/:id(.:format) snippets#update + # DELETE /:project_id/snippets/:id(.:format) snippets#destroy + describe SnippetsController, 'routing' do + it 'to #raw' do + expect(get('/gitlab/gitlabhq/snippets/1/raw')).to route_to('projects/snippets#raw', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #index' do + expect(get('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #create' do + expect(post('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#create', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #new' do + expect(get('/gitlab/gitlabhq/snippets/new')).to route_to('projects/snippets#new', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #edit' do + expect(get('/gitlab/gitlabhq/snippets/1/edit')).to route_to('projects/snippets#edit', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #show' do + expect(get('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #update' do + expect(put('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#update', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it 'to #destroy' do + expect(delete('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + end + + # test_project_hook GET /:project_id/hooks/:id/test(.:format) hooks#test + # project_hooks GET /:project_id/hooks(.:format) hooks#index + # POST /:project_id/hooks(.:format) hooks#create + # project_hook DELETE /:project_id/hooks/:id(.:format) hooks#destroy + describe Projects::HooksController, 'routing' do + it 'to #test' do + expect(get('/gitlab/gitlabhq/hooks/1/test')).to route_to('projects/hooks#test', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + end + + it_behaves_like 'RESTful project resources' do + let(:actions) { [:index, :create, :destroy] } + let(:controller) { 'hooks' } + end + end + + # project_commit GET /:project_id/commit/:id(.:format) commit#show {id: /\h{7,40}/, project_id: /[^\/]+/} + describe Projects::CommitController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/commit/4246fbd')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd') + expect(get('/gitlab/gitlabhq/commit/4246fbd.diff')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd', format: 'diff') + expect(get('/gitlab/gitlabhq/commit/4246fbd.patch')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd', format: 'patch') + expect(get('/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5') + end + end + + # patch_project_commit GET /:project_id/commits/:id/patch(.:format) commits#patch + # project_commits GET /:project_id/commits(.:format) commits#index + # POST /:project_id/commits(.:format) commits#create + # project_commit GET /:project_id/commits/:id(.:format) commits#show + describe Projects::CommitsController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:actions) { [:show] } + let(:controller) { 'commits' } + end + + it 'to #show' do + expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom') + end + end + + # project_project_members GET /:project_id/project_members(.:format) project_members#index + # POST /:project_id/project_members(.:format) project_members#create + # PUT /:project_id/project_members/:id(.:format) project_members#update + # DELETE /:project_id/project_members/:id(.:format) project_members#destroy + describe Projects::ProjectMembersController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:actions) { [:index, :create, :update, :destroy] } + let(:controller) { 'project_members' } + end + end + + # project_milestones GET /:project_id/milestones(.:format) milestones#index + # POST /:project_id/milestones(.:format) milestones#create + # new_project_milestone GET /:project_id/milestones/new(.:format) milestones#new + # edit_project_milestone GET /:project_id/milestones/:id/edit(.:format) milestones#edit + # project_milestone GET /:project_id/milestones/:id(.:format) milestones#show + # PUT /:project_id/milestones/:id(.:format) milestones#update + # DELETE /:project_id/milestones/:id(.:format) milestones#destroy + describe Projects::MilestonesController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:controller) { 'milestones' } + let(:actions) { [:index, :create, :new, :edit, :show, :update] } + end + end + + # project_labels GET /:project_id/labels(.:format) labels#index + describe Projects::LabelsController, 'routing' do + it 'to #index' do + expect(get('/gitlab/gitlabhq/labels')).to route_to('projects/labels#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + end + + # sort_project_issues POST /:project_id/issues/sort(.:format) issues#sort + # bulk_update_project_issues POST /:project_id/issues/bulk_update(.:format) issues#bulk_update + # search_project_issues GET /:project_id/issues/search(.:format) issues#search + # project_issues GET /:project_id/issues(.:format) issues#index + # POST /:project_id/issues(.:format) issues#create + # new_project_issue GET /:project_id/issues/new(.:format) issues#new + # edit_project_issue GET /:project_id/issues/:id/edit(.:format) issues#edit + # project_issue GET /:project_id/issues/:id(.:format) issues#show + # PUT /:project_id/issues/:id(.:format) issues#update + # DELETE /:project_id/issues/:id(.:format) issues#destroy + describe Projects::IssuesController, 'routing' do + it 'to #bulk_update' do + expect(post('/gitlab/gitlabhq/issues/bulk_update')).to route_to('projects/issues#bulk_update', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it_behaves_like 'RESTful project resources' do + let(:controller) { 'issues' } + let(:actions) { [:index, :create, :new, :edit, :show, :update] } + end + end + + # project_notes GET /:project_id/notes(.:format) notes#index + # POST /:project_id/notes(.:format) notes#create + # project_note DELETE /:project_id/notes/:id(.:format) notes#destroy + describe Projects::NotesController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:actions) { [:index, :create, :destroy] } + let(:controller) { 'notes' } + end + end + + # project_blame GET /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/} + describe Projects::BlameController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/blame/master/app/models/project.rb')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + expect(get('/gitlab/gitlabhq/blame/master/files.scss')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') + end + end + + # project_blob GET /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/} + describe Projects::BlobController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + expect(get('/gitlab/gitlabhq/blob/master/app/models/compare.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/compare.rb') + expect(get('/gitlab/gitlabhq/blob/master/app/models/diff.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/diff.js') + expect(get('/gitlab/gitlabhq/blob/master/files.scss')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') + end + end + + # project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/} + describe Projects::TreeController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + expect(get('/gitlab/gitlabhq/tree/master/files.scss')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') + end + end + + # project_find_file GET /:namespace_id/:project_id/find_file/*id(.:format) projects/find_file#show {:id=>/.+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?/html/} + # project_files GET /:namespace_id/:project_id/files/*id(.:format) projects/find_file#list {:id=>/(?:[^.]|\.(?!json$))+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?/json/} + describe Projects::FindFileController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/find_file/master')).to route_to('projects/find_file#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') + end + + it 'to #list' do + expect(get('/gitlab/gitlabhq/files/master.json')).to route_to('projects/find_file#list', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') + end + end + + describe Projects::BlobController, 'routing' do + it 'to #edit' do + expect(get('/gitlab/gitlabhq/edit/master/app/models/project.rb')).to( + route_to('projects/blob#edit', + namespace_id: 'gitlab', project_id: 'gitlabhq', + id: 'master/app/models/project.rb')) + end + + it 'to #preview' do + expect(post('/gitlab/gitlabhq/preview/master/app/models/project.rb')).to( + route_to('projects/blob#preview', + namespace_id: 'gitlab', project_id: 'gitlabhq', + id: 'master/app/models/project.rb')) + end + end + + # project_compare_index GET /:project_id/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/} + # POST /:project_id/compare(.:format) compare#create {id: /[^\/]+/, project_id: /[^\/]+/} + # project_compare /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/} + describe Projects::CompareController, 'routing' do + it 'to #index' do + expect(get('/gitlab/gitlabhq/compare')).to route_to('projects/compare#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #compare' do + expect(post('/gitlab/gitlabhq/compare')).to route_to('projects/compare#create', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #show' do + expect(get('/gitlab/gitlabhq/compare/master...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'master', to: 'stable') + expect(get('/gitlab/gitlabhq/compare/issue/1234...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable') + end + end + + describe Projects::NetworkController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') + expect(get('/gitlab/gitlabhq/network/ends-with.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json') + expect(get('/gitlab/gitlabhq/network/master?format=json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') + end + end + + describe Projects::GraphsController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') + expect(get('/gitlab/gitlabhq/graphs/ends-with.json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'ends-with.json') + expect(get('/gitlab/gitlabhq/graphs/master?format=json')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') + end + end + + describe Projects::ForksController, 'routing' do + it 'to #new' do + expect(get('/gitlab/gitlabhq/forks/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #create' do + expect(post('/gitlab/gitlabhq/forks')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + end + + # project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy + describe Projects::AvatarsController, 'routing' do + it 'to #destroy' do + expect(delete('/gitlab/gitlabhq/avatar')).to route_to( + 'projects/avatars#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq') + end end end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index f15c45cbaac..9f6defe1450 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -9,7 +9,7 @@ require 'spec_helper' # user_calendar_activities GET /u/:username/calendar_activities(.:format) describe UsersController, "routing" do it "to #show" do - allow(User).to receive(:find_by).and_return(true) + allow_any_instance_of(UserUrlConstrainer).to receive(:matches?).and_return(true) expect(get("/User")).to route_to('users#show', username: 'User') end @@ -195,6 +195,8 @@ describe Profiles::KeysController, "routing" do # get all the ssh-keys of a user it "to #get_keys" do + allow_any_instance_of(UserUrlConstrainer).to receive(:matches?).and_return(true) + expect(get("/foo.keys")).to route_to('profiles/keys#get_keys', username: 'foo') end end @@ -263,13 +265,17 @@ end describe "Groups", "routing" do let(:name) { 'complex.group-namegit' } + before { allow_any_instance_of(GroupUrlConstrainer).to receive(:matches?).and_return(true) } + it "to #show" do expect(get("/groups/#{name}")).to route_to('groups#show', id: name) end - it "also display group#show on the short path" do - allow(Group).to receive(:find_by).and_return(true) + it "also supports nested groups" do + expect(get("/#{name}/#{name}")).to route_to('groups#show', id: "#{name}/#{name}") + end + it "also display group#show on the short path" do expect(get("/#{name}")).to route_to('groups#show', id: name) end @@ -284,6 +290,10 @@ describe "Groups", "routing" do it "to #members" do expect(get("/groups/#{name}/group_members")).to route_to('groups/group_members#index', group_id: name) end + + it "also display group#show with slash in the path" do + expect(get('/group/subgroup')).to route_to('groups#show', id: 'group/subgroup') + end end describe HealthCheckController, 'routing' do -- cgit v1.2.1 From 5636825fd0bd8b11ab9d85350246cdcc0fb28afe Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Tue, 22 Nov 2016 14:32:48 +0500 Subject: Move abuse report spinach test to rspec part of https://gitlab.com/gitlab-org/gitlab-ce/issues/23036 --- spec/features/abuse_report_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 spec/features/abuse_report_spec.rb (limited to 'spec') diff --git a/spec/features/abuse_report_spec.rb b/spec/features/abuse_report_spec.rb new file mode 100644 index 00000000000..1e11fb756b2 --- /dev/null +++ b/spec/features/abuse_report_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +feature 'Abuse reports', feature: true do + let(:another_user) { create(:user) } + + before do + login_as :user + end + + scenario 'Report abuse' do + visit user_path(another_user) + + click_link 'Report abuse' + + fill_in 'abuse_report_message', with: 'This user send spam' + click_button 'Send report' + + expect(page).to have_content 'Thank you for your report' + + visit user_path(another_user) + + expect(page).to have_button("Already reported for abuse") + end +end -- cgit v1.2.1 From 73f6218ec4f3cf9e403880990565673b730666d9 Mon Sep 17 00:00:00 2001 From: Semyon Pupkov Date: Wed, 23 Nov 2016 10:57:12 +0500 Subject: Move admin abuse report spinach test to rspec https://gitlab.com/gitlab-org/gitlab-ce/issues/23036 --- spec/features/admin/admin_abuse_reports_spec.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'spec') diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb index c1731e6414a..7fcfe5a54c7 100644 --- a/spec/features/admin/admin_abuse_reports_spec.rb +++ b/spec/features/admin/admin_abuse_reports_spec.rb @@ -4,17 +4,21 @@ describe "Admin::AbuseReports", feature: true, js: true do let(:user) { create(:user) } context 'as an admin' do + before do + login_as :admin + end + describe 'if a user has been reported for abuse' do - before do - create(:abuse_report, user: user) - login_as :admin - end + let!(:abuse_report) { create(:abuse_report, user: user) } describe 'in the abuse report view' do - it "presents a link to the user's profile" do + it 'presents information about abuse report' do visit admin_abuse_reports_path - expect(page).to have_link user.name, href: user_path(user) + expect(page).to have_content('Abuse Reports') + expect(page).to have_content(abuse_report.message) + expect(page).to have_link(user.name, href: user_path(user)) + expect(page).to have_link('Remove user') end end -- cgit v1.2.1 From 9ad2dba250e3facc18ff2f21217ebe006451dd8c Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 24 Nov 2016 02:33:55 +0800 Subject: Use Commit#author so we share logic and cache Closes #24900 --- spec/lib/gitlab/identifier_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/identifier_spec.rb b/spec/lib/gitlab/identifier_spec.rb index f42c4453dd1..bb758a8a202 100644 --- a/spec/lib/gitlab/identifier_spec.rb +++ b/spec/lib/gitlab/identifier_spec.rb @@ -40,7 +40,7 @@ describe Gitlab::Identifier do describe '#identify_using_commit' do it "returns the User for an existing commit author's Email address" do - commit = double(:commit, author_email: user.email) + commit = double(:commit, author: user, author_email: user.email) expect(project).to receive(:commit).with('123').and_return(commit) @@ -62,10 +62,9 @@ describe Gitlab::Identifier do end it 'caches the found users per Email' do - commit = double(:commit, author_email: user.email) + commit = double(:commit, author: user, author_email: user.email) expect(project).to receive(:commit).with('123').twice.and_return(commit) - expect(User).to receive(:find_by_any_email).once.and_call_original 2.times do expect(identifier.identify_using_commit(project, '123')).to eq(user) -- cgit v1.2.1 From 8434a642f19798f8ed8ce283af6a1006920bef30 Mon Sep 17 00:00:00 2001 From: vrod Date: Sat, 19 Nov 2016 15:58:31 -0200 Subject: Simplify copy on "Create a new list" dropdown in Issue Boards --- spec/features/boards/boards_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 4aa84fb65d9..973d5b286e9 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -158,7 +158,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'removes checkmark in new list dropdown after deleting' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within(find('.board:nth-child(2)')) do @@ -304,7 +304,7 @@ describe 'Issue Boards', feature: true, js: true do context 'new list' do it 'shows all labels in new list dropdown' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within('.dropdown-menu-issues-board-new') do @@ -315,7 +315,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'creates new list for label' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within('.dropdown-menu-issues-board-new') do @@ -328,7 +328,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'creates new list for Backlog label' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within('.dropdown-menu-issues-board-new') do @@ -341,7 +341,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'creates new list for Done label' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within('.dropdown-menu-issues-board-new') do @@ -354,7 +354,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'keeps dropdown open after adding new list' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within('.dropdown-menu-issues-board-new') do @@ -369,7 +369,7 @@ describe 'Issue Boards', feature: true, js: true do it 'moves issues from backlog into new list' do wait_for_board_cards(1, 6) - click_button 'Create new list' + click_button 'Add list' wait_for_ajax page.within('.dropdown-menu-issues-board-new') do @@ -382,7 +382,7 @@ describe 'Issue Boards', feature: true, js: true do end it 'creates new list from a new label' do - click_button 'Create new list' + click_button 'Add list' wait_for_ajax -- cgit v1.2.1 From 7a9b545fb9c443cef1a3bb6394223e6bbe0cef9a Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Wed, 23 Nov 2016 13:32:38 -0600 Subject: Added test that checks the correct select box is there for the LFS enabled setting. --- spec/views/projects/edit.html.haml_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 spec/views/projects/edit.html.haml_spec.rb (limited to 'spec') diff --git a/spec/views/projects/edit.html.haml_spec.rb b/spec/views/projects/edit.html.haml_spec.rb new file mode 100644 index 00000000000..d2575702ecc --- /dev/null +++ b/spec/views/projects/edit.html.haml_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'projects/edit' do + include Devise::Test::ControllerHelpers + + let(:project) { create(:empty_project) } + let(:user) { create(:admin) } + + before do + assign(:project, project) + + allow(controller).to receive(:current_user).and_return(user) + allow(view).to receive_messages(current_user: user, can?: true) + allow(Gitlab.config.lfs).to receive(:enabled).and_return(true) + end + + context 'LFS enabled setting' do + it 'displays the correct elements' do + render + expect(rendered).to have_select('project_lfs_enabled') + expect(rendered).to have_content('Git Large File Storage') + end + end +end -- cgit v1.2.1