summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorMatija Čupić <matteeyah@gmail.com>2017-12-21 02:34:35 +0100
committerMatija Čupić <matteeyah@gmail.com>2017-12-21 02:34:35 +0100
commit8c449310e245083e72513ec3addd0d2355333127 (patch)
treea9ca028f0f19cab55e9d3d8afeffd58cc85bf192 /spec
parent52b4a74a73cbd0b13d46d0bcd9b063e36b520f05 (diff)
parent5d8d72f18e9329978987fcb046467ceacd13c3ab (diff)
downloadgitlab-ce-refactor-cluster-show-page.tar.gz
Merge branch 'master' into refactor-cluster-show-pagerefactor-cluster-show-page
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb10
-rw-r--r--spec/controllers/projects/pipeline_schedules_controller_spec.rb67
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb13
-rw-r--r--spec/features/calendar_spec.rb2
-rw-r--r--spec/features/help_pages_spec.rb18
-rw-r--r--spec/features/issues/issue_detail_spec.rb2
-rw-r--r--spec/features/issues_spec.rb1006
-rw-r--r--spec/features/merge_requests/image_diff_notes_spec.rb (renamed from spec/features/merge_requests/image_diff_notes.rb)45
-rw-r--r--spec/features/merge_requests/mini_pipeline_graph_spec.rb8
-rw-r--r--spec/features/milestone_spec.rb4
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb8
-rw-r--r--spec/features/projects/issuable_templates_spec.rb8
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb4
-rw-r--r--spec/features/tags/master_views_tags_spec.rb5
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_widget.json (renamed from spec/fixtures/api/schemas/entities/merge_request.json)8
-rw-r--r--spec/helpers/notes_helper_spec.rb14
-rw-r--r--spec/javascripts/collapsed_sidebar_todo_spec.js3
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_graph_spec.js12
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_spec.js26
-rw-r--r--spec/javascripts/helpers/locale_helper.js11
-rw-r--r--spec/javascripts/lib/utils/tick_formats_spec.js40
-rw-r--r--spec/javascripts/line_highlighter_spec.js3
-rw-r--r--spec/javascripts/locale/index_spec.js35
-rw-r--r--spec/javascripts/merge_request_notes_spec.js4
-rw-r--r--spec/javascripts/merge_request_spec.js3
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js19
-rw-r--r--spec/javascripts/notes_spec.js4
-rw-r--r--spec/javascripts/right_sidebar_spec.js3
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js28
-rw-r--r--spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js13
-rw-r--r--spec/lib/gitlab/action_rate_limiter_spec.rb29
-rw-r--r--spec/lib/gitlab/git/gitlab_projects_spec.rb6
-rw-r--r--spec/lib/gitlab/github_import/importer/repository_importer_spec.rb8
-rw-r--r--spec/models/blob_viewer/package_json_spec.rb47
-rw-r--r--spec/models/ci/pipeline_spec.rb12
-rw-r--r--spec/models/commit_spec.rb39
-rw-r--r--spec/models/concerns/blocks_json_serialization_spec.rb17
-rw-r--r--spec/models/concerns/issuable_spec.rb4
-rw-r--r--spec/models/concerns/milestoneish_spec.rb4
-rw-r--r--spec/models/project_services/jira_service_spec.rb20
-rw-r--r--spec/models/project_spec.rb5
-rw-r--r--spec/models/repository_spec.rb74
-rw-r--r--spec/models/user_spec.rb1
-rw-r--r--spec/policies/ci/pipeline_schedule_policy_spec.rb92
-rw-r--r--spec/requests/api/merge_requests_spec.rb20
-rw-r--r--spec/serializers/merge_request_serializer_spec.rb48
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb (renamed from spec/serializers/merge_request_entity_spec.rb)41
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb6
-rw-r--r--spec/services/issuable/destroy_service_spec.rb16
-rw-r--r--spec/services/notes/destroy_service_spec.rb16
-rw-r--r--spec/services/projects/unlink_fork_service_spec.rb20
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb8
-rw-r--r--spec/services/system_note_service_spec.rb4
-rw-r--r--spec/services/todo_service_spec.rb23
-rw-r--r--spec/support/api/time_tracking_shared_examples.rb6
-rw-r--r--spec/support/api/v3/time_tracking_shared_examples.rb6
-rw-r--r--spec/views/events/event/_push.html.haml_spec.rb55
-rw-r--r--spec/workers/concerns/project_import_options_spec.rb40
-rw-r--r--spec/workers/repository_fork_worker_spec.rb29
-rw-r--r--spec/workers/repository_import_worker_spec.rb23
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb39
62 files changed, 1460 insertions, 726 deletions
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index c5d08cb0b9d..a2ef937609b 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -874,7 +874,7 @@ describe Projects::IssuesController do
end
it 'delegates the update of the todos count cache to TodoService' do
- expect_any_instance_of(TodoService).to receive(:destroy_issuable).with(issue, owner).once
+ expect_any_instance_of(TodoService).to receive(:destroy_target).with(issue).once
delete :destroy, namespace_id: project.namespace, project_id: project, id: issue.iid
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 51d5d6a52b3..58116e6e0fe 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -91,11 +91,11 @@ describe Projects::MergeRequestsController do
end
end
- context 'without basic serializer param' do
- it 'renders the merge request in the json format' do
- go(format: :json)
+ context 'with widget serializer param' do
+ it 'renders widget MR entity as json' do
+ go(serializer: 'widget', format: :json)
- expect(response).to match_response_schema('entities/merge_request')
+ expect(response).to match_response_schema('entities/merge_request_widget')
end
end
end
@@ -468,7 +468,7 @@ describe Projects::MergeRequestsController do
end
it 'delegates the update of the todos count cache to TodoService' do
- expect_any_instance_of(TodoService).to receive(:destroy_issuable).with(merge_request, owner).once
+ expect_any_instance_of(TodoService).to receive(:destroy_target).with(merge_request).once
delete :destroy, namespace_id: project.namespace, project_id: project, id: merge_request.iid
end
diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
index 4e52e261920..966ffdf6996 100644
--- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb
+++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
@@ -3,10 +3,12 @@ require 'spec_helper'
describe Projects::PipelineSchedulesController do
include AccessMatchersForController
- set(:project) { create(:project, :public) }
- let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
+ set(:project) { create(:project, :public, :repository) }
+ set(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
describe 'GET #index' do
+ render_views
+
let(:scope) { nil }
let!(:inactive_pipeline_schedule) do
create(:ci_pipeline_schedule, :inactive, project: project)
@@ -96,7 +98,7 @@ describe Projects::PipelineSchedulesController do
end
end
- context 'when variables_attributes has two variables and duplicted' do
+ context 'when variables_attributes has two variables and duplicated' do
let(:schedule) do
basic_param.merge({
variables_attributes: [{ key: 'AAA', value: 'AAA123' }, { key: 'AAA', value: 'BBB123' }]
@@ -364,6 +366,65 @@ describe Projects::PipelineSchedulesController do
end
end
+ describe 'POST #play', :clean_gitlab_redis_cache do
+ set(:user) { create(:user) }
+ let(:ref) { 'master' }
+
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+ end
+
+ context 'when an anonymous user makes the request' do
+ before do
+ sign_out(user)
+ end
+
+ it 'does not allow pipeline to be executed' do
+ expect(RunPipelineScheduleWorker).not_to receive(:perform_async)
+
+ post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when a developer makes the request' do
+ it 'executes a new pipeline' do
+ expect(RunPipelineScheduleWorker).to receive(:perform_async).with(pipeline_schedule.id, user.id).and_return('job-123')
+
+ post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
+
+ expect(flash[:notice]).to start_with 'Successfully scheduled a pipeline to run'
+ expect(response).to have_gitlab_http_status(302)
+ end
+
+ it 'prevents users from scheduling the same pipeline repeatedly' do
+ 2.times do
+ post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
+ end
+
+ expect(flash.to_a.size).to eq(2)
+ expect(flash[:alert]).to eq 'You cannot play this scheduled pipeline at the moment. Please wait a minute.'
+ expect(response).to have_gitlab_http_status(302)
+ end
+ end
+
+ context 'when a developer attempts to schedule a protected ref' do
+ it 'does not allow pipeline to be executed' do
+ create(:protected_branch, project: project, name: ref)
+ protected_schedule = create(:ci_pipeline_schedule, project: project, ref: ref)
+
+ expect(RunPipelineScheduleWorker).not_to receive(:perform_async)
+
+ post :play, namespace_id: project.namespace.to_param, project_id: project, id: protected_schedule.id
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
describe 'DELETE #destroy' do
set(:user) { create(:user) }
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 1604a2da485..35ac999cc65 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -17,13 +17,10 @@ describe Projects::PipelinesController do
describe 'GET index.json' do
before do
- branch_head = project.commit
- parent = branch_head.parent
-
- create(:ci_empty_pipeline, status: 'pending', project: project, sha: branch_head.id)
- create(:ci_empty_pipeline, status: 'running', project: project, sha: branch_head.id)
- create(:ci_empty_pipeline, status: 'created', project: project, sha: parent.id)
- create(:ci_empty_pipeline, status: 'success', project: project, sha: parent.id)
+ %w(pending running created success).each_with_index do |status, index|
+ sha = project.commit("HEAD~#{index}")
+ create(:ci_empty_pipeline, status: status, project: project, sha: sha)
+ end
end
subject do
@@ -46,7 +43,7 @@ describe Projects::PipelinesController do
context 'when performing gitaly calls', :request_store do
it 'limits the Gitaly requests' do
- expect { subject }.to change { Gitlab::GitalyClient.get_request_count }.by(8)
+ expect { subject }.to change { Gitlab::GitalyClient.get_request_count }.by(3)
end
end
end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index a9530becb65..70faf28e09d 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -12,7 +12,7 @@ feature 'Contributions Calendar', :js do
issue_params = { title: issue_title }
def get_cell_color_selector(contributions)
- activity_colors = %w[#ededed #acd5f2 #7fa8c9 #527ba0 #254e77]
+ activity_colors = ["#ededed", "rgb(172, 213, 242)", "rgb(127, 168, 201)", "rgb(82, 123, 160)", "rgb(37, 78, 119)"]
# We currently don't actually test the cases with contributions >= 20
activity_colors_index =
if contributions > 0 && contributions < 10
diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb
index ab896a310be..0d04ed612c2 100644
--- a/spec/features/help_pages_spec.rb
+++ b/spec/features/help_pages_spec.rb
@@ -32,6 +32,24 @@ describe 'Help Pages' do
it_behaves_like 'help page', prefix: '/gitlab'
end
+
+ context 'quick link shortcuts', :js do
+ before do
+ visit help_path
+ end
+
+ it 'focuses search bar' do
+ find('.js-trigger-search-bar').click
+
+ expect(page).to have_selector('#search:focus')
+ end
+
+ it 'opens shortcuts help dialog' do
+ find('.js-trigger-shortcut').click
+
+ expect(page).to have_selector('#modal-shortcuts')
+ end
+ end
end
context 'in a production environment with version check enabled', :js do
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index 4224a8fe5d4..babb0285590 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -24,7 +24,7 @@ feature 'Issue Detail', :js do
visit project_issue_path(project, issue)
wait_for_requests
- click_link 'Edit'
+ page.find('.js-issuable-edit').click
fill_in 'issuable-title', with: 'issue title'
click_button 'Save'
wait_for_requests
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 852d9e368aa..d1ff057a0c6 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -8,729 +8,753 @@ describe 'Issues' do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
- before do
- sign_in(user)
- user2 = create(:user)
-
- project.team << [[user, user2], :developer]
- end
+ describe 'while user is signed out' do
+ describe 'empty state' do
+ it 'user sees empty state' do
+ visit project_issues_path(project)
- describe 'Edit issue' do
- let!(:issue) do
- create(:issue,
- author: user,
- assignees: [user],
- project: project)
+ expect(page).to have_content('Register / Sign In')
+ expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project.')
+ expect(page).to have_content('You can register or sign in to create issues for this project.')
+ end
end
+ end
+ describe 'while user is signed in' do
before do
- visit edit_project_issue_path(project, issue)
- find('.js-zen-enter').click
- end
-
- it 'opens new issue popup' do
- expect(page).to have_content("Issue ##{issue.iid}")
- end
- end
+ sign_in(user)
+ user2 = create(:user)
- describe 'Editing issue assignee' do
- let!(:issue) do
- create(:issue,
- author: user,
- assignees: [user],
- project: project)
+ project.team << [[user, user2], :developer]
end
- it 'allows user to select unassigned', :js do
- visit edit_project_issue_path(project, issue)
-
- expect(page).to have_content "Assignee #{user.name}"
+ describe 'empty state' do
+ it 'user sees empty state' do
+ visit project_issues_path(project)
- first('.js-user-search').click
- click_link 'Unassigned'
+ expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project')
+ expect(page).to have_content('Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.')
+ expect(page).to have_content('New issue')
+ end
+ end
- click_button 'Save changes'
+ describe 'Edit issue' do
+ let!(:issue) do
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project)
+ end
- page.within('.assignee') do
- expect(page).to have_content 'No assignee - assign yourself'
+ before do
+ visit edit_project_issue_path(project, issue)
+ find('.js-zen-enter').click
end
- expect(issue.reload.assignees).to be_empty
+ it 'opens new issue popup' do
+ expect(page).to have_content("Issue ##{issue.iid}")
+ end
end
- end
- describe 'due date', :js do
- context 'on new form' do
- before do
- visit new_project_issue_path(project)
+ describe 'Editing issue assignee' do
+ let!(:issue) do
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project)
end
- it 'saves with due date' do
- date = Date.today.at_beginning_of_month
-
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
- find('#issuable-due-date').click
+ it 'allows user to select unassigned', :js do
+ visit edit_project_issue_path(project, issue)
- page.within '.pika-single' do
- click_button date.day
- end
+ expect(page).to have_content "Assignee #{user.name}"
- expect(find('#issuable-due-date').value).to eq date.to_s
+ first('.js-user-search').click
+ click_link 'Unassigned'
- click_button 'Submit issue'
+ click_button 'Save changes'
- page.within '.issuable-sidebar' do
- expect(page).to have_content date.to_s(:medium)
+ page.within('.assignee') do
+ expect(page).to have_content 'No assignee - assign yourself'
end
+
+ expect(issue.reload.assignees).to be_empty
end
end
- context 'on edit form' do
- let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) }
+ describe 'due date', :js do
+ context 'on new form' do
+ before do
+ visit new_project_issue_path(project)
+ end
- before do
- visit edit_project_issue_path(project, issue)
- end
+ it 'saves with due date' do
+ date = Date.today.at_beginning_of_month
- it 'saves with due date' do
- date = Date.today.at_beginning_of_month
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+ find('#issuable-due-date').click
- expect(find('#issuable-due-date').value).to eq date.to_s
+ page.within '.pika-single' do
+ click_button date.day
+ end
- date = date.tomorrow
+ expect(find('#issuable-due-date').value).to eq date.to_s
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
- find('#issuable-due-date').click
+ click_button 'Submit issue'
- page.within '.pika-single' do
- click_button date.day
+ page.within '.issuable-sidebar' do
+ expect(page).to have_content date.to_s(:medium)
+ end
end
+ end
- expect(find('#issuable-due-date').value).to eq date.to_s
+ context 'on edit form' do
+ let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) }
- click_button 'Save changes'
-
- page.within '.issuable-sidebar' do
- expect(page).to have_content date.to_s(:medium)
+ before do
+ visit edit_project_issue_path(project, issue)
end
- end
- it 'warns about version conflict' do
- issue.update(title: "New title")
+ it 'saves with due date' do
+ date = Date.today.at_beginning_of_month
- fill_in 'issue_title', with: 'bug 345'
- fill_in 'issue_description', with: 'bug description'
+ expect(find('#issuable-due-date').value).to eq date.to_s
- click_button 'Save changes'
+ date = date.tomorrow
- expect(page).to have_content 'Someone edited the issue the same time you did'
- end
- end
- end
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+ find('#issuable-due-date').click
+
+ page.within '.pika-single' do
+ click_button date.day
+ end
- describe 'Issue info' do
- it 'links to current issue in breadcrubs' do
- issue = create(:issue, project: project)
+ expect(find('#issuable-due-date').value).to eq date.to_s
- visit project_issue_path(project, issue)
+ click_button 'Save changes'
- expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue))
- end
+ page.within '.issuable-sidebar' do
+ expect(page).to have_content date.to_s(:medium)
+ end
+ end
- it 'excludes award_emoji from comment count' do
- issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar')
- create(:award_emoji, awardable: issue)
+ it 'warns about version conflict' do
+ issue.update(title: "New title")
- visit project_issues_path(project, assignee_id: user.id)
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
- expect(page).to have_content 'foobar'
- expect(page.all('.no-comments').first.text).to eq "0"
- end
- end
+ click_button 'Save changes'
- describe 'Filter issue' do
- before do
- %w(foobar barbaz gitlab).each do |title|
- create(:issue,
- author: user,
- assignees: [user],
- project: project,
- title: title)
+ expect(page).to have_content 'Someone edited the issue the same time you did'
+ end
end
-
- @issue = Issue.find_by(title: 'foobar')
- @issue.milestone = create(:milestone, project: project)
- @issue.assignees = []
- @issue.save
end
- let(:issue) { @issue }
+ describe 'Issue info' do
+ it 'links to current issue in breadcrubs' do
+ issue = create(:issue, project: project)
- it 'allows filtering by issues with no specified assignee' do
- visit project_issues_path(project, assignee_id: IssuableFinder::NONE)
+ visit project_issue_path(project, issue)
- expect(page).to have_content 'foobar'
- expect(page).not_to have_content 'barbaz'
- expect(page).not_to have_content 'gitlab'
- end
+ expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue))
+ end
- it 'allows filtering by a specified assignee' do
- visit project_issues_path(project, assignee_id: user.id)
+ it 'excludes award_emoji from comment count' do
+ issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar')
+ create(:award_emoji, awardable: issue)
- expect(page).not_to have_content 'foobar'
- expect(page).to have_content 'barbaz'
- expect(page).to have_content 'gitlab'
- end
- end
+ visit project_issues_path(project, assignee_id: user.id)
- describe 'filter issue' do
- titles = %w[foo bar baz]
- titles.each_with_index do |title, index|
- let!(title.to_sym) do
- create(:issue, title: title,
- project: project,
- created_at: Time.now - (index * 60))
+ expect(page).to have_content 'foobar'
+ expect(page.all('.no-comments').first.text).to eq "0"
end
end
- let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') }
- let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
- it 'sorts by newest' do
- visit project_issues_path(project, sort: sort_value_created_date)
+ describe 'Filter issue' do
+ before do
+ %w(foobar barbaz gitlab).each do |title|
+ create(:issue,
+ author: user,
+ assignees: [user],
+ project: project,
+ title: title)
+ end
- expect(first_issue).to include('foo')
- expect(last_issue).to include('baz')
- end
+ @issue = Issue.find_by(title: 'foobar')
+ @issue.milestone = create(:milestone, project: project)
+ @issue.assignees = []
+ @issue.save
+ end
- it 'sorts by most recently updated' do
- baz.updated_at = Time.now + 100
- baz.save
- visit project_issues_path(project, sort: sort_value_recently_updated)
+ let(:issue) { @issue }
- expect(first_issue).to include('baz')
- end
+ it 'allows filtering by issues with no specified assignee' do
+ visit project_issues_path(project, assignee_id: IssuableFinder::NONE)
- describe 'sorting by due date' do
- before do
- foo.update(due_date: 1.day.from_now)
- bar.update(due_date: 6.days.from_now)
+ expect(page).to have_content 'foobar'
+ expect(page).not_to have_content 'barbaz'
+ expect(page).not_to have_content 'gitlab'
end
- it 'sorts by due date' do
- visit project_issues_path(project, sort: sort_value_due_date)
+ it 'allows filtering by a specified assignee' do
+ visit project_issues_path(project, assignee_id: user.id)
- expect(first_issue).to include('foo')
+ expect(page).not_to have_content 'foobar'
+ expect(page).to have_content 'barbaz'
+ expect(page).to have_content 'gitlab'
end
+ end
- it 'sorts by due date by excluding nil due dates' do
- bar.update(due_date: nil)
+ describe 'filter issue' do
+ titles = %w[foo bar baz]
+ titles.each_with_index do |title, index|
+ let!(title.to_sym) do
+ create(:issue, title: title,
+ project: project,
+ created_at: Time.now - (index * 60))
+ end
+ end
+ let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') }
+ let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
- visit project_issues_path(project, sort: sort_value_due_date)
+ it 'sorts by newest' do
+ visit project_issues_path(project, sort: sort_value_created_date)
expect(first_issue).to include('foo')
+ expect(last_issue).to include('baz')
end
- context 'with a filter on labels' do
- let(:label) { create(:label, project: project) }
+ it 'sorts by most recently updated' do
+ baz.updated_at = Time.now + 100
+ baz.save
+ visit project_issues_path(project, sort: sort_value_recently_updated)
+ expect(first_issue).to include('baz')
+ end
+
+ describe 'sorting by due date' do
before do
- create(:label_link, label: label, target: foo)
+ foo.update(due_date: 1.day.from_now)
+ bar.update(due_date: 6.days.from_now)
+ end
+
+ it 'sorts by due date' do
+ visit project_issues_path(project, sort: sort_value_due_date)
+
+ expect(first_issue).to include('foo')
end
- it 'sorts by least recently due date by excluding nil due dates' do
+ it 'sorts by due date by excluding nil due dates' do
bar.update(due_date: nil)
- visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later)
+ visit project_issues_path(project, sort: sort_value_due_date)
expect(first_issue).to include('foo')
end
- end
- end
- describe 'filtering by due date' do
- before do
- foo.update(due_date: 1.day.from_now)
- bar.update(due_date: 6.days.from_now)
- end
+ context 'with a filter on labels' do
+ let(:label) { create(:label, project: project) }
+
+ before do
+ create(:label_link, label: label, target: foo)
+ end
+
+ it 'sorts by least recently due date by excluding nil due dates' do
+ bar.update(due_date: nil)
- it 'filters by none' do
- visit project_issues_path(project, due_date: Issue::NoDueDate.name)
+ visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later)
- page.within '.issues-holder' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
+ expect(first_issue).to include('foo')
+ end
end
end
- it 'filters by any' do
- visit project_issues_path(project, due_date: Issue::AnyDueDate.name)
+ describe 'filtering by due date' do
+ before do
+ foo.update(due_date: 1.day.from_now)
+ bar.update(due_date: 6.days.from_now)
+ end
+
+ it 'filters by none' do
+ visit project_issues_path(project, due_date: Issue::NoDueDate.name)
- page.within '.issues-holder' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).to have_content('baz')
+ page.within '.issues-holder' do
+ expect(page).not_to have_content('foo')
+ expect(page).not_to have_content('bar')
+ expect(page).to have_content('baz')
+ end
+ end
+
+ it 'filters by any' do
+ visit project_issues_path(project, due_date: Issue::AnyDueDate.name)
+
+ page.within '.issues-holder' do
+ expect(page).to have_content('foo')
+ expect(page).to have_content('bar')
+ expect(page).to have_content('baz')
+ end
end
- end
- it 'filters by due this week' do
- foo.update(due_date: Date.today.beginning_of_week + 2.days)
- bar.update(due_date: Date.today.end_of_week)
- baz.update(due_date: Date.today - 8.days)
+ it 'filters by due this week' do
+ foo.update(due_date: Date.today.beginning_of_week + 2.days)
+ bar.update(due_date: Date.today.end_of_week)
+ baz.update(due_date: Date.today - 8.days)
- visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
+ visit project_issues_path(project, due_date: Issue::DueThisWeek.name)
- page.within '.issues-holder' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).not_to have_content('baz')
+ page.within '.issues-holder' do
+ expect(page).to have_content('foo')
+ expect(page).to have_content('bar')
+ expect(page).not_to have_content('baz')
+ end
end
- end
- it 'filters by due this month' do
- foo.update(due_date: Date.today.beginning_of_month + 2.days)
- bar.update(due_date: Date.today.end_of_month)
- baz.update(due_date: Date.today - 50.days)
+ it 'filters by due this month' do
+ foo.update(due_date: Date.today.beginning_of_month + 2.days)
+ bar.update(due_date: Date.today.end_of_month)
+ baz.update(due_date: Date.today - 50.days)
- visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
+ visit project_issues_path(project, due_date: Issue::DueThisMonth.name)
- page.within '.issues-holder' do
- expect(page).to have_content('foo')
- expect(page).to have_content('bar')
- expect(page).not_to have_content('baz')
+ page.within '.issues-holder' do
+ expect(page).to have_content('foo')
+ expect(page).to have_content('bar')
+ expect(page).not_to have_content('baz')
+ end
end
- end
- it 'filters by overdue' do
- foo.update(due_date: Date.today + 2.days)
- bar.update(due_date: Date.today + 20.days)
- baz.update(due_date: Date.yesterday)
+ it 'filters by overdue' do
+ foo.update(due_date: Date.today + 2.days)
+ bar.update(due_date: Date.today + 20.days)
+ baz.update(due_date: Date.yesterday)
- visit project_issues_path(project, due_date: Issue::Overdue.name)
+ visit project_issues_path(project, due_date: Issue::Overdue.name)
- page.within '.issues-holder' do
- expect(page).not_to have_content('foo')
- expect(page).not_to have_content('bar')
- expect(page).to have_content('baz')
+ page.within '.issues-holder' do
+ expect(page).not_to have_content('foo')
+ expect(page).not_to have_content('bar')
+ expect(page).to have_content('baz')
+ end
end
end
- end
- describe 'sorting by milestone' do
- before do
- foo.milestone = newer_due_milestone
- foo.save
- bar.milestone = later_due_milestone
- bar.save
- end
+ describe 'sorting by milestone' do
+ before do
+ foo.milestone = newer_due_milestone
+ foo.save
+ bar.milestone = later_due_milestone
+ bar.save
+ end
- it 'sorts by milestone' do
- visit project_issues_path(project, sort: sort_value_milestone)
+ it 'sorts by milestone' do
+ visit project_issues_path(project, sort: sort_value_milestone)
- expect(first_issue).to include('foo')
- expect(last_issue).to include('baz')
+ expect(first_issue).to include('foo')
+ expect(last_issue).to include('baz')
+ end
end
- end
- describe 'combine filter and sort' do
- let(:user2) { create(:user) }
+ describe 'combine filter and sort' do
+ let(:user2) { create(:user) }
- before do
- foo.assignees << user2
- foo.save
- bar.assignees << user2
- bar.save
- end
+ before do
+ foo.assignees << user2
+ foo.save
+ bar.assignees << user2
+ bar.save
+ end
- it 'sorts with a filter applied' do
- visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id)
+ it 'sorts with a filter applied' do
+ visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id)
- expect(first_issue).to include('foo')
- expect(last_issue).to include('bar')
- expect(page).not_to have_content('baz')
+ expect(first_issue).to include('foo')
+ expect(last_issue).to include('bar')
+ expect(page).not_to have_content('baz')
+ end
end
end
- end
- describe 'when I want to reset my incoming email token' do
- let(:project1) { create(:project, namespace: user.namespace) }
- let!(:issue) { create(:issue, project: project1) }
+ 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
- stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
- project1.team << [user, :master]
- visit namespace_project_issues_path(user.namespace, project1)
- end
+ before do
+ stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
+ project1.team << [user, :master]
+ visit namespace_project_issues_path(user.namespace, project1)
+ end
- it 'changes incoming email address token', :js do
- find('.issuable-email-modal-btn').click
- previous_token = find('input#issuable_email').value
- find('.incoming-email-token-reset').click
+ it 'changes incoming email address token', :js do
+ find('.issuable-email-modal-btn').click
+ previous_token = find('input#issuable_email').value
+ find('.incoming-email-token-reset').click
- wait_for_requests
+ wait_for_requests
- expect(page).to have_no_field('issuable_email', with: previous_token)
- new_token = project1.new_issuable_address(user.reload, 'issue')
- expect(page).to have_field(
- 'issuable_email',
- with: new_token
- )
+ expect(page).to have_no_field('issuable_email', with: previous_token)
+ new_token = project1.new_issuable_address(user.reload, 'issue')
+ expect(page).to have_field(
+ 'issuable_email',
+ with: new_token
+ )
+ end
end
- end
- describe 'update labels from issue#show', :js do
- let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
- let!(:label) { create(:label, project: project) }
+ describe 'update labels from issue#show', :js do
+ let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
+ let!(:label) { create(:label, project: project) }
- before do
- visit project_issue_path(project, issue)
- end
+ before do
+ visit project_issue_path(project, issue)
+ end
- it 'will not send ajax request when no data is changed' do
- page.within '.labels' do
- click_link 'Edit'
+ it 'will not send ajax request when no data is changed' do
+ page.within '.labels' do
+ click_link 'Edit'
- find('.dropdown-menu-close', match: :first).click
+ find('.dropdown-menu-close', match: :first).click
- expect(page).not_to have_selector('.block-loading')
+ expect(page).not_to have_selector('.block-loading')
+ end
end
end
- end
- describe 'update assignee from issue#show' do
- let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
+ describe 'update assignee from issue#show' do
+ let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
- context 'by authorized user' do
- it 'allows user to select unassigned', :js do
- visit project_issue_path(project, issue)
+ context 'by authorized user' do
+ it 'allows user to select unassigned', :js do
+ visit project_issue_path(project, issue)
- page.within('.assignee') do
- expect(page).to have_content "#{user.name}"
+ page.within('.assignee') do
+ expect(page).to have_content "#{user.name}"
- click_link 'Edit'
- click_link 'Unassigned'
- first('.title').click
- expect(page).to have_content 'No assignee'
- end
+ click_link 'Edit'
+ click_link 'Unassigned'
+ first('.title').click
+ expect(page).to have_content 'No assignee'
+ end
- # wait_for_requests does not work with vue-resource at the moment
- sleep 1
+ # wait_for_requests does not work with vue-resource at the moment
+ sleep 1
- expect(issue.reload.assignees).to be_empty
- end
+ expect(issue.reload.assignees).to be_empty
+ end
- it 'allows user to select an assignee', :js do
- issue2 = create(:issue, project: project, author: user)
- visit project_issue_path(project, issue2)
+ it 'allows user to select an assignee', :js do
+ issue2 = create(:issue, project: project, author: user)
+ visit project_issue_path(project, issue2)
- page.within('.assignee') do
- expect(page).to have_content "No assignee"
- end
+ page.within('.assignee') do
+ expect(page).to have_content "No assignee"
+ end
- page.within '.assignee' do
- click_link 'Edit'
- end
+ page.within '.assignee' do
+ click_link 'Edit'
+ end
- page.within '.dropdown-menu-user' do
- click_link user.name
- end
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
- page.within('.assignee') do
- expect(page).to have_content user.name
+ page.within('.assignee') do
+ expect(page).to have_content user.name
+ end
end
- end
- it 'allows user to unselect themselves', :js do
- issue2 = create(:issue, project: project, author: user)
- visit project_issue_path(project, issue2)
+ it 'allows user to unselect themselves', :js do
+ issue2 = create(:issue, project: project, author: user)
+ visit project_issue_path(project, issue2)
- page.within '.assignee' do
- click_link 'Edit'
- click_link user.name
+ page.within '.assignee' do
+ click_link 'Edit'
+ click_link user.name
- page.within '.value .author' do
- expect(page).to have_content user.name
- end
+ page.within '.value .author' do
+ expect(page).to have_content user.name
+ end
- click_link 'Edit'
- click_link user.name
+ click_link 'Edit'
+ click_link user.name
- page.within '.value .assign-yourself' do
- expect(page).to have_content "No assignee"
+ page.within '.value .assign-yourself' do
+ expect(page).to have_content "No assignee"
+ end
end
end
end
- end
- context 'by unauthorized user' do
- let(:guest) { create(:user) }
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
- before do
- project.team << [[guest], :guest]
- end
+ before do
+ project.team << [[guest], :guest]
+ end
- it 'shows assignee text', :js do
- sign_out(:user)
- sign_in(guest)
+ it 'shows assignee text', :js do
+ sign_out(:user)
+ sign_in(guest)
- visit project_issue_path(project, issue)
- expect(page).to have_content issue.assignees.first.name
+ visit project_issue_path(project, issue)
+ expect(page).to have_content issue.assignees.first.name
+ end
end
end
- end
- describe 'update milestone from issue#show' do
- let!(:issue) { create(:issue, project: project, author: user) }
- let!(:milestone) { create(:milestone, project: project) }
+ describe 'update milestone from issue#show' do
+ let!(:issue) { create(:issue, project: project, author: user) }
+ let!(:milestone) { create(:milestone, project: project) }
- context 'by authorized user' do
- it 'allows user to select unassigned', :js do
- visit project_issue_path(project, issue)
+ context 'by authorized user' do
+ it 'allows user to select unassigned', :js do
+ visit project_issue_path(project, issue)
- page.within('.milestone') do
- expect(page).to have_content "None"
- end
+ page.within('.milestone') do
+ expect(page).to have_content "None"
+ end
- find('.block.milestone .edit-link').click
- sleep 2 # wait for ajax stuff to complete
- first('.dropdown-content li').click
- sleep 2
- page.within('.milestone') do
- expect(page).to have_content 'None'
+ find('.block.milestone .edit-link').click
+ sleep 2 # wait for ajax stuff to complete
+ first('.dropdown-content li').click
+ sleep 2
+ page.within('.milestone') do
+ expect(page).to have_content 'None'
+ end
+
+ expect(issue.reload.milestone).to be_nil
end
- expect(issue.reload.milestone).to be_nil
- end
+ it 'allows user to de-select milestone', :js do
+ visit project_issue_path(project, issue)
- it 'allows user to de-select milestone', :js do
- visit project_issue_path(project, issue)
+ page.within('.milestone') do
+ click_link 'Edit'
+ click_link milestone.title
- page.within('.milestone') do
- click_link 'Edit'
- click_link milestone.title
-
- page.within '.value' do
- expect(page).to have_content milestone.title
- end
+ page.within '.value' do
+ expect(page).to have_content milestone.title
+ end
- click_link 'Edit'
- click_link milestone.title
+ click_link 'Edit'
+ click_link milestone.title
- page.within '.value' do
- expect(page).to have_content 'None'
+ page.within '.value' do
+ expect(page).to have_content 'None'
+ end
end
end
end
- end
- context 'by unauthorized user' do
- let(:guest) { create(:user) }
+ context 'by unauthorized user' do
+ let(:guest) { create(:user) }
- before do
- project.team << [guest, :guest]
- issue.milestone = milestone
- issue.save
- end
+ before do
+ project.team << [guest, :guest]
+ issue.milestone = milestone
+ issue.save
+ end
- it 'shows milestone text', :js do
- sign_out(:user)
- sign_in(guest)
+ it 'shows milestone text', :js do
+ sign_out(:user)
+ sign_in(guest)
- visit project_issue_path(project, issue)
- expect(page).to have_content milestone.title
+ visit project_issue_path(project, issue)
+ expect(page).to have_content milestone.title
+ end
end
end
- end
- describe 'new issue' do
- let!(:issue) { create(:issue, project: project) }
+ describe 'new issue' do
+ let!(:issue) { create(:issue, project: project) }
- context 'by unauthenticated user' do
- before do
- sign_out(:user)
- end
+ context 'by unauthenticated user' do
+ before do
+ sign_out(:user)
+ end
- it 'redirects to signin then back to new issue after signin' do
- visit project_issues_path(project)
+ it 'redirects to signin then back to new issue after signin' do
+ visit project_issues_path(project)
- page.within '.nav-controls' do
- click_link 'New issue'
- end
+ page.within '.nav-controls' do
+ click_link 'New issue'
+ end
- expect(current_path).to eq new_user_session_path
+ expect(current_path).to eq new_user_session_path
- gitlab_sign_in(create(:user))
+ gitlab_sign_in(create(:user))
- expect(current_path).to eq new_project_issue_path(project)
+ expect(current_path).to eq new_project_issue_path(project)
+ end
end
- end
- context 'dropzone upload file', :js do
- before do
- visit new_project_issue_path(project)
- end
+ context 'dropzone upload file', :js do
+ before do
+ visit new_project_issue_path(project)
+ end
- it 'uploads file when dragging into textarea' do
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+ it 'uploads file when dragging into textarea' do
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- expect(page.find_field("issue_description").value).to have_content 'banana_sample'
- end
+ expect(page.find_field("issue_description").value).to have_content 'banana_sample'
+ end
- it "doesn't add double newline to end of a single attachment markdown" do
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+ it "doesn't add double newline to end of a single attachment markdown" do
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- expect(page.find_field("issue_description").value).not_to match /\n\n$/
- end
+ expect(page.find_field("issue_description").value).not_to match /\n\n$/
+ end
- it "cancels a file upload correctly" do
- slow_requests do
- dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
+ it "cancels a file upload correctly" do
+ slow_requests do
+ dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
- click_button 'Cancel'
- end
+ click_button 'Cancel'
+ end
- expect(page).to have_button('Attach a file')
- expect(page).not_to have_button('Cancel')
- expect(page).not_to have_selector('.uploading-progress-container', visible: true)
+ expect(page).to have_button('Attach a file')
+ expect(page).not_to have_button('Cancel')
+ expect(page).not_to have_selector('.uploading-progress-container', visible: true)
+ end
end
- end
- context 'form filled by URL parameters' do
- let(:project) { create(:project, :public, :repository) }
+ context 'form filled by URL parameters' do
+ let(:project) { create(:project, :public, :repository) }
- before do
- project.repository.create_file(
- user,
- '.gitlab/issue_templates/bug.md',
- 'this is a test "bug" template',
- message: 'added issue template',
- branch_name: 'master')
-
- visit new_project_issue_path(project, issuable_template: 'bug')
- end
+ before do
+ project.repository.create_file(
+ user,
+ '.gitlab/issue_templates/bug.md',
+ 'this is a test "bug" template',
+ message: 'added issue template',
+ branch_name: 'master')
+
+ visit new_project_issue_path(project, issuable_template: 'bug')
+ end
- it 'fills in template' do
- expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug')
+ it 'fills in template' do
+ expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug')
+ end
end
end
- end
- describe 'new issue by email' do
- shared_examples 'show the email in the modal' do
- let(:issue) { create(:issue, project: project) }
+ 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")
+ before do
+ project.issues << issue
+ stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab")
- visit project_issues_path(project)
- click_button('Email a new issue')
- end
+ visit project_issues_path(project)
+ click_button('Email a new issue')
+ end
- it 'click the button to show modal for the new email' do
- page.within '#issuable-email-modal' do
- email = project.new_issuable_address(user, 'issue')
+ it 'click the button to show modal for the new email' do
+ page.within '#issuable-email-modal' do
+ email = project.new_issuable_address(user, 'issue')
- expect(page).to have_selector("input[value='#{email}']")
+ expect(page).to have_selector("input[value='#{email}']")
+ end
end
end
- end
- context 'with existing issues' do
- let!(:issue) { create(:issue, project: project, author: user) }
+ context 'with existing issues' do
+ let!(:issue) { create(:issue, project: project, author: user) }
- it_behaves_like 'show the email in the modal'
- end
+ it_behaves_like 'show the email in the modal'
+ end
- context 'without existing issues' do
- it_behaves_like 'show the email in the modal'
+ context 'without existing issues' do
+ it_behaves_like 'show the email in the modal'
+ end
end
- end
- describe 'due date' do
- context 'update due on issue#show', :js do
- let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
+ describe 'due date' do
+ context 'update due on issue#show', :js do
+ let(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
- before do
- visit project_issue_path(project, issue)
- end
+ before do
+ visit project_issue_path(project, issue)
+ end
- it 'adds due date to issue' do
- date = Date.today.at_beginning_of_month + 2.days
+ it 'adds due date to issue' do
+ date = Date.today.at_beginning_of_month + 2.days
- page.within '.due_date' do
- click_link 'Edit'
+ page.within '.due_date' do
+ click_link 'Edit'
- page.within '.pika-single' do
- click_button date.day
- end
+ page.within '.pika-single' do
+ click_button date.day
+ end
- wait_for_requests
+ wait_for_requests
- expect(find('.value').text).to have_content date.strftime('%b %-d, %Y')
+ expect(find('.value').text).to have_content date.strftime('%b %-d, %Y')
+ end
end
- end
- it 'removes due date from issue' do
- date = Date.today.at_beginning_of_month + 2.days
+ it 'removes due date from issue' do
+ date = Date.today.at_beginning_of_month + 2.days
- page.within '.due_date' do
- click_link 'Edit'
+ page.within '.due_date' do
+ click_link 'Edit'
- page.within '.pika-single' do
- click_button date.day
- end
+ page.within '.pika-single' do
+ click_button date.day
+ end
- wait_for_requests
+ wait_for_requests
- expect(page).to have_no_content 'No due date'
+ expect(page).to have_no_content 'No due date'
- click_link 'remove due date'
- expect(page).to have_content 'No due date'
+ click_link 'remove due date'
+ expect(page).to have_content 'No due date'
+ end
end
end
end
- end
- describe 'title issue#show', :js do
- it 'updates the title', :js do
- issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title')
+ describe 'title issue#show', :js do
+ it 'updates the title', :js do
+ issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title')
- visit project_issue_path(project, issue)
+ visit project_issue_path(project, issue)
- expect(page).to have_text("new title")
+ expect(page).to have_text("new title")
- issue.update(title: "updated title")
+ issue.update(title: "updated title")
- wait_for_requests
- expect(page).to have_text("updated title")
+ wait_for_requests
+ expect(page).to have_text("updated title")
+ end
end
- end
- describe 'confidential issue#show', :js do
- it 'shows confidential sibebar information as confidential and can be turned off' do
- issue = create(:issue, :confidential, project: project)
+ describe 'confidential issue#show', :js do
+ it 'shows confidential sibebar information as confidential and can be turned off' do
+ issue = create(:issue, :confidential, project: project)
- visit project_issue_path(project, issue)
+ visit project_issue_path(project, issue)
- expect(page).to have_css('.issuable-note-warning')
- expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active')
- expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active')
+ expect(page).to have_css('.issuable-note-warning')
+ expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active')
+ expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active')
- find('.confidential-edit').click
- expect(page).to have_css('.sidebar-item-warning-message')
+ find('.confidential-edit').click
+ expect(page).to have_css('.sidebar-item-warning-message')
- within('.sidebar-item-warning-message') do
- find('.btn-close').click
- end
+ within('.sidebar-item-warning-message') do
+ find('.btn-close').click
+ end
- wait_for_requests
+ wait_for_requests
- visit project_issue_path(project, issue)
+ visit project_issue_path(project, issue)
- expect(page).not_to have_css('.is-active')
+ expect(page).not_to have_css('.is-active')
+ end
end
end
end
diff --git a/spec/features/merge_requests/image_diff_notes.rb b/spec/features/merge_requests/image_diff_notes_spec.rb
index 021c4e03428..b53570835cb 100644
--- a/spec/features/merge_requests/image_diff_notes.rb
+++ b/spec/features/merge_requests/image_diff_notes_spec.rb
@@ -10,11 +10,10 @@ feature 'image diff notes', :js do
project.team << [user, :master]
sign_in user
- page.driver.set_cookie('sidebar_collapsed', 'true')
-
# Stub helper to return any blob file as image from public app folder.
# This is necessary to run this specs since we don't display repo images in capybara.
- allow_any_instance_of(DiffHelper).to receive(:diff_file_blob_raw_path).and_return('/apple-touch-icon.png')
+ allow_any_instance_of(DiffHelper).to receive(:diff_file_blob_raw_url).and_return('/apple-touch-icon.png')
+ allow_any_instance_of(DiffHelper).to receive(:diff_file_old_blob_raw_url).and_return('/favicon.ico')
end
context 'create commit diff notes' do
@@ -141,13 +140,13 @@ feature 'image diff notes', :js do
end
it 'allows expanding/collapsing the discussion notes' do
- page.all('.js-diff-notes-toggle')[0].trigger('click')
- page.all('.js-diff-notes-toggle')[1].trigger('click')
+ page.all('.js-diff-notes-toggle')[0].click
+ page.all('.js-diff-notes-toggle')[1].click
expect(page).not_to have_content('image diff test comment')
- page.all('.js-diff-notes-toggle')[0].trigger('click')
- page.all('.js-diff-notes-toggle')[1].trigger('click')
+ page.all('.js-diff-notes-toggle')[0].click
+ page.all('.js-diff-notes-toggle')[1].click
expect(page).to have_content('image diff test comment')
end
@@ -196,13 +195,31 @@ feature 'image diff notes', :js do
expect(find('.onion-skin-frame')['style']).to match('width: 228px; height: 240px;')
end
+
+ it 'resets onion skin view mode opacity when toggling between view modes' do
+ find('.view-modes-menu .onion-skin').click
+
+ # Simulate dragging onion-skin slider
+ drag_and_drop_by(find('.dragger'), -30, 0)
+
+ expect(find('.onion-skin-frame .frame.added', visible: false)['style']).not_to match('opacity: 1;')
+
+ find('.view-modes-menu .swipe').click
+ find('.view-modes-menu .onion-skin').click
+
+ expect(find('.onion-skin-frame .frame.added', visible: false)['style']).to match('opacity: 1;')
+ end
end
-end
-def create_image_diff_note
- find('.js-add-image-diff-note-button', match: :first).click
- page.all('.js-add-image-diff-note-button')[0].trigger('click')
- find('.diff-content .note-textarea').native.send_keys('image diff test comment')
- click_button 'Comment'
- wait_for_requests
+ def drag_and_drop_by(element, right_by, down_by)
+ page.driver.browser.action.drag_and_drop_by(element.native, right_by, down_by).perform
+ end
+
+ def create_image_diff_note
+ find('.js-add-image-diff-note-button', match: :first).click
+ page.all('.js-add-image-diff-note-button')[0].click
+ find('.diff-content .note-textarea').native.send_keys('image diff test comment')
+ click_button 'Comment'
+ wait_for_requests
+ end
end
diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb
index 93c5e945453..a7e7c0eeff6 100644
--- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb
+++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb
@@ -15,8 +15,8 @@ feature 'Mini Pipeline Graph', :js do
visit_merge_request
end
- def visit_merge_request(format = :html)
- visit project_merge_request_path(project, merge_request, format: format)
+ def visit_merge_request(format: :html, serializer: nil)
+ visit project_merge_request_path(project, merge_request, format: format, serializer: serializer)
end
it 'should display a mini pipeline graph' do
@@ -33,12 +33,12 @@ feature 'Mini Pipeline Graph', :js do
end
it 'avoids repeated database queries' do
- before = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) }
+ before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file2)
create(:ci_build, pipeline: pipeline, when: 'manual')
- after = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) }
+ after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') }
expect(before.count).to eq(after.count)
expect(before.cached_count).to eq(after.cached_count)
diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb
index 27efc32c95b..9f24193a2ac 100644
--- a/spec/features/milestone_spec.rb
+++ b/spec/features/milestone_spec.rb
@@ -82,9 +82,9 @@ feature 'Milestone' do
milestone = create(:milestone, project: project, title: 8.7)
issue1 = create(:issue, project: project, milestone: milestone)
issue2 = create(:issue, project: project, milestone: milestone)
- issue1.spend_time(duration: 3600, user: user)
+ issue1.spend_time(duration: 3600, user_id: user.id)
issue1.save!
- issue2.spend_time(duration: 7200, user: user)
+ issue2.spend_time(duration: 7200, user_id: user.id)
issue2.save!
visit project_milestone_path(project, milestone)
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 6c616bf0456..8ac9821b879 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -2,15 +2,15 @@ require 'spec_helper'
feature 'project owner sees a link to create a license file in empty project', :js do
let(:project_master) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project_empty_repo) }
+
background do
- project.team << [project_master, :master]
+ project.add_master(project_master)
sign_in(project_master)
end
scenario 'project master creates a license file from a template' do
visit project_path(project)
- click_link 'Create empty bare repository'
click_on 'LICENSE'
expect(page).to have_content('New file')
@@ -26,8 +26,6 @@ feature 'project owner sees a link to create a license file in empty project', :
expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
- # Remove pre-receive hook so we can push without auth
- FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive'))
click_button 'Commit changes'
expect(current_path).to eq(
diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb
index 0257cd157c9..4319fc2746c 100644
--- a/spec/features/projects/issuable_templates_spec.rb
+++ b/spec/features/projects/issuable_templates_spec.rb
@@ -32,9 +32,7 @@ feature 'issuable templates', :js do
message: 'added issue template',
branch_name: 'master')
visit project_issue_path project, issue
- page.within('.js-issuable-actions') do
- click_on 'Edit'
- end
+ page.find('.js-issuable-edit').click
fill_in :'issuable-title', with: 'test issue title'
end
@@ -77,9 +75,7 @@ feature 'issuable templates', :js do
message: 'added issue template',
branch_name: 'master')
visit project_issue_path project, issue
- page.within('.js-issuable-actions') do
- click_on 'Edit'
- end
+ page.find('.js-issuable-edit').click
fill_in :'issuable-title', with: 'test issue title'
fill_in :'issue-description', with: prior_description
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 888e290292b..3987cea0b4f 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -152,7 +152,7 @@ describe 'Pipeline', :js do
end
it 'shows counter in Jobs tab' do
- expect(page.find('.js-builds-counter').text).to eq(pipeline.statuses.count.to_s)
+ expect(page.find('.js-builds-counter').text).to eq(pipeline.total_size.to_s)
end
it 'shows Pipeline tab as active' do
@@ -248,7 +248,7 @@ describe 'Pipeline', :js do
end
it 'shows counter in Jobs tab' do
- expect(page.find('.js-builds-counter').text).to eq(pipeline.statuses.count.to_s)
+ expect(page.find('.js-builds-counter').text).to eq(pipeline.total_size.to_s)
end
it 'shows Jobs tab as active' do
diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb
index 9edc7ced163..4662367d843 100644
--- a/spec/features/tags/master_views_tags_spec.rb
+++ b/spec/features/tags/master_views_tags_spec.rb
@@ -4,18 +4,17 @@ feature 'Master views tags' do
let(:user) { create(:user) }
before do
- project.team << [user, :master]
+ project.add_master(user)
sign_in(user)
end
context 'when project has no tags' do
let(:project) { create(:project_empty_repo) }
+
before do
visit project_path(project)
click_on 'README'
fill_in :commit_message, with: 'Add a README file', visible: true
- # Remove pre-receive hook so we can push without auth
- FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive'))
click_button 'Commit changes'
visit project_tags_path(project)
end
diff --git a/spec/fixtures/api/schemas/entities/merge_request.json b/spec/fixtures/api/schemas/entities/merge_request_widget.json
index ba094ba1657..342890c3dee 100644
--- a/spec/fixtures/api/schemas/entities/merge_request.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_widget.json
@@ -80,15 +80,15 @@
"target_branch_tree_path": { "type": "string" },
"source_branch_path": { "type": "string" },
"conflict_resolution_path": { "type": ["string", "null"] },
- "cancel_merge_when_pipeline_succeeds_path": { "type": "string" },
- "create_issue_to_resolve_discussions_path": { "type": "string" },
- "merge_path": { "type": "string" },
+ "cancel_merge_when_pipeline_succeeds_path": { "type": ["string", "null"] },
+ "create_issue_to_resolve_discussions_path": { "type": ["string", "null"] },
+ "merge_path": { "type": ["string", "null"] },
"cherry_pick_in_fork_path": { "type": ["string", "null"] },
"revert_in_fork_path": { "type": ["string", "null"] },
"email_patches_path": { "type": "string" },
"plain_diff_path": { "type": "string" },
"status_path": { "type": "string" },
- "new_blob_path": { "type": "string" },
+ "new_blob_path": { "type": ["string", "null"] },
"merge_check_path": { "type": "string" },
"ci_environments_status_path": { "type": "string" },
"merge_commit_message_with_description": { "type": "string" },
diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb
index cd15e27b497..36a44f8567a 100644
--- a/spec/helpers/notes_helper_spec.rb
+++ b/spec/helpers/notes_helper_spec.rb
@@ -41,6 +41,7 @@ describe NotesHelper do
describe '#discussion_path' do
let(:project) { create(:project, :repository) }
+ let(:anchor) { discussion.line_code }
context 'for a merge request discusion' do
let(:merge_request) { create(:merge_request, source_project: project, target_project: project, importing: true) }
@@ -151,6 +152,15 @@ describe NotesHelper do
expect(helper.discussion_path(discussion)).to be_nil
end
end
+
+ context 'for a contextual commit discussion' do
+ let(:commit) { merge_request.commits.last }
+ let(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, commit_id: commit.id).to_discussion }
+
+ it 'returns the merge request diff discussion scoped in the commit' do
+ expect(helper.discussion_path(discussion)).to eq(diffs_project_merge_request_path(project, merge_request, commit_id: commit.id, anchor: anchor))
+ end
+ end
end
context 'for a commit discussion' do
@@ -160,7 +170,7 @@ describe NotesHelper do
let(:discussion) { create(:diff_note_on_commit, project: project).to_discussion }
it 'returns the commit path with the line code' do
- expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: discussion.line_code))
+ expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: anchor))
end
end
@@ -168,7 +178,7 @@ describe NotesHelper do
let(:discussion) { create(:legacy_diff_note_on_commit, project: project).to_discussion }
it 'returns the commit path with the line code' do
- expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: discussion.line_code))
+ expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: anchor))
end
end
diff --git a/spec/javascripts/collapsed_sidebar_todo_spec.js b/spec/javascripts/collapsed_sidebar_todo_spec.js
index 974815fe939..5026eaafaca 100644
--- a/spec/javascripts/collapsed_sidebar_todo_spec.js
+++ b/spec/javascripts/collapsed_sidebar_todo_spec.js
@@ -1,7 +1,6 @@
-/* global Sidebar */
/* eslint-disable no-new */
import _ from 'underscore';
-import '~/right_sidebar';
+import Sidebar from '~/right_sidebar';
describe('Issuable right sidebar collapsed todo toggle', () => {
const fixtureName = 'issues/open-issue.html.raw';
diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
index 861f26e162f..6599839a526 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
@@ -1,8 +1,10 @@
/* eslint-disable quotes, jasmine/no-suite-dupes, vars-on-top, no-var */
-
-import d3 from 'd3';
+import { scaleLinear, scaleTime } from 'd3-scale';
+import { timeParse } from 'd3-time-format';
import { ContributorsGraph, ContributorsMasterGraph } from '~/graphs/stat_graph_contributors_graph';
+const d3 = { scaleLinear, scaleTime, timeParse };
+
describe("ContributorsGraph", function () {
describe("#set_x_domain", function () {
it("set the x_domain", function () {
@@ -53,7 +55,7 @@ describe("ContributorsGraph", function () {
it("sets the instance's x domain using the prototype's x_domain", function () {
ContributorsGraph.prototype.x_domain = 20;
var instance = new ContributorsGraph();
- instance.x = d3.time.scale().range([0, 100]).clamp(true);
+ instance.x = d3.scaleTime().range([0, 100]).clamp(true);
spyOn(instance.x, 'domain');
instance.set_x_domain();
expect(instance.x.domain).toHaveBeenCalledWith(20);
@@ -64,7 +66,7 @@ describe("ContributorsGraph", function () {
it("sets the instance's y domain using the prototype's y_domain", function () {
ContributorsGraph.prototype.y_domain = 30;
var instance = new ContributorsGraph();
- instance.y = d3.scale.linear().range([100, 0]).nice();
+ instance.y = d3.scaleLinear().range([100, 0]).nice();
spyOn(instance.y, 'domain');
instance.set_y_domain();
expect(instance.y.domain).toHaveBeenCalledWith(30);
@@ -118,7 +120,7 @@ describe("ContributorsMasterGraph", function () {
describe("#parse_dates", function () {
it("parses the dates", function () {
var graph = new ContributorsMasterGraph();
- var parseDate = d3.time.format("%Y-%m-%d").parse;
+ var parseDate = d3.timeParse("%Y-%m-%d");
var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }];
var correct = [{ date: parseDate(data[0].date) }, { date: parseDate(data[1].date) }];
graph.parse_dates(data);
diff --git a/spec/javascripts/graphs/stat_graph_contributors_spec.js b/spec/javascripts/graphs/stat_graph_contributors_spec.js
new file mode 100644
index 00000000000..962423462e7
--- /dev/null
+++ b/spec/javascripts/graphs/stat_graph_contributors_spec.js
@@ -0,0 +1,26 @@
+import ContributorsStatGraph from '~/graphs/stat_graph_contributors';
+import { ContributorsGraph } from '~/graphs/stat_graph_contributors_graph';
+
+import { setLanguage } from '../helpers/locale_helper';
+
+describe('ContributorsStatGraph', () => {
+ describe('change_date_header', () => {
+ beforeAll(() => {
+ setLanguage('de');
+ });
+
+ afterAll(() => {
+ setLanguage(null);
+ });
+
+ it('uses the locale to display date ranges', () => {
+ ContributorsGraph.init_x_domain([{ date: '2013-01-31' }, { date: '2012-01-31' }]);
+ setFixtures('<div id="date_header"></div>');
+ const graph = new ContributorsStatGraph();
+
+ graph.change_date_header();
+
+ expect(document.getElementById('date_header').innerText).toBe('31. Januar 2012 – 31. Januar 2013');
+ });
+ });
+});
diff --git a/spec/javascripts/helpers/locale_helper.js b/spec/javascripts/helpers/locale_helper.js
new file mode 100644
index 00000000000..99e6ce61234
--- /dev/null
+++ b/spec/javascripts/helpers/locale_helper.js
@@ -0,0 +1,11 @@
+/* eslint-disable import/prefer-default-export */
+
+export const setLanguage = (languageCode) => {
+ const htmlElement = document.querySelector('html');
+
+ if (languageCode) {
+ htmlElement.setAttribute('lang', languageCode);
+ } else {
+ htmlElement.removeAttribute('lang');
+ }
+};
diff --git a/spec/javascripts/lib/utils/tick_formats_spec.js b/spec/javascripts/lib/utils/tick_formats_spec.js
new file mode 100644
index 00000000000..283989b4fc8
--- /dev/null
+++ b/spec/javascripts/lib/utils/tick_formats_spec.js
@@ -0,0 +1,40 @@
+import { dateTickFormat, initDateFormats } from '~/lib/utils/tick_formats';
+
+import { setLanguage } from '../../helpers/locale_helper';
+
+describe('tick formats', () => {
+ describe('dateTickFormat', () => {
+ beforeAll(() => {
+ setLanguage('de');
+ initDateFormats();
+ });
+
+ afterAll(() => {
+ setLanguage(null);
+ });
+
+ it('returns year for first of January', () => {
+ const tick = dateTickFormat(new Date('2001-01-01'));
+
+ expect(tick).toBe('2001');
+ });
+
+ it('returns month for first of February', () => {
+ const tick = dateTickFormat(new Date('2001-02-01'));
+
+ expect(tick).toBe('Februar');
+ });
+
+ it('returns day and month for second of February', () => {
+ const tick = dateTickFormat(new Date('2001-02-02'));
+
+ expect(tick).toBe('2. Feb.');
+ });
+
+ it('ignores time', () => {
+ const tick = dateTickFormat(new Date('2001-02-02 12:34:56'));
+
+ expect(tick).toBe('2. Feb.');
+ });
+ });
+});
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index 645664a5219..89f4b85541d 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -1,7 +1,6 @@
/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, jasmine/no-spec-dupes, no-underscore-dangle, max-len */
-/* global LineHighlighter */
-import '~/line_highlighter';
+import LineHighlighter from '~/line_highlighter';
(function() {
describe('LineHighlighter', function() {
diff --git a/spec/javascripts/locale/index_spec.js b/spec/javascripts/locale/index_spec.js
new file mode 100644
index 00000000000..29b0b21eed7
--- /dev/null
+++ b/spec/javascripts/locale/index_spec.js
@@ -0,0 +1,35 @@
+import { createDateTimeFormat, languageCode } from '~/locale';
+
+import { setLanguage } from '../helpers/locale_helper';
+
+describe('locale', () => {
+ afterEach(() => {
+ setLanguage(null);
+ });
+
+ describe('languageCode', () => {
+ it('parses the lang attribute', () => {
+ setLanguage('ja');
+
+ expect(languageCode()).toBe('ja');
+ });
+
+ it('falls back to English', () => {
+ setLanguage(null);
+
+ expect(languageCode()).toBe('en');
+ });
+ });
+
+ describe('createDateTimeFormat', () => {
+ beforeEach(() => {
+ setLanguage('de');
+ });
+
+ it('creates an instance of Intl.DateTimeFormat', () => {
+ const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' });
+
+ expect(dateFormat.format(new Date(2015, 6, 3))).toBe('3. Juli 2015');
+ });
+ });
+});
diff --git a/spec/javascripts/merge_request_notes_spec.js b/spec/javascripts/merge_request_notes_spec.js
index 6054b75d0b8..e983e4de3fc 100644
--- a/spec/javascripts/merge_request_notes_spec.js
+++ b/spec/javascripts/merge_request_notes_spec.js
@@ -1,11 +1,9 @@
-/* global Notes */
-
import 'autosize';
import '~/gl_form';
import '~/lib/utils/text_utility';
import '~/render_gfm';
import '~/render_math';
-import '~/notes';
+import Notes from '~/notes';
const upArrowKeyCode = 38;
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index 70ae63ba036..2f02c11482f 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -1,7 +1,6 @@
/* eslint-disable space-before-function-paren, no-return-assign */
-/* global MergeRequest */
-import '~/merge_request';
+import MergeRequest from '~/merge_request';
import CloseReopenReportToggle from '~/close_reopen_report_toggle';
import IssuablesHelper from '~/helpers/issuables_helper';
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index 31426ceb110..050f0ea9ebd 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -1,5 +1,4 @@
/* eslint-disable no-var, comma-dangle, object-shorthand */
-/* global Notes */
import * as urlUtils from '~/lib/utils/url_utility';
import MergeRequestTabs from '~/merge_request_tabs';
@@ -7,7 +6,7 @@ import '~/commit/pipelines/pipelines_bundle';
import '~/breakpoints';
import '~/lib/utils/common_utils';
import Diff from '~/diff';
-import '~/notes';
+import Notes from '~/notes';
import 'vendor/jquery.scrollTo';
(function () {
@@ -279,8 +278,8 @@ import 'vendor/jquery.scrollTo';
loadFixtures('merge_requests/diff_comment.html.raw');
$('body').attr('data-page', 'projects:merge_requests:show');
window.gl.ImageFile = () => {};
- window.notes = new Notes('', []);
- spyOn(window.notes, 'toggleDiffNote').and.callThrough();
+ Notes.initialize('', []);
+ spyOn(Notes.instance, 'toggleDiffNote').and.callThrough();
});
afterEach(() => {
@@ -338,7 +337,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteId.length).toBeGreaterThan(0);
- expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({
+ expect(Notes.instance.toggleDiffNote).toHaveBeenCalledWith({
target: jasmine.any(Object),
lineType: 'old',
forceShow: true,
@@ -349,7 +348,7 @@ import 'vendor/jquery.scrollTo';
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
- expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
+ expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
@@ -359,7 +358,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteLineNumId.length).toBeGreaterThan(0);
- expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
+ expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
});
@@ -393,7 +392,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteId.length).toBeGreaterThan(0);
- expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({
+ expect(Notes.instance.toggleDiffNote).toHaveBeenCalledWith({
target: jasmine.any(Object),
lineType: 'new',
forceShow: true,
@@ -404,7 +403,7 @@ import 'vendor/jquery.scrollTo';
spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
- expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
+ expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
@@ -414,7 +413,7 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
expect(noteLineNumId.length).toBeGreaterThan(0);
- expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
+ expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index e09b8dc7fc5..167f074fb9b 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -1,12 +1,10 @@
/* eslint-disable space-before-function-paren, no-unused-expressions, no-var, object-shorthand, comma-dangle, max-len */
-/* global Notes */
-
import * as urlUtils from '~/lib/utils/url_utility';
import 'autosize';
import '~/gl_form';
import '~/lib/utils/text_utility';
import '~/render_gfm';
-import '~/notes';
+import Notes from '~/notes';
(function() {
window.gon || (window.gon = {});
diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js
index 72790eb215a..3267e29585b 100644
--- a/spec/javascripts/right_sidebar_spec.js
+++ b/spec/javascripts/right_sidebar_spec.js
@@ -1,8 +1,7 @@
/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-return-assign, new-cap, vars-on-top, max-len */
-/* global Sidebar */
import '~/commons/bootstrap';
-import '~/right_sidebar';
+import Sidebar from '~/right_sidebar';
(function() {
var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState;
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 9e6d0aa472c..74b343c573e 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options';
import eventHub from '~/vue_merge_request_widget/event_hub';
import notify from '~/lib/utils/notify';
+import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
import mockData from './mock_data';
import mountComponent from '../helpers/vue_mount_component_helper';
@@ -344,4 +345,31 @@ describe('mrWidgetOptions', () => {
expect(comps['mr-widget-merge-when-pipeline-succeeds']).toBeDefined();
});
});
+
+ describe('rendering relatedLinks', () => {
+ beforeEach((done) => {
+ vm.mr.relatedLinks = {
+ assignToMe: null,
+ closing: `
+ <a class="close-related-link" href="#'>
+ Close
+ </a>
+ `,
+ mentioned: '',
+ };
+ Vue.nextTick(done);
+ });
+
+ it('renders if there are relatedLinks', () => {
+ expect(vm.$el.querySelector('.close-related-link')).toBeDefined();
+ });
+
+ it('does not render if state is nothingToMerge', (done) => {
+ vm.mr.state = stateKey.nothingToMerge;
+ Vue.nextTick(() => {
+ expect(vm.$el.querySelector('.close-related-link')).toBeNull();
+ done();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
index 8e5614b20f0..33d052aceb2 100644
--- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -1,4 +1,5 @@
import MergeRequestStore from '~/vue_merge_request_widget/stores/mr_widget_store';
+import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
import mockData from '../mock_data';
describe('MergeRequestStore', () => {
@@ -52,5 +53,17 @@ describe('MergeRequestStore', () => {
expect(store.isPipelineSkipped).toBe(false);
});
});
+
+ describe('isNothingToMergeState', () => {
+ it('returns true when nothingToMerge', () => {
+ store.state = stateKey.nothingToMerge;
+ expect(store.isNothingToMergeState).toEqual(true);
+ });
+
+ it('returns false when not nothingToMerge', () => {
+ store.state = 'state';
+ expect(store.isNothingToMergeState).toEqual(false);
+ });
+ });
});
});
diff --git a/spec/lib/gitlab/action_rate_limiter_spec.rb b/spec/lib/gitlab/action_rate_limiter_spec.rb
new file mode 100644
index 00000000000..542fc03e555
--- /dev/null
+++ b/spec/lib/gitlab/action_rate_limiter_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe Gitlab::ActionRateLimiter do
+ let(:redis) { double('redis') }
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:key) { [user, project] }
+ let(:cache_key) { "action_rate_limiter:test_action:user:#{user.id}:project:#{project.id}" }
+
+ subject { described_class.new(action: :test_action, expiry_time: 100) }
+
+ before do
+ allow(Gitlab::Redis::Cache).to receive(:with).and_yield(redis)
+ end
+
+ it 'increases the throttle count and sets the expire time' do
+ expect(redis).to receive(:incr).with(cache_key).and_return(1)
+ expect(redis).to receive(:expire).with(cache_key, 100)
+
+ expect(subject.throttled?(key, 1)).to be false
+ end
+
+ it 'returns true if the key is throttled' do
+ expect(redis).to receive(:incr).with(cache_key).and_return(2)
+ expect(redis).not_to receive(:expire)
+
+ expect(subject.throttled?(key, 1)).to be true
+ end
+end
diff --git a/spec/lib/gitlab/git/gitlab_projects_spec.rb b/spec/lib/gitlab/git/gitlab_projects_spec.rb
index 18906955df6..24da9589458 100644
--- a/spec/lib/gitlab/git/gitlab_projects_spec.rb
+++ b/spec/lib/gitlab/git/gitlab_projects_spec.rb
@@ -41,7 +41,8 @@ describe Gitlab::Git::GitlabProjects do
end
it "fails if the source path doesn't exist" do
- expect(logger).to receive(:error).with("mv-project failed: source path <#{tmp_repos_path}/bad-src.git> does not exist.")
+ expected_source_path = File.join(tmp_repos_path, 'bad-src.git')
+ expect(logger).to receive(:error).with("mv-project failed: source path <#{expected_source_path}> does not exist.")
result = build_gitlab_projects(tmp_repos_path, 'bad-src.git').mv_project('repo.git')
expect(result).to be_falsy
@@ -50,7 +51,8 @@ describe Gitlab::Git::GitlabProjects do
it 'fails if the destination path already exists' do
FileUtils.mkdir_p(File.join(tmp_repos_path, 'already-exists.git'))
- message = "mv-project failed: destination path <#{tmp_repos_path}/already-exists.git> already exists."
+ expected_distination_path = File.join(tmp_repos_path, 'already-exists.git')
+ message = "mv-project failed: destination path <#{expected_distination_path}> already exists."
expect(logger).to receive(:error).with(message)
expect(gl_projects.mv_project('already-exists.git')).to be_falsy
diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
index 168e5d07504..46a57e08963 100644
--- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
@@ -70,7 +70,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
describe '#execute' do
it 'imports the repository and wiki' do
- expect(repository)
+ expect(project)
.to receive(:empty_repo?)
.and_return(true)
@@ -93,7 +93,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
end
it 'does not import the repository if it already exists' do
- expect(repository)
+ expect(project)
.to receive(:empty_repo?)
.and_return(false)
@@ -115,7 +115,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
end
it 'does not import the wiki if it is disabled' do
- expect(repository)
+ expect(project)
.to receive(:empty_repo?)
.and_return(true)
@@ -137,7 +137,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
end
it 'does not import the wiki if the repository could not be imported' do
- expect(repository)
+ expect(project)
.to receive(:empty_repo?)
.and_return(true)
diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb
index 0f8330e91c1..5ed2f4400bc 100644
--- a/spec/models/blob_viewer/package_json_spec.rb
+++ b/spec/models/blob_viewer/package_json_spec.rb
@@ -22,4 +22,51 @@ describe BlobViewer::PackageJson do
expect(subject.package_name).to eq('module-name')
end
end
+
+ describe '#package_url' do
+ it 'returns the package URL' do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_url).to eq("https://www.npmjs.com/package/#{subject.package_name}")
+ end
+ end
+
+ describe '#package_type' do
+ it 'returns "package"' do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_type).to eq('package')
+ end
+ end
+
+ context 'when package.json has "private": true' do
+ let(:data) do
+ <<-SPEC.strip_heredoc
+ {
+ "name": "module-name",
+ "version": "10.3.1",
+ "private": true,
+ "homepage": "myawesomepackage.com"
+ }
+ SPEC
+ end
+ let(:blob) { fake_blob(path: 'package.json', data: data) }
+ subject { described_class.new(blob) }
+
+ describe '#package_url' do
+ it 'returns homepage if any' do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_url).to eq('myawesomepackage.com')
+ end
+ end
+
+ describe '#package_type' do
+ it 'returns "private package"' do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_type).to eq('private package')
+ end
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 856e17b20bd..a1f63a2534b 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1530,4 +1530,16 @@ describe Ci::Pipeline, :mailer do
expect(query_count).to eq(1)
end
end
+
+ describe '#total_size' do
+ let!(:build_job1) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
+ let!(:build_job2) { create(:ci_build, pipeline: pipeline, stage_idx: 0) }
+ let!(:test_job_failed_and_retried) { create(:ci_build, :failed, :retried, pipeline: pipeline, stage_idx: 1) }
+ let!(:second_test_job) { create(:ci_build, pipeline: pipeline, stage_idx: 1) }
+ let!(:deploy_job) { create(:ci_build, pipeline: pipeline, stage_idx: 2) }
+
+ it 'returns all jobs (including failed and retried)' do
+ expect(pipeline.total_size).to eq(5)
+ end
+ end
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index d18a5c9dfa6..cd955a5eb69 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -13,6 +13,45 @@ describe Commit do
it { is_expected.to include_module(StaticModel) }
end
+ describe '.lazy' do
+ set(:project) { create(:project, :repository) }
+
+ context 'when the commits are found' do
+ let(:oids) do
+ %w(
+ 498214de67004b1da3d820901307bed2a68a8ef6
+ c642fe9b8b9f28f9225d7ea953fe14e74748d53b
+ 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9
+ 048721d90c449b244b7b4c53a9186b04330174ec
+ 281d3a76f31c812dbf48abce82ccf6860adedd81
+ )
+ end
+
+ subject { oids.map { |oid| described_class.lazy(project, oid) } }
+
+ it 'batches requests for commits' do
+ expect(project.repository).to receive(:commits_by).once.and_call_original
+
+ subject.first.title
+ subject.last.title
+ end
+
+ it 'maintains ordering' do
+ subject.each_with_index do |commit, i|
+ expect(commit.id).to eq(oids[i])
+ end
+ end
+ end
+
+ context 'when not found' do
+ it 'returns nil as commit' do
+ commit = described_class.lazy(project, 'deadbeef').__sync
+
+ expect(commit).to be_nil
+ end
+ end
+ end
+
describe '#author' do
it 'looks up the author in a case-insensitive way' do
user = create(:user, email: commit.author_email.upcase)
diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb
new file mode 100644
index 00000000000..5906b588d0e
--- /dev/null
+++ b/spec/models/concerns/blocks_json_serialization_spec.rb
@@ -0,0 +1,17 @@
+require 'rails_helper'
+
+describe BlocksJsonSerialization do
+ DummyModel = Class.new do
+ include BlocksJsonSerialization
+ end
+
+ it 'blocks as_json' do
+ expect { DummyModel.new.as_json }
+ .to raise_error(described_class::JsonSerializationError, /DummyModel/)
+ end
+
+ it 'blocks to_json' do
+ expect { DummyModel.new.to_json }
+ .to raise_error(described_class::JsonSerializationError, /DummyModel/)
+ end
+end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 9df26f06a11..4b217df2e8f 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -291,7 +291,7 @@ describe Issuable do
context 'total_time_spent is updated' do
before do
- issue.spend_time(duration: 2, user: user, spent_at: Time.now)
+ issue.spend_time(duration: 2, user_id: user.id, spent_at: Time.now)
issue.save
expect(Gitlab::HookData::IssuableBuilder)
.to receive(:new).with(issue).and_return(builder)
@@ -485,7 +485,7 @@ describe Issuable do
let(:issue) { create(:issue) }
def spend_time(seconds)
- issue.spend_time(duration: seconds, user: user)
+ issue.spend_time(duration: seconds, user_id: user.id)
issue.save!
end
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 9048da0c73d..673c609f534 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -189,9 +189,9 @@ describe Milestone, 'Milestoneish' do
describe '#total_issue_time_spent' do
it 'calculates total issue time spent' do
- closed_issue_1.spend_time(duration: 300, user: author)
+ closed_issue_1.spend_time(duration: 300, user_id: author.id)
closed_issue_1.save!
- closed_issue_2.spend_time(duration: 600, user: assignee)
+ closed_issue_2.spend_time(duration: 600, user_id: assignee.id)
closed_issue_2.save!
expect(milestone.total_issue_time_spent).to eq(900)
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index ad22fb2a386..c9b3c6cf602 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -395,6 +395,26 @@ describe JiraService do
end
end
+ describe 'additional cookies' do
+ let(:project) { create(:project) }
+
+ context 'provides additional cookies to allow basic auth with oracle webgate' do
+ before do
+ @service = project.create_jira_service(
+ active: true, properties: { url: 'http://jira.com' })
+ end
+
+ after do
+ @service.destroy!
+ end
+
+ it 'is initialized' do
+ expect(@service.options[:use_cookies]).to eq(true)
+ expect(@service.options[:additional_cookies]).to eq(["OBBasicAuth=fromDialog"])
+ end
+ end
+ end
+
describe 'project and issue urls' do
let(:project) { create(:project) }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index f805f2dcddb..cbeac2f05d3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1863,11 +1863,10 @@ describe Project do
project.change_head(project.default_branch)
end
- it 'creates the new reference' do
- expect(project.repository.raw_repository).to receive(:write_ref).with('HEAD',
+ it 'creates the new reference with rugged' do
+ expect(project.repository.rugged.references).to receive(:create).with('HEAD',
"refs/heads/#{project.default_branch}",
force: true)
-
project.change_head(project.default_branch)
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 799d99c0369..9a68ae086ea 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -239,6 +239,54 @@ describe Repository do
end
end
+ describe '#commits_by' do
+ set(:project) { create(:project, :repository) }
+
+ shared_examples 'batch commits fetching' do
+ let(:oids) { TestEnv::BRANCH_SHA.values }
+
+ subject { project.repository.commits_by(oids: oids) }
+
+ it 'finds each commit' do
+ expect(subject).not_to include(nil)
+ expect(subject.size).to eq(oids.size)
+ end
+
+ it 'returns only Commit instances' do
+ expect(subject).to all( be_a(Commit) )
+ end
+
+ context 'when some commits are not found ' do
+ let(:oids) do
+ ['deadbeef'] + TestEnv::BRANCH_SHA.values.first(10)
+ end
+
+ it 'returns only found commits' do
+ expect(subject).not_to include(nil)
+ expect(subject.size).to eq(10)
+ end
+ end
+
+ context 'when no oids are passed' do
+ let(:oids) { [] }
+
+ it 'does not call #batch_by_oid' do
+ expect(Gitlab::Git::Commit).not_to receive(:batch_by_oid)
+
+ subject
+ end
+ end
+ end
+
+ context 'when Gitaly list_commits_by_oid is enabled' do
+ it_behaves_like 'batch commits fetching'
+ end
+
+ context 'when Gitaly list_commits_by_oid is enabled', :disable_gitaly do
+ it_behaves_like 'batch commits fetching'
+ end
+ end
+
describe '#find_commits_by_message' do
shared_examples 'finding commits by message' do
it 'returns commits with messages containing a given string' do
@@ -1163,6 +1211,15 @@ describe Repository do
end
end
+ describe '#tag_exists?' do
+ it 'uses tag_names' do
+ allow(repository).to receive(:tag_names).and_return(['foobar'])
+
+ expect(repository.tag_exists?('foobar')).to eq(true)
+ expect(repository.tag_exists?('master')).to eq(false)
+ end
+ end
+
describe '#branch_names', :use_clean_rails_memory_store_caching do
let(:fake_branch_names) { ['foobar'] }
@@ -1922,23 +1979,6 @@ describe Repository do
File.delete(path)
end
-
- it "attempting to call keep_around when exists a lock does not fail" do
- ref = repository.send(:keep_around_ref_name, sample_commit.id)
- path = File.join(repository.path, ref)
- lock_path = "#{path}.lock"
-
- FileUtils.mkdir_p(File.dirname(path))
- File.open(lock_path, 'w') { |f| f.write('') }
-
- begin
- expect { repository.keep_around(sample_commit.id) }.not_to raise_error(Gitlab::Git::Repository::GitError)
-
- expect(File.exist?(lock_path)).to be_falsey
- ensure
- File.delete(path)
- end
- end
end
describe '#update_ref' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 4687d9dfa00..e58e7588df0 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -12,6 +12,7 @@ describe User do
it { is_expected.to include_module(Referable) }
it { is_expected.to include_module(Sortable) }
it { is_expected.to include_module(TokenAuthenticatable) }
+ it { is_expected.to include_module(BlocksJsonSerialization) }
end
describe 'delegations' do
diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb
new file mode 100644
index 00000000000..1b0e9fac355
--- /dev/null
+++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb
@@ -0,0 +1,92 @@
+require 'spec_helper'
+
+describe Ci::PipelineSchedulePolicy, :models do
+ set(:user) { create(:user) }
+ set(:project) { create(:project, :repository) }
+ set(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project) }
+
+ let(:policy) do
+ described_class.new(user, pipeline_schedule)
+ end
+
+ describe 'rules' do
+ describe 'rules for protected ref' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'when no one can push or merge to the branch' do
+ before do
+ create(:protected_branch, :no_one_can_push,
+ name: pipeline_schedule.ref, project: project)
+ end
+
+ it 'does not include ability to play pipeline schedule' do
+ expect(policy).to be_disallowed :play_pipeline_schedule
+ end
+ end
+
+ context 'when developers can push to the branch' do
+ before do
+ create(:protected_branch, :developers_can_merge,
+ name: pipeline_schedule.ref, project: project)
+ end
+
+ it 'includes ability to update pipeline' do
+ expect(policy).to be_allowed :play_pipeline_schedule
+ end
+ end
+
+ context 'when no one can create the tag' do
+ let(:tag) { 'v1.0.0' }
+
+ before do
+ pipeline_schedule.update(ref: tag)
+
+ create(:protected_tag, :no_one_can_create,
+ name: pipeline_schedule.ref, project: project)
+ end
+
+ it 'does not include ability to play pipeline schedule' do
+ expect(policy).to be_disallowed :play_pipeline_schedule
+ end
+ end
+
+ context 'when no one can create the tag but it is not a tag' do
+ before do
+ create(:protected_tag, :no_one_can_create,
+ name: pipeline_schedule.ref, project: project)
+ end
+
+ it 'includes ability to play pipeline schedule' do
+ expect(policy).to be_allowed :play_pipeline_schedule
+ end
+ end
+ end
+
+ describe 'rules for owner of schedule' do
+ before do
+ project.add_developer(user)
+ pipeline_schedule.update(owner: user)
+ end
+
+ it 'includes abilities to do do all operations on pipeline schedule' do
+ expect(policy).to be_allowed :play_pipeline_schedule
+ expect(policy).to be_allowed :update_pipeline_schedule
+ expect(policy).to be_allowed :admin_pipeline_schedule
+ end
+ end
+
+ describe 'rules for a master' do
+ before do
+ project.add_master(user)
+ end
+
+ it 'includes abilities to do do all operations on pipeline schedule' do
+ expect(policy).to be_allowed :play_pipeline_schedule
+ expect(policy).to be_allowed :update_pipeline_schedule
+ expect(policy).to be_allowed :admin_pipeline_schedule
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 91616da6d9a..60dbd74d59d 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -150,6 +150,26 @@ describe API::MergeRequests do
expect(json_response.length).to eq(1)
expect(json_response.first['id']).to eq(merge_request3.id)
end
+
+ context 'search params' do
+ before do
+ merge_request.update(title: 'Search title', description: 'Search description')
+ end
+
+ it 'returns merge requests matching given search string for title' do
+ get api("/merge_requests", user), search: merge_request.title
+
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+
+ it 'returns merge requests for project matching given search string for description' do
+ get api("/merge_requests", user), project_id: project.id, search: merge_request.description
+
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+ end
end
end
diff --git a/spec/serializers/merge_request_serializer_spec.rb b/spec/serializers/merge_request_serializer_spec.rb
index e3abefa6d63..1ad974c774b 100644
--- a/spec/serializers/merge_request_serializer_spec.rb
+++ b/spec/serializers/merge_request_serializer_spec.rb
@@ -1,37 +1,43 @@
require 'spec_helper'
describe MergeRequestSerializer do
- let(:user) { build_stubbed(:user) }
- let(:merge_request) { build_stubbed(:merge_request) }
-
- let(:serializer) do
+ let(:user) { create(:user) }
+ let(:resource) { create(:merge_request) }
+ let(:json_entity) do
described_class.new(current_user: user)
+ .represent(resource, serializer: serializer)
+ .with_indifferent_access
end
- describe '#represent' do
- let(:opts) { { serializer: serializer_entity } }
- subject { serializer.represent(merge_request, serializer: serializer_entity) }
+ context 'widget merge request serialization' do
+ let(:serializer) { 'widget' }
- context 'when passing basic serializer param' do
- let(:serializer_entity) { 'basic' }
+ it 'matches issue json schema' do
+ expect(json_entity).to match_schema('entities/merge_request_widget')
+ end
+ end
- it 'calls super class #represent with correct params' do
- expect_any_instance_of(BaseSerializer).to receive(:represent)
- .with(merge_request, opts, MergeRequestBasicEntity)
+ context 'sidebar merge request serialization' do
+ let(:serializer) { 'sidebar' }
- subject
- end
+ it 'matches basic merge request json schema' do
+ expect(json_entity).to match_schema('entities/merge_request_basic')
end
+ end
- context 'when serializer param is falsy' do
- let(:serializer_entity) { nil }
+ context 'basic merge request serialization' do
+ let(:serializer) { 'basic' }
+
+ it 'matches basic merge request json schema' do
+ expect(json_entity).to match_schema('entities/merge_request_basic')
+ end
+ end
- it 'calls super class #represent with correct params' do
- expect_any_instance_of(BaseSerializer).to receive(:represent)
- .with(merge_request, opts, MergeRequestEntity)
+ context 'no serializer' do
+ let(:serializer) { nil }
- subject
- end
+ it 'raises an error' do
+ expect { json_entity }.to raise_error(NoMethodError)
end
end
end
diff --git a/spec/serializers/merge_request_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 1ad672fd355..a5924a8589c 100644
--- a/spec/serializers/merge_request_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe MergeRequestEntity do
+describe MergeRequestWidgetEntity do
let(:project) { create :project, :repository }
let(:resource) { create(:merge_request, source_project: project, target_project: project) }
let(:user) { create(:user) }
@@ -35,33 +35,6 @@ describe MergeRequestEntity do
end
end
- it 'includes issues_links' do
- issues_links = subject[:issues_links]
-
- expect(issues_links).to include(:closing, :mentioned_but_not_closing,
- :assign_to_closing)
- end
-
- it 'has Issuable attributes' do
- expect(subject).to include(:id, :iid, :author_id, :description, :lock_version, :milestone_id,
- :title, :updated_by_id, :created_at, :updated_at, :milestone, :labels)
- end
-
- it 'has time estimation attributes' do
- expect(subject).to include(:time_estimate, :total_time_spent, :human_time_estimate, :human_total_time_spent)
- end
-
- it 'has important MergeRequest attributes' do
- expect(subject).to include(:state, :deleted_at, :diff_head_sha, :merge_commit_message,
- :has_conflicts, :has_ci, :merge_path,
- :conflict_resolution_path,
- :cancel_merge_when_pipeline_succeeds_path,
- :create_issue_to_resolve_discussions_path,
- :source_branch_path, :target_branch_commits_path,
- :target_branch_tree_path, :commits_count, :merge_ongoing,
- :ff_only_enabled)
- end
-
it 'has email_patches_path' do
expect(subject[:email_patches_path])
.to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.patch")
@@ -116,18 +89,6 @@ describe MergeRequestEntity do
end
end
- it 'includes merge_event' do
- create(:event, :merged, author: user, project: resource.project, target: resource)
-
- expect(subject[:merge_event]).to include(:author, :updated_at)
- end
-
- it 'includes closed_event' do
- create(:event, :closed, author: user, project: resource.project, target: resource)
-
- expect(subject[:closed_event]).to include(:author, :updated_at)
- end
-
describe 'diverged_commits_count' do
context 'when MR open and its diverging' do
it 'returns diverged commits count' do
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index 88d347322a6..c38795ad1a1 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -1,6 +1,7 @@
require 'spec_helper'
describe PipelineSerializer do
+ set(:project) { create(:project, :repository) }
set(:user) { create(:user) }
let(:serializer) do
@@ -16,7 +17,7 @@ describe PipelineSerializer do
end
context 'when a single object is being serialized' do
- let(:resource) { create(:ci_empty_pipeline) }
+ let(:resource) { create(:ci_empty_pipeline, project: project) }
it 'serializers the pipeline object' do
expect(subject[:id]).to eq resource.id
@@ -24,7 +25,7 @@ describe PipelineSerializer do
end
context 'when multiple objects are being serialized' do
- let(:resource) { create_list(:ci_pipeline, 2) }
+ let(:resource) { create_list(:ci_pipeline, 2, project: project) }
it 'serializers the array of pipelines' do
expect(subject).not_to be_empty
@@ -100,7 +101,6 @@ describe PipelineSerializer do
context 'number of queries' do
let(:resource) { Ci::Pipeline.all }
- let(:project) { create(:project) }
before do
# Since RequestStore.active? is true we have to allow the
diff --git a/spec/services/issuable/destroy_service_spec.rb b/spec/services/issuable/destroy_service_spec.rb
index d74d98c6079..0a3647a814f 100644
--- a/spec/services/issuable/destroy_service_spec.rb
+++ b/spec/services/issuable/destroy_service_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Issuable::DestroyService do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :public) }
subject(:service) { described_class.new(project, user) }
@@ -19,6 +19,13 @@ describe Issuable::DestroyService do
service.execute(issue)
end
+
+ it 'updates the todo caches for users with todos on the issue' do
+ create(:todo, target: issue, user: user, author: user, project: project)
+
+ expect { service.execute(issue) }
+ .to change { user.todos_pending_count }.from(1).to(0)
+ end
end
context 'when issuable is a merge request' do
@@ -33,6 +40,13 @@ describe Issuable::DestroyService do
service.execute(merge_request)
end
+
+ it 'updates the todo caches for users with todos on the merge request' do
+ create(:todo, target: merge_request, user: user, author: user, project: project)
+
+ expect { service.execute(merge_request) }
+ .to change { user.todos_pending_count }.from(1).to(0)
+ end
end
end
end
diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb
index c9a99a43edb..64445be560e 100644
--- a/spec/services/notes/destroy_service_spec.rb
+++ b/spec/services/notes/destroy_service_spec.rb
@@ -1,15 +1,25 @@
require 'spec_helper'
describe Notes::DestroyService do
+ set(:project) { create(:project, :public) }
+ set(:issue) { create(:issue, project: project) }
+ let(:user) { issue.author }
+
describe '#execute' do
it 'deletes a note' do
- project = create(:project)
- issue = create(:issue, project: project)
note = create(:note, project: project, noteable: issue)
- described_class.new(project, note.author).execute(note)
+ described_class.new(project, user).execute(note)
expect(project.issues.find(issue.id).notes).not_to include(note)
end
+
+ it 'updates the todo counts for users with todos for the note' do
+ note = create(:note, project: project, noteable: issue)
+ create(:todo, note: note, target: issue, user: user, author: user, project: project)
+
+ expect { described_class.new(project, user).execute(note) }
+ .to change { user.todos_pending_count }.from(1).to(0)
+ end
end
end
diff --git a/spec/services/projects/unlink_fork_service_spec.rb b/spec/services/projects/unlink_fork_service_spec.rb
index 2bba71fef4f..3ec6139bfa6 100644
--- a/spec/services/projects/unlink_fork_service_spec.rb
+++ b/spec/services/projects/unlink_fork_service_spec.rb
@@ -62,6 +62,26 @@ describe Projects::UnlinkForkService do
expect(source.forks_count).to be_zero
end
+ context 'when the source has LFS objects' do
+ let(:lfs_object) { create(:lfs_object) }
+
+ before do
+ lfs_object.projects << project
+ end
+
+ it 'links the fork to the lfs object before unlinking' do
+ subject.execute
+
+ expect(lfs_object.projects).to include(forked_project)
+ end
+
+ it 'does not fail if the lfs objects were already linked' do
+ lfs_object.projects << forked_project
+
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+
context 'when the original project was deleted' do
it 'does not fail when the original project is deleted' do
source = forked_project.forked_from_project
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index c35177f6ebc..eb46480fa54 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -209,7 +209,7 @@ describe QuickActions::InterpretService do
expect(updates).to eq(spend_time: {
duration: 3600,
- user: developer,
+ user_id: developer.id,
spent_at: DateTime.now.to_date
})
end
@@ -221,7 +221,7 @@ describe QuickActions::InterpretService do
expect(updates).to eq(spend_time: {
duration: -1800,
- user: developer,
+ user_id: developer.id,
spent_at: DateTime.now.to_date
})
end
@@ -233,7 +233,7 @@ describe QuickActions::InterpretService do
expect(updates).to eq(spend_time: {
duration: 1800,
- user: developer,
+ user_id: developer.id,
spent_at: Date.parse(date)
})
end
@@ -267,7 +267,7 @@ describe QuickActions::InterpretService do
it 'populates spend_time: :reset if content contains /remove_time_spent' do
_, updates = service.execute(content, issuable)
- expect(updates).to eq(spend_time: { duration: :reset, user: developer })
+ expect(updates).to eq(spend_time: { duration: :reset, user_id: developer.id })
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 47412110b4b..9025589ae0b 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -927,7 +927,7 @@ describe SystemNoteService do
# We need a custom noteable in order to the shared examples to be green.
let(:noteable) do
mr = create(:merge_request, source_project: project)
- mr.spend_time(duration: 360000, user: author)
+ mr.spend_time(duration: 360000, user_id: author.id)
mr.save!
mr
end
@@ -965,7 +965,7 @@ describe SystemNoteService do
end
def spend_time!(seconds)
- noteable.spend_time(duration: seconds, user: author)
+ noteable.spend_time(duration: seconds, user_id: author.id)
noteable.save!
end
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index dc2673abc73..88013acae0a 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -248,11 +248,26 @@ describe TodoService do
end
end
- describe '#destroy_issuable' do
- it 'refresh the todos count cache for the user' do
- expect(john_doe).to receive(:update_todos_count_cache).and_call_original
+ describe '#destroy_target' do
+ it 'refreshes the todos count cache for users with todos on the target' do
+ create(:todo, target: issue, user: john_doe, author: john_doe, project: issue.project)
- service.destroy_issuable(issue, john_doe)
+ expect_any_instance_of(User).to receive(:update_todos_count_cache).and_call_original
+
+ service.destroy_target(issue) { }
+ end
+
+ it 'does not refresh the todos count cache for users with only done todos on the target' do
+ create(:todo, :done, target: issue, user: john_doe, author: john_doe, project: issue.project)
+
+ expect_any_instance_of(User).not_to receive(:update_todos_count_cache)
+
+ service.destroy_target(issue) { }
+ end
+
+ it 'yields the target to the caller' do
+ expect { |b| service.destroy_target(issue, &b) }
+ .to yield_with_args(issue)
end
end
diff --git a/spec/support/api/time_tracking_shared_examples.rb b/spec/support/api/time_tracking_shared_examples.rb
index af1083f4bfd..dd3089d22e5 100644
--- a/spec/support/api/time_tracking_shared_examples.rb
+++ b/spec/support/api/time_tracking_shared_examples.rb
@@ -79,7 +79,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
context 'when subtracting time' do
it 'subtracts time of the total spent time' do
- issuable.update_attributes!(spend_time: { duration: 7200, user: user })
+ issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
duration: '-1h'
@@ -91,7 +91,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
context 'when time to subtract is greater than the total spent time' do
it 'does not modify the total time spent' do
- issuable.update_attributes!(spend_time: { duration: 7200, user: user })
+ issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
duration: '-1w'
@@ -119,7 +119,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
describe "GET /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_stats" do
it "returns the time stats for #{issuable_name}" do
- issuable.update_attributes!(spend_time: { duration: 1800, user: user },
+ issuable.update_attributes!(spend_time: { duration: 1800, user_id: user.id },
time_estimate: 3600)
get api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_stats", user)
diff --git a/spec/support/api/v3/time_tracking_shared_examples.rb b/spec/support/api/v3/time_tracking_shared_examples.rb
index afe0f4cecda..f27a2d06c83 100644
--- a/spec/support/api/v3/time_tracking_shared_examples.rb
+++ b/spec/support/api/v3/time_tracking_shared_examples.rb
@@ -75,7 +75,7 @@ shared_examples 'V3 time tracking endpoints' do |issuable_name|
context 'when subtracting time' do
it 'subtracts time of the total spent time' do
- issuable.update_attributes!(spend_time: { duration: 7200, user: user })
+ issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user),
duration: '-1h'
@@ -87,7 +87,7 @@ shared_examples 'V3 time tracking endpoints' do |issuable_name|
context 'when time to subtract is greater than the total spent time' do
it 'does not modify the total time spent' do
- issuable.update_attributes!(spend_time: { duration: 7200, user: user })
+ issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id })
post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user),
duration: '-1w'
@@ -115,7 +115,7 @@ shared_examples 'V3 time tracking endpoints' do |issuable_name|
describe "GET /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_stats" do
it "returns the time stats for #{issuable_name}" do
- issuable.update_attributes!(spend_time: { duration: 1800, user: user },
+ issuable.update_attributes!(spend_time: { duration: 1800, user_id: user.id },
time_estimate: 3600)
get v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_stats", user)
diff --git a/spec/views/events/event/_push.html.haml_spec.rb b/spec/views/events/event/_push.html.haml_spec.rb
new file mode 100644
index 00000000000..f5634de4916
--- /dev/null
+++ b/spec/views/events/event/_push.html.haml_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe 'events/event/_push.html.haml' do
+ let(:event) { build_stubbed(:push_event) }
+
+ context 'with a branch' do
+ let(:payload) { build_stubbed(:push_event_payload, event: event) }
+
+ before do
+ allow(event).to receive(:push_event_payload).and_return(payload)
+ end
+
+ it 'links to the branch' do
+ allow(event.project.repository).to receive(:branch_exists?).with(event.ref_name).and_return(true)
+ link = project_commits_path(event.project, event.ref_name)
+
+ render partial: 'events/event/push', locals: { event: event }
+
+ expect(rendered).to have_link(event.ref_name, href: link)
+ end
+
+ context 'that has been deleted' do
+ it 'does not link to the branch' do
+ render partial: 'events/event/push', locals: { event: event }
+
+ expect(rendered).not_to have_link(event.ref_name)
+ end
+ end
+ end
+
+ context 'with a tag' do
+ let(:payload) { build_stubbed(:push_event_payload, event: event, ref_type: :tag, ref: 'v0.1.0') }
+
+ before do
+ allow(event).to receive(:push_event_payload).and_return(payload)
+ end
+
+ it 'links to the tag' do
+ allow(event.project.repository).to receive(:tag_exists?).with(event.ref_name).and_return(true)
+ link = project_commits_path(event.project, event.ref_name)
+
+ render partial: 'events/event/push', locals: { event: event }
+
+ expect(rendered).to have_link(event.ref_name, href: link)
+ end
+
+ context 'that has been deleted' do
+ it 'does not link to the tag' do
+ render partial: 'events/event/push', locals: { event: event }
+
+ expect(rendered).not_to have_link(event.ref_name)
+ end
+ end
+ end
+end
diff --git a/spec/workers/concerns/project_import_options_spec.rb b/spec/workers/concerns/project_import_options_spec.rb
new file mode 100644
index 00000000000..b6c111df8b9
--- /dev/null
+++ b/spec/workers/concerns/project_import_options_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe ProjectImportOptions do
+ let(:project) { create(:project, :import_started) }
+ let(:job) { { 'args' => [project.id, nil, nil], 'jid' => '123' } }
+ let(:worker_class) do
+ Class.new do
+ include Sidekiq::Worker
+ include ProjectImportOptions
+ end
+ end
+
+ it 'sets default retry limit' do
+ expect(worker_class.sidekiq_options['retry']).to eq(ProjectImportOptions::IMPORT_RETRY_COUNT)
+ end
+
+ it 'sets default status expiration' do
+ expect(worker_class.sidekiq_options['status_expiration']).to eq(StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
+ end
+
+ describe '.sidekiq_retries_exhausted' do
+ it 'marks fork as failed' do
+ expect { worker_class.sidekiq_retries_exhausted_block.call(job) }.to change { project.reload.import_status }.from("started").to("failed")
+ end
+
+ it 'logs the appropriate error message for forked projects' do
+ allow_any_instance_of(Project).to receive(:forked?).and_return(true)
+
+ worker_class.sidekiq_retries_exhausted_block.call(job)
+
+ expect(project.reload.import_error).to include("fork")
+ end
+
+ it 'logs the appropriate error message for forked projects' do
+ worker_class.sidekiq_retries_exhausted_block.call(job)
+
+ expect(project.reload.import_error).to include("import")
+ end
+ end
+end
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index 74c85848b7e..31598586f59 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -1,17 +1,21 @@
require 'spec_helper'
describe RepositoryForkWorker do
- let(:project) { create(:project, :repository) }
- let(:fork_project) { create(:project, :repository, :import_scheduled, forked_from_project: project) }
- let(:shell) { Gitlab::Shell.new }
-
- subject { described_class.new }
-
- before do
- allow(subject).to receive(:gitlab_shell).and_return(shell)
+ describe 'modules' do
+ it 'includes ProjectImportOptions' do
+ expect(described_class).to include_module(ProjectImportOptions)
+ end
end
describe "#perform" do
+ let(:project) { create(:project, :repository) }
+ let(:fork_project) { create(:project, :repository, :import_scheduled, forked_from_project: project) }
+ let(:shell) { Gitlab::Shell.new }
+
+ before do
+ allow(subject).to receive(:gitlab_shell).and_return(shell)
+ end
+
def perform!
subject.perform(fork_project.id, '/test/path', project.disk_path)
end
@@ -60,14 +64,7 @@ describe RepositoryForkWorker do
expect_fork_repository.and_return(false)
- expect { perform! }.to raise_error(RepositoryForkWorker::ForkError, error_message)
- end
-
- it 'handles unexpected error' do
- expect_fork_repository.and_raise(RuntimeError)
-
- expect { perform! }.to raise_error(RepositoryForkWorker::ForkError)
- expect(fork_project.reload.import_status).to eq('failed')
+ expect { perform! }.to raise_error(StandardError, error_message)
end
end
end
diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb
index 0af537647ad..85ac14eb347 100644
--- a/spec/workers/repository_import_worker_spec.rb
+++ b/spec/workers/repository_import_worker_spec.rb
@@ -1,11 +1,15 @@
require 'spec_helper'
describe RepositoryImportWorker do
- let(:project) { create(:project, :import_scheduled) }
-
- subject { described_class.new }
+ describe 'modules' do
+ it 'includes ProjectImportOptions' do
+ expect(described_class).to include_module(ProjectImportOptions)
+ end
+ end
describe '#perform' do
+ let(:project) { create(:project, :import_scheduled) }
+
context 'when worker was reset without cleanup' do
let(:jid) { '12345678' }
let(:started_project) { create(:project, :import_started, import_jid: jid) }
@@ -44,22 +48,11 @@ describe RepositoryImportWorker do
expect do
subject.perform(project.id)
- end.to raise_error(RepositoryImportWorker::ImportError, error)
+ end.to raise_error(StandardError, error)
expect(project.reload.import_jid).not_to be_nil
end
end
- context 'with unexpected error' do
- it 'marks import as failed' do
- allow_any_instance_of(Projects::ImportService).to receive(:execute).and_raise(RuntimeError)
-
- expect do
- subject.perform(project.id)
- end.to raise_error(RepositoryImportWorker::ImportError)
- expect(project.reload.import_status).to eq('failed')
- end
- end
-
context 'when using an asynchronous importer' do
it 'does not mark the import process as finished' do
service = double(:service)
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
new file mode 100644
index 00000000000..481a84837f9
--- /dev/null
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe RunPipelineScheduleWorker do
+ describe '#perform' do
+ set(:project) { create(:project) }
+ set(:user) { create(:user) }
+ set(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) }
+ let(:worker) { described_class.new }
+
+ context 'when a project not found' do
+ it 'does not call the Service' do
+ expect(Ci::CreatePipelineService).not_to receive(:new)
+ expect(worker).not_to receive(:run_pipeline_schedule)
+
+ worker.perform(100000, user.id)
+ end
+ end
+
+ context 'when a user not found' do
+ it 'does not call the Service' do
+ expect(Ci::CreatePipelineService).not_to receive(:new)
+ expect(worker).not_to receive(:run_pipeline_schedule)
+
+ worker.perform(pipeline_schedule.id, 10000)
+ end
+ end
+
+ context 'when everything is ok' do
+ let(:create_pipeline_service) { instance_double(Ci::CreatePipelineService) }
+
+ it 'calls the Service' do
+ expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service)
+ expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule)
+
+ worker.perform(pipeline_schedule.id, user.id)
+ end
+ end
+ end
+end