[ckan-changes] [okfn/ckan] 676d7a: [#2304] More work on follower_create tests
GitHub
noreply at github.com
Sat Apr 28 20:16:04 UTC 2012
Branch: refs/heads/feature-2304-follow
Home: https://github.com/okfn/ckan
Commit: 676d7a332824af1e27d433ac455ac507ff0abbaf
https://github.com/okfn/ckan/commit/676d7a332824af1e27d433ac455ac507ff0abbaf
Author: Sean Hammond <seanhammond at lavabit.com>
Date: 2012-04-28 (Sat, 28 Apr 2012)
Changed paths:
M ckan/tests/functional/api/test_follow.py
Log Message:
-----------
[#2304] More work on follower_create tests
Broke long test methods into lots of smaller ones, and also added in
some test conditions, including testing responses from am_following
diff --git a/ckan/tests/functional/api/test_follow.py b/ckan/tests/functional/api/test_follow.py
index 867300f..569071a 100644
--- a/ckan/tests/functional/api/test_follow.py
+++ b/ckan/tests/functional/api/test_follow.py
@@ -13,6 +13,7 @@ def datetime_from_string(s):
return datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
class TestFollow(object):
+ '''Tests for the follow API.'''
@classmethod
def setup_class(self):
@@ -51,15 +52,21 @@ def _start_following(self, follower_id, api_key, object_id, object_type,
assert response['success'] is True
count_before = response['result']
+ # Check that the user is not already following the object.
+ params = json.dumps({'id': object_id})
+ extra_environ = {'Authorization': str(api_key)}
+ response = self.app.post('/api/action/am_following',
+ params=params, extra_environ=extra_environ).json
+ assert response['success'] is True
+ assert response['result'] is False
+
# Make the user start following the object.
before = datetime.datetime.now()
params = json.dumps({
'object_id': object_arg,
'object_type': object_type,
})
- extra_environ = {
- 'Authorization': str(api_key)
- }
+ extra_environ = {'Authorization': str(api_key)}
response = self.app.post('/api/action/follower_create',
params=params, extra_environ=extra_environ).json
after = datetime.datetime.now()
@@ -73,6 +80,14 @@ def _start_following(self, follower_id, api_key, object_id, object_type,
timestamp = datetime_from_string(follower['datetime'])
assert (timestamp >= before and timestamp <= after), str(timestamp)
+ # Check that am_following now returns True.
+ params = json.dumps({'id': object_id})
+ extra_environ = {'Authorization': str(api_key)}
+ response = self.app.post('/api/action/am_following',
+ params=params, extra_environ=extra_environ).json
+ assert response['success'] is True
+ assert response['result'] is True
+
# Check that the user appears in the object's list of followers.
params = json.dumps({'id': object_id})
response = self.app.post('/api/action/follower_list',
@@ -91,48 +106,35 @@ def _start_following(self, follower_id, api_key, object_id, object_type,
assert response['success'] is True
assert response['result'] == count_before + 1
- def test_user_follow_user(self):
-
- # Test with a bad API key.
- params = json.dumps({
- 'object_id': self.russianfan.id,
- 'object_type': 'user',
- })
- extra_environ = {
- 'Authorization': 'bad api key'
- }
- response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=403).json
- assert response['success'] == False
- assert response['error']['message'] == 'Access denied'
-
- # Test with a bad object ID.
- params = json.dumps({
- 'object_id': 'bad id',
- 'object_type': 'user',
- })
- extra_environ = {
- 'Authorization': str(self.annafan.apikey),
- }
- response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=409).json
- assert response['success'] == False
- assert response['error']['object_id'] == ['Not found: User']
+ def test_01_user_follow_user_bad_api_key(self):
+ for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
+ params = json.dumps({
+ 'object_id': self.russianfan.id,
+ 'object_type': 'user',
+ })
+ extra_environ = {
+ 'Authorization': apikey,
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=403).json
+ assert response['success'] == False
+ assert response['error']['message'] == 'Access denied'
- # Test with a bad object type.
- params = json.dumps({
- 'object_id': self.russianfan.id,
- 'object_type': 'foobar',
- })
- extra_environ = {
- 'Authorization': str(self.annafan.apikey),
- }
- response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=409).json
- assert response['success'] == False
- assert response['error']['object_id'] == ['object_type foobar not recognised']
+ def test_01_user_follow_dataset_bad_api_key(self):
+ for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
+ params = json.dumps({
+ 'object_id': self.warandpeace.id,
+ 'object_type': 'dataset',
+ })
+ extra_environ = {
+ 'Authorization': 'bad api key'
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=403).json
+ assert response['success'] == False
+ assert response['error']['message'] == 'Access denied'
- # Test with missing API key.
+ def test_01_user_follow_user_missing_api_key(self):
params = json.dumps({
'object_id': self.russianfan.id,
'object_type': 'user',
@@ -142,43 +144,20 @@ def test_user_follow_user(self):
assert response['success'] == False
assert response['error']['message'] == 'Access denied'
- # Test with missing object_id.
+ def test_01_user_follow_dataset_missing_api_key(self):
params = json.dumps({
- 'object_type': 'user',
- })
- extra_environ = {
- 'Authorization': str(self.annafan.apikey),
- }
- response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=409).json
- assert response['success'] == False
- assert response['error']['object_id'] == ['Missing value']
-
- # Test with missing object_type.
- params = json.dumps({
- 'object_id': self.russianfan.id,
+ 'object_id': self.warandpeace.id,
+ 'object_type': 'dataset',
})
- extra_environ = {
- 'Authorization': str(self.annafan.apikey),
- }
response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=409).json
+ params=params, status=403).json
assert response['success'] == False
- assert response['error']['object_type'] == ['Missing value']
-
- # Test with good arguments.
- self._start_following(self.annafan.id, self.annafan.apikey,
- self.russianfan.id, 'user', self.russianfan.id)
-
- # Test with good arguments, by name.
- self._start_following(self.annafan.id, self.annafan.apikey,
- self.testsysadmin.id, 'user', self.testsysadmin.name)
+ assert response['error']['message'] == 'Access denied'
- # Test trying to follow a user that the user is already following.
- for object_id in (self.russianfan.id, self.russianfan.name,
- self.testsysadmin.id, self.testsysadmin.name):
+ def test_01_user_follow_user_bad_object_id(self):
+ for object_id in ('bad id', '', ' ', None, 3, 35.7, 'xxx'):
params = json.dumps({
- 'object_id': object_id,
+ 'object_id': 'bad id',
'object_type': 'user',
})
extra_environ = {
@@ -187,14 +166,24 @@ def test_user_follow_user(self):
response = self.app.post('/api/action/follower_create',
params=params, extra_environ=extra_environ, status=409).json
assert response['success'] == False
- assert response['error']['message'].startswith(
- 'Follower {follower_id} -> '.format(
- follower_id = self.annafan.id))
- assert response['error']['message'].endswith(' already exists')
+ assert response['error']['object_id'] == ['Not found: User']
+
+ def test_01_user_follow_dataset_bad_object_id(self):
+ for object_id in ('bad id', '', ' ', None, 3, 35.7, 'xxx'):
+ params = json.dumps({
+ 'object_id': 'bad id',
+ 'object_type': 'dataset',
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=409).json
+ assert response['success'] == False
+ assert response['error']['object_id'] == ['Not found: Dataset']
- # Test that a user cannot follow herself.
+ def test_01_user_follow_user_missing_object_id(self):
params = json.dumps({
- 'object_id': self.annafan.id,
'object_type': 'user',
})
extra_environ = {
@@ -203,27 +192,10 @@ def test_user_follow_user(self):
response = self.app.post('/api/action/follower_create',
params=params, extra_environ=extra_environ, status=409).json
assert response['success'] == False
- assert response['error']['object_id'] == [
- 'An object cannot follow itself']
-
- def test_user_follow_dataset(self):
-
- # Test with a bad API key.
- params = json.dumps({
- 'object_id': self.warandpeace.id,
- 'object_type': 'dataset',
- })
- extra_environ = {
- 'Authorization': 'bad api key'
- }
- response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=403).json
- assert response['success'] == False
- assert response['error']['message'] == 'Access denied'
+ assert response['error']['object_id'] == ['Missing value']
- # Test with a bad object ID.
+ def test_01_user_follow_dataset_missing_object_id(self):
params = json.dumps({
- 'object_id': 'bad id',
'object_type': 'dataset',
})
extra_environ = {
@@ -232,34 +204,39 @@ def test_user_follow_dataset(self):
response = self.app.post('/api/action/follower_create',
params=params, extra_environ=extra_environ, status=409).json
assert response['success'] == False
- assert response['error']['object_id'] == ['Not found: Dataset']
+ assert response['error']['object_id'] == ['Missing value']
- # Test with a bad object type.
- params = json.dumps({
- 'object_id': self.warandpeace.id,
- 'object_type': 'foobar',
- })
- extra_environ = {
- 'Authorization': str(self.annafan.apikey),
- }
- response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ, status=409).json
- assert response['success'] == False
- assert response['error']['object_id'] == ['object_type foobar not recognised']
+ def test_01_user_follow_user_bad_object_type(self):
+ for object_type in ('foobar', 'dataset', '', ' ', None, 3, 35.7):
+ params = json.dumps({
+ 'object_id': self.russianfan.id,
+ 'object_type': 'foobar',
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=409).json
+ assert response['success'] == False
+ assert response['error']['object_id'] == ['object_type foobar not recognised']
- # Test with missing API key.
- params = json.dumps({
- 'object_id': self.warandpeace.id,
- 'object_type': 'dataset',
- })
- response = self.app.post('/api/action/follower_create',
- params=params, status=403).json
- assert response['success'] == False
- assert response['error']['message'] == 'Access denied'
+ def test_01_user_follow_dataset_bad_object_type(self):
+ for object_type in ('foobar', 'user', '', ' ', None, 3, 35.7):
+ params = json.dumps({
+ 'object_id': self.warandpeace.id,
+ 'object_type': 'foobar',
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=409).json
+ assert response['success'] == False
+ assert response['error']['object_id'] == ['object_type foobar not recognised']
- # Test with missing object_id.
+ def test_01_user_follow_user_missing_object_type(self):
params = json.dumps({
- 'object_type': 'dataset',
+ 'object_id': self.russianfan.id,
})
extra_environ = {
'Authorization': str(self.annafan.apikey),
@@ -267,9 +244,9 @@ def test_user_follow_dataset(self):
response = self.app.post('/api/action/follower_create',
params=params, extra_environ=extra_environ, status=409).json
assert response['success'] == False
- assert response['error']['object_id'] == ['Missing value']
+ assert response['error']['object_type'] == ['Missing value']
- # Test with missing object_type.
+ def test_01_user_follow_dataset_missing_object_type(self):
params = json.dumps({
'object_id': self.warandpeace.id,
})
@@ -281,15 +258,41 @@ def test_user_follow_dataset(self):
assert response['success'] == False
assert response['error']['object_type'] == ['Missing value']
- # Test with good arguments.
+ def test_02_user_follow_user_by_id(self):
+ self._start_following(self.annafan.id, self.annafan.apikey,
+ self.russianfan.id, 'user', self.russianfan.id)
+
+ def test_02_user_follow_dataset_by_id(self):
self._start_following(self.annafan.id, self.annafan.apikey,
self.warandpeace.id, 'dataset', self.warandpeace.id)
- # Test with good arguments, by name.
+ def test_02_user_follow_user_by_name(self):
+ self._start_following(self.annafan.id, self.annafan.apikey,
+ self.testsysadmin.id, 'user', self.testsysadmin.name)
+
+ def test_02_user_follow_dataset_by_name(self):
self._start_following(self.annafan.id, self.annafan.apikey,
self.annakarenina.id, 'dataset', self.annakarenina.name)
- # Test trying to follow a dataset that the user is already following.
+ def test_03_user_follow_user_already_following(self):
+ for object_id in (self.russianfan.id, self.russianfan.name,
+ self.testsysadmin.id, self.testsysadmin.name):
+ params = json.dumps({
+ 'object_id': object_id,
+ 'object_type': 'user',
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=409).json
+ assert response['success'] == False
+ assert response['error']['message'].startswith(
+ 'Follower {follower_id} -> '.format(
+ follower_id = self.annafan.id))
+ assert response['error']['message'].endswith(' already exists')
+
+ def test_03_user_follow_dataset_already_following(self):
for object_id in (self.warandpeace.id, self.warandpeace.name,
self.annakarenina.id, self.annakarenina.name):
params = json.dumps({
@@ -307,4 +310,18 @@ def test_user_follow_dataset(self):
follower_id = self.annafan.id))
assert response['error']['message'].endswith(' already exists')
+ def test_03_user_cannot_follow_herself(self):
+ params = json.dumps({
+ 'object_id': self.annafan.id,
+ 'object_type': 'user',
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_create',
+ params=params, extra_environ=extra_environ, status=409).json
+ assert response['success'] == False
+ assert response['error']['object_id'] == [
+ 'An object cannot follow itself']
+
# Test follow with datetime, should be ignored.
================================================================
Commit: 1848f0ba1da79b0fda33d0b2a5f9a2df54727cc1
https://github.com/okfn/ckan/commit/1848f0ba1da79b0fda33d0b2a5f9a2df54727cc1
Author: Sean Hammond <seanhammond at lavabit.com>
Date: 2012-04-28 (Sat, 28 Apr 2012)
Changed paths:
M ckan/tests/functional/api/test_follow.py
Log Message:
-----------
[#2304] Add one more test for follower_create
diff --git a/ckan/tests/functional/api/test_follow.py b/ckan/tests/functional/api/test_follow.py
index 569071a..293e771 100644
--- a/ckan/tests/functional/api/test_follow.py
+++ b/ckan/tests/functional/api/test_follow.py
@@ -22,7 +22,7 @@ def setup_class(self):
self.annafan = ckan.model.User.get('annafan')
self.russianfan = ckan.model.User.get('russianfan')
self.tester = ckan.model.User.get('tester')
- self.tester = ckan.model.User.get('joeadmin')
+ self.joeadmin = ckan.model.User.get('joeadmin')
self.warandpeace = ckan.model.Package.get('warandpeace')
self.annakarenina = ckan.model.Package.get('annakarenina')
self.app = paste.fixture.TestApp(pylons.test.pylonsapp)
@@ -32,7 +32,7 @@ def teardown_class(self):
ckan.model.repo.rebuild_db()
def _start_following(self, follower_id, api_key, object_id, object_type,
- object_arg):
+ object_arg, datetime_param=None):
'''Test a user starting to follow an object via the API.
:param follower_id: id of the user that will be following something.
@@ -42,6 +42,8 @@ def _start_following(self, follower_id, api_key, object_id, object_type,
user, e.g. 'user' or 'dataset'.
:param object_arg: the argument to pass to follower_create as the id of
the object that will be followed, could be the object's id or name.
+ :param datetime_param Will be passed as 'datetime' arg to
+ follower_create
'''
@@ -62,13 +64,15 @@ def _start_following(self, follower_id, api_key, object_id, object_type,
# Make the user start following the object.
before = datetime.datetime.now()
- params = json.dumps({
+ params = {
'object_id': object_arg,
'object_type': object_type,
- })
+ }
+ if datetime_param:
+ params['datetime'] = datetime_param
extra_environ = {'Authorization': str(api_key)}
response = self.app.post('/api/action/follower_create',
- params=params, extra_environ=extra_environ).json
+ params=json.dumps(params), extra_environ=extra_environ).json
after = datetime.datetime.now()
assert response['success'] is True
assert response['result']
@@ -274,6 +278,12 @@ def test_02_user_follow_dataset_by_name(self):
self._start_following(self.annafan.id, self.annafan.apikey,
self.annakarenina.id, 'dataset', self.annakarenina.name)
+ def test_02_user_follow_user_with_datetime(self):
+ 'Test that a datetime passed to follower_create is ignored.'
+ self._start_following(self.annafan.id, self.annafan.apikey,
+ self.joeadmin.id, 'user', self.joeadmin.name,
+ datetime_param = str(datetime.datetime.min))
+
def test_03_user_follow_user_already_following(self):
for object_id in (self.russianfan.id, self.russianfan.name,
self.testsysadmin.id, self.testsysadmin.name):
@@ -323,5 +333,3 @@ def test_03_user_cannot_follow_herself(self):
assert response['success'] == False
assert response['error']['object_id'] == [
'An object cannot follow itself']
-
-# Test follow with datetime, should be ignored.
================================================================
Commit: 22347eb1f5d177e317f8316caf0bbe16a61d6977
https://github.com/okfn/ckan/commit/22347eb1f5d177e317f8316caf0bbe16a61d6977
Author: Sean Hammond <seanhammond at lavabit.com>
Date: 2012-04-28 (Sat, 28 Apr 2012)
Changed paths:
M ckan/logic/action/delete.py
M ckan/tests/functional/api/test_follow.py
Log Message:
-----------
[#2304] Add tests for follower_delete api
diff --git a/ckan/logic/action/delete.py b/ckan/logic/action/delete.py
index 41bb593..d3ad5b8 100644
--- a/ckan/logic/action/delete.py
+++ b/ckan/logic/action/delete.py
@@ -217,17 +217,17 @@ def follower_delete(context, data_dict):
follower_id = userobj.id
object_id = data_dict.get('id')
- if not object_id:
+ if object_id is None:
raise ValidationError({'id': _('id not in data')})
+ check_access('follower_delete', context,
+ {'follower_id': follower_id, 'object_id':object_id})
+
follower_obj = model.Follower.get(follower_id, object_id)
if follower_obj is None:
raise NotFound(
_('Could not find follower {follower} -> {object}').format(
follower=follower_id, object=object_id))
- check_access('follower_delete', context,
- {'follower_id': follower_id, 'object_id':object_id})
-
follower_obj.delete()
model.repo.commit()
diff --git a/ckan/tests/functional/api/test_follow.py b/ckan/tests/functional/api/test_follow.py
index 293e771..b668c2e 100644
--- a/ckan/tests/functional/api/test_follow.py
+++ b/ckan/tests/functional/api/test_follow.py
@@ -12,8 +12,87 @@ def datetime_from_string(s):
'''
return datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
+def start_following(app, follower_id, api_key, object_id, object_type,
+ object_arg, datetime_param=None):
+ '''Test a user starting to follow an object via the API.
+
+ :param follower_id: id of the user that will be following something.
+ :param api_key: API key of the user that will be following something.
+ :param object_id: id of the object that will be followed by the user.
+ :param object_type: type of the object that will be followed by the
+ user, e.g. 'user' or 'dataset'.
+ :param object_arg: the argument to pass to follower_create as the id of
+ the object that will be followed, could be the object's id or name.
+ :param datetime_param Will be passed as 'datetime' arg to
+ follower_create
+
+ '''
+
+ # Record the object's number of followers before.
+ params = json.dumps({'id': object_id})
+ response = app.post('/api/action/follower_count',
+ params=params).json
+ assert response['success'] is True
+ count_before = response['result']
+
+ # Check that the user is not already following the object.
+ params = json.dumps({'id': object_id})
+ extra_environ = {'Authorization': str(api_key)}
+ response = app.post('/api/action/am_following',
+ params=params, extra_environ=extra_environ).json
+ assert response['success'] is True
+ assert response['result'] is False
+
+ # Make the user start following the object.
+ before = datetime.datetime.now()
+ params = {
+ 'object_id': object_arg,
+ 'object_type': object_type,
+ }
+ if datetime_param:
+ params['datetime'] = datetime_param
+ extra_environ = {'Authorization': str(api_key)}
+ response = app.post('/api/action/follower_create',
+ params=json.dumps(params), extra_environ=extra_environ).json
+ after = datetime.datetime.now()
+ assert response['success'] is True
+ assert response['result']
+ follower = response['result']
+ assert follower['follower_id'] == follower_id
+ assert follower['follower_type'] == 'user'
+ assert follower['object_id'] == object_id
+ assert follower['object_type'] == object_type
+ timestamp = datetime_from_string(follower['datetime'])
+ assert (timestamp >= before and timestamp <= after), str(timestamp)
+
+ # Check that am_following now returns True.
+ params = json.dumps({'id': object_id})
+ extra_environ = {'Authorization': str(api_key)}
+ response = app.post('/api/action/am_following',
+ params=params, extra_environ=extra_environ).json
+ assert response['success'] is True
+ assert response['result'] is True
+
+ # Check that the user appears in the object's list of followers.
+ params = json.dumps({'id': object_id})
+ response = app.post('/api/action/follower_list',
+ params=params).json
+ assert response['success'] is True
+ assert response['result']
+ followers = response['result']
+ assert len(followers) == count_before + 1
+ assert len([follower for follower in followers if follower['id'] ==
+ follower_id]) == 1
+
+ # Check that the object's follower count has increased by 1.
+ params = json.dumps({'id': object_id})
+ response = app.post('/api/action/follower_count',
+ params=params).json
+ assert response['success'] is True
+ assert response['result'] == count_before + 1
+
class TestFollow(object):
- '''Tests for the follow API.'''
+ '''Tests for the follower API.'''
@classmethod
def setup_class(self):
@@ -31,85 +110,6 @@ def setup_class(self):
def teardown_class(self):
ckan.model.repo.rebuild_db()
- def _start_following(self, follower_id, api_key, object_id, object_type,
- object_arg, datetime_param=None):
- '''Test a user starting to follow an object via the API.
-
- :param follower_id: id of the user that will be following something.
- :param api_key: API key of the user that will be following something.
- :param object_id: id of the object that will be followed by the user.
- :param object_type: type of the object that will be followed by the
- user, e.g. 'user' or 'dataset'.
- :param object_arg: the argument to pass to follower_create as the id of
- the object that will be followed, could be the object's id or name.
- :param datetime_param Will be passed as 'datetime' arg to
- follower_create
-
- '''
-
- # Record the object's number of followers before.
- params = json.dumps({'id': object_id})
- response = self.app.post('/api/action/follower_count',
- params=params).json
- assert response['success'] is True
- count_before = response['result']
-
- # Check that the user is not already following the object.
- params = json.dumps({'id': object_id})
- extra_environ = {'Authorization': str(api_key)}
- response = self.app.post('/api/action/am_following',
- params=params, extra_environ=extra_environ).json
- assert response['success'] is True
- assert response['result'] is False
-
- # Make the user start following the object.
- before = datetime.datetime.now()
- params = {
- 'object_id': object_arg,
- 'object_type': object_type,
- }
- if datetime_param:
- params['datetime'] = datetime_param
- extra_environ = {'Authorization': str(api_key)}
- response = self.app.post('/api/action/follower_create',
- params=json.dumps(params), extra_environ=extra_environ).json
- after = datetime.datetime.now()
- assert response['success'] is True
- assert response['result']
- follower = response['result']
- assert follower['follower_id'] == follower_id
- assert follower['follower_type'] == 'user'
- assert follower['object_id'] == object_id
- assert follower['object_type'] == object_type
- timestamp = datetime_from_string(follower['datetime'])
- assert (timestamp >= before and timestamp <= after), str(timestamp)
-
- # Check that am_following now returns True.
- params = json.dumps({'id': object_id})
- extra_environ = {'Authorization': str(api_key)}
- response = self.app.post('/api/action/am_following',
- params=params, extra_environ=extra_environ).json
- assert response['success'] is True
- assert response['result'] is True
-
- # Check that the user appears in the object's list of followers.
- params = json.dumps({'id': object_id})
- response = self.app.post('/api/action/follower_list',
- params=params).json
- assert response['success'] is True
- assert response['result']
- followers = response['result']
- assert len(followers) == 1
- follower = followers[0]
- assert follower['id'] == follower_id
-
- # Check that the object's follower count has increased by 1.
- params = json.dumps({'id': object_id})
- response = self.app.post('/api/action/follower_count',
- params=params).json
- assert response['success'] is True
- assert response['result'] == count_before + 1
-
def test_01_user_follow_user_bad_api_key(self):
for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
params = json.dumps({
@@ -263,24 +263,24 @@ def test_01_user_follow_dataset_missing_object_type(self):
assert response['error']['object_type'] == ['Missing value']
def test_02_user_follow_user_by_id(self):
- self._start_following(self.annafan.id, self.annafan.apikey,
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
self.russianfan.id, 'user', self.russianfan.id)
def test_02_user_follow_dataset_by_id(self):
- self._start_following(self.annafan.id, self.annafan.apikey,
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
self.warandpeace.id, 'dataset', self.warandpeace.id)
def test_02_user_follow_user_by_name(self):
- self._start_following(self.annafan.id, self.annafan.apikey,
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
self.testsysadmin.id, 'user', self.testsysadmin.name)
def test_02_user_follow_dataset_by_name(self):
- self._start_following(self.annafan.id, self.annafan.apikey,
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
self.annakarenina.id, 'dataset', self.annakarenina.name)
def test_02_user_follow_user_with_datetime(self):
'Test that a datetime passed to follower_create is ignored.'
- self._start_following(self.annafan.id, self.annafan.apikey,
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
self.joeadmin.id, 'user', self.joeadmin.name,
datetime_param = str(datetime.datetime.min))
@@ -333,3 +333,166 @@ def test_03_user_cannot_follow_herself(self):
assert response['success'] == False
assert response['error']['object_id'] == [
'An object cannot follow itself']
+
+class TestFollowerDelete(object):
+ '''Tests for the follower_delete API.'''
+
+ @classmethod
+ def setup_class(self):
+ ckan.tests.CreateTestData.create()
+ self.testsysadmin = ckan.model.User.get('testsysadmin')
+ self.annafan = ckan.model.User.get('annafan')
+ self.russianfan = ckan.model.User.get('russianfan')
+ self.tester = ckan.model.User.get('tester')
+ self.joeadmin = ckan.model.User.get('joeadmin')
+ self.warandpeace = ckan.model.Package.get('warandpeace')
+ self.annakarenina = ckan.model.Package.get('annakarenina')
+ self.app = paste.fixture.TestApp(pylons.test.pylonsapp)
+ start_following(self.app, self.testsysadmin.id, self.testsysadmin.apikey,
+ self.joeadmin.id, 'user', self.joeadmin.id)
+ start_following(self.app, self.tester.id, self.tester.apikey,
+ self.joeadmin.id, 'user', self.joeadmin.id)
+ start_following(self.app, self.russianfan.id, self.russianfan.apikey,
+ self.joeadmin.id, 'user', self.joeadmin.id)
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
+ self.joeadmin.id, 'user', self.joeadmin.id)
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
+ self.tester.id, 'user', self.tester.id)
+
+ @classmethod
+ def teardown_class(self):
+ ckan.model.repo.rebuild_db()
+
+ def test_01_follower_delete_not_exists(self):
+ '''Test the error response when a user tries to unfollow something
+ that she is not following.
+
+ '''
+ params = json.dumps({
+ 'id': self.russianfan.id,
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_delete',
+ params=params, extra_environ=extra_environ, status=404).json
+ assert response['success'] == False
+ assert response['error']['message'].startswith(
+ 'Not found: Could not find follower ')
+
+ def test_01_follower_delete_bad_api_key(self):
+ '''Test the error response when a user tries to unfollow something
+ but provides a bad API key.
+
+ '''
+ for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
+ params = json.dumps({
+ 'id': self.joeadmin.id,
+ })
+ extra_environ = {
+ 'Authorization': apikey,
+ }
+ response = self.app.post('/api/action/follower_delete',
+ params=params, extra_environ=extra_environ, status=403).json
+ assert response['success'] == False
+ assert response['error']['message'] == 'Access denied'
+
+ def test_01_follower_delete_missing_api_key(self):
+ params = json.dumps({
+ 'id': self.joeadmin.id,
+ })
+ response = self.app.post('/api/action/follower_delete',
+ params=params, status=403).json
+ assert response['success'] == False
+ assert response['error']['message'] == 'Access denied'
+
+ def test_01_follower_delete_bad_object_id(self):
+ '''Test error response when calling follower_delete with a bad object
+ id.
+
+ '''
+ for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
+ params = json.dumps({
+ 'id': object_id,
+ })
+ extra_environ = {
+ 'Authorization': str(self.annafan.apikey),
+ }
+ response = self.app.post('/api/action/follower_delete',
+ params=params, extra_environ=extra_environ, status=404).json
+ assert response['success'] == False
+ assert response['error']['message'].startswith(
+ 'Not found: Could not find follower ')
+
+ def test_01_follower_delete_missing_object_id(self):
+ params = json.dumps({})
+ extra_environ = {'Authorization': str(self.annafan.apikey),}
+ response = self.app.post('/api/action/follower_delete',
+ params=params, extra_environ=extra_environ, status=409).json
+ assert response['success'] == False
+ assert response['error']['id'] == 'id not in data'
+
+ def _stop_following(self, follower_id, api_key, object_id, object_arg):
+ '''Test a user unfollowing an object via the API.
+
+ :param follower_id: id of the user.
+ :param api_key: API key of the user.
+ :param object_id: id of the object to unfollow.
+ :param object_arg: the argument to pass to follower_delete as the id of
+ the object to unfollow, could be the object's id or name.
+
+ '''
+
+ # Record the object's number of followers before.
+ params = json.dumps({'id': object_id})
+ response = self.app.post('/api/action/follower_count',
+ params=params).json
+ assert response['success'] is True
+ count_before = response['result']
+
+ # Check that the user is following the object.
+ params = json.dumps({'id': object_id})
+ extra_environ = {'Authorization': str(api_key)}
+ response = self.app.post('/api/action/am_following',
+ params=params, extra_environ=extra_environ).json
+ assert response['success'] is True
+ assert response['result'] is True
+
+ # Make the user unfollow the object.
+ params = {
+ 'id': object_arg,
+ }
+ extra_environ = {'Authorization': str(api_key)}
+ response = self.app.post('/api/action/follower_delete',
+ params=json.dumps(params), extra_environ=extra_environ).json
+ after = datetime.datetime.now()
+ assert response['success'] is True
+
+ # Check that am_following now returns False.
+ params = json.dumps({'id': object_id})
+ extra_environ = {'Authorization': str(api_key)}
+ response = self.app.post('/api/action/am_following',
+ params=params, extra_environ=extra_environ).json
+ assert response['success'] is True
+ assert response['result'] is False
+
+ # Check that the user doesn't appear in the object's list of followers.
+ params = json.dumps({'id': object_id})
+ response = self.app.post('/api/action/follower_list',
+ params=params).json
+ assert response['success'] is True
+ assert response['result']
+ followers = response['result']
+ assert len([follower for follower in followers if follower['id'] ==
+ follower_id]) == 0
+
+ # Check that the object's follower count has decreased by 1.
+ params = json.dumps({'id': object_id})
+ response = self.app.post('/api/action/follower_count',
+ params=params).json
+ assert response['success'] is True
+ assert response['result'] == count_before - 1
+
+ def test_02_follower_delete_by_id(self):
+ self._stop_following(self.annafan.id, self.annafan.apikey,
+ self.joeadmin.id, self.joeadmin.id)
================================================================
Commit: e273bea8f71b0898d75b1b48a6f0e894dd00728b
https://github.com/okfn/ckan/commit/e273bea8f71b0898d75b1b48a6f0e894dd00728b
Author: Sean Hammond <seanhammond at lavabit.com>
Date: 2012-04-28 (Sat, 28 Apr 2012)
Changed paths:
M ckan/logic/action/get.py
M ckan/tests/functional/api/test_follow.py
Log Message:
-----------
[#2304] Add a few more follow api tests
diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py
index c429f2e..b45c973 100644
--- a/ckan/logic/action/get.py
+++ b/ckan/logic/action/get.py
@@ -1383,8 +1383,8 @@ def follower_count(context, data_dict):
'''Return the number of followers of an object.'''
model = context['model']
object_id = data_dict.get('id')
- if not object_id:
- raise ValidationError({'id': 'id not in data'})
+ if object_id is None:
+ raise ValidationError({'id': _('id not in data')})
return model.Follower.follower_count(object_id)
def follower_list(context, data_dict):
@@ -1393,8 +1393,8 @@ def follower_list(context, data_dict):
# Get the list of Follower objects.
model = context['model']
object_id = data_dict.get('id')
- if not object_id:
- raise ValidationError({'id': 'id not in data'})
+ if object_id is None:
+ raise ValidationError({'id': _('id not in data')})
followers = model.Follower.follower_list(object_id)
# Convert the list of Follower objects to a list of User objects.
diff --git a/ckan/tests/functional/api/test_follow.py b/ckan/tests/functional/api/test_follow.py
index b668c2e..0ec1c9e 100644
--- a/ckan/tests/functional/api/test_follow.py
+++ b/ckan/tests/functional/api/test_follow.py
@@ -334,6 +334,52 @@ def test_03_user_cannot_follow_herself(self):
assert response['error']['object_id'] == [
'An object cannot follow itself']
+ def test_04_follower_count_bad_id(self):
+ # follower_count always succeeds, but just returns 0 for bad IDs.
+ for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
+ params = json.dumps({'id': object_id})
+ response = self.app.post('/api/action/follower_count',
+ params=params).json
+ assert response['success'] is True
+ assert response['result'] == 0
+
+ def test_04_follower_count_missing_id(self):
+ params = json.dumps({})
+ response = self.app.post('/api/action/follower_count',
+ params=params, status=409).json
+ assert response['success'] is False
+ assert response['error']['id'] == 'id not in data'
+
+ def test_04_follower_count_no_followers(self):
+ params = json.dumps({'id': self.annafan.id})
+ response = self.app.post('/api/action/follower_count',
+ params=params).json
+ assert response['success'] is True
+ assert response['result'] == 0
+
+ def test_04_follower_list_bad_id(self):
+ # follower_list always succeeds, but just returns [] for bad IDs.
+ for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
+ params = json.dumps({'id': object_id})
+ response = self.app.post('/api/action/follower_list',
+ params=params).json
+ assert response['success'] is True
+ assert response['result'] == []
+
+ def test_04_follower_list_missing_id(self):
+ params = json.dumps({})
+ response = self.app.post('/api/action/follower_list',
+ params=params, status=409).json
+ assert response['success'] is False
+ assert response['error']['id'] == 'id not in data'
+
+ def test_04_follower_list_no_followers(self):
+ params = json.dumps({'id': self.annafan.id})
+ response = self.app.post('/api/action/follower_list',
+ params=params).json
+ assert response['success'] is True
+ assert response['result'] == []
+
class TestFollowerDelete(object):
'''Tests for the follower_delete API.'''
@@ -358,6 +404,14 @@ def setup_class(self):
self.joeadmin.id, 'user', self.joeadmin.id)
start_following(self.app, self.annafan.id, self.annafan.apikey,
self.tester.id, 'user', self.tester.id)
+ start_following(self.app, self.testsysadmin.id, self.testsysadmin.apikey,
+ self.warandpeace.id, 'dataset', self.warandpeace.id)
+ start_following(self.app, self.tester.id, self.tester.apikey,
+ self.warandpeace.id, 'dataset', self.warandpeace.id)
+ start_following(self.app, self.russianfan.id, self.russianfan.apikey,
+ self.warandpeace.id, 'dataset', self.warandpeace.id)
+ start_following(self.app, self.annafan.id, self.annafan.apikey,
+ self.warandpeace.id, 'dataset', self.warandpeace.id)
@classmethod
def teardown_class(self):
@@ -496,3 +550,5 @@ def _stop_following(self, follower_id, api_key, object_id, object_arg):
def test_02_follower_delete_by_id(self):
self._stop_following(self.annafan.id, self.annafan.apikey,
self.joeadmin.id, self.joeadmin.id)
+ self._stop_following(self.annafan.id, self.annafan.apikey,
+ self.warandpeace.id, self.warandpeace.id)
================================================================
Compare: https://github.com/okfn/ckan/compare/2c13b2b...e273bea
More information about the ckan-changes
mailing list