diff --git a/ckan/lib/search/query.py b/ckan/lib/search/query.py
index 73a31107544..0cd266304ad 100644
--- a/ckan/lib/search/query.py
+++ b/ckan/lib/search/query.py
@@ -247,7 +247,14 @@ def run(self, query):
query['q'] = "*:*"
# number of results
- query['rows'] = min(1000, int(query.get('rows', 10)))
+ rows_to_return = min(1000, int(query.get('rows', 10)))
+ if rows_to_return > 0:
+ # #1683 Work around problem of last result being out of order
+ # in SOLR 1.4
+ rows_to_query = rows_to_return + 1
+ else:
+ rows_to_query = rows_to_return
+ query['rows'] = rows_to_query
# order by score if no 'sort' term given
order_by = query.get('sort')
@@ -297,6 +304,9 @@ def run(self, query):
self.count = response.get('numFound', 0)
self.results = response.get('docs', [])
+ # #1683 Filter out the last row that is sometimes out of order
+ self.results = self.results[:rows_to_return]
+
# get any extras and add to 'extras' dict
for result in self.results:
extra_keys = filter(lambda x: x.startswith('extras_'), result.keys())
diff --git a/ckan/tests/functional/test_pagination.py b/ckan/tests/functional/test_pagination.py
index adc95ddd9d9..436622d0469 100644
--- a/ckan/tests/functional/test_pagination.py
+++ b/ckan/tests/functional/test_pagination.py
@@ -1,8 +1,32 @@
+import re
+
+from nose.tools import assert_equal
+
from ckan.lib.create_test_data import CreateTestData
import ckan.model as model
from ckan.tests import TestController, url_for, setup_test_search_index
-class TestPagination(TestController):
+def scrape_search_results(response, object_type):
+ assert object_type in ('dataset', 'group', 'user')
+ results = re.findall('href="/%s/%s_(\d\d)"' % (object_type, object_type),
+ str(response))
+ return results
+
+def test_scrape():
+ html = '''
+
+ user_00
+
+ ...
+
+ user_01
+
+
+ '''
+ res = scrape_search_results(html, 'user')
+ assert_equal(res, ['00', '01'])
+
+class TestPaginationPackage(TestController):
@classmethod
def setup_class(cls):
setup_test_search_index()
@@ -10,63 +34,103 @@ def setup_class(cls):
# no. entities per page is hardcoded into the controllers, so
# create enough of each here so that we can test pagination
- cls.num_groups = 21
cls.num_packages_in_large_group = 51
- cls.num_users = 21
- groups = [u'group_%s' % str(i).zfill(2) for i in range(1, cls.num_groups)]
- users = [u'user_%s' % str(i).zfill(2) for i in range(cls.num_users)]
packages = []
for i in range(cls.num_packages_in_large_group):
packages.append({
- 'name': u'package_%s' % str(i).zfill(2),
+ 'name': u'dataset_%s' % str(i).zfill(2),
'groups': u'group_00'
})
- CreateTestData.create_arbitrary(
- packages, extra_group_names=groups, extra_user_names = users,
- )
+ CreateTestData.create_arbitrary(packages)
@classmethod
def teardown_class(self):
model.repo.rebuild_db()
-
- def test_search(self):
+
+ def test_package_search_p1(self):
res = self.app.get(url_for(controller='package', action='search', q='groups:group_00'))
assert 'href="/dataset?q=groups%3Agroup_00&page=2"' in res
- assert 'href="/dataset/package_00"' in res, res
- assert 'href="/dataset/package_19"' in res, res
+ pkg_numbers = scrape_search_results(res, 'dataset')
+ assert_equal(['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], pkg_numbers)
+ def test_package_search_p2(self):
res = self.app.get(url_for(controller='package', action='search', q='groups:group_00', page=2))
assert 'href="/dataset?q=groups%3Agroup_00&page=1"' in res
- assert 'href="/dataset/package_20"' in res
- assert 'href="/dataset/package_39"' in res
+ pkg_numbers = scrape_search_results(res, 'dataset')
+ assert_equal(['20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39'], pkg_numbers)
+
+ def test_group_read_p1(self):
+ res = self.app.get(url_for(controller='group', action='read', id='group_00'))
+ assert 'href="/group/group_00?page=2' in res
+ pkg_numbers = scrape_search_results(res, 'dataset')
+ assert_equal(['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29'], pkg_numbers)
+
+ def test_group_read_p2(self):
+ res = self.app.get(url_for(controller='group', action='read', id='group_00', page=2))
+ assert 'href="/group/group_00?page=1' in res
+ pkg_numbers = scrape_search_results(res, 'dataset')
+ assert_equal(['30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50'], pkg_numbers)
+
+class TestPaginationGroup(TestController):
+ @classmethod
+ def setup_class(cls):
+ # no. entities per page is hardcoded into the controllers, so
+ # create enough of each here so that we can test pagination
+ cls.num_groups = 21
+
+ groups = [u'group_%s' % str(i).zfill(2) for i in range(0, cls.num_groups)]
+
+ CreateTestData.create_arbitrary(
+ [], extra_group_names=groups
+ )
+
+ @classmethod
+ def teardown_class(self):
+ model.repo.rebuild_db()
def test_group_index(self):
res = self.app.get(url_for(controller='group', action='index'))
- assert 'href="/group?page=2"' in res
- assert 'href="/group/group_19"' in res
+ assert 'href="/group?page=2"' in res, res
+ grp_numbers = scrape_search_results(res, 'group')
+ assert_equal(['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], grp_numbers)
res = self.app.get(url_for(controller='group', action='index', page=2))
assert 'href="/group?page=1"' in res
- assert 'href="/group/group_20"' in res
+ grp_numbers = scrape_search_results(res, 'group')
+ assert_equal(['20'], grp_numbers)
- def test_group_read(self):
- res = self.app.get(url_for(controller='group', action='read', id='group_00'))
- assert 'href="/group/group_00?page=2' in res
- assert 'href="/dataset/package_29"' in res
+class TestPaginationUsers(TestController):
+ @classmethod
+ def setup_class(cls):
+ # Delete default user as it appears in the first page of results
+ model.User.by_name(u'logged_in').purge()
+ model.repo.commit_and_remove()
- res = self.app.get(url_for(controller='group', action='read', id='group_00', page=2))
- assert 'href="/group/group_00?page=1' in res
- assert 'href="/dataset/package_30"' in res
+ # no. entities per page is hardcoded into the controllers, so
+ # create enough of each here so that we can test pagination
+ cls.num_users = 21
+
+ users = [u'user_%s' % str(i).zfill(2) for i in range(cls.num_users)]
+
+ CreateTestData.create_arbitrary(
+ [], extra_user_names = users,
+ )
+
+ @classmethod
+ def teardown_class(self):
+ model.repo.rebuild_db()
def test_users_index(self):
# allow for 2 extra users shown on user listing, 'logged_in' and 'visitor'
res = self.app.get(url_for(controller='user', action='index'))
- assert 'href="/user/user_18"' in res
assert 'href="/user?q=&order_by=name&page=2"' in res
+ user_numbers = scrape_search_results(res, 'user')
+ assert_equal(['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], user_numbers)
res = self.app.get(url_for(controller='user', action='index', page=2))
- assert 'href="/user/user_20"' in res
assert 'href="/user?q=&order_by=name&page=1"' in res
+ user_numbers = scrape_search_results(res, 'user')
+ assert_equal(['20'], user_numbers)