summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/groups/milestones_controller_spec.rb135
-rw-r--r--spec/controllers/groups_controller_spec.rb257
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb26
-rw-r--r--spec/controllers/projects/labels_controller_spec.rb70
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb12
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb38
-rw-r--r--spec/controllers/projects_controller_spec.rb199
-rw-r--r--spec/controllers/users_controller_spec.rb253
-rw-r--r--spec/features/issues/note_polling_spec.rb24
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb2
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request.json1
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_basic.json3
-rw-r--r--spec/javascripts/abuse_reports_spec.js4
-rw-r--r--spec/javascripts/activities_spec.js6
-rw-r--r--spec/javascripts/ajax_loading_spinner_spec.js8
-rw-r--r--spec/javascripts/api_spec.js281
-rw-r--r--spec/javascripts/awards_handler_spec.js2
-rw-r--r--spec/javascripts/behaviors/autosize_spec.js2
-rw-r--r--spec/javascripts/behaviors/quick_submit_spec.js2
-rw-r--r--spec/javascripts/behaviors/requires_input_spec.js2
-rw-r--r--spec/javascripts/blob/create_branch_dropdown_spec.js6
-rw-r--r--spec/javascripts/blob/target_branch_dropdown_spec.js6
-rw-r--r--spec/javascripts/boards/board_card_spec.js10
-rw-r--r--spec/javascripts/boards/board_new_issue_spec.js4
-rw-r--r--spec/javascripts/commits_spec.js6
-rw-r--r--spec/javascripts/datetime_utility_spec.js2
-rw-r--r--spec/javascripts/diff_comments_store_spec.js6
-rw-r--r--spec/javascripts/extensions/array_spec.js2
-rw-r--r--spec/javascripts/filtered_search/dropdown_user_spec.js8
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js8
-rw-r--r--spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js8
-rw-r--r--spec/javascripts/filtered_search/filtered_search_manager_spec.js15
-rw-r--r--spec/javascripts/filtered_search/filtered_search_token_keys_spec.js4
-rw-r--r--spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js6
-rw-r--r--spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js4
-rw-r--r--spec/javascripts/gfm_auto_complete_spec.js4
-rw-r--r--spec/javascripts/gl_dropdown_spec.js6
-rw-r--r--spec/javascripts/gl_field_errors_spec.js2
-rw-r--r--spec/javascripts/gl_form_spec.js22
-rw-r--r--spec/javascripts/header_spec.js4
-rw-r--r--spec/javascripts/helpers/class_spec_helper.js4
-rw-r--r--spec/javascripts/helpers/class_spec_helper_spec.js2
-rw-r--r--spec/javascripts/helpers/filtered_search_spec_helper.js4
-rw-r--r--spec/javascripts/issuable_spec.js4
-rw-r--r--spec/javascripts/issue_spec.js2
-rw-r--r--spec/javascripts/labels_issue_sidebar_spec.js16
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js2
-rw-r--r--spec/javascripts/lib/utils/text_utility_spec.js2
-rw-r--r--spec/javascripts/line_highlighter_spec.js2
-rw-r--r--spec/javascripts/merge_request_spec.js2
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js16
-rw-r--r--spec/javascripts/new_branch_spec.js2
-rw-r--r--spec/javascripts/notes_spec.js1
-rw-r--r--spec/javascripts/pager_spec.js2
-rw-r--r--spec/javascripts/pretty_time_spec.js2
-rw-r--r--spec/javascripts/project_title_spec.js10
-rw-r--r--spec/javascripts/search_autocomplete_spec.js8
-rw-r--r--spec/javascripts/shortcuts_issuable_spec.js4
-rw-r--r--spec/javascripts/signin_tabs_memoizer_spec.js2
-rw-r--r--spec/javascripts/smart_interval_spec.js2
-rw-r--r--spec/javascripts/syntax_highlight_spec.js2
-rw-r--r--spec/javascripts/test_bundle.js14
-rw-r--r--spec/javascripts/todos_spec.js4
-rw-r--r--spec/javascripts/u2f/authenticate_spec.js10
-rw-r--r--spec/javascripts/u2f/register_spec.js10
-rw-r--r--spec/javascripts/version_check_image_spec.js5
-rw-r--r--spec/javascripts/visibility_select_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js2
-rw-r--r--spec/javascripts/zen_mode_spec.js2
-rw-r--r--spec/migrations/fix_wrongly_renamed_routes_spec.rb73
-rw-r--r--spec/migrations/rename_users_with_renamed_namespace_spec.rb22
-rw-r--r--spec/migrations/upate_retried_for_ci_builds_spec.rb17
-rw-r--r--spec/models/ci/pipeline_spec.rb10
-rw-r--r--spec/routing/project_routing_spec.rb5
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/milestone_tabs_examples.rb2
77 files changed, 1254 insertions, 479 deletions
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index 7cf2996ffd0..f3263bc177d 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -21,7 +21,6 @@ describe Groups::MilestonesController do
sign_in(user)
group.add_owner(user)
project.team << [user, :master]
- controller.instance_variable_set(:@group, group)
end
it_behaves_like 'milestone tabs'
@@ -29,7 +28,7 @@ describe Groups::MilestonesController do
describe "#create" do
it "creates group milestone with Chinese title" do
post :create,
- group_id: group.id,
+ group_id: group.to_param,
milestone: { project_ids: [project.id, project2.id], title: title }
expect(response).to redirect_to(group_milestone_path(group, title.to_slug.to_s, title: title))
@@ -37,9 +36,139 @@ describe Groups::MilestonesController do
end
it "redirects to new when there are no project ids" do
- post :create, group_id: group.id, milestone: { title: title, project_ids: [""] }
+ post :create, group_id: group.to_param, milestone: { title: title, project_ids: [""] }
expect(response).to render_template :new
expect(assigns(:milestone).errors).not_to be_nil
end
end
+
+ describe '#ensure_canonical_path' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a GET request' do
+ context 'when requesting the canonical path' do
+ context 'non-show path' do
+ context 'with exactly matching casing' do
+ it 'does not redirect' do
+ get :index, group_id: group.to_param
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get :index, group_id: group.to_param.upcase
+
+ expect(response).to redirect_to(group_milestones_path(group.to_param))
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+
+ context 'show path' do
+ context 'with exactly matching casing' do
+ it 'does not redirect' do
+ get :show, group_id: group.to_param, id: title
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get :show, group_id: group.to_param.upcase, id: title
+
+ expect(response).to redirect_to(group_milestone_path(group.to_param, title))
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+
+ it 'redirects to the canonical path' do
+ get :merge_requests, group_id: redirect_route.path, id: title
+
+ expect(response).to redirect_to(merge_requests_group_milestone_path(group.to_param, title))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+
+ context 'when the old group path is a substring of the scheme or host' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'http') }
+
+ it 'does not modify the requested host' do
+ get :merge_requests, group_id: redirect_route.path, id: title
+
+ expect(response).to redirect_to(merge_requests_group_milestone_path(group.to_param, title))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+
+ context 'when the old group path is substring of groups' do
+ # I.e. /groups/oups should not become /grfoo/oups
+ let(:redirect_route) { group.redirect_routes.create(path: 'oups') }
+
+ it 'does not modify the /groups part of the path' do
+ get :merge_requests, group_id: redirect_route.path, id: title
+
+ expect(response).to redirect_to(merge_requests_group_milestone_path(group.to_param, title))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+
+ context 'when the old group path is substring of groups plus the new path' do
+ # I.e. /groups/oups/oup should not become /grfoos
+ let(:redirect_route) { group.redirect_routes.create(path: 'oups/oup') }
+
+ it 'does not modify the /groups part of the path' do
+ get :merge_requests, group_id: redirect_route.path, id: title
+
+ expect(response).to redirect_to(merge_requests_group_milestone_path(group.to_param, title))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+ end
+ end
+ end
+
+ context 'for a non-GET request' do
+ context 'when requesting the canonical path with different casing' do
+ it 'does not 404' do
+ post :create,
+ group_id: group.to_param,
+ milestone: { project_ids: [project.id, project2.id], title: title }
+
+ expect(response).not_to have_http_status(404)
+ end
+
+ it 'does not redirect to the correct casing' do
+ post :create,
+ group_id: group.to_param,
+ milestone: { project_ids: [project.id, project2.id], title: title }
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+
+ it 'returns not found' do
+ post :create,
+ group_id: redirect_route.path,
+ milestone: { project_ids: [project.id, project2.id], title: title }
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ def group_moved_message(redirect_route, group)
+ "Group '#{redirect_route.path}' was moved to '#{group.full_path}'. Please update any links and bookmarks that may still have the old path."
+ end
end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 15dae3231ca..4626f1ebc29 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -84,26 +84,6 @@ describe GroupsController do
expect(assigns(:issues)).to eq [issue_2, issue_1]
end
end
-
- context 'when requesting the canonical path with different casing' do
- it 'redirects to the correct casing' do
- get :issues, id: group.to_param.upcase
-
- expect(response).to redirect_to(issues_group_path(group.to_param))
- expect(controller).not_to set_flash[:notice]
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
-
- it 'redirects to the canonical path' do
- get :issues, id: redirect_route.path
-
- expect(response).to redirect_to(issues_group_path(group.to_param))
- expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
- end
- end
end
describe 'GET #merge_requests' do
@@ -129,26 +109,6 @@ describe GroupsController do
expect(assigns(:merge_requests)).to eq [merge_request_2, merge_request_1]
end
end
-
- context 'when requesting the canonical path with different casing' do
- it 'redirects to the correct casing' do
- get :merge_requests, id: group.to_param.upcase
-
- expect(response).to redirect_to(merge_requests_group_path(group.to_param))
- expect(controller).not_to set_flash[:notice]
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
-
- it 'redirects to the canonical path' do
- get :merge_requests, id: redirect_route.path
-
- expect(response).to redirect_to(merge_requests_group_path(group.to_param))
- expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
- end
- end
end
describe 'DELETE #destroy' do
@@ -178,30 +138,6 @@ describe GroupsController do
expect(response).to redirect_to(root_path)
end
-
- context 'when requesting the canonical path with different casing' do
- it 'does not 404' do
- delete :destroy, id: group.to_param.upcase
-
- expect(response).not_to have_http_status(404)
- end
-
- it 'does not redirect to the correct casing' do
- delete :destroy, id: group.to_param.upcase
-
- expect(response).not_to redirect_to(group_path(group.to_param))
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
-
- it 'returns not found' do
- delete :destroy, id: redirect_route.path
-
- expect(response).to have_http_status(404)
- end
- end
end
end
@@ -224,28 +160,197 @@ describe GroupsController do
expect(assigns(:group).errors).not_to be_empty
expect(assigns(:group).path).not_to eq('new_path')
end
+ end
+
+ describe '#ensure_canonical_path' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a GET request' do
+ context 'when requesting groups at the root path' do
+ before do
+ allow(request).to receive(:original_fullpath).and_return("/#{group_full_path}")
+ get :show, id: group_full_path
+ end
+
+ context 'when requesting the canonical path with different casing' do
+ let(:group_full_path) { group.to_param.upcase }
+
+ it 'redirects to the correct casing' do
+ expect(response).to redirect_to(group)
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ let(:group_full_path) { redirect_route.path }
+
+ it 'redirects to the canonical path' do
+ expect(response).to redirect_to(group)
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+
+ context 'when the old group path is a substring of the scheme or host' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'http') }
+
+ it 'does not modify the requested host' do
+ expect(response).to redirect_to(group)
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+
+ context 'when the old group path is substring of groups' do
+ # I.e. /groups/oups should not become /grfoo/oups
+ let(:redirect_route) { group.redirect_routes.create(path: 'oups') }
+
+ it 'does not modify the /groups part of the path' do
+ expect(response).to redirect_to(group)
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+ end
+ end
+
+ context 'when requesting groups under the /groups path' do
+ context 'when requesting the canonical path' do
+ context 'non-show path' do
+ context 'with exactly matching casing' do
+ it 'does not redirect' do
+ get :issues, id: group.to_param
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get :issues, id: group.to_param.upcase
+
+ expect(response).to redirect_to(issues_group_path(group.to_param))
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+
+ context 'show path' do
+ context 'with exactly matching casing' do
+ it 'does not redirect' do
+ get :show, id: group.to_param
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing at the root path' do
+ get :show, id: group.to_param.upcase
+
+ expect(response).to redirect_to(group)
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+
+ it 'redirects to the canonical path' do
+ get :issues, id: redirect_route.path
+
+ expect(response).to redirect_to(issues_group_path(group.to_param))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+
+ context 'when the old group path is a substring of the scheme or host' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'http') }
+
+ it 'does not modify the requested host' do
+ get :issues, id: redirect_route.path
+
+ expect(response).to redirect_to(issues_group_path(group.to_param))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+
+ context 'when the old group path is substring of groups' do
+ # I.e. /groups/oups should not become /grfoo/oups
+ let(:redirect_route) { group.redirect_routes.create(path: 'oups') }
+
+ it 'does not modify the /groups part of the path' do
+ get :issues, id: redirect_route.path
+
+ expect(response).to redirect_to(issues_group_path(group.to_param))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+
+ context 'when the old group path is substring of groups plus the new path' do
+ # I.e. /groups/oups/oup should not become /grfoos
+ let(:redirect_route) { group.redirect_routes.create(path: 'oups/oup') }
+
+ it 'does not modify the /groups part of the path' do
+ get :issues, id: redirect_route.path
+
+ expect(response).to redirect_to(issues_group_path(group.to_param))
+ expect(controller).to set_flash[:notice].to(group_moved_message(redirect_route, group))
+ end
+ end
+ end
+ end
+ end
- context 'when requesting the canonical path with different casing' do
- it 'does not 404' do
- post :update, id: group.to_param.upcase, group: { path: 'new_path' }
+ context 'for a POST request' do
+ context 'when requesting the canonical path with different casing' do
+ it 'does not 404' do
+ post :update, id: group.to_param.upcase, group: { path: 'new_path' }
+
+ expect(response).not_to have_http_status(404)
+ end
+
+ it 'does not redirect to the correct casing' do
+ post :update, id: group.to_param.upcase, group: { path: 'new_path' }
- expect(response).not_to have_http_status(404)
+ expect(response).not_to have_http_status(301)
+ end
end
- it 'does not redirect to the correct casing' do
- post :update, id: group.to_param.upcase, group: { path: 'new_path' }
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
- expect(response).not_to redirect_to(group_path(group.to_param))
+ it 'returns not found' do
+ post :update, id: redirect_route.path, group: { path: 'new_path' }
+
+ expect(response).to have_http_status(404)
+ end
end
end
- context 'when requesting a redirected path' do
- let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+ context 'for a DELETE request' do
+ context 'when requesting the canonical path with different casing' do
+ it 'does not 404' do
+ delete :destroy, id: group.to_param.upcase
+
+ expect(response).not_to have_http_status(404)
+ end
+
+ it 'does not redirect to the correct casing' do
+ delete :destroy, id: group.to_param.upcase
- it 'returns not found' do
- post :update, id: redirect_route.path, group: { path: 'new_path' }
+ expect(response).not_to have_http_status(301)
+ end
+ end
- expect(response).to have_http_status(404)
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { group.redirect_routes.create(path: 'old-path') }
+
+ it 'returns not found' do
+ delete :destroy, id: redirect_route.path
+
+ expect(response).to have_http_status(404)
+ end
end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 1f79e72495a..04afd07c59e 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -156,6 +156,32 @@ describe Projects::IssuesController do
end
end
+ describe 'Redirect after sign in' do
+ context 'with an AJAX request' do
+ it 'does not store the visited URL' do
+ xhr :get,
+ :show,
+ format: :json,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: issue.iid
+
+ expect(session['user_return_to']).to be_blank
+ end
+ end
+
+ context 'without an AJAX request' do
+ it 'stores the visited URL' do
+ get :show,
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: issue.iid
+
+ expect(session['user_return_to']).to eq("/#{project.namespace.to_param}/#{project.to_param}/issues/#{issue.iid}")
+ end
+ end
+ end
+
describe 'PUT #update' do
before do
sign_in(user)
diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb
index 05999431d8f..130b0b744b5 100644
--- a/spec/controllers/projects/labels_controller_spec.rb
+++ b/spec/controllers/projects/labels_controller_spec.rb
@@ -157,4 +157,74 @@ describe Projects::LabelsController do
end
end
end
+
+ describe '#ensure_canonical_path' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a GET request' do
+ context 'when requesting the canonical path' do
+ context 'non-show path' do
+ context 'with exactly matching casing' do
+ it 'does not redirect' do
+ get :index, namespace_id: project.namespace, project_id: project.to_param
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get :index, namespace_id: project.namespace, project_id: project.to_param.upcase
+
+ expect(response).to redirect_to(namespace_project_labels_path(project.namespace, project))
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let!(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
+
+ it 'redirects to the canonical path' do
+ get :index, namespace_id: project.namespace, project_id: project.to_param + 'old'
+
+ expect(response).to redirect_to(namespace_project_labels_path(project.namespace, project))
+ expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, project))
+ end
+ end
+ end
+ end
+
+ context 'for a non-GET request' do
+ context 'when requesting the canonical path with different casing' do
+ it 'does not 404' do
+ post :generate, namespace_id: project.namespace, project_id: project
+
+ expect(response).not_to have_http_status(404)
+ end
+
+ it 'does not redirect to the correct casing' do
+ post :generate, namespace_id: project.namespace, project_id: project
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let!(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
+
+ it 'returns not found' do
+ post :generate, namespace_id: project.namespace, project_id: project.to_param + 'old'
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ def project_moved_message(redirect_route, project)
+ "Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
+ end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 0b3492a8fed..f0dc6df15ee 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -119,6 +119,18 @@ describe Projects::MergeRequestsController do
expect(response).to match_response_schema('entities/merge_request')
end
end
+
+ context 'number of queries' do
+ it 'verifies number of queries' do
+ # pre-create objects
+ merge_request
+
+ recorded = ActiveRecord::QueryRecorder.new { go(format: :json) }
+
+ expect(recorded.count).to be_within(1).of(51)
+ expect(recorded.cached_count).to eq(0)
+ end
+ end
end
describe "as diff" do
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index fb4a4721a58..c880da1e36a 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -38,7 +38,7 @@ describe Projects::PipelinesController do
end
describe 'GET show JSON' do
- let!(:pipeline) { create(:ci_pipeline_with_one_job, project: project) }
+ let(:pipeline) { create(:ci_pipeline_with_one_job, project: project) }
it 'returns the pipeline' do
get_pipeline_json
@@ -49,20 +49,48 @@ describe Projects::PipelinesController do
expect(json_response['details']).to have_key 'stages'
end
- context 'when the pipeline has multiple jobs' do
+ context 'when the pipeline has multiple stages and groups' do
+ before do
+ RequestStore.begin!
+
+ create_build('build', 0, 'build')
+ create_build('test', 1, 'rspec 0')
+ create_build('deploy', 2, 'production')
+ create_build('post deploy', 3, 'pages 0')
+ end
+
+ after do
+ RequestStore.end!
+ RequestStore.clear!
+ end
+
+ let(:project) { create(:project) }
+ let(:pipeline) do
+ create(:ci_empty_pipeline, project: project, user: user, sha: project.commit.id)
+ end
+
it 'does not perform N + 1 queries' do
control_count = ActiveRecord::QueryRecorder.new { get_pipeline_json }.count
- create(:ci_build, pipeline: pipeline)
+ create_build('test', 1, 'rspec 1')
+ create_build('test', 1, 'spinach 0')
+ create_build('test', 1, 'spinach 1')
+ create_build('test', 1, 'audit')
+ create_build('post deploy', 3, 'pages 1')
+ create_build('post deploy', 3, 'pages 2')
- # The plus 2 is needed to group and sort
- expect { get_pipeline_json }.not_to exceed_query_limit(control_count + 2)
+ new_count = ActiveRecord::QueryRecorder.new { get_pipeline_json }.count
+ expect(new_count).to be_within(12).of(control_count)
end
end
def get_pipeline_json
get :show, namespace_id: project.namespace, project_id: project, id: pipeline, format: :json
end
+
+ def create_build(stage, stage_idx, name)
+ create(:ci_build, pipeline: pipeline, stage: stage, stage_idx: stage_idx, name: name)
+ end
end
describe 'GET stages.json' do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index e230944d52e..a8be6768a47 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -169,27 +169,6 @@ describe ProjectsController do
end
end
- context "when requested with case sensitive namespace and project path" do
- context "when there is a match with the same casing" do
- it "loads the project" do
- get :show, namespace_id: public_project.namespace, id: public_project
-
- expect(assigns(:project)).to eq(public_project)
- expect(response).to have_http_status(200)
- end
- end
-
- context "when there is a match with different casing" do
- it "redirects to the normalized path" do
- get :show, namespace_id: public_project.namespace, id: public_project.path.upcase
-
- expect(assigns(:project)).to eq(public_project)
- expect(response).to redirect_to("/#{public_project.full_path}")
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
context "when the url contains .atom" do
let(:public_project_with_dot_atom) { build(:empty_project, :public, name: 'my.atom', path: 'my.atom') }
@@ -219,17 +198,6 @@ describe ProjectsController do
expect(response).to redirect_to(namespace_project_path)
end
end
-
- context 'when requesting a redirected path' do
- let!(:redirect_route) { public_project.redirect_routes.create!(path: "foo/bar") }
-
- it 'redirects to the canonical path' do
- get :show, namespace_id: 'foo', id: 'bar'
-
- expect(response).to redirect_to(public_project)
- expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, public_project))
- end
- end
end
describe "#update" do
@@ -256,34 +224,6 @@ describe ProjectsController do
expect(assigns(:repository).path).to eq(project.repository.path)
expect(response).to have_http_status(302)
end
-
- context 'when requesting the canonical path' do
- it "is case-insensitive" do
- controller.instance_variable_set(:@project, project)
-
- put :update,
- namespace_id: 'FOo',
- id: 'baR',
- project: project_params
-
- expect(project.repository.path).to include(new_path)
- expect(assigns(:repository).path).to eq(project.repository.path)
- expect(response).to have_http_status(302)
- end
- end
-
- context 'when requesting a redirected path' do
- let!(:redirect_route) { project.redirect_routes.create!(path: "foo/bar") }
-
- it 'returns not found' do
- put :update,
- namespace_id: 'foo',
- id: 'bar',
- project: project_params
-
- expect(response).to have_http_status(404)
- end
- end
end
describe "#destroy" do
@@ -319,31 +259,6 @@ describe ProjectsController do
expect(merge_request.reload.state).to eq('closed')
end
end
-
- context 'when requesting the canonical path' do
- it "is case-insensitive" do
- controller.instance_variable_set(:@project, project)
- sign_in(admin)
-
- orig_id = project.id
- delete :destroy, namespace_id: project.namespace, id: project.path.upcase
-
- expect { Project.find(orig_id) }.to raise_error(ActiveRecord::RecordNotFound)
- expect(response).to have_http_status(302)
- expect(response).to redirect_to(dashboard_projects_path)
- end
- end
-
- context 'when requesting a redirected path' do
- let!(:redirect_route) { project.redirect_routes.create!(path: "foo/bar") }
-
- it 'returns not found' do
- sign_in(admin)
- delete :destroy, namespace_id: 'foo', id: 'bar'
-
- expect(response).to have_http_status(404)
- end
- end
end
describe 'PUT #new_issue_address' do
@@ -465,17 +380,6 @@ describe ProjectsController do
expect(parsed_body["Tags"]).to include("v1.0.0")
expect(parsed_body["Commits"]).to include("123456")
end
-
- context 'when requesting a redirected path' do
- let!(:redirect_route) { public_project.redirect_routes.create!(path: "foo/bar") }
-
- it 'redirects to the canonical path' do
- get :refs, namespace_id: 'foo', id: 'bar'
-
- expect(response).to redirect_to(refs_namespace_project_path(namespace_id: public_project.namespace, id: public_project))
- expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, public_project))
- end
- end
end
describe 'POST #preview_markdown' do
@@ -488,6 +392,109 @@ describe ProjectsController do
end
end
+ describe '#ensure_canonical_path' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a GET request' do
+ context 'when requesting the canonical path' do
+ context "with exactly matching casing" do
+ it "loads the project" do
+ get :show, namespace_id: public_project.namespace, id: public_project
+
+ expect(assigns(:project)).to eq(public_project)
+ expect(response).to have_http_status(200)
+ end
+ end
+
+ context "with different casing" do
+ it "redirects to the normalized path" do
+ get :show, namespace_id: public_project.namespace, id: public_project.path.upcase
+
+ expect(assigns(:project)).to eq(public_project)
+ expect(response).to redirect_to("/#{public_project.full_path}")
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let!(:redirect_route) { public_project.redirect_routes.create!(path: "foo/bar") }
+
+ it 'redirects to the canonical path' do
+ get :show, namespace_id: 'foo', id: 'bar'
+
+ expect(response).to redirect_to(public_project)
+ expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, public_project))
+ end
+
+ it 'redirects to the canonical path (testing non-show action)' do
+ get :refs, namespace_id: 'foo', id: 'bar'
+
+ expect(response).to redirect_to(refs_namespace_project_path(namespace_id: public_project.namespace, id: public_project))
+ expect(controller).to set_flash[:notice].to(project_moved_message(redirect_route, public_project))
+ end
+ end
+ end
+
+ context 'for a POST request' do
+ context 'when requesting the canonical path with different casing' do
+ it 'does not 404' do
+ post :toggle_star, namespace_id: public_project.namespace, id: public_project.path.upcase
+
+ expect(response).not_to have_http_status(404)
+ end
+
+ it 'does not redirect to the correct casing' do
+ post :toggle_star, namespace_id: public_project.namespace, id: public_project.path.upcase
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let!(:redirect_route) { public_project.redirect_routes.create!(path: "foo/bar") }
+
+ it 'returns not found' do
+ post :toggle_star, namespace_id: 'foo', id: 'bar'
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'for a DELETE request' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ context 'when requesting the canonical path with different casing' do
+ it 'does not 404' do
+ delete :destroy, namespace_id: project.namespace, id: project.path.upcase
+
+ expect(response).not_to have_http_status(404)
+ end
+
+ it 'does not redirect to the correct casing' do
+ delete :destroy, namespace_id: project.namespace, id: project.path.upcase
+
+ expect(response).not_to have_http_status(301)
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let!(:redirect_route) { project.redirect_routes.create!(path: "foo/bar") }
+
+ it 'returns not found' do
+ delete :destroy, namespace_id: 'foo', id: 'bar'
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+ end
+
def project_moved_message(redirect_route, project)
"Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
end
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 1d61719f1d0..d33e2ba1e53 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -53,40 +53,6 @@ describe UsersController do
end
end
- context 'when requesting the canonical path' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- before { sign_in(user) }
-
- context 'with exactly matching casing' do
- it 'responds with success' do
- get :show, username: user.username
-
- expect(response).to be_success
- end
- end
-
- context 'with different casing' do
- it 'redirects to the correct casing' do
- get :show, username: user.username.downcase
-
- expect(response).to redirect_to(user)
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
-
- it 'redirects to the canonical path' do
- get :show, username: redirect_route.path
-
- expect(response).to redirect_to(user)
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
-
context 'when a user by that username does not exist' do
context 'when logged out' do
it 'redirects to login page' do
@@ -131,40 +97,6 @@ describe UsersController do
expect(assigns(:contributions_calendar).projects.count).to eq(2)
end
end
-
- context 'when requesting the canonical path' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- before { sign_in(user) }
-
- context 'with exactly matching casing' do
- it 'responds with success' do
- get :calendar, username: user.username
-
- expect(response).to be_success
- end
- end
-
- context 'with different casing' do
- it 'redirects to the correct casing' do
- get :calendar, username: user.username.downcase
-
- expect(response).to redirect_to(user_calendar_path(user))
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
-
- it 'redirects to the canonical path' do
- get :calendar, username: redirect_route.path
-
- expect(response).to redirect_to(user_calendar_path(user))
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
end
describe 'GET #calendar_activities' do
@@ -187,38 +119,6 @@ describe UsersController do
get :calendar_activities, username: user.username
expect(response).to render_template('calendar_activities')
end
-
- context 'when requesting the canonical path' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- context 'with exactly matching casing' do
- it 'responds with success' do
- get :calendar_activities, username: user.username
-
- expect(response).to be_success
- end
- end
-
- context 'with different casing' do
- it 'redirects to the correct casing' do
- get :calendar_activities, username: user.username.downcase
-
- expect(response).to redirect_to(user_calendar_activities_path(user))
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
-
- it 'redirects to the canonical path' do
- get :calendar_activities, username: redirect_route.path
-
- expect(response).to redirect_to(user_calendar_activities_path(user))
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
end
describe 'GET #snippets' do
@@ -241,38 +141,6 @@ describe UsersController do
expect(JSON.parse(response.body)).to have_key('html')
end
end
-
- context 'when requesting the canonical path' do
- let(:user) { create(:user, username: 'CamelCaseUser') }
-
- context 'with exactly matching casing' do
- it 'responds with success' do
- get :snippets, username: user.username
-
- expect(response).to be_success
- end
- end
-
- context 'with different casing' do
- it 'redirects to the correct casing' do
- get :snippets, username: user.username.downcase
-
- expect(response).to redirect_to(user_snippets_path(user))
- expect(controller).not_to set_flash[:notice]
- end
- end
- end
-
- context 'when requesting a redirected path' do
- let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-username') }
-
- it 'redirects to the canonical path' do
- get :snippets, username: redirect_route.path
-
- expect(response).to redirect_to(user_snippets_path(user))
- expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
- end
- end
end
describe 'GET #exists' do
@@ -321,6 +189,127 @@ describe UsersController do
end
end
+ describe '#ensure_canonical_path' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a GET request' do
+ context 'when requesting users at the root path' do
+ context 'when requesting the canonical path' do
+ let(:user) { create(:user, username: 'CamelCaseUser') }
+
+ context 'with exactly matching casing' do
+ it 'responds with success' do
+ get :show, username: user.username
+
+ expect(response).to be_success
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get :show, username: user.username.downcase
+
+ expect(response).to redirect_to(user)
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
+
+ it 'redirects to the canonical path' do
+ get :show, username: redirect_route.path
+
+ expect(response).to redirect_to(user)
+ expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
+ end
+
+ context 'when the old path is a substring of the scheme or host' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
+
+ it 'does not modify the requested host' do
+ get :show, username: redirect_route.path
+
+ expect(response).to redirect_to(user)
+ expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
+ end
+ end
+
+ context 'when the old path is substring of users' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
+
+ it 'redirects to the canonical path' do
+ get :show, username: redirect_route.path
+
+ expect(response).to redirect_to(user)
+ expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
+ end
+ end
+ end
+ end
+
+ context 'when requesting users under the /users path' do
+ context 'when requesting the canonical path' do
+ let(:user) { create(:user, username: 'CamelCaseUser') }
+
+ context 'with exactly matching casing' do
+ it 'responds with success' do
+ get :projects, username: user.username
+
+ expect(response).to be_success
+ end
+ end
+
+ context 'with different casing' do
+ it 'redirects to the correct casing' do
+ get :projects, username: user.username.downcase
+
+ expect(response).to redirect_to(user_projects_path(user))
+ expect(controller).not_to set_flash[:notice]
+ end
+ end
+ end
+
+ context 'when requesting a redirected path' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'old-path') }
+
+ it 'redirects to the canonical path' do
+ get :projects, username: redirect_route.path
+
+ expect(response).to redirect_to(user_projects_path(user))
+ expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
+ end
+
+ context 'when the old path is a substring of the scheme or host' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'http') }
+
+ it 'does not modify the requested host' do
+ get :projects, username: redirect_route.path
+
+ expect(response).to redirect_to(user_projects_path(user))
+ expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
+ end
+ end
+
+ context 'when the old path is substring of users' do
+ let(:redirect_route) { user.namespace.redirect_routes.create(path: 'ser') }
+
+ # I.e. /users/ser should not become /ufoos/ser
+ it 'does not modify the /users part of the path' do
+ get :projects, username: redirect_route.path
+
+ expect(response).to redirect_to(user_projects_path(user))
+ expect(controller).to set_flash[:notice].to(user_moved_message(redirect_route, user))
+ end
+ end
+ end
+ end
+ end
+ end
+
def user_moved_message(redirect_route, user)
"User '#{redirect_route.path}' was moved to '#{user.full_path}'. Please update any links and bookmarks that may still have the old path."
end
diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb
index da81fa4e367..80f57906506 100644
--- a/spec/features/issues/note_polling_spec.rb
+++ b/spec/features/issues/note_polling_spec.rb
@@ -31,12 +31,12 @@ feature 'Issue notes polling', :feature, :js do
it 'has .original-note-content to compare against' do
expect(page).to have_selector("#note_#{existing_note.id}", text: note_text)
- expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", visible: false)
+ expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false)
update_note(existing_note, updated_text)
expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text)
- expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", visible: false)
+ expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false)
end
it 'displays the updated content' do
@@ -98,12 +98,28 @@ feature 'Issue notes polling', :feature, :js do
it 'has .original-note-content to compare against' do
expect(page).to have_selector("#note_#{existing_note.id}", text: note_text)
- expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", visible: false)
+ expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false)
update_note(existing_note, updated_text)
expect(page).to have_selector("#note_#{existing_note.id}", text: updated_text)
- expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", visible: false)
+ expect(page).to have_selector("#note_#{existing_note.id} .original-note-content", count: 1, visible: false)
+ end
+ end
+
+ context 'system notes' do
+ let(:user) { create(:user) }
+ let(:note_text) { "Some system note" }
+ let!(:system_note) { create(:system_note, noteable: issue, project: project, author: user, note: note_text) }
+
+ before do
+ login_as(user)
+ visit namespace_project_issue_path(project.namespace, project, issue)
+ end
+
+ it 'has .original-note-content to compare against' do
+ expect(page).to have_selector("#note_#{system_note.id}", text: note_text)
+ expect(page).to have_selector("#note_#{system_note.id} .original-note-content", count: 1, visible: false)
end
end
end
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 03a30bfb996..1211b17b3d8 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -38,7 +38,7 @@ feature 'Pipeline Schedules', :feature do
end
it 'creates a new scheduled pipeline' do
- click_link 'New Schedule'
+ click_link 'New schedule'
expect(page).to have_content('Schedule a new pipeline')
end
diff --git a/spec/fixtures/api/schemas/entities/merge_request.json b/spec/fixtures/api/schemas/entities/merge_request.json
index e5df3e7b6d1..4afbb87453e 100644
--- a/spec/fixtures/api/schemas/entities/merge_request.json
+++ b/spec/fixtures/api/schemas/entities/merge_request.json
@@ -3,7 +3,6 @@
"properties" : {
"id": { "type": "integer" },
"iid": { "type": "integer" },
- "assignee_id": { "type": ["integer", "null"] },
"author_id": { "type": "integer" },
"description": { "type": ["string", "null"] },
"lock_version": { "type": ["string", "null"] },
diff --git a/spec/fixtures/api/schemas/entities/merge_request_basic.json b/spec/fixtures/api/schemas/entities/merge_request_basic.json
index ea6364b878c..6b14188582a 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_basic.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_basic.json
@@ -8,7 +8,8 @@
"total_time_spent": { "type": "integer" },
"human_time_estimate": { "type": ["string", "null"] },
"human_total_time_spent": { "type": ["string", "null"] },
- "merge_error": { "type": ["string", "null"] }
+ "merge_error": { "type": ["string", "null"] },
+ "assignee_id": { "type": ["integer", "null"] }
},
"additionalProperties": false
}
diff --git a/spec/javascripts/abuse_reports_spec.js b/spec/javascripts/abuse_reports_spec.js
index 76b370b345b..069d857eab6 100644
--- a/spec/javascripts/abuse_reports_spec.js
+++ b/spec/javascripts/abuse_reports_spec.js
@@ -1,5 +1,5 @@
-require('~/lib/utils/text_utility');
-require('~/abuse_reports');
+import '~/lib/utils/text_utility';
+import '~/abuse_reports';
((global) => {
describe('Abuse Reports', () => {
diff --git a/spec/javascripts/activities_spec.js b/spec/javascripts/activities_spec.js
index e6a6fc36ca1..e8c5f721423 100644
--- a/spec/javascripts/activities_spec.js
+++ b/spec/javascripts/activities_spec.js
@@ -1,8 +1,8 @@
/* eslint-disable no-unused-expressions, no-prototype-builtins, no-new, no-shadow, max-len */
-require('vendor/jquery.endless-scroll.js');
-require('~/pager');
-require('~/activities');
+import 'vendor/jquery.endless-scroll';
+import '~/pager';
+import '~/activities';
(() => {
window.gon || (window.gon = {});
diff --git a/spec/javascripts/ajax_loading_spinner_spec.js b/spec/javascripts/ajax_loading_spinner_spec.js
index a68bccb16f4..1518ae68b0d 100644
--- a/spec/javascripts/ajax_loading_spinner_spec.js
+++ b/spec/javascripts/ajax_loading_spinner_spec.js
@@ -1,7 +1,7 @@
-require('~/extensions/array');
-require('jquery');
-require('jquery-ujs');
-require('~/ajax_loading_spinner');
+import '~/extensions/array';
+import 'jquery';
+import 'jquery-ujs';
+import '~/ajax_loading_spinner';
describe('Ajax Loading Spinner', () => {
const fixtureTemplate = 'static/ajax_loading_spinner.html.raw';
diff --git a/spec/javascripts/api_spec.js b/spec/javascripts/api_spec.js
new file mode 100644
index 00000000000..867322ce8ae
--- /dev/null
+++ b/spec/javascripts/api_spec.js
@@ -0,0 +1,281 @@
+import Api from '~/api';
+
+describe('Api', () => {
+ const dummyApiVersion = 'v3000';
+ const dummyUrlRoot = 'http://host.invalid';
+ const dummyGon = {
+ api_version: dummyApiVersion,
+ relative_url_root: dummyUrlRoot,
+ };
+ const dummyResponse = 'hello from outer space!';
+ const sendDummyResponse = () => {
+ const deferred = $.Deferred();
+ deferred.resolve(dummyResponse);
+ return deferred.promise();
+ };
+ let originalGon;
+
+ beforeEach(() => {
+ originalGon = window.gon;
+ window.gon = dummyGon;
+ });
+
+ afterEach(() => {
+ window.gon = originalGon;
+ });
+
+ describe('buildUrl', () => {
+ it('adds URL root and fills in API version', () => {
+ const input = '/api/:version/foo/bar';
+ const expectedOutput = `${dummyUrlRoot}/api/${dummyApiVersion}/foo/bar`;
+
+ const builtUrl = Api.buildUrl(input);
+
+ expect(builtUrl).toEqual(expectedOutput);
+ });
+ });
+
+ describe('group', () => {
+ it('fetches a group', (done) => {
+ const groupId = '123456';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}.json`;
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ return sendDummyResponse();
+ });
+
+ Api.group(groupId, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('groups', () => {
+ it('fetches groups', (done) => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups.json`;
+ const expectedData = Object.assign({
+ search: query,
+ per_page: 20,
+ }, options);
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.groups(query, options, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('namespaces', () => {
+ it('fetches namespaces', (done) => {
+ const query = 'dummy query';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/namespaces.json`;
+ const expectedData = {
+ search: query,
+ per_page: 20,
+ };
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.namespaces(query, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('projects', () => {
+ it('fetches projects', (done) => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json?simple=true`;
+ const expectedData = Object.assign({
+ search: query,
+ per_page: 20,
+ membership: true,
+ }, options);
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.projects(query, options, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('newLabel', () => {
+ it('creates a new label', (done) => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const labelData = { some: 'data' };
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/labels`;
+ const expectedData = {
+ label: labelData,
+ };
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.type).toEqual('POST');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.newLabel(namespace, project, labelData, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('groupProjects', () => {
+ it('fetches group projects', (done) => {
+ const groupId = '123456';
+ const query = 'dummy query';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
+ const expectedData = {
+ search: query,
+ per_page: 20,
+ };
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.groupProjects(groupId, query, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('licenseText', () => {
+ it('fetches a license text', (done) => {
+ const licenseKey = "driver's license";
+ const data = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/licenses/${licenseKey}`;
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.data).toEqual(data);
+ return sendDummyResponse();
+ });
+
+ Api.licenseText(licenseKey, data, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('gitignoreText', () => {
+ it('fetches a gitignore text', (done) => {
+ const gitignoreKey = 'ignore git';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/gitignores/${gitignoreKey}`;
+ spyOn(jQuery, 'get').and.callFake((url, callback) => {
+ expect(url).toEqual(expectedUrl);
+ callback(dummyResponse);
+ });
+
+ Api.gitignoreText(gitignoreKey, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('gitlabCiYml', () => {
+ it('fetches a .gitlab-ci.yml', (done) => {
+ const gitlabCiYmlKey = 'Y CI ML';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/gitlab_ci_ymls/${gitlabCiYmlKey}`;
+ spyOn(jQuery, 'get').and.callFake((url, callback) => {
+ expect(url).toEqual(expectedUrl);
+ callback(dummyResponse);
+ });
+
+ Api.gitlabCiYml(gitlabCiYmlKey, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('dockerfileYml', () => {
+ it('fetches a Dockerfile', (done) => {
+ const dockerfileYmlKey = 'a giant whale';
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/dockerfiles/${dockerfileYmlKey}`;
+ spyOn(jQuery, 'get').and.callFake((url, callback) => {
+ expect(url).toEqual(expectedUrl);
+ callback(dummyResponse);
+ });
+
+ Api.dockerfileYml(dockerfileYmlKey, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('issueTemplate', () => {
+ it('fetches an issue template', (done) => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const templateKey = 'template key';
+ const templateType = 'template type';
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${templateKey}`;
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ return sendDummyResponse();
+ });
+
+ Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
+ expect(error).toBe(null);
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
+ });
+
+ describe('users', () => {
+ it('fetches users', (done) => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users.json`;
+ const expectedData = Object.assign({
+ search: query,
+ per_page: 20,
+ }, options);
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.users(query, options)
+ .then((response) => {
+ expect(response).toBe(dummyResponse);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js
index 68ad5f66676..3fc03324d16 100644
--- a/spec/javascripts/awards_handler_spec.js
+++ b/spec/javascripts/awards_handler_spec.js
@@ -3,7 +3,7 @@
import Cookies from 'js-cookie';
import AwardsHandler from '~/awards_handler';
-require('~/lib/utils/common_utils');
+import '~/lib/utils/common_utils';
(function() {
var awardsHandler, lazyAssert, urlRoot, openAndWaitForEmojiMenu;
diff --git a/spec/javascripts/behaviors/autosize_spec.js b/spec/javascripts/behaviors/autosize_spec.js
index 3deaf258cae..67afba19190 100644
--- a/spec/javascripts/behaviors/autosize_spec.js
+++ b/spec/javascripts/behaviors/autosize_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, no-var, comma-dangle, no-return-assign, max-len */
-require('~/behaviors/autosize');
+import '~/behaviors/autosize';
(function() {
describe('Autosize behavior', function() {
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js
index 4820ce41ade..f56b99f8a16 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/javascripts/behaviors/quick_submit_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, no-var, no-return-assign, comma-dangle, jasmine/no-spec-dupes, new-cap, max-len */
-require('~/behaviors/quick_submit');
+import '~/behaviors/quick_submit';
(function() {
describe('Quick Submit behavior', function() {
diff --git a/spec/javascripts/behaviors/requires_input_spec.js b/spec/javascripts/behaviors/requires_input_spec.js
index 3a84013a2ed..f9fa814b801 100644
--- a/spec/javascripts/behaviors/requires_input_spec.js
+++ b/spec/javascripts/behaviors/requires_input_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, no-var */
-require('~/behaviors/requires_input');
+import '~/behaviors/requires_input';
(function() {
describe('requiresInput', function() {
diff --git a/spec/javascripts/blob/create_branch_dropdown_spec.js b/spec/javascripts/blob/create_branch_dropdown_spec.js
index 9f0d373cb81..6dbaa47c544 100644
--- a/spec/javascripts/blob/create_branch_dropdown_spec.js
+++ b/spec/javascripts/blob/create_branch_dropdown_spec.js
@@ -1,6 +1,6 @@
-require('~/gl_dropdown');
-require('~/blob/create_branch_dropdown');
-require('~/blob/target_branch_dropdown');
+import '~/gl_dropdown';
+import '~/blob/create_branch_dropdown';
+import '~/blob/target_branch_dropdown';
describe('CreateBranchDropdown', () => {
const fixtureTemplate = 'static/target_branch_dropdown.html.raw';
diff --git a/spec/javascripts/blob/target_branch_dropdown_spec.js b/spec/javascripts/blob/target_branch_dropdown_spec.js
index 76ed3dc1a2d..99c9537d2ec 100644
--- a/spec/javascripts/blob/target_branch_dropdown_spec.js
+++ b/spec/javascripts/blob/target_branch_dropdown_spec.js
@@ -1,6 +1,6 @@
-require('~/gl_dropdown');
-require('~/blob/create_branch_dropdown');
-require('~/blob/target_branch_dropdown');
+import '~/gl_dropdown';
+import '~/blob/create_branch_dropdown';
+import '~/blob/target_branch_dropdown';
describe('TargetBranchDropdown', () => {
const fixtureTemplate = 'static/target_branch_dropdown.html.raw';
diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js
index 376e706d1db..447b244c71f 100644
--- a/spec/javascripts/boards/board_card_spec.js
+++ b/spec/javascripts/boards/board_card_spec.js
@@ -8,11 +8,11 @@
import Vue from 'vue';
import '~/boards/models/assignee';
-require('~/boards/models/list');
-require('~/boards/models/label');
-require('~/boards/stores/boards_store');
-const boardCard = require('~/boards/components/board_card').default;
-require('./mock_data');
+import '~/boards/models/list';
+import '~/boards/models/label';
+import '~/boards/stores/boards_store';
+import boardCard from '~/boards/components/board_card';
+import './mock_data';
describe('Issue card', () => {
let vm;
diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js
index 4999933c0c1..45d12e252c4 100644
--- a/spec/javascripts/boards/board_new_issue_spec.js
+++ b/spec/javascripts/boards/board_new_issue_spec.js
@@ -6,8 +6,8 @@
import Vue from 'vue';
import boardNewIssue from '~/boards/components/board_new_issue';
-require('~/boards/models/list');
-require('./mock_data');
+import '~/boards/models/list';
+import './mock_data';
describe('Issue boards new issue form', () => {
let vm;
diff --git a/spec/javascripts/commits_spec.js b/spec/javascripts/commits_spec.js
index 05260760c43..187db7485a5 100644
--- a/spec/javascripts/commits_spec.js
+++ b/spec/javascripts/commits_spec.js
@@ -1,8 +1,8 @@
/* global CommitsList */
-require('vendor/jquery.endless-scroll');
-require('~/pager');
-require('~/commits');
+import 'vendor/jquery.endless-scroll';
+import '~/pager';
+import '~/commits';
(() => {
// TODO: remove this hack!
diff --git a/spec/javascripts/datetime_utility_spec.js b/spec/javascripts/datetime_utility_spec.js
index d5eec10be42..e347c980c78 100644
--- a/spec/javascripts/datetime_utility_spec.js
+++ b/spec/javascripts/datetime_utility_spec.js
@@ -1,4 +1,4 @@
-require('~/lib/utils/datetime_utility');
+import '~/lib/utils/datetime_utility';
(() => {
describe('Date time utils', () => {
diff --git a/spec/javascripts/diff_comments_store_spec.js b/spec/javascripts/diff_comments_store_spec.js
index 66ece7e4f41..d6fc6b56b82 100644
--- a/spec/javascripts/diff_comments_store_spec.js
+++ b/spec/javascripts/diff_comments_store_spec.js
@@ -1,9 +1,9 @@
/* eslint-disable jasmine/no-global-setup, dot-notation, jasmine/no-expect-in-setup-teardown, max-len */
/* global CommentsStore */
-require('~/diff_notes/models/discussion');
-require('~/diff_notes/models/note');
-require('~/diff_notes/stores/comments');
+import '~/diff_notes/models/discussion';
+import '~/diff_notes/models/note';
+import '~/diff_notes/stores/comments';
function createDiscussion(noteId = 1, resolved = true) {
CommentsStore.create({
diff --git a/spec/javascripts/extensions/array_spec.js b/spec/javascripts/extensions/array_spec.js
index 4b871fe967d..b1b81b4efc2 100644
--- a/spec/javascripts/extensions/array_spec.js
+++ b/spec/javascripts/extensions/array_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, no-var */
-require('~/extensions/array');
+import '~/extensions/array';
(function() {
describe('Array extensions', function() {
diff --git a/spec/javascripts/filtered_search/dropdown_user_spec.js b/spec/javascripts/filtered_search/dropdown_user_spec.js
index 3f92fe4701e..0d8bdf4c8e7 100644
--- a/spec/javascripts/filtered_search/dropdown_user_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_user_spec.js
@@ -1,7 +1,7 @@
-require('~/filtered_search/dropdown_utils');
-require('~/filtered_search/filtered_search_tokenizer');
-require('~/filtered_search/filtered_search_dropdown');
-require('~/filtered_search/dropdown_user');
+import '~/filtered_search/dropdown_utils';
+import '~/filtered_search/filtered_search_tokenizer';
+import '~/filtered_search/filtered_search_dropdown';
+import '~/filtered_search/dropdown_user';
describe('Dropdown User', () => {
describe('getSearchInput', () => {
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js
index c820c955172..a68e315e3e4 100644
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js
@@ -1,7 +1,7 @@
-require('~/extensions/array');
-require('~/filtered_search/dropdown_utils');
-require('~/filtered_search/filtered_search_tokenizer');
-require('~/filtered_search/filtered_search_dropdown_manager');
+import '~/extensions/array';
+import '~/filtered_search/dropdown_utils';
+import '~/filtered_search/filtered_search_tokenizer';
+import '~/filtered_search/filtered_search_dropdown_manager';
describe('Dropdown Utils', () => {
describe('getEscapedText', () => {
diff --git a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js
index 17bf8932489..c92a147b937 100644
--- a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js
@@ -1,7 +1,7 @@
-require('~/extensions/array');
-require('~/filtered_search/filtered_search_visual_tokens');
-require('~/filtered_search/filtered_search_tokenizer');
-require('~/filtered_search/filtered_search_dropdown_manager');
+import '~/extensions/array';
+import '~/filtered_search/filtered_search_visual_tokens';
+import '~/filtered_search/filtered_search_tokenizer';
+import '~/filtered_search/filtered_search_dropdown_manager';
describe('Filtered Search Dropdown Manager', () => {
describe('addWordToInput', () => {
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_manager_spec.js
index 063d547d00c..7c7def3470d 100644
--- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js
@@ -1,14 +1,13 @@
import * as recentSearchesStoreSrc from '~/filtered_search/stores/recent_searches_store';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
import RecentSearchesServiceError from '~/filtered_search/services/recent_searches_service_error';
-
-require('~/lib/utils/url_utility');
-require('~/lib/utils/common_utils');
-require('~/filtered_search/filtered_search_token_keys');
-require('~/filtered_search/filtered_search_tokenizer');
-require('~/filtered_search/filtered_search_dropdown_manager');
-require('~/filtered_search/filtered_search_manager');
-const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper');
+import '~/lib/utils/url_utility';
+import '~/lib/utils/common_utils';
+import '~/filtered_search/filtered_search_token_keys';
+import '~/filtered_search/filtered_search_tokenizer';
+import '~/filtered_search/filtered_search_dropdown_manager';
+import '~/filtered_search/filtered_search_manager';
+import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Manager', () => {
let input;
diff --git a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
index 6f9fa434c35..1a7631994b4 100644
--- a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
@@ -1,5 +1,5 @@
-require('~/extensions/array');
-require('~/filtered_search/filtered_search_token_keys');
+import '~/extensions/array';
+import '~/filtered_search/filtered_search_token_keys';
describe('Filtered Search Token Keys', () => {
describe('get', () => {
diff --git a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
index 3e2e577f115..9561580c839 100644
--- a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
@@ -1,6 +1,6 @@
-require('~/extensions/array');
-require('~/filtered_search/filtered_search_token_keys');
-require('~/filtered_search/filtered_search_tokenizer');
+import '~/extensions/array';
+import '~/filtered_search/filtered_search_token_keys';
+import '~/filtered_search/filtered_search_tokenizer';
describe('Filtered Search Tokenizer', () => {
describe('processTokens', () => {
diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
index 8b750561eb7..c5fa2b17106 100644
--- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
@@ -1,7 +1,7 @@
import AjaxCache from '~/lib/utils/ajax_cache';
-require('~/filtered_search/filtered_search_visual_tokens');
-const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper');
+import '~/filtered_search/filtered_search_visual_tokens';
+import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Visual Tokens', () => {
let tokensContainer;
diff --git a/spec/javascripts/gfm_auto_complete_spec.js b/spec/javascripts/gfm_auto_complete_spec.js
index d0f15c902b5..ad0c7264616 100644
--- a/spec/javascripts/gfm_auto_complete_spec.js
+++ b/spec/javascripts/gfm_auto_complete_spec.js
@@ -2,8 +2,8 @@
import GfmAutoComplete from '~/gfm_auto_complete';
-require('vendor/jquery.caret');
-require('vendor/jquery.atwho');
+import 'vendor/jquery.caret';
+import 'vendor/jquery.atwho';
describe('GfmAutoComplete', function () {
const gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index 8f90ed69e64..3292590b9ed 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -1,8 +1,8 @@
/* eslint-disable comma-dangle, no-param-reassign, no-unused-expressions, max-len */
-require('~/gl_dropdown');
-require('~/lib/utils/common_utils');
-require('~/lib/utils/url_utility');
+import '~/gl_dropdown';
+import '~/lib/utils/common_utils';
+import '~/lib/utils/url_utility';
(() => {
const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link';
diff --git a/spec/javascripts/gl_field_errors_spec.js b/spec/javascripts/gl_field_errors_spec.js
index 733023481f5..fa24aa426b6 100644
--- a/spec/javascripts/gl_field_errors_spec.js
+++ b/spec/javascripts/gl_field_errors_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, arrow-body-style */
-require('~/gl_field_errors');
+import '~/gl_field_errors';
((global) => {
preloadFixtures('static/gl_field_errors.html.raw');
diff --git a/spec/javascripts/gl_form_spec.js b/spec/javascripts/gl_form_spec.js
index 5ed18d0a76b..837feacec1d 100644
--- a/spec/javascripts/gl_form_spec.js
+++ b/spec/javascripts/gl_form_spec.js
@@ -1,9 +1,9 @@
-/* global autosize */
+import autosize from 'vendor/autosize';
+import '~/gl_form';
+import '~/lib/utils/text_utility';
+import '~/lib/utils/common_utils';
-window.autosize = require('vendor/autosize');
-require('~/gl_form');
-require('~/lib/utils/text_utility');
-require('~/lib/utils/common_utils');
+window.autosize = autosize;
describe('GLForm', () => {
const global = window.gl || (window.gl = {});
@@ -27,7 +27,7 @@ describe('GLForm', () => {
$.prototype.off.calls.reset();
$.prototype.on.calls.reset();
$.prototype.css.calls.reset();
- autosize.calls.reset();
+ window.autosize.calls.reset();
done();
});
});
@@ -51,7 +51,7 @@ describe('GLForm', () => {
});
it('should autosize the textarea', () => {
- expect(autosize).toHaveBeenCalledWith(jasmine.any(Object));
+ expect(window.autosize).toHaveBeenCalledWith(jasmine.any(Object));
});
it('should set the resize css property to vertical', () => {
@@ -81,7 +81,7 @@ describe('GLForm', () => {
spyOn($.prototype, 'data');
spyOn($.prototype, 'outerHeight').and.returnValue(200);
spyOn(window, 'outerHeight').and.returnValue(400);
- spyOn(autosize, 'destroy');
+ spyOn(window.autosize, 'destroy');
this.glForm.destroyAutosize();
});
@@ -95,7 +95,7 @@ describe('GLForm', () => {
});
it('should call autosize destroy', () => {
- expect(autosize.destroy).toHaveBeenCalledWith(this.textarea);
+ expect(window.autosize.destroy).toHaveBeenCalledWith(this.textarea);
});
it('should set the data-height attribute', () => {
@@ -114,9 +114,9 @@ describe('GLForm', () => {
it('should return undefined if the data-height equals the outerHeight', () => {
spyOn($.prototype, 'outerHeight').and.returnValue(200);
spyOn($.prototype, 'data').and.returnValue(200);
- spyOn(autosize, 'destroy');
+ spyOn(window.autosize, 'destroy');
expect(this.glForm.destroyAutosize()).toBeUndefined();
- expect(autosize.destroy).not.toHaveBeenCalled();
+ expect(window.autosize.destroy).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/javascripts/header_spec.js b/spec/javascripts/header_spec.js
index b5dde5525e5..0e01934d3a3 100644
--- a/spec/javascripts/header_spec.js
+++ b/spec/javascripts/header_spec.js
@@ -1,7 +1,7 @@
/* eslint-disable space-before-function-paren, no-var */
-require('~/header');
-require('~/lib/utils/text_utility');
+import '~/header';
+import '~/lib/utils/text_utility';
(function() {
describe('Header', function() {
diff --git a/spec/javascripts/helpers/class_spec_helper.js b/spec/javascripts/helpers/class_spec_helper.js
index 61db27a8fcc..7a60d33b471 100644
--- a/spec/javascripts/helpers/class_spec_helper.js
+++ b/spec/javascripts/helpers/class_spec_helper.js
@@ -1,4 +1,4 @@
-class ClassSpecHelper {
+export default class ClassSpecHelper {
static itShouldBeAStaticMethod(base, method) {
return it('should be a static method', () => {
expect(Object.prototype.hasOwnProperty.call(base, method)).toBeTruthy();
@@ -7,5 +7,3 @@ class ClassSpecHelper {
}
window.ClassSpecHelper = ClassSpecHelper;
-
-module.exports = ClassSpecHelper;
diff --git a/spec/javascripts/helpers/class_spec_helper_spec.js b/spec/javascripts/helpers/class_spec_helper_spec.js
index a1cfc8ba820..686b8eaed31 100644
--- a/spec/javascripts/helpers/class_spec_helper_spec.js
+++ b/spec/javascripts/helpers/class_spec_helper_spec.js
@@ -1,6 +1,6 @@
/* global ClassSpecHelper */
-require('./class_spec_helper');
+import './class_spec_helper';
describe('ClassSpecHelper', () => {
describe('itShouldBeAStaticMethod', function () {
diff --git a/spec/javascripts/helpers/filtered_search_spec_helper.js b/spec/javascripts/helpers/filtered_search_spec_helper.js
index b8d4a93b1ab..0d7092a2357 100644
--- a/spec/javascripts/helpers/filtered_search_spec_helper.js
+++ b/spec/javascripts/helpers/filtered_search_spec_helper.js
@@ -1,4 +1,4 @@
-class FilteredSearchSpecHelper {
+export default class FilteredSearchSpecHelper {
static createFilterVisualTokenHTML(name, value, isSelected) {
return FilteredSearchSpecHelper.createFilterVisualToken(name, value, isSelected).outerHTML;
}
@@ -53,5 +53,3 @@ class FilteredSearchSpecHelper {
`;
}
}
-
-module.exports = FilteredSearchSpecHelper;
diff --git a/spec/javascripts/issuable_spec.js b/spec/javascripts/issuable_spec.js
index 26d87cc5931..49fa2cb8367 100644
--- a/spec/javascripts/issuable_spec.js
+++ b/spec/javascripts/issuable_spec.js
@@ -1,7 +1,7 @@
/* global Issuable */
-require('~/lib/utils/url_utility');
-require('~/issuable');
+import '~/lib/utils/url_utility';
+import '~/issuable';
(() => {
const BASE_URL = '/user/project/issues?scope=all&state=closed';
diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js
index 763f5ee9e50..df97a100b0d 100644
--- a/spec/javascripts/issue_spec.js
+++ b/spec/javascripts/issue_spec.js
@@ -1,7 +1,7 @@
/* eslint-disable space-before-function-paren, one-var, one-var-declaration-per-line, no-use-before-define, comma-dangle, max-len */
import Issue from '~/issue';
-require('~/lib/utils/text_utility');
+import '~/lib/utils/text_utility';
describe('Issue', function() {
let $boxClosed, $boxOpen, $btnClose, $btnReopen;
diff --git a/spec/javascripts/labels_issue_sidebar_spec.js b/spec/javascripts/labels_issue_sidebar_spec.js
index 53aba191b19..c99f379b871 100644
--- a/spec/javascripts/labels_issue_sidebar_spec.js
+++ b/spec/javascripts/labels_issue_sidebar_spec.js
@@ -2,14 +2,14 @@
/* global IssuableContext */
/* global LabelsSelect */
-require('~/gl_dropdown');
-require('select2');
-require('vendor/jquery.nicescroll');
-require('~/api');
-require('~/create_label');
-require('~/issuable_context');
-require('~/users_select');
-require('~/labels_select');
+import '~/gl_dropdown';
+import 'select2';
+import 'vendor/jquery.nicescroll';
+import '~/api';
+import '~/create_label';
+import '~/issuable_context';
+import '~/users_select';
+import '~/labels_select';
(() => {
let saveLabelCount = 0;
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 42a9067ade5..e9bffd74d90 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable promise/catch-or-return */
-require('~/lib/utils/common_utils');
+import '~/lib/utils/common_utils';
(() => {
describe('common_utils', () => {
diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js
index daef9b93fa5..ca1b1b7cc3c 100644
--- a/spec/javascripts/lib/utils/text_utility_spec.js
+++ b/spec/javascripts/lib/utils/text_utility_spec.js
@@ -1,4 +1,4 @@
-require('~/lib/utils/text_utility');
+import '~/lib/utils/text_utility';
describe('text_utility', () => {
describe('gl.text.getTextWidth', () => {
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index b1b08989028..aee274641e8 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -1,7 +1,7 @@
/* 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 */
-require('~/line_highlighter');
+import '~/line_highlighter';
(function() {
describe('LineHighlighter', function() {
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index fd97dced870..1173fa40947 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -1,7 +1,7 @@
/* eslint-disable space-before-function-paren, no-return-assign */
/* global MergeRequest */
-require('~/merge_request');
+import '~/merge_request';
(function() {
describe('MergeRequest', function() {
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index 254a41db160..3d1706aab68 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -1,13 +1,13 @@
/* eslint-disable no-var, comma-dangle, object-shorthand */
-require('~/merge_request_tabs');
-require('~/commit/pipelines/pipelines_bundle.js');
-require('~/breakpoints');
-require('~/lib/utils/common_utils');
-require('~/diff');
-require('~/single_file_diff');
-require('~/files_comment_button');
-require('vendor/jquery.scrollTo');
+import '~/merge_request_tabs';
+import '~/commit/pipelines/pipelines_bundle';
+import '~/breakpoints';
+import '~/lib/utils/common_utils';
+import '~/diff';
+import '~/single_file_diff';
+import '~/files_comment_button';
+import 'vendor/jquery.scrollTo';
(function () {
// TODO: remove this hack!
diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js
index 90a429beeca..c57f44dae17 100644
--- a/spec/javascripts/new_branch_spec.js
+++ b/spec/javascripts/new_branch_spec.js
@@ -1,7 +1,7 @@
/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, quotes, max-len */
/* global NewBranchForm */
-require('~/new_branch_form');
+import '~/new_branch_form';
(function() {
describe('Branch', function() {
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index d3494aaa94f..025f08ee332 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -139,6 +139,7 @@ import '~/notes';
]);
notes = jasmine.createSpyObj('notes', [
+ 'setupNewNote',
'refresh',
'collapseLongCommitList',
'updateNotesCount',
diff --git a/spec/javascripts/pager_spec.js b/spec/javascripts/pager_spec.js
index d966226909b..1d3e1263371 100644
--- a/spec/javascripts/pager_spec.js
+++ b/spec/javascripts/pager_spec.js
@@ -1,6 +1,6 @@
/* global fixture */
-require('~/pager');
+import '~/pager';
describe('pager', () => {
const Pager = window.Pager;
diff --git a/spec/javascripts/pretty_time_spec.js b/spec/javascripts/pretty_time_spec.js
index a4662cfb557..de99e7e3894 100644
--- a/spec/javascripts/pretty_time_spec.js
+++ b/spec/javascripts/pretty_time_spec.js
@@ -1,4 +1,4 @@
-require('~/lib/utils/pretty_time');
+import '~/lib/utils/pretty_time';
(() => {
const prettyTime = gl.utils.prettyTime;
diff --git a/spec/javascripts/project_title_spec.js b/spec/javascripts/project_title_spec.js
index 5c51e855401..3dba2e817ff 100644
--- a/spec/javascripts/project_title_spec.js
+++ b/spec/javascripts/project_title_spec.js
@@ -1,11 +1,11 @@
/* eslint-disable space-before-function-paren, no-unused-expressions, no-return-assign, no-param-reassign, no-var, new-cap, wrap-iife, no-unused-vars, quotes, jasmine/no-expect-in-setup-teardown, max-len */
/* global Project */
-require('select2/select2.js');
-require('~/gl_dropdown');
-require('~/api');
-require('~/project_select');
-require('~/project');
+import 'select2/select2';
+import '~/gl_dropdown';
+import '~/api';
+import '~/project_select';
+import '~/project';
(function() {
describe('Project Title', function() {
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index fa52a8a0dd2..a53f58b5d0d 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -1,9 +1,9 @@
/* eslint-disable space-before-function-paren, max-len, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, comma-dangle, object-shorthand, prefer-template, quotes, new-parens, vars-on-top, new-cap, max-len */
-require('~/gl_dropdown');
-require('~/search_autocomplete');
-require('~/lib/utils/common_utils');
-require('vendor/fuzzaldrin-plus');
+import '~/gl_dropdown';
+import '~/search_autocomplete';
+import '~/lib/utils/common_utils';
+import 'vendor/fuzzaldrin-plus';
(function() {
var addBodyAttributes, assertLinks, dashboardIssuesPath, dashboardMRsPath, groupIssuesPath, groupMRsPath, groupName, mockDashboardOptions, mockGroupOptions, mockProjectOptions, projectIssuesPath, projectMRsPath, projectName, userId, widget;
diff --git a/spec/javascripts/shortcuts_issuable_spec.js b/spec/javascripts/shortcuts_issuable_spec.js
index 757b8d595a4..3515dfbc60b 100644
--- a/spec/javascripts/shortcuts_issuable_spec.js
+++ b/spec/javascripts/shortcuts_issuable_spec.js
@@ -1,8 +1,8 @@
/* eslint-disable space-before-function-paren, no-return-assign, no-var, quotes */
/* global ShortcutsIssuable */
-require('~/copy_as_gfm');
-require('~/shortcuts_issuable');
+import '~/copy_as_gfm';
+import '~/shortcuts_issuable';
(function() {
describe('ShortcutsIssuable', function() {
diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js b/spec/javascripts/signin_tabs_memoizer_spec.js
index 5b4f5933b34..0a32797c3e2 100644
--- a/spec/javascripts/signin_tabs_memoizer_spec.js
+++ b/spec/javascripts/signin_tabs_memoizer_spec.js
@@ -1,6 +1,6 @@
import AccessorUtilities from '~/lib/utils/accessor';
-require('~/signin_tabs_memoizer');
+import '~/signin_tabs_memoizer';
((global) => {
describe('SigninTabsMemoizer', () => {
diff --git a/spec/javascripts/smart_interval_spec.js b/spec/javascripts/smart_interval_spec.js
index 4366ec2a5b8..7833bf3fb04 100644
--- a/spec/javascripts/smart_interval_spec.js
+++ b/spec/javascripts/smart_interval_spec.js
@@ -1,4 +1,4 @@
-require('~/smart_interval');
+import '~/smart_interval';
(() => {
const DEFAULT_MAX_INTERVAL = 100;
diff --git a/spec/javascripts/syntax_highlight_spec.js b/spec/javascripts/syntax_highlight_spec.js
index cea223bd243..946f98379ce 100644
--- a/spec/javascripts/syntax_highlight_spec.js
+++ b/spec/javascripts/syntax_highlight_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, no-var, no-return-assign, quotes */
-require('~/syntax_highlight');
+import '~/syntax_highlight';
(function() {
describe('Syntax Highlighter', function() {
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index 0464b5d2329..13827a26571 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -1,13 +1,15 @@
-// enable test fixtures
-require('jasmine-jquery');
+import $ from 'jquery';
+import _ from 'underscore';
+import 'jasmine-jquery';
+import '~/commons';
+// enable test fixtures
jasmine.getFixtures().fixturesPath = '/base/spec/javascripts/fixtures';
jasmine.getJSONFixtures().fixturesPath = '/base/spec/javascripts/fixtures';
-// include common libraries
-require('~/commons/index.js');
-window.$ = window.jQuery = require('jquery');
-window._ = require('underscore');
+// globalize common libraries
+window.$ = window.jQuery = $;
+window._ = _;
// stub expected globals
window.gl = window.gl || {};
diff --git a/spec/javascripts/todos_spec.js b/spec/javascripts/todos_spec.js
index 66e4fbd6304..cd74aba4a4e 100644
--- a/spec/javascripts/todos_spec.js
+++ b/spec/javascripts/todos_spec.js
@@ -1,5 +1,5 @@
-require('~/todos');
-require('~/lib/utils/common_utils');
+import '~/todos';
+import '~/lib/utils/common_utils';
describe('Todos', () => {
preloadFixtures('todos/todos.html.raw');
diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js
index af2d02b6b29..a160c86308d 100644
--- a/spec/javascripts/u2f/authenticate_spec.js
+++ b/spec/javascripts/u2f/authenticate_spec.js
@@ -2,11 +2,11 @@
/* global MockU2FDevice */
/* global U2FAuthenticate */
-require('~/u2f/authenticate');
-require('~/u2f/util');
-require('~/u2f/error');
-require('vendor/u2f');
-require('./mock_u2f_device');
+import '~/u2f/authenticate';
+import '~/u2f/util';
+import '~/u2f/error';
+import 'vendor/u2f';
+import './mock_u2f_device';
(function() {
describe('U2FAuthenticate', function() {
diff --git a/spec/javascripts/u2f/register_spec.js b/spec/javascripts/u2f/register_spec.js
index 3960759f7cb..a445c80f2af 100644
--- a/spec/javascripts/u2f/register_spec.js
+++ b/spec/javascripts/u2f/register_spec.js
@@ -2,11 +2,11 @@
/* global MockU2FDevice */
/* global U2FRegister */
-require('~/u2f/register');
-require('~/u2f/util');
-require('~/u2f/error');
-require('vendor/u2f');
-require('./mock_u2f_device');
+import '~/u2f/register';
+import '~/u2f/util';
+import '~/u2f/error';
+import 'vendor/u2f';
+import './mock_u2f_device';
(function() {
describe('U2FRegister', function() {
diff --git a/spec/javascripts/version_check_image_spec.js b/spec/javascripts/version_check_image_spec.js
index 83ffeca253a..9637bd0414a 100644
--- a/spec/javascripts/version_check_image_spec.js
+++ b/spec/javascripts/version_check_image_spec.js
@@ -1,6 +1,5 @@
-const ClassSpecHelper = require('./helpers/class_spec_helper');
-const VersionCheckImage = require('~/version_check_image');
-require('jquery');
+import VersionCheckImage from '~/version_check_image';
+import ClassSpecHelper from './helpers/class_spec_helper';
describe('VersionCheckImage', function () {
describe('bindErrorEvent', function () {
diff --git a/spec/javascripts/visibility_select_spec.js b/spec/javascripts/visibility_select_spec.js
index b26ed41f27a..c2eaea7c2ed 100644
--- a/spec/javascripts/visibility_select_spec.js
+++ b/spec/javascripts/visibility_select_spec.js
@@ -1,4 +1,4 @@
-require('~/visibility_select');
+import '~/visibility_select';
(() => {
const VisibilitySelect = gl.VisibilitySelect;
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 74df99415c9..d043ad38b8b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -80,7 +80,7 @@ describe('MRWidgetReadyToMerge', () => {
});
describe('mergeButtonClass', () => {
- const defaultClass = 'btn btn-success accept-merge-request';
+ const defaultClass = 'btn btn-small btn-success accept-merge-request';
const failedClass = `${defaultClass} btn-danger`;
const inActionClass = `${defaultClass} btn-info`;
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 22ee7dcf0e7..bdc18243a15 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -227,13 +227,11 @@ describe('mrWidgetOptions', () => {
describe('handleMounted', () => {
it('should call required methods to do the initial kick-off', () => {
- spyOn(vm, 'checkStatus');
spyOn(vm, 'initDeploymentsPolling');
spyOn(vm, 'setFavicon');
vm.handleMounted();
- expect(vm.checkStatus).toHaveBeenCalled();
expect(vm.setFavicon).toHaveBeenCalled();
expect(vm.initDeploymentsPolling).toHaveBeenCalled();
});
diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js
index 99515f2e5f2..4399c8b2025 100644
--- a/spec/javascripts/zen_mode_spec.js
+++ b/spec/javascripts/zen_mode_spec.js
@@ -3,7 +3,7 @@
/* global Mousetrap */
/* global ZenMode */
-require('~/zen_mode');
+import '~/zen_mode';
(function() {
var enterZen, escapeKeydown, exitZen;
diff --git a/spec/migrations/fix_wrongly_renamed_routes_spec.rb b/spec/migrations/fix_wrongly_renamed_routes_spec.rb
new file mode 100644
index 00000000000..148290b0e7d
--- /dev/null
+++ b/spec/migrations/fix_wrongly_renamed_routes_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170518231126_fix_wrongly_renamed_routes.rb')
+
+describe FixWronglyRenamedRoutes, truncate: true do
+ let(:subject) { described_class.new }
+ let(:broken_namespace) do
+ namespace = create(:group, name: 'apiis')
+ namespace.route.update_attribute(:path, 'api0is')
+ namespace
+ end
+
+ describe '#wrongly_renamed' do
+ it "includes routes that have names that don't match their namespace" do
+ broken_namespace
+ _other_namespace = create(:group, name: 'api0')
+
+ expect(subject.wrongly_renamed.map(&:id))
+ .to contain_exactly(broken_namespace.route.id)
+ end
+ end
+
+ describe "#paths_and_corrections" do
+ it 'finds the wrong path and gets the correction from the namespace' do
+ broken_namespace
+ namespace = create(:group, name: 'uploads-test')
+ namespace.route.update_attribute(:path, 'uploads0-test')
+
+ expected_result = [
+ { 'namespace_path' => 'apiis', 'path' => 'api0is' },
+ { 'namespace_path' => 'uploads-test', 'path' => 'uploads0-test' }
+ ]
+
+ expect(subject.paths_and_corrections).to include(*expected_result)
+ end
+ end
+
+ describe '#routes_in_namespace_query' do
+ it 'includes only the required routes' do
+ namespace = create(:group, path: 'hello')
+ project = create(:empty_project, namespace: namespace)
+ _other_namespace = create(:group, path: 'hello0')
+
+ result = Route.where(subject.routes_in_namespace_query('hello'))
+
+ expect(result).to contain_exactly(namespace.route, project.route)
+ end
+ end
+
+ describe '#up' do
+ let(:broken_project) do
+ project = create(:empty_project, namespace: broken_namespace, path: 'broken-project')
+ project.route.update_attribute(:path, 'api0is/broken-project')
+ project
+ end
+
+ it 'renames incorrectly named routes' do
+ broken_project
+
+ subject.up
+
+ expect(broken_project.route.reload.path).to eq('apiis/broken-project')
+ expect(broken_namespace.route.reload.path).to eq('apiis')
+ end
+
+ it "doesn't touch namespaces that look like something that should be renamed" do
+ namespace = create(:group, path: 'api0')
+
+ subject.up
+
+ expect(namespace.route.reload.path).to eq('api0')
+ end
+ end
+end
diff --git a/spec/migrations/rename_users_with_renamed_namespace_spec.rb b/spec/migrations/rename_users_with_renamed_namespace_spec.rb
new file mode 100644
index 00000000000..1e9aab3d9a1
--- /dev/null
+++ b/spec/migrations/rename_users_with_renamed_namespace_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170518200835_rename_users_with_renamed_namespace.rb')
+
+describe RenameUsersWithRenamedNamespace, truncate: true do
+ it 'renames a user that had their namespace renamed to the namespace path' do
+ other_user = create(:user, username: 'kodingu')
+ other_user1 = create(:user, username: 'api0')
+
+ user = create(:user, username: "Users0")
+ user.update_attribute(:username, 'Users')
+ user1 = create(:user, username: "import0")
+ user1.update_attribute(:username, 'import')
+
+ described_class.new.up
+
+ expect(user.reload.username).to eq('Users0')
+ expect(user1.reload.username).to eq('import0')
+
+ expect(other_user.reload.username).to eq('kodingu')
+ expect(other_user1.reload.username).to eq('api0')
+ end
+end
diff --git a/spec/migrations/upate_retried_for_ci_builds_spec.rb b/spec/migrations/upate_retried_for_ci_builds_spec.rb
new file mode 100644
index 00000000000..5cdb8a3c7da
--- /dev/null
+++ b/spec/migrations/upate_retried_for_ci_builds_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170503004427_upate_retried_for_ci_build.rb')
+
+describe UpateRetriedForCiBuild, truncate: true do
+ let(:pipeline) { create(:ci_pipeline) }
+ let!(:build_old) { create(:ci_build, pipeline: pipeline, name: 'test') }
+ let!(:build_new) { create(:ci_build, pipeline: pipeline, name: 'test') }
+
+ before do
+ described_class.new.up
+ end
+
+ it 'updates ci_builds.is_retried' do
+ expect(build_old.reload).to be_retried
+ expect(build_new.reload).not_to be_retried
+ end
+end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 157d17fbb68..56b24ce62f3 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -854,6 +854,16 @@ describe Ci::Pipeline, models: true do
end
end
end
+
+ context 'when there is a manual action present in the pipeline' do
+ before do
+ create(:ci_build, :manual, pipeline: pipeline)
+ end
+
+ it 'is not cancelable' do
+ expect(pipeline).not_to be_cancelable
+ end
+ end
end
describe '#cancel_running' do
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 50e96d56191..d5400bbaaf1 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -243,7 +243,6 @@ describe 'project routing' do
# diffs_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/diffs(.:format) projects/merge_requests#diffs
# commits_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/commits(.:format) projects/merge_requests#commits
# merge_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/merge(.:format) projects/merge_requests#merge
- # merge_check_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/merge_check(.:format) projects/merge_requests#merge_check
# ci_status_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/ci_status(.:format) projects/merge_requests#ci_status
# toggle_subscription_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/toggle_subscription(.:format) projects/merge_requests#toggle_subscription
# branch_from_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/branch_from(.:format) projects/merge_requests#branch_from
@@ -272,10 +271,6 @@ describe 'project routing' do
)
end
- it 'to #merge_check' do
- expect(get('/gitlab/gitlabhq/merge_requests/1/merge_check')).to route_to('projects/merge_requests#merge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
- end
-
it 'to #branch_from' do
expect(get('/gitlab/gitlabhq/merge_requests/branch_from')).to route_to('projects/merge_requests#branch_from', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e2d5928e5b2..a58f4e664b7 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -10,7 +10,7 @@ require 'shoulda/matchers'
require 'rspec/retry'
rspec_profiling_is_configured =
- ENV['RSPEC_PROFILING_POSTGRES_URL'] ||
+ ENV['RSPEC_PROFILING_POSTGRES_URL'].present? ||
ENV['RSPEC_PROFILING']
branch_can_be_profiled =
ENV['GITLAB_DATABASE'] == 'postgresql' &&
diff --git a/spec/support/milestone_tabs_examples.rb b/spec/support/milestone_tabs_examples.rb
index c69f8e11008..4ad8b0a16e1 100644
--- a/spec/support/milestone_tabs_examples.rb
+++ b/spec/support/milestone_tabs_examples.rb
@@ -1,7 +1,7 @@
shared_examples 'milestone tabs' do
def go(path, extra_params = {})
params = if milestone.is_a?(GlobalMilestone)
- { group_id: group.id, id: milestone.safe_title, title: milestone.title }
+ { group_id: group.to_param, id: milestone.safe_title, title: milestone.title }
else
{ namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid }
end