Skip to content

Commit 50b1030

Browse files
committed
fix: test the adapter-specific query ordering
1 parent 9156734 commit 50b1030

File tree

3 files changed

+70
-33
lines changed

3 files changed

+70
-33
lines changed

test/controllers/controller_test.rb

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -494,15 +494,15 @@ def test_sorting_by_relationship_field
494494

495495
assert_response :success
496496
assert json_response['data'].length > 10, 'there are enough records to show sort'
497+
expected = Post
498+
.all
499+
.left_joins(:author)
500+
.merge(Person.order(name: :asc))
501+
.map(&:id)
502+
.map(&:to_s)
503+
ids = json_response['data'].map {|data| data['id'] }
497504

498-
# Postgres sorts nulls last, whereas sqlite and mysql sort nulls first
499-
if ENV['DATABASE_URL'].starts_with?('postgres')
500-
assert_equal '17', json_response['data'][-1]['id'], 'nil is at the start'
501-
assert_equal post.id.to_s, json_response['data'][0]['id'], 'alphabetically first user is not first'
502-
else
503-
assert_equal '17', json_response['data'][0]['id'], 'nil is at the end'
504-
assert_equal post.id.to_s, json_response['data'][1]['id'], 'alphabetically first user is second'
505-
end
505+
assert_equal expected, ids, "since adapter_sorts_nulls_last=#{adapter_sorts_nulls_last}"
506506
end
507507

508508
def test_desc_sorting_by_relationship_field
@@ -512,14 +512,15 @@ def test_desc_sorting_by_relationship_field
512512
assert_response :success
513513
assert json_response['data'].length > 10, 'there are enough records to show sort'
514514

515-
# Postgres sorts nulls last, whereas sqlite and mysql sort nulls first
516-
if ENV['DATABASE_URL'].starts_with?('postgres')
517-
assert_equal '17', json_response['data'][0]['id'], 'nil is at the start'
518-
assert_equal post.id.to_s, json_response['data'][-1]['id']
519-
else
520-
assert_equal '17', json_response['data'][-1]['id'], 'nil is at the end'
521-
assert_equal post.id.to_s, json_response['data'][-2]['id'], 'alphabetically first user is second last'
522-
end
515+
expected = Post
516+
.all
517+
.left_joins(:author)
518+
.merge(Person.order(name: :desc))
519+
.map(&:id)
520+
.map(&:to_s)
521+
ids = json_response['data'].map {|data| data['id'] }
522+
523+
assert_equal expected, ids, "since adapter_sorts_nulls_last=#{adapter_sorts_nulls_last}"
523524
end
524525

525526
def test_sorting_by_relationship_field_include
@@ -529,13 +530,15 @@ def test_sorting_by_relationship_field_include
529530
assert_response :success
530531
assert json_response['data'].length > 10, 'there are enough records to show sort'
531532

532-
if ENV['DATABASE_URL'].starts_with?('postgres')
533-
assert_equal '17', json_response['data'][-1]['id'], 'nil is at the top'
534-
assert_equal post.id.to_s, json_response['data'][0]['id']
535-
else
536-
assert_equal '17', json_response['data'][0]['id'], 'nil is at the top'
537-
assert_equal post.id.to_s, json_response['data'][1]['id'], 'alphabetically first user is second'
538-
end
533+
expected = Post
534+
.all
535+
.left_joins(:author)
536+
.merge(Person.order(name: :asc))
537+
.map(&:id)
538+
.map(&:to_s)
539+
ids = json_response['data'].map {|data| data['id'] }
540+
541+
assert_equal expected, ids, "since adapter_sorts_nulls_last=#{adapter_sorts_nulls_last}"
539542
end
540543

541544
def test_invalid_sort_param
@@ -4772,11 +4775,11 @@ def test_fetch_robots_with_sort_by_name
47724775
assert_cacheable_get :index, params: {sort: 'name'}
47734776
assert_response :success
47744777

4775-
if ENV['DATABASE_URL'].starts_with?('postgres')
4776-
assert_equal 'jane', json_response['data'].first['attributes']['name']
4777-
else
4778-
assert_equal 'John', json_response['data'].first['attributes']['name']
4779-
end
4778+
expected_names = Robot
4779+
.all
4780+
.order(name: :asc)
4781+
.map(&:name)
4782+
assert_equal expected_names.first, json_response['data'].first['attributes']['name'], "since adapter_sorts_nulls_last=#{adapter_sorts_nulls_last}"
47804783
end
47814784

47824785
def test_fetch_robots_with_sort_by_lower_name

test/integration/requests/request_test.rb

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,16 +1443,32 @@ def test_sort_primary_attribute
14431443
end
14441444

14451445
def test_sort_included_attribute
1446-
# Postgres sorts nulls last, whereas sqlite and mysql sort nulls first
1447-
pg = ENV['DATABASE_URL'].starts_with?('postgres')
1448-
14491446
get '/api/v6/authors?sort=author_detail.author_stuff', headers: { 'Accept' => JSONAPI::MEDIA_TYPE }
14501447
assert_jsonapi_response 200
1451-
assert_equal pg ? '1001' : '1000', json_response['data'][0]['id']
1448+
up_expected_ids = AuthorResource
1449+
._model_class
1450+
.all
1451+
.left_joins(:author_detail)
1452+
.merge(AuthorDetail.order(author_stuff: :asc))
1453+
.map(&:id)
1454+
expected = up_expected_ids.first.to_s
1455+
ids = json_response['data'].map {|data| data['id'] }
1456+
actual = ids.first
1457+
assert_equal expected, actual, "since adapter_sorts_nulls_last=#{adapter_sorts_nulls_last} ands actual=#{ids} vs. expected=#{up_expected_ids}"
14521458

14531459
get '/api/v6/authors?sort=-author_detail.author_stuff', headers: { 'Accept' => JSONAPI::MEDIA_TYPE }
14541460
assert_jsonapi_response 200
1455-
assert_equal pg ? '1000' : '1002', json_response['data'][0]['id']
1461+
down_expected_ids = AuthorResource
1462+
._model_class
1463+
.all
1464+
.left_joins(:author_detail)
1465+
.merge(AuthorDetail.order(author_stuff: :desc))
1466+
.map(&:id)
1467+
expected = down_expected_ids.first.to_s
1468+
ids = json_response['data'].map {|data| data['id'] }
1469+
actual = ids.first
1470+
assert_equal expected, actual, "since adapter_sorts_nulls_last=#{adapter_sorts_nulls_last} ands actual=#{ids} vs. expected=#{down_expected_ids}"
1471+
refute_equal up_expected_ids, down_expected_ids # sanity check
14561472
end
14571473

14581474
def test_include_parameter_quoted

test/test_helper.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,24 @@ def run_in_transaction?
459459

460460
self.fixture_path = "#{Rails.root}/fixtures"
461461
fixtures :all
462+
463+
def adapter_name
464+
ActiveRecord::Base.connection.adapter_name
465+
end
466+
467+
# Postgres sorts nulls last, whereas sqlite and mysql sort nulls first
468+
def adapter_sorts_nulls_last
469+
case adapter_name
470+
when 'PostgreSQL' then true
471+
when 'SQLite', 'Mysql2' then false
472+
else
473+
fail ArgumentError, "Unhandled adapter #{adapter_name} in #{__callee__}"
474+
end
475+
end
476+
477+
def db_true
478+
ActiveRecord::Base.connection.quote(true)
479+
end
462480
end
463481

464482
class ActiveSupport::TestCase

0 commit comments

Comments
 (0)