Commit cf21118f authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents d0e7914f 9b581d41
...@@ -93,6 +93,6 @@ class UrlValidator < ActiveModel::EachValidator ...@@ -93,6 +93,6 @@ class UrlValidator < ActiveModel::EachValidator
end end
def allow_setting_local_requests? def allow_setting_local_requests?
ApplicationSetting.current&.allow_local_requests_from_hooks_and_services? Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services?
end end
end end
---
title: 'API: Sort tie breaker with id DESC'
merge_request: 25311
author: Nermin Vehabovic
type: changed
...@@ -15,6 +15,10 @@ include: ...@@ -15,6 +15,10 @@ include:
- [Visibility and access controls](visibility_and_access_controls.md) - [Visibility and access controls](visibility_and_access_controls.md)
- [Custom templates repository](instance_template_repository.md) - [Custom templates repository](instance_template_repository.md)
NOTE: **Note:**
You can change the [first day of the week](../../profile/preferences.md) for the entire GitLab instance
in the **Localization** section of **Admin area > Settings > Preferences**.
## GitLab.com admin area settings ## GitLab.com admin area settings
Most of the settings under the admin area change the behavior of the whole Most of the settings under the admin area change the behavior of the whole
......
...@@ -312,6 +312,12 @@ module API ...@@ -312,6 +312,12 @@ module API
items.search(text) items.search(text)
end end
def order_options_with_tie_breaker
order_options = { params[:order_by] => params[:sort] }
order_options['id'] ||= 'desc'
order_options
end
# error helpers # error helpers
def forbidden!(reason = nil) def forbidden!(reason = nil)
...@@ -406,7 +412,7 @@ module API ...@@ -406,7 +412,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def reorder_projects(projects) def reorder_projects(projects)
projects.reorder(params[:order_by] => params[:sort]) projects.reorder(order_options_with_tie_breaker)
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
......
...@@ -31,8 +31,7 @@ module API ...@@ -31,8 +31,7 @@ module API
issues = IssuesFinder.new(current_user, args).execute issues = IssuesFinder.new(current_user, args).execute
.preload(:assignees, :labels, :notes, :timelogs, :project, :author, :closed_by) .preload(:assignees, :labels, :notes, :timelogs, :project, :author, :closed_by)
issues.reorder(order_options_with_tie_breaker)
issues.reorder(args[:order_by] => args[:sort])
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
......
...@@ -40,7 +40,7 @@ module API ...@@ -40,7 +40,7 @@ module API
args[:scope] = args[:scope].underscore if args[:scope] args[:scope] = args[:scope].underscore if args[:scope]
merge_requests = MergeRequestsFinder.new(current_user, args).execute merge_requests = MergeRequestsFinder.new(current_user, args).execute
.reorder(args[:order_by] => args[:sort]) .reorder(order_options_with_tie_breaker)
merge_requests = paginate(merge_requests) merge_requests = paginate(merge_requests)
.preload(:source_project, :target_project) .preload(:source_project, :target_project)
......
...@@ -39,7 +39,7 @@ module API ...@@ -39,7 +39,7 @@ module API
# at the DB query level (which we cannot in that case), the current # at the DB query level (which we cannot in that case), the current
# page can have less elements than :per_page even if # page can have less elements than :per_page even if
# there's more than one page. # there's more than one page.
raw_notes = noteable.notes.with_metadata.reorder(params[:order_by] => params[:sort]) raw_notes = noteable.notes.with_metadata.reorder(order_options_with_tie_breaker)
notes = notes =
# paginate() only works with a relation. This could lead to a # paginate() only works with a relation. This could lead to a
# mismatch between the pagination headers info and the actual notes # mismatch between the pagination headers info and the actual notes
......
...@@ -26,7 +26,7 @@ module API ...@@ -26,7 +26,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def reorder_users(users) def reorder_users(users)
if params[:order_by] && params[:sort] if params[:order_by] && params[:sort]
users.reorder(params[:order_by] => params[:sort]) users.reorder(order_options_with_tie_breaker)
else else
users users
end end
......
...@@ -14,9 +14,8 @@ describe Gitlab::CurrentSettings do ...@@ -14,9 +14,8 @@ describe Gitlab::CurrentSettings do
describe '#current_application_settings', :use_clean_rails_memory_store_caching do describe '#current_application_settings', :use_clean_rails_memory_store_caching do
it 'allows keys to be called directly' do it 'allows keys to be called directly' do
db_settings = create(:application_setting, db_settings = ApplicationSetting.first || create(:application_setting)
home_page_url: 'http://mydomain.com', db_settings.update!(home_page_url: 'http://mydomain.com', signup_enabled: false)
signup_enabled: false)
expect(described_class.home_page_url).to eq(db_settings.home_page_url) expect(described_class.home_page_url).to eq(db_settings.home_page_url)
expect(described_class.signup_enabled?).to be_falsey expect(described_class.signup_enabled?).to be_falsey
...@@ -109,7 +108,7 @@ describe Gitlab::CurrentSettings do ...@@ -109,7 +108,7 @@ describe Gitlab::CurrentSettings do
context 'with pending migrations' do context 'with pending migrations' do
before do before do
expect(ActiveRecord::Migrator).to receive(:needs_migration?).and_return(true) allow(ActiveRecord::Migrator).to receive(:needs_migration?).and_return(true)
end end
shared_examples 'a non-persisted ApplicationSetting object' do shared_examples 'a non-persisted ApplicationSetting object' do
......
...@@ -46,9 +46,7 @@ describe LfsDownloadObject do ...@@ -46,9 +46,7 @@ describe LfsDownloadObject do
subject { described_class.new(oid: oid, size: size, link: 'http://192.168.1.1') } subject { described_class.new(oid: oid, size: size, link: 'http://192.168.1.1') }
before do before do
allow(ApplicationSetting) stub_application_setting(allow_local_requests_from_hooks_and_services: setting)
.to receive(:current)
.and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: setting))
end end
context 'are allowed' do context 'are allowed' do
......
...@@ -363,10 +363,38 @@ describe API::Issues do ...@@ -363,10 +363,38 @@ describe API::Issues do
expect_paginated_array_response([]) expect_paginated_array_response([])
end end
it 'sorts by created_at descending by default' do context 'without sort params' do
get api('/issues', user) it 'sorts by created_at descending by default' do
get api('/issues', user)
expect_paginated_array_response([issue.id, closed_issue.id]) expect_paginated_array_response([issue.id, closed_issue.id])
end
context 'with 2 issues with same created_at' do
let!(:closed_issue2) do
create :closed_issue,
author: user,
assignees: [user],
project: project,
milestone: milestone,
created_at: closed_issue.created_at,
updated_at: 1.hour.ago,
title: issue_title,
description: issue_description
end
it 'page breaks first page correctly' do
get api('/issues?per_page=2', user)
expect_paginated_array_response([issue.id, closed_issue2.id])
end
it 'page breaks second page correctly' do
get api('/issues?per_page=2&page=2', user)
expect_paginated_array_response([closed_issue.id])
end
end
end end
it 'sorts ascending when requested' do it 'sorts ascending when requested' do
...@@ -617,10 +645,38 @@ describe API::Issues do ...@@ -617,10 +645,38 @@ describe API::Issues do
expect_paginated_array_response(group_confidential_issue.id) expect_paginated_array_response(group_confidential_issue.id)
end end
it 'sorts by created_at descending by default' do context 'without sort params' do
get api(base_url, user) it 'sorts by created_at descending by default' do
get api(base_url, user)
expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id]) expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
end
context 'with 2 issues with same created_at' do
let!(:group_issue2) do
create :issue,
author: user,
assignees: [user],
project: group_project,
milestone: group_milestone,
updated_at: 1.hour.ago,
title: issue_title,
description: issue_description,
created_at: group_issue.created_at
end
it 'page breaks first page correctly' do
get api("#{base_url}?per_page=3", user)
expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue2.id])
end
it 'page breaks second page correctly' do
get api("#{base_url}?per_page=3&page=2", user)
expect_paginated_array_response([group_issue.id])
end
end
end end
it 'sorts ascending when requested' do it 'sorts ascending when requested' do
...@@ -832,10 +888,38 @@ describe API::Issues do ...@@ -832,10 +888,38 @@ describe API::Issues do
expect_paginated_array_response([issue.id, closed_issue.id]) expect_paginated_array_response([issue.id, closed_issue.id])
end end
it 'sorts by created_at descending by default' do context 'without sort params' do
get api("#{base_url}/issues", user) it 'sorts by created_at descending by default' do
get api("#{base_url}/issues", user)
expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id]) expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
end
context 'with 2 issues with same created_at' do
let!(:closed_issue2) do
create :closed_issue,
author: user,
assignees: [user],
project: project,
milestone: milestone,
created_at: closed_issue.created_at,
updated_at: 1.hour.ago,
title: issue_title,
description: issue_description
end
it 'page breaks first page correctly' do
get api("#{base_url}/issues?per_page=3", user)
expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue2.id])
end
it 'page breaks second page correctly' do
get api("#{base_url}/issues?per_page=3&page=2", user)
expect_paginated_array_response([closed_issue.id])
end
end
end end
it 'sorts ascending when requested' do it 'sorts ascending when requested' do
......
...@@ -257,6 +257,38 @@ shared_examples 'merge requests list' do ...@@ -257,6 +257,38 @@ shared_examples 'merge requests list' do
expect(response_dates).to eq(response_dates.sort.reverse) expect(response_dates).to eq(response_dates.sort.reverse)
end end
context '2 merge requests with equal created_at' do
let!(:closed_mr2) do
create :merge_request,
state: 'closed',
milestone: milestone1,
author: user,
assignee: user,
source_project: project,
target_project: project,
title: "Test",
created_at: @mr_earlier.created_at
end
it 'page breaks first page correctly' do
get api("#{endpoint_path}?sort=desc&per_page=4", user)
response_ids = json_response.map { |merge_request| merge_request['id'] }
expect(response_ids).to include(closed_mr2.id)
expect(response_ids).not_to include(@mr_earlier.id)
end
it 'page breaks second page correctly' do
get api("#{endpoint_path}?sort=desc&per_page=4&page=2", user)
response_ids = json_response.map { |merge_request| merge_request['id'] }
expect(response_ids).not_to include(closed_mr2.id)
expect(response_ids).to include(@mr_earlier.id)
end
end
it 'returns an array of merge_requests ordered by updated_at' do it 'returns an array of merge_requests ordered by updated_at' do
path = endpoint_path + '?order_by=updated_at' path = endpoint_path + '?order_by=updated_at'
......
...@@ -8,13 +8,45 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name| ...@@ -8,13 +8,45 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
create_list(:note, 3, params) create_list(:note, 3, params)
end end
it 'sorts by created_at in descending order by default' do context 'without sort params' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user) it 'sorts by created_at in descending order by default' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user)
response_dates = json_response.map { |note| note['created_at'] } response_dates = json_response.map { |note| note['created_at'] }
expect(json_response.length).to eq(4) expect(json_response.length).to eq(4)
expect(response_dates).to eq(response_dates.sort.reverse) expect(response_dates).to eq(response_dates.sort.reverse)
end
context '2 notes with equal created_at' do
before do
@first_note = Note.first
params = { noteable: noteable, author: user }
params[:project] = parent if parent.is_a?(Project)
params[:created_at] = @first_note.created_at
@note2 = create(:note, params)
end
it 'page breaks first page correctly' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?per_page=4", user)
response_ids = json_response.map { |note| note['id'] }
expect(response_ids).to include(@note2.id)
expect(response_ids).not_to include(@first_note.id)
end
it 'page breaks second page correctly' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?per_page=4&page=2", user)
response_ids = json_response.map { |note| note['id'] }
expect(response_ids).not_to include(@note2.id)
expect(response_ids).to include(@first_note.id)
end
end
end end
it 'sorts by ascending order when requested' do it 'sorts by ascending order when requested' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment