')
-
- def test_registered_user_login_bad_password(self):
- '''
- Registered user is redirected to appropriate place if they submit
- invalid login details at /user/login.
- '''
- app = helpers._get_test_app()
-
- # make a user
- user = factories.User()
-
- # get the form
- response = app.get('/user/login')
- # ...it's the second one
- login_form = response.forms[1]
-
- # fill it in
- login_form['login'] = user['name']
- login_form['password'] = 'BadPass1'
-
- # submit it
- submit_response = login_form.submit()
- # let's go to the last redirect in the chain
- final_response = helpers.webtest_maybe_follow(submit_response)
-
- # the response is the login page again
- final_response.mustcontain('
Login
',
- 'Login failed. Bad username or password.')
- # and we're definitely not on the dashboard.
- final_response.mustcontain(no='Dashboard'),
- final_response.mustcontain(no='{0}'
- .format(user['fullname']))
-
-
-class TestLogout(helpers.FunctionalTestBase):
-
- def test_user_logout_url_redirect(self):
- '''_logout url redirects to logged out page.
-
- Note: this doesn't test the actual logout of a logged in user, just
- the associated redirect.
- '''
- app = self._get_test_app()
-
- logout_url = url_for('user.logout')
- logout_response = app.get(logout_url, status=302)
- final_response = helpers.webtest_maybe_follow(logout_response)
-
- assert_true('You are now logged out.' in final_response)
-
- @helpers.change_config('ckan.root_path', '/my/prefix')
- def test_non_root_user_logout_url_redirect(self):
- '''
- _logout url redirects to logged out page with `ckan.root_path`
- prefixed.
-
- Note: this doesn't test the actual logout of a logged in user, just
- the associated redirect.
- '''
- app = self._get_test_app()
-
- logout_url = url_for('user.logout')
- # Remove the prefix otherwise the test app won't find the correct route
- logout_url = logout_url.replace('/my/prefix', '')
- logout_response = app.get(logout_url, status=302)
- assert_equal(logout_response.status_int, 302)
- assert_true('/my/prefix/user/logout' in logout_response.location)
-
-
-class TestUser(helpers.FunctionalTestBase):
-
- def test_not_logged_in_dashboard(self):
- app = self._get_test_app()
-
- for route in ['index', 'organizations', 'datasets', 'groups']:
- app.get(
- url=url_for(u'dashboard.{}'.format(route)),
- status=403
- )
-
- def test_own_datasets_show_up_on_user_dashboard(self):
- user = factories.User()
- dataset_title = 'My very own dataset'
- factories.Dataset(user=user,
- name='my-own-dataset',
- title=dataset_title)
-
- app = self._get_test_app()
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = app.get(
- url=url_for('dashboard.datasets'),
- extra_environ=env,
- )
+@pytest.mark.usefixtures("clean_db")
+def test_register_a_user(app):
+ response = app.get(url=url_for("user.register"))
+
+ form = response.forms["user-register-form"]
+ form["name"] = "newuser"
+ form["fullname"] = "New User"
+ form["email"] = "test@test.com"
+ form["password1"] = "TestPassword1"
+ form["password2"] = "TestPassword1"
+ response = submit_and_follow(app, form, name="save")
+ response = response.follow()
+ assert 200 == response.status_int
+
+ user = helpers.call_action("user_show", id="newuser")
+ assert user["name"] == "newuser"
+ assert user["fullname"] == "New User"
+ assert not (user["sysadmin"])
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_register_user_bad_password(app):
+ response = app.get(url=url_for("user.register"))
+
+ form = response.forms["user-register-form"]
+ form["name"] = "newuser"
+ form["fullname"] = "New User"
+ form["email"] = "test@test.com"
+ form["password1"] = "TestPassword1"
+ form["password2"] = ""
+
+ response = form.submit("save")
+ assert "The passwords you entered do not match" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_create_user_as_sysadmin(app):
+ admin_pass = "RandomPassword123"
+ sysadmin = factories.Sysadmin(password=admin_pass)
+
+ # Have to do an actual login as this test relies on repoze
+ # cookie handling.
+
+ # get the form
+ response = app.get("/user/login")
+ # ...it's the second one
+ login_form = response.forms[1]
+ # fill it in
+ login_form["login"] = sysadmin["name"]
+ login_form["password"] = admin_pass
+ # submit it
+ login_form.submit("save")
+
+ response = app.get(url=url_for("user.register"))
+ assert "user-register-form" in response.forms
+ form = response.forms["user-register-form"]
+ form["name"] = "newestuser"
+ form["fullname"] = "Newest User"
+ form["email"] = "test@test.com"
+ form["password1"] = "NewPassword1"
+ form["password2"] = "NewPassword1"
+ response2 = form.submit("save")
+ assert "/user/activity" in response2.location
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_registered_user_login(app):
+ """
+ Registered user can submit valid login details at /user/login and
+ be returned to appropriate place.
+ """
+
+ # make a user
+ user = factories.User()
- assert_true(dataset_title in response)
-
- def test_other_datasets_dont_show_up_on_user_dashboard(self):
- user1 = factories.User()
- user2 = factories.User()
- dataset_title = 'Someone else\'s dataset'
- factories.Dataset(user=user1,
- name='someone-elses-dataset',
- title=dataset_title)
-
- app = self._get_test_app()
- env = {'REMOTE_USER': user2['name'].encode('ascii')}
- response = app.get(
- url=url_for('dashboard.datasets'),
- extra_environ=env,
- )
+ # get the form
+ response = app.get("/user/login")
+ # ...it's the second one
+ login_form = response.forms[1]
+
+ # fill it in
+ login_form["login"] = user["name"]
+ login_form["password"] = "RandomPassword123"
- assert_false(dataset_title in response)
+ # submit it
+ submit_response = login_form.submit()
+ # let's go to the last redirect in the chain
+ final_response = helpers.webtest_maybe_follow(submit_response)
+ # the response is the user dashboard, right?
+ final_response.mustcontain(
+ 'Dashboard',
+ '{0}'.format(user["fullname"]),
+ )
+ # and we're definitely not back on the login page.
+ final_response.mustcontain(no='
Login
')
-class TestUserEdit(helpers.FunctionalTestBase):
- def test_user_edit_no_user(self):
- app = self._get_test_app()
- response = app.get(
- url_for('user.edit', id=None),
- status=400
- )
- assert_true('No user specified' in response)
-
- def test_user_edit_unknown_user(self):
- '''Attempt to read edit user for an unknown user redirects to login
- page.'''
- app = self._get_test_app()
- response = app.get(
- url_for('user.edit', id='unknown_person'),
- status=403)
-
- def test_user_edit_not_logged_in(self):
- '''Attempt to read edit user for an existing, not-logged in user
- redirects to login page.'''
- app = self._get_test_app()
- user = factories.User()
- username = user['name']
- response = app.get(
- url_for('user.edit', id=username),
- status=403
- )
+@pytest.mark.usefixtures("clean_db")
+def test_registered_user_login_bad_password(app):
+ """
+ Registered user is redirected to appropriate place if they submit
+ invalid login details at /user/login.
+ """
- def test_edit_user(self):
- user = factories.User(password='TestPassword1')
- app = self._get_test_app()
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = app.get(
- url=url_for('user.edit'),
- extra_environ=env,
- )
- # existing values in the form
- form = response.forms['user-edit-form']
- assert_equal(form['name'].value, user['name'])
- assert_equal(form['fullname'].value, user['fullname'])
- assert_equal(form['email'].value, user['email'])
- assert_equal(form['about'].value, user['about'])
- assert_equal(form['activity_streams_email_notifications'].value, None)
- assert_equal(form['password1'].value, '')
- assert_equal(form['password2'].value, '')
-
- # new values
- # form['name'] = 'new-name'
- form['fullname'] = 'new full name'
- form['email'] = 'new@example.com'
- form['about'] = 'new about'
- form['activity_streams_email_notifications'] = True
- form['old_password'] = 'TestPassword1'
- form['password1'] = 'NewPass1'
- form['password2'] = 'NewPass1'
- response = submit_and_follow(app, form, env, 'save')
-
- user = model.Session.query(model.User).get(user['id'])
- # assert_equal(user.name, 'new-name')
- assert_equal(user.fullname, 'new full name')
- assert_equal(user.email, 'new@example.com')
- assert_equal(user.about, 'new about')
- assert_equal(user.activity_streams_email_notifications, True)
-
- def test_email_change_without_password(self):
-
- app = self._get_test_app()
- env, response, user = _get_user_edit_page(app)
-
- form = response.forms['user-edit-form']
-
- # new values
- form['email'] = 'new@example.com'
-
- # factory returns user with password 'pass'
- form.fields['old_password'][0].value = 'Wrong-pass1'
-
- response = webtest_submit(form, 'save', status=200, extra_environ=env)
- assert_true('Old Password: incorrect password' in response)
-
- def test_email_change_with_password(self):
- app = self._get_test_app()
- env, response, user = _get_user_edit_page(app)
-
- form = response.forms['user-edit-form']
-
- # new values
- form['email'] = 'new@example.com'
-
- # factory returns user with password 'pass'
- form.fields['old_password'][0].value = 'RandomPassword123'
-
- response = submit_and_follow(app, form, env, 'save')
- assert_true('Profile updated' in response)
-
- def test_edit_user_logged_in_username_change(self):
-
- user_pass = 'TestPassword1'
- user = factories.User(password=user_pass)
- app = self._get_test_app()
-
- # Have to do an actual login as this test relys on repoze cookie handling.
- # get the form
- response = app.get('/user/login')
- # ...it's the second one
- login_form = response.forms[1]
- # fill it in
- login_form['login'] = user['name']
- login_form['password'] = user_pass
- # submit it
- login_form.submit()
-
- # Now the cookie is set, run the test
- response = app.get(
- url=url_for('user.edit'),
- )
- # existing values in the form
- form = response.forms['user-edit-form']
-
- # new values
- form['name'] = 'new-name'
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = webtest_submit(form, 'save', status=200, extra_environ=env)
- assert_true('That login name can not be modified' in response)
-
- def test_edit_user_logged_in_username_change_by_name(self):
- user_pass = 'TestPassword1'
- user = factories.User(password=user_pass)
- app = self._get_test_app()
-
- # Have to do an actual login as this test relys on repoze cookie handling.
- # get the form
- response = app.get('/user/login')
- # ...it's the second one
- login_form = response.forms[1]
- # fill it in
- login_form['login'] = user['name']
- login_form['password'] = user_pass
- # submit it
- login_form.submit()
-
- # Now the cookie is set, run the test
- response = app.get(
- url=url_for('user.edit', id=user['name']),
- )
- # existing values in the form
- form = response.forms['user-edit-form']
-
- # new values
- form['name'] = 'new-name'
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = webtest_submit(form, 'save', status=200, extra_environ=env)
- assert_true('That login name can not be modified' in response)
-
- def test_edit_user_logged_in_username_change_by_id(self):
- user_pass = 'TestPassword1'
- user = factories.User(password=user_pass)
- app = self._get_test_app()
-
- # Have to do an actual login as this test relys on repoze cookie handling.
- # get the form
- response = app.get('/user/login')
- # ...it's the second one
- login_form = response.forms[1]
- # fill it in
- login_form['login'] = user['name']
- login_form['password'] = user_pass
- # submit it
- login_form.submit()
-
- # Now the cookie is set, run the test
- response = app.get(
- url=url_for('user.edit', id=user['id']),
+ # make a user
+ user = factories.User()
+
+ # get the form
+ response = app.get("/user/login")
+ # ...it's the second one
+ login_form = response.forms[1]
+
+ # fill it in
+ login_form["login"] = user["name"]
+ login_form["password"] = "BadPass1"
+
+ # submit it
+ submit_response = login_form.submit()
+ # let's go to the last redirect in the chain
+ final_response = helpers.webtest_maybe_follow(submit_response)
+
+ # the response is the login page again
+ final_response.mustcontain(
+ '
Login
',
+ "Login failed. Bad username or password.",
+ )
+ # and we're definitely not on the dashboard.
+ final_response.mustcontain(no='Dashboard'),
+ final_response.mustcontain(
+ no='{0}'.format(user["fullname"])
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_logout_url_redirect(app):
+ """_logout url redirects to logged out page.
+
+ Note: this doesn't test the actual logout of a logged in user, just
+ the associated redirect.
+ """
+
+ logout_url = url_for("user.logout")
+ logout_response = app.get(logout_url, status=302)
+ final_response = helpers.webtest_maybe_follow(logout_response)
+
+ assert "You are now logged out." in final_response
+
+
+@pytest.mark.ckan_config("ckan.root_path", "/my/prefix")
+@pytest.mark.usefixtures("clean_db")
+def test_non_root_user_logout_url_redirect(app):
+ """
+ _logout url redirects to logged out page with `ckan.root_path`
+ prefixed.
+
+ Note: this doesn't test the actual logout of a logged in user, just
+ the associated redirect.
+ """
+
+ logout_url = url_for("user.logout")
+ # Remove the prefix otherwise the test app won't find the correct route
+ logout_url = logout_url.replace("/my/prefix", "")
+ logout_response = app.get(logout_url, status=302)
+ assert logout_response.status_int == 302
+ assert "/my/prefix/user/logout" in logout_response.location
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_not_logged_in_dashboard(app):
+
+ for route in ["index", "organizations", "datasets", "groups"]:
+ app.get(url=url_for(u"dashboard.{}".format(route)), status=403)
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_own_datasets_show_up_on_user_dashboard(app):
+ user = factories.User()
+ dataset_title = "My very own dataset"
+ factories.Dataset(user=user, name="my-own-dataset", title=dataset_title)
+
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = app.get(url=url_for("dashboard.datasets"), extra_environ=env)
+
+ assert dataset_title in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_other_datasets_dont_show_up_on_user_dashboard(app):
+ user1 = factories.User()
+ user2 = factories.User()
+ dataset_title = "Someone else's dataset"
+ factories.Dataset(
+ user=user1, name="someone-elses-dataset", title=dataset_title
+ )
+
+ env = {"REMOTE_USER": user2["name"].encode("ascii")}
+ response = app.get(url=url_for("dashboard.datasets"), extra_environ=env)
+
+ assert not (dataset_title in response)
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_edit_no_user(app):
+
+ response = app.get(url_for("user.edit", id=None), status=400)
+ assert "No user specified" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_edit_unknown_user(app):
+ """Attempt to read edit user for an unknown user redirects to login
+ page."""
+
+ response = app.get(url_for("user.edit", id="unknown_person"), status=403)
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_edit_not_logged_in(app):
+ """Attempt to read edit user for an existing, not-logged in user
+ redirects to login page."""
+
+ user = factories.User()
+ username = user["name"]
+ response = app.get(url_for("user.edit", id=username), status=403)
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_edit_user(app):
+ user = factories.User(password="TestPassword1")
+
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = app.get(url=url_for("user.edit"), extra_environ=env)
+ # existing values in the form
+ form = response.forms["user-edit-form"]
+ assert form["name"].value == user["name"]
+ assert form["fullname"].value == user["fullname"]
+ assert form["email"].value == user["email"]
+ assert form["about"].value == user["about"]
+ assert form["activity_streams_email_notifications"].value is None
+ assert form["password1"].value == ""
+ assert form["password2"].value == ""
+
+ # new values
+ # form['name'] = 'new-name'
+ form["fullname"] = "new full name"
+ form["email"] = "new@example.com"
+ form["about"] = "new about"
+ form["activity_streams_email_notifications"] = True
+ form["old_password"] = "TestPassword1"
+ form["password1"] = "NewPass1"
+ form["password2"] = "NewPass1"
+ response = submit_and_follow(app, form, env, "save")
+
+ user = model.Session.query(model.User).get(user["id"])
+ # assert(user.name== 'new-name')
+ assert user.fullname == "new full name"
+ assert user.email == "new@example.com"
+ assert user.about == "new about"
+ assert user.activity_streams_email_notifications
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_email_change_without_password(app):
+
+ env, response, user = _get_user_edit_page(app)
+
+ form = response.forms["user-edit-form"]
+
+ # new values
+ form["email"] = "new@example.com"
+
+ # factory returns user with password 'pass'
+ form.fields["old_password"][0].value = "Wrong-pass1"
+
+ response = webtest_submit(form, "save", status=200, extra_environ=env)
+ assert "Old Password: incorrect password" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_email_change_with_password(app):
+
+ env, response, user = _get_user_edit_page(app)
+
+ form = response.forms["user-edit-form"]
+
+ # new values
+ form["email"] = "new@example.com"
+
+ # factory returns user with password 'pass'
+ form.fields["old_password"][0].value = "RandomPassword123"
+
+ response = submit_and_follow(app, form, env, "save")
+ assert "Profile updated" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_edit_user_logged_in_username_change(app):
+
+ user_pass = "TestPassword1"
+ user = factories.User(password=user_pass)
+
+ # Have to do an actual login as this test relys on repoze cookie handling.
+ # get the form
+ response = app.get("/user/login")
+ # ...it's the second one
+ login_form = response.forms[1]
+ # fill it in
+ login_form["login"] = user["name"]
+ login_form["password"] = user_pass
+ # submit it
+ login_form.submit()
+
+ # Now the cookie is set, run the test
+ response = app.get(url=url_for("user.edit"))
+ # existing values in the form
+ form = response.forms["user-edit-form"]
+
+ # new values
+ form["name"] = "new-name"
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = webtest_submit(form, "save", status=200, extra_environ=env)
+ assert "That login name can not be modified" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_edit_user_logged_in_username_change_by_name(app):
+ user_pass = "TestPassword1"
+ user = factories.User(password=user_pass)
+
+ # Have to do an actual login as this test relys on repoze cookie handling.
+ # get the form
+ response = app.get("/user/login")
+ # ...it's the second one
+ login_form = response.forms[1]
+ # fill it in
+ login_form["login"] = user["name"]
+ login_form["password"] = user_pass
+ # submit it
+ login_form.submit()
+
+ # Now the cookie is set, run the test
+ response = app.get(url=url_for("user.edit", id=user["name"]))
+ # existing values in the form
+ form = response.forms["user-edit-form"]
+
+ # new values
+ form["name"] = "new-name"
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = webtest_submit(form, "save", status=200, extra_environ=env)
+ assert "That login name can not be modified" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_edit_user_logged_in_username_change_by_id(app):
+ user_pass = "TestPassword1"
+ user = factories.User(password=user_pass)
+
+ # Have to do an actual login as this test relys on repoze cookie handling.
+ # get the form
+ response = app.get("/user/login")
+ # ...it's the second one
+ login_form = response.forms[1]
+ # fill it in
+ login_form["login"] = user["name"]
+ login_form["password"] = user_pass
+ # submit it
+ login_form.submit()
+
+ # Now the cookie is set, run the test
+ response = app.get(url=url_for("user.edit", id=user["id"]))
+ # existing values in the form
+ form = response.forms["user-edit-form"]
+
+ # new values
+ form["name"] = "new-name"
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = webtest_submit(form, "save", status=200, extra_environ=env)
+ assert "That login name can not be modified" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_perform_reset_for_key_change(app):
+ password = "TestPassword1"
+ params = {"password1": password, "password2": password}
+ user = factories.User()
+ user_obj = helpers.model.User.by_name(user["name"])
+ create_reset_key(user_obj)
+ key = user_obj.reset_key
+
+ offset = url_for(
+ controller="user",
+ action="perform_reset",
+ id=user_obj.id,
+ key=user_obj.reset_key,
+ )
+ response = app.post(offset, params=params, status=302)
+ user_obj = helpers.model.User.by_name(user["name"]) # Update user_obj
+
+ assert key != user_obj.reset_key
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_password_reset_correct_password(app):
+ """
+ user password reset attempted with correct old password
+ """
+
+ env, response, user = _get_user_edit_page(app)
+
+ form = response.forms["user-edit-form"]
+
+ # factory returns user with password 'RandomPassword123'
+ form.fields["old_password"][0].value = "RandomPassword123"
+ form.fields["password1"][0].value = "NewPassword1"
+ form.fields["password2"][0].value = "NewPassword1"
+
+ response = submit_and_follow(app, form, env, "save")
+ assert "Profile updated" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_password_reset_incorrect_password(app):
+ """
+ user password reset attempted with invalid old password
+ """
+
+ env, response, user = _get_user_edit_page(app)
+
+ form = response.forms["user-edit-form"]
+
+ # factory returns user with password 'RandomPassword123'
+ form.fields["old_password"][0].value = "Wrong-Pass1"
+ form.fields["password1"][0].value = "NewPassword1"
+ form.fields["password2"][0].value = "NewPassword1"
+
+ response = webtest_submit(form, "save", status=200, extra_environ=env)
+ assert "Old Password: incorrect password" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_follow(app):
+
+ user_one = factories.User()
+ user_two = factories.User()
+
+ env = {"REMOTE_USER": user_one["name"].encode("ascii")}
+ follow_url = url_for(controller="user", action="follow", id=user_two["id"])
+ response = app.post(follow_url, extra_environ=env, status=302)
+ response = response.follow()
+ assert (
+ "You are now following {0}".format(user_two["display_name"])
+ in response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_follow_not_exist(app):
+ """Pass an id for a user that doesn't exist"""
+
+ user_one = factories.User()
+
+ env = {"REMOTE_USER": user_one["name"].encode("ascii")}
+ follow_url = url_for(controller="user", action="follow", id="not-here")
+ response = app.post(follow_url, extra_environ=env, status=302)
+ response = response.follow(status=302)
+ assert "user/login" in response.headers["location"]
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_unfollow(app):
+
+ user_one = factories.User()
+ user_two = factories.User()
+
+ env = {"REMOTE_USER": user_one["name"].encode("ascii")}
+ follow_url = url_for(controller="user", action="follow", id=user_two["id"])
+ app.post(follow_url, extra_environ=env, status=302)
+
+ unfollow_url = url_for("user.unfollow", id=user_two["id"])
+ unfollow_response = app.post(unfollow_url, extra_environ=env, status=302)
+ unfollow_response = unfollow_response.follow()
+
+ assert (
+ "You are no longer following {0}".format(user_two["display_name"])
+ in unfollow_response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_unfollow_not_following(app):
+ """Unfollow a user not currently following"""
+
+ user_one = factories.User()
+ user_two = factories.User()
+
+ env = {"REMOTE_USER": user_one["name"].encode("ascii")}
+ unfollow_url = url_for("user.unfollow", id=user_two["id"])
+ unfollow_response = app.post(unfollow_url, extra_environ=env, status=302)
+ unfollow_response = unfollow_response.follow()
+
+ assert (
+ "You are not following {0}".format(user_two["id"]) in unfollow_response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_unfollow_not_exist(app):
+ """Unfollow a user that doesn't exist."""
+
+ user_one = factories.User()
+
+ env = {"REMOTE_USER": user_one["name"].encode("ascii")}
+ unfollow_url = url_for("user.unfollow", id="not-here")
+ unfollow_response = app.post(unfollow_url, extra_environ=env, status=302)
+ unfollow_response = unfollow_response.follow(status=302)
+ assert "user/login" in unfollow_response.headers["location"]
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_follower_list(app):
+ """Following users appear on followers list page."""
+
+ user_one = factories.Sysadmin()
+ user_two = factories.User()
+
+ env = {"REMOTE_USER": user_one["name"].encode("ascii")}
+ follow_url = url_for(controller="user", action="follow", id=user_two["id"])
+ app.post(follow_url, extra_environ=env, status=302)
+
+ followers_url = url_for("user.followers", id=user_two["id"])
+
+ # Only sysadmins can view the followers list pages
+ followers_response = app.get(followers_url, extra_environ=env, status=200)
+ assert user_one["display_name"] in followers_response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_page_anon_access(app):
+ """Anon users can access the user list page"""
+
+ user_url = url_for("user.index")
+ user_response = app.get(user_url, status=200)
+ assert "All Users - CKAN" in user_response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_page_lists_users(app):
+ """/users/ lists registered users"""
+ initial_user_count = model.User.count()
+ factories.User(fullname="User One")
+ factories.User(fullname="User Two")
+ factories.User(fullname="User Three")
+
+ user_url = url_for("user.index")
+ user_response = app.get(user_url, status=200)
+
+ user_response_html = BeautifulSoup(user_response.body)
+ user_list = user_response_html.select("ul.user-list li")
+ assert len(user_list) == 3 + initial_user_count
+
+ user_names = [u.text.strip() for u in user_list]
+ assert "User One" in user_names
+ assert "User Two" in user_names
+ assert "User Three" in user_names
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_page_doesnot_list_deleted_users(app):
+ """/users/ doesn't list deleted users"""
+ initial_user_count = model.User.count()
+
+ factories.User(fullname="User One", state="deleted")
+ factories.User(fullname="User Two")
+ factories.User(fullname="User Three")
+
+ user_url = url_for("user.index")
+ user_response = app.get(user_url, status=200)
+
+ user_response_html = BeautifulSoup(user_response.body)
+ user_list = user_response_html.select("ul.user-list li")
+ assert len(user_list) == 2 + initial_user_count
+
+ user_names = [u.text.strip() for u in user_list]
+ assert "User One" not in user_names
+ assert "User Two" in user_names
+ assert "User Three" in user_names
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_page_anon_search(app):
+ """Anon users can search for users by username."""
+
+ factories.User(fullname="User One", email="useroneemail@example.com")
+ factories.User(fullname="Person Two")
+ factories.User(fullname="Person Three")
+
+ user_url = url_for("user.index")
+ user_response = app.get(user_url, status=200)
+ search_form = user_response.forms["user-search-form"]
+ search_form["q"] = "Person"
+ search_response = webtest_submit(search_form, status=200)
+
+ search_response_html = BeautifulSoup(search_response.body)
+ user_list = search_response_html.select("ul.user-list li")
+ assert len(user_list) == 2
+
+ user_names = [u.text.strip() for u in user_list]
+ assert "Person Two" in user_names
+ assert "Person Three" in user_names
+ assert "User One" not in user_names
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_page_anon_search_not_by_email(app):
+ """Anon users can not search for users by email."""
+
+ factories.User(fullname="User One", email="useroneemail@example.com")
+ factories.User(fullname="Person Two")
+ factories.User(fullname="Person Three")
+
+ user_url = url_for("user.index")
+ user_response = app.get(user_url, status=200)
+ search_form = user_response.forms["user-search-form"]
+ search_form["q"] = "useroneemail@example.com"
+ search_response = webtest_submit(search_form, status=200)
+
+ search_response_html = BeautifulSoup(search_response.body)
+ user_list = search_response_html.select("ul.user-list li")
+ assert len(user_list) == 0
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_user_page_sysadmin_user(app):
+ """Sysadmin can search for users by email."""
+
+ sysadmin = factories.Sysadmin()
+
+ factories.User(fullname="User One", email="useroneemail@example.com")
+ factories.User(fullname="Person Two")
+ factories.User(fullname="Person Three")
+
+ env = {"REMOTE_USER": sysadmin["name"].encode("ascii")}
+ user_url = url_for("user.index")
+ user_response = app.get(user_url, status=200, extra_environ=env)
+ search_form = user_response.forms["user-search-form"]
+ search_form["q"] = "useroneemail@example.com"
+ search_response = webtest_submit(
+ search_form, status=200, extra_environ=env
+ )
+
+ search_response_html = BeautifulSoup(search_response.body)
+ user_list = search_response_html.select("ul.user-list li")
+ assert len(user_list) == 1
+ assert user_list[0].text.strip() == "User One"
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_simple(app):
+ """Checking the template shows the activity stream."""
+
+ user = factories.User()
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert "Mr. Test User" in response
+ assert "signed up" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_create_user(app):
+
+ user = factories.User()
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "signed up" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_change_user(app):
+
+ user = factories.User()
+ _clear_activities()
+ user["fullname"] = "Mr. Changed Name"
+ helpers.call_action("user_update", context={"user": user["name"]}, **user)
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert (
+ 'Mr. Changed Name'.format(user["name"]) in response
+ )
+ assert "updated their profile" in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_create_dataset(app):
+
+ user = factories.User()
+ _clear_activities()
+ dataset = factories.Dataset(user=user)
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "created the dataset" in response
+ assert (
+ 'Test Dataset'.format(dataset["id"]) in response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_change_dataset(app):
+
+ user = factories.User()
+ dataset = factories.Dataset(user=user)
+ _clear_activities()
+ dataset["title"] = "Dataset with changed title"
+ helpers.call_action(
+ "package_update", context={"user": user["name"]}, **dataset
+ )
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "updated the dataset" in response
+ assert (
+ 'Dataset with changed title'.format(
+ dataset["id"]
)
- # existing values in the form
- form = response.forms['user-edit-form']
-
- # new values
- form['name'] = 'new-name'
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = webtest_submit(form, 'save', status=200, extra_environ=env)
- assert_true('That login name can not be modified' in response)
-
- def test_perform_reset_for_key_change(self):
- password = 'TestPassword1'
- params = {'password1': password, 'password2': password}
- user = factories.User()
- user_obj = helpers.model.User.by_name(user['name'])
- create_reset_key(user_obj)
- key = user_obj.reset_key
-
- app = self._get_test_app()
- offset = url_for(controller='user',
- action='perform_reset',
- id=user_obj.id,
- key=user_obj.reset_key)
- response = app.post(offset, params=params, status=302)
- user_obj = helpers.model.User.by_name(user['name']) # Update user_obj
-
- assert_true(key != user_obj.reset_key)
-
- def test_password_reset_correct_password(self):
- """
- user password reset attempted with correct old password
- """
- app = self._get_test_app()
- env, response, user = _get_user_edit_page(app)
-
- form = response.forms['user-edit-form']
-
- # factory returns user with password 'RandomPassword123'
- form.fields['old_password'][0].value = 'RandomPassword123'
- form.fields['password1'][0].value = 'NewPassword1'
- form.fields['password2'][0].value = 'NewPassword1'
-
- response = submit_and_follow(app, form, env, 'save')
- assert_true('Profile updated' in response)
-
- def test_password_reset_incorrect_password(self):
- """
- user password reset attempted with invalid old password
- """
-
- app = self._get_test_app()
- env, response, user = _get_user_edit_page(app)
-
- form = response.forms['user-edit-form']
-
- # factory returns user with password 'RandomPassword123'
- form.fields['old_password'][0].value = 'Wrong-Pass1'
- form.fields['password1'][0].value = 'NewPassword1'
- form.fields['password2'][0].value = 'NewPassword1'
-
- response = webtest_submit(form, 'save', status=200, extra_environ=env)
- assert_true('Old Password: incorrect password' in response)
-
-
-class TestUserFollow(helpers.FunctionalTestBase):
-
- def test_user_follow(self):
- app = self._get_test_app()
-
- user_one = factories.User()
- user_two = factories.User()
-
- env = {'REMOTE_USER': user_one['name'].encode('ascii')}
- follow_url = url_for(controller='user',
- action='follow',
- id=user_two['id'])
- response = app.post(follow_url, extra_environ=env, status=302)
- response = response.follow()
- assert_true('You are now following {0}'
- .format(user_two['display_name'])
- in response)
-
- def test_user_follow_not_exist(self):
- '''Pass an id for a user that doesn't exist'''
- app = self._get_test_app()
-
- user_one = factories.User()
-
- env = {'REMOTE_USER': user_one['name'].encode('ascii')}
- follow_url = url_for(controller='user',
- action='follow',
- id='not-here')
- response = app.post(follow_url, extra_environ=env, status=302)
- response = response.follow(status=302)
- assert_in('user/login', response.headers['location'])
-
- def test_user_unfollow(self):
- app = self._get_test_app()
-
- user_one = factories.User()
- user_two = factories.User()
-
- env = {'REMOTE_USER': user_one['name'].encode('ascii')}
- follow_url = url_for(controller='user',
- action='follow',
- id=user_two['id'])
- app.post(follow_url, extra_environ=env, status=302)
-
- unfollow_url = url_for('user.unfollow',
- id=user_two['id'])
- unfollow_response = app.post(unfollow_url, extra_environ=env,
- status=302)
- unfollow_response = unfollow_response.follow()
-
- assert_true('You are no longer following {0}'
- .format(user_two['display_name'])
- in unfollow_response)
-
- def test_user_unfollow_not_following(self):
- '''Unfollow a user not currently following'''
- app = self._get_test_app()
-
- user_one = factories.User()
- user_two = factories.User()
-
- env = {'REMOTE_USER': user_one['name'].encode('ascii')}
- unfollow_url = url_for('user.unfollow',
- id=user_two['id'])
- unfollow_response = app.post(unfollow_url, extra_environ=env,
- status=302)
- unfollow_response = unfollow_response.follow()
-
- assert_true('You are not following {0}'.format(user_two['id'])
- in unfollow_response)
-
- def test_user_unfollow_not_exist(self):
- '''Unfollow a user that doesn't exist.'''
- app = self._get_test_app()
-
- user_one = factories.User()
-
- env = {'REMOTE_USER': user_one['name'].encode('ascii')}
- unfollow_url = url_for('user.unfollow',
- id='not-here')
- unfollow_response = app.post(unfollow_url, extra_environ=env,
- status=302)
- unfollow_response = unfollow_response.follow(status=302)
- assert_in('user/login', unfollow_response.headers['location'])
-
- def test_user_follower_list(self):
- '''Following users appear on followers list page.'''
- app = self._get_test_app()
-
- user_one = factories.Sysadmin()
- user_two = factories.User()
-
- env = {'REMOTE_USER': user_one['name'].encode('ascii')}
- follow_url = url_for(controller='user',
- action='follow',
- id=user_two['id'])
- app.post(follow_url, extra_environ=env, status=302)
-
- followers_url = url_for('user.followers',
- id=user_two['id'])
-
- # Only sysadmins can view the followers list pages
- followers_response = app.get(followers_url, extra_environ=env,
- status=200)
- assert_true(user_one['display_name'] in followers_response)
-
-
-class TestUserSearch(helpers.FunctionalTestBase):
-
- def test_user_page_anon_access(self):
- '''Anon users can access the user list page'''
- app = self._get_test_app()
-
- user_url = url_for('user.index')
- user_response = app.get(user_url, status=200)
- assert_true('All Users - CKAN'
- in user_response)
-
- def test_user_page_lists_users(self):
- '''/users/ lists registered users'''
- app = self._get_test_app()
- factories.User(fullname='User One')
- factories.User(fullname='User Two')
- factories.User(fullname='User Three')
-
- user_url = url_for('user.index')
- user_response = app.get(user_url, status=200)
-
- user_response_html = BeautifulSoup(user_response.body)
- user_list = user_response_html.select('ul.user-list li')
- assert_equal(len(user_list), 3)
-
- user_names = [u.text.strip() for u in user_list]
- assert_true('User One' in user_names)
- assert_true('User Two' in user_names)
- assert_true('User Three' in user_names)
-
- def test_user_page_doesnot_list_deleted_users(self):
- '''/users/ doesn't list deleted users'''
- app = self._get_test_app()
- factories.User(fullname='User One', state='deleted')
- factories.User(fullname='User Two')
- factories.User(fullname='User Three')
-
- user_url = url_for('user.index')
- user_response = app.get(user_url, status=200)
-
- user_response_html = BeautifulSoup(user_response.body)
- user_list = user_response_html.select('ul.user-list li')
- assert_equal(len(user_list), 2)
-
- user_names = [u.text.strip() for u in user_list]
- assert_true('User One' not in user_names)
- assert_true('User Two' in user_names)
- assert_true('User Three' in user_names)
-
- def test_user_page_anon_search(self):
- '''Anon users can search for users by username.'''
- app = self._get_test_app()
- factories.User(fullname='User One', email='useroneemail@example.com')
- factories.User(fullname='Person Two')
- factories.User(fullname='Person Three')
-
- user_url = url_for('user.index')
- user_response = app.get(user_url, status=200)
- search_form = user_response.forms['user-search-form']
- search_form['q'] = 'Person'
- search_response = webtest_submit(search_form, status=200)
-
- search_response_html = BeautifulSoup(search_response.body)
- user_list = search_response_html.select('ul.user-list li')
- assert_equal(len(user_list), 2)
-
- user_names = [u.text.strip() for u in user_list]
- assert_true('Person Two' in user_names)
- assert_true('Person Three' in user_names)
- assert_true('User One' not in user_names)
-
- def test_user_page_anon_search_not_by_email(self):
- '''Anon users can not search for users by email.'''
- app = self._get_test_app()
- factories.User(fullname='User One', email='useroneemail@example.com')
- factories.User(fullname='Person Two')
- factories.User(fullname='Person Three')
-
- user_url = url_for('user.index')
- user_response = app.get(user_url, status=200)
- search_form = user_response.forms['user-search-form']
- search_form['q'] = 'useroneemail@example.com'
- search_response = webtest_submit(search_form, status=200)
-
- search_response_html = BeautifulSoup(search_response.body)
- user_list = search_response_html.select('ul.user-list li')
- assert_equal(len(user_list), 0)
-
- def test_user_page_sysadmin_user(self):
- '''Sysadmin can search for users by email.'''
- app = self._get_test_app()
- sysadmin = factories.Sysadmin()
-
- factories.User(fullname='User One', email='useroneemail@example.com')
- factories.User(fullname='Person Two')
- factories.User(fullname='Person Three')
-
- env = {'REMOTE_USER': sysadmin['name'].encode('ascii')}
- user_url = url_for('user.index')
- user_response = app.get(user_url, status=200, extra_environ=env)
- search_form = user_response.forms['user-search-form']
- search_form['q'] = 'useroneemail@example.com'
- search_response = webtest_submit(search_form, status=200,
- extra_environ=env)
-
- search_response_html = BeautifulSoup(search_response.body)
- user_list = search_response_html.select('ul.user-list li')
- assert_equal(len(user_list), 1)
- assert_equal(user_list[0].text.strip(), 'User One')
-
-
-class TestActivity(helpers.FunctionalTestBase):
- def test_simple(self):
- '''Checking the template shows the activity stream.'''
- app = self._get_test_app()
- user = factories.User()
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User', response)
- assert_in('signed up', response)
-
- def test_create_user(self):
- app = self._get_test_app()
- user = factories.User()
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('signed up', response)
-
- def _clear_activities(self):
- model.Session.query(model.ActivityDetail).delete()
- model.Session.query(model.Activity).delete()
- model.Session.flush()
-
- def test_change_user(self):
- app = self._get_test_app()
- user = factories.User()
- self._clear_activities()
- user['fullname'] = 'Mr. Changed Name'
- helpers.call_action(
- 'user_update', context={'user': user['name']}, **user)
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Changed Name'.format(user['name']),
- response)
- assert_in('updated their profile', response)
-
- def test_create_dataset(self):
- app = self._get_test_app()
- user = factories.User()
- self._clear_activities()
- dataset = factories.Dataset(user=user)
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('created the dataset', response)
- assert_in('Test Dataset'.format(dataset['id']),
- response)
-
- def test_change_dataset(self):
- app = self._get_test_app()
- user = factories.User()
- dataset = factories.Dataset(user=user)
- self._clear_activities()
- dataset['title'] = 'Dataset with changed title'
- helpers.call_action(
- 'package_update', context={'user': user['name']}, **dataset)
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('updated the dataset', response)
- assert_in('Dataset with changed title'
- .format(dataset['id']),
- response)
-
- def test_delete_dataset(self):
- app = self._get_test_app()
- user = factories.User()
- dataset = factories.Dataset(user=user)
- self._clear_activities()
- helpers.call_action(
- 'package_delete', context={'user': user['name']}, **dataset)
-
- url = url_for('user.activity',
- id=user['id'])
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = app.get(url, extra_environ=env)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('deleted the dataset', response)
- assert_in('Test Dataset'
- .format(dataset['id']),
- response)
-
- def test_create_group(self):
- app = self._get_test_app()
- user = factories.User()
- group = factories.Group(user=user)
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('created the group', response)
- assert_in('Test Group'.format(
- group['id']), response)
-
- def test_change_group(self):
- app = self._get_test_app()
- user = factories.User()
- group = factories.Group(user=user)
- self._clear_activities()
- group['title'] = 'Group with changed title'
- helpers.call_action(
- 'group_update', context={'user': user['name']}, **group)
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('updated the group', response)
- assert_in('Group with changed title'
- .format(group['id']), response)
-
- def test_delete_group_using_group_delete(self):
- app = self._get_test_app()
- user = factories.User()
- group = factories.Group(user=user)
- self._clear_activities()
- helpers.call_action(
- 'group_delete', context={'user': user['name']}, **group)
-
- url = url_for('user.activity',
- id=user['id'])
- response = app.get(url)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('deleted the group', response)
- assert_in('Test Group'
- .format(group['id']), response)
-
- def test_delete_group_by_updating_state(self):
- app = self._get_test_app()
- user = factories.User()
- group = factories.Group(user=user)
- self._clear_activities()
- group['state'] = 'deleted'
- helpers.call_action(
- 'group_update', context={'user': user['name']}, **group)
-
- url = url_for('group.activity',
- id=group['id'])
- env = {'REMOTE_USER': user['name'].encode('ascii')}
- response = app.get(url, extra_environ=env)
- assert_in('Mr. Test User'.format(user['name']),
- response)
- assert_in('deleted the group', response)
- assert_in('Test Group'
- .format(group['name']), response)
-
-
-class TestUserResetRequest(helpers.FunctionalTestBase):
- @mock.patch('ckan.lib.mailer.send_reset_link')
- def test_request_reset_by_email(self, send_reset_link):
- user = factories.User()
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- response = app.post(offset, params=dict(user=user['email']),
- status=302).follow()
-
- assert_in('A reset link has been emailed to you', response)
- assert_equal(send_reset_link.call_args[0][0].id, user['id'])
-
- @mock.patch('ckan.lib.mailer.send_reset_link')
- def test_request_reset_by_name(self, send_reset_link):
- user = factories.User()
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- response = app.post(offset, params=dict(user=user['name']),
- status=302).follow()
-
- assert_in('A reset link has been emailed to you', response)
- assert_equal(send_reset_link.call_args[0][0].id, user['id'])
-
- @mock.patch('ckan.lib.mailer.send_reset_link')
- def test_request_reset_when_duplicate_emails(self, send_reset_link):
- user_a = factories.User(email='me@example.com')
- user_b = factories.User(email='me@example.com')
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- response = app.post(offset, params=dict(user='me@example.com'),
- status=302).follow()
-
- assert_in('A reset link has been emailed to you', response)
- emailed_users = [call[0][0].name
- for call in send_reset_link.call_args_list]
- assert_equal(emailed_users, [user_a['name'], user_b['name']])
-
- def test_request_reset_without_param(self):
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- response = app.post(offset).follow()
-
- assert_in('Email is required', response)
-
- @mock.patch('ckan.lib.mailer.send_reset_link')
- def test_request_reset_for_unknown_username(self, send_reset_link):
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- response = app.post(offset, params=dict(user='unknown'),
- status=302).follow()
-
- # doesn't reveal account does or doesn't exist
- assert_in('A reset link has been emailed to you', response)
- send_reset_link.assert_not_called()
-
- @mock.patch('ckan.lib.mailer.send_reset_link')
- def test_request_reset_for_unknown_email(self, send_reset_link):
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- response = app.post(offset, params=dict(user='unknown@example.com'),
- status=302).follow()
-
- # doesn't reveal account does or doesn't exist
- assert_in('A reset link has been emailed to you', response)
- send_reset_link.assert_not_called()
-
- @mock.patch('ckan.lib.mailer.send_reset_link')
- def test_request_reset_but_mailer_not_configured(self, send_reset_link):
- user = factories.User()
- app = self._get_test_app()
- offset = url_for('user.request_reset')
- # This is the exception when the mailer is not configured:
- send_reset_link.side_effect = MailerException(
- 'SMTP server could not be connected to: "localhost" '
- '[Errno 111] Connection refused')
- response = app.post(offset, params=dict(user=user['name']),
- status=302).follow()
-
- assert_in('Error sending the email', response)
+ in response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_delete_dataset(app):
+
+ user = factories.User()
+ dataset = factories.Dataset(user=user)
+ _clear_activities()
+ helpers.call_action(
+ "package_delete", context={"user": user["name"]}, **dataset
+ )
+
+ url = url_for("user.activity", id=user["id"])
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = app.get(url, extra_environ=env)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "deleted the dataset" in response
+ assert (
+ 'Test Dataset'.format(dataset["id"]) in response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_create_group(app):
+
+ user = factories.User()
+ group = factories.Group(user=user)
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "created the group" in response
+ assert 'Test Group'.format(group["id"]) in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_change_group(app):
+
+ user = factories.User()
+ group = factories.Group(user=user)
+ _clear_activities()
+ group["title"] = "Group with changed title"
+ helpers.call_action(
+ "group_update", context={"user": user["name"]}, **group
+ )
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "updated the group" in response
+ assert (
+ 'Group with changed title'.format(group["id"])
+ in response
+ )
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_delete_group_using_group_delete(app):
+
+ user = factories.User()
+ group = factories.Group(user=user)
+ _clear_activities()
+ helpers.call_action(
+ "group_delete", context={"user": user["name"]}, **group
+ )
+
+ url = url_for("user.activity", id=user["id"])
+ response = app.get(url)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "deleted the group" in response
+ assert 'Test Group'.format(group["id"]) in response
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_delete_group_by_updating_state(app):
+
+ user = factories.User()
+ group = factories.Group(user=user)
+ _clear_activities()
+ group["state"] = "deleted"
+ helpers.call_action(
+ "group_update", context={"user": user["name"]}, **group
+ )
+
+ url = url_for("group.activity", id=group["id"])
+ env = {"REMOTE_USER": user["name"].encode("ascii")}
+ response = app.get(url, extra_environ=env)
+ assert 'Mr. Test User'.format(user["name"]) in response
+ assert "deleted the group" in response
+ assert 'Test Group'.format(group["name"]) in response
+
+
+@mock.patch("ckan.lib.mailer.send_reset_link")
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_by_email(send_reset_link, app):
+ user = factories.User()
+
+ offset = url_for("user.request_reset")
+ response = app.post(
+ offset, params=dict(user=user["email"]), status=302
+ ).follow()
+
+ assert "A reset link has been emailed to you" in response
+ assert send_reset_link.call_args[0][0].id == user["id"]
+
+
+@mock.patch("ckan.lib.mailer.send_reset_link")
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_by_name(send_reset_link, app):
+ user = factories.User()
+
+ offset = url_for("user.request_reset")
+ response = app.post(
+ offset, params=dict(user=user["name"]), status=302
+ ).follow()
+
+ assert "A reset link has been emailed to you" in response
+ assert send_reset_link.call_args[0][0].id == user["id"]
+
+
+@mock.patch("ckan.lib.mailer.send_reset_link")
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_when_duplicate_emails(send_reset_link, app):
+ user_a = factories.User(email="me@example.com")
+ user_b = factories.User(email="me@example.com")
+
+ offset = url_for("user.request_reset")
+ response = app.post(
+ offset, params=dict(user="me@example.com"), status=302
+ ).follow()
+
+ assert "A reset link has been emailed to you" in response
+ emailed_users = [
+ call[0][0].name for call in send_reset_link.call_args_list
+ ]
+ assert emailed_users == [user_a["name"], user_b["name"]]
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_without_param(app):
+
+ offset = url_for("user.request_reset")
+ response = app.post(offset).follow()
+
+ assert "Email is required" in response
+
+
+@mock.patch("ckan.lib.mailer.send_reset_link")
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_for_unknown_username(send_reset_link, app):
+
+ offset = url_for("user.request_reset")
+ response = app.post(
+ offset, params=dict(user="unknown"), status=302
+ ).follow()
+
+ # doesn't reveal account does or doesn't exist
+ assert "A reset link has been emailed to you" in response
+ send_reset_link.assert_not_called()
+
+
+@mock.patch("ckan.lib.mailer.send_reset_link")
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_for_unknown_email(send_reset_link, app):
+
+ offset = url_for("user.request_reset")
+ response = app.post(
+ offset, params=dict(user="unknown@example.com"), status=302
+ ).follow()
+
+ # doesn't reveal account does or doesn't exist
+ assert "A reset link has been emailed to you" in response
+ send_reset_link.assert_not_called()
+
+
+@mock.patch("ckan.lib.mailer.send_reset_link")
+@pytest.mark.usefixtures("clean_db")
+def test_request_reset_but_mailer_not_configured(send_reset_link, app):
+ user = factories.User()
+
+ offset = url_for("user.request_reset")
+ # This is the exception when the mailer is not configured:
+ send_reset_link.side_effect = MailerException(
+ 'SMTP server could not be connected to: "localhost" '
+ "[Errno 111] Connection refused"
+ )
+ response = app.post(
+ offset, params=dict(user=user["name"]), status=302
+ ).follow()
+
+ assert "Error sending the email" in response
diff --git a/ckan/tests/controllers/test_util.py b/ckan/tests/controllers/test_util.py
index 9e59ba9f2b2..44d5a0d7583 100644
--- a/ckan/tests/controllers/test_util.py
+++ b/ckan/tests/controllers/test_util.py
@@ -1,43 +1,27 @@
# encoding: utf-8
-from nose.tools import assert_equal
+import pytest
from ckan.lib.helpers import url_for as url_for
-import ckan.tests.helpers as helpers
-
-
-class TestUtil(helpers.FunctionalTestBase):
- def test_redirect_ok(self):
- app = self._get_test_app()
- response = app.get(
- url=url_for('util.internal_redirect'),
- params={'url': '/dataset'},
- status=302,
- )
- assert_equal(response.headers.get('Location'),
- 'http://test.ckan.net/dataset')
-
- def test_redirect_external(self):
- app = self._get_test_app()
- response = app.get(
- url=url_for('util.internal_redirect'),
- params={'url': 'http://nastysite.com'},
- status=403,
- )
-
- def test_redirect_no_params(self):
- app = self._get_test_app()
- response = app.get(
- url=url_for('util.internal_redirect'),
- params={},
- status=400,
- )
-
- def test_redirect_no_params_2(self):
- app = self._get_test_app()
- response = app.get(
- url=url_for('util.internal_redirect'),
- params={'url': ''},
- status=400,
- )
+
+def test_redirect_ok(app):
+ response = app.get(
+ url=url_for("util.internal_redirect"),
+ params={"url": "/dataset"},
+ status=302,
+ )
+ assert response.headers.get("Location") == "http://test.ckan.net/dataset"
+
+
+def test_redirect_external(app):
+ app.get(
+ url=url_for("util.internal_redirect"),
+ params={"url": "http://nastysite.com"},
+ status=403,
+ )
+
+
+@pytest.mark.parametrize("params", [{}, {"url": ""}])
+def test_redirect_no_params(params, app):
+ app.get(url=url_for("util.internal_redirect"), params=params, status=400)
diff --git a/ckan/tests/factories.py b/ckan/tests/factories.py
index ab47cc37e2e..40aa4b5d408 100644
--- a/ckan/tests/factories.py
+++ b/ckan/tests/factories.py
@@ -1,6 +1,6 @@
# encoding: utf-8
-'''This is a collection of factory classes for building CKAN users, datasets,
+"""This is a collection of factory classes for building CKAN users, datasets,
etc.
These are meant to be used by tests to create any objects that are needed for
@@ -37,7 +37,7 @@
# to the factory:
user = factories.User(**user_attributes_dict)
-'''
+"""
import random
import string
import factory
@@ -49,69 +49,69 @@
def _get_action_user_name(kwargs):
- '''Return the name of the user in kwargs, defaulting to the site user
+ """Return the name of the user in kwargs, defaulting to the site user
It can be overriden by explictly setting {'user': None} in the keyword
arguments. In that case, this method will return None.
- '''
+ """
- if 'user' in kwargs:
- user = kwargs['user']
+ if "user" in kwargs:
+ user = kwargs["user"]
else:
- user = helpers.call_action('get_site_user')
+ user = helpers.call_action("get_site_user")
if user is None:
user_name = None
else:
- user_name = user['name']
+ user_name = user["name"]
return user_name
def _generate_email(user):
- '''Return an email address for the given User factory stub object.'''
+ """Return an email address for the given User factory stub object."""
- return '{0}@ckan.org'.format(user.name).lower()
+ return "{0}@ckan.org".format(user.name).lower()
def _generate_reset_key(user):
- '''Return a reset key for the given User factory stub object.'''
+ """Return a reset key for the given User factory stub object."""
- return '{0}_reset_key'.format(user.name).lower()
+ return "{0}_reset_key".format(user.name).lower()
def _generate_user_id(user):
- '''Return a user id for the given User factory stub object.'''
+ """Return a user id for the given User factory stub object."""
- return '{0}_user_id'.format(user.name).lower()
+ return "{0}_user_id".format(user.name).lower()
def _generate_group_title(group):
- '''Return a title for the given Group factory stub object.'''
+ """Return a title for the given Group factory stub object."""
- return group.name.replace('_', ' ').title()
+ return group.name.replace("_", " ").title()
def _generate_random_string(length=6):
- '''Return a random string of the defined length.'''
+ """Return a random string of the defined length."""
- return ''.join(random.sample(string.ascii_lowercase, length))
+ return "".join(random.sample(string.ascii_lowercase, length))
class User(factory.Factory):
- '''A factory class for creating CKAN users.'''
+ """A factory class for creating CKAN users."""
# This is the class that UserFactory will create and return instances
# of.
FACTORY_FOR = ckan.model.User
# These are the default params that will be used to create new users.
- fullname = 'Mr. Test User'
- password = 'RandomPassword123'
- about = 'Just another test user.'
+ fullname = "Mr. Test User"
+ password = "RandomPassword123"
+ about = "Just another test user."
# Generate a different user name param for each user that gets created.
- name = factory.Sequence(lambda n: 'test_user_{0:02d}'.format(n))
+ name = factory.Sequence(lambda n: "test_user_{0:02d}".format(n))
# Compute the email param for each user based on the values of the other
# params above.
@@ -131,20 +131,20 @@ def _build(cls, target_class, *args, **kwargs):
def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- user_dict = helpers.call_action('user_create', **kwargs)
+ user_dict = helpers.call_action("user_create", **kwargs)
return user_dict
class Resource(factory.Factory):
- '''A factory class for creating CKAN resources.'''
+ """A factory class for creating CKAN resources."""
FACTORY_FOR = ckan.model.Resource
- name = factory.Sequence(lambda n: 'test_resource_{0:02d}'.format(n))
- description = 'Just another test resource.'
- format = 'res_format'
- url = 'http://link.to.some.data'
- package_id = factory.LazyAttribute(lambda _: Dataset()['id'])
+ name = factory.Sequence(lambda n: "test_resource_{0:02d}".format(n))
+ description = "Just another test resource."
+ format = "res_format"
+ url = "http://link.to.some.data"
+ package_id = factory.LazyAttribute(lambda _: Dataset()["id"])
@classmethod
def _build(cls, target_class, *args, **kwargs):
@@ -155,39 +155,35 @@ def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- context = {'user': _get_action_user_name(kwargs)}
+ context = {"user": _get_action_user_name(kwargs)}
- resource_dict = helpers.call_action('resource_create', context=context,
- **kwargs)
+ resource_dict = helpers.call_action(
+ "resource_create", context=context, **kwargs
+ )
return resource_dict
class ResourceView(factory.Factory):
- '''A factory class for creating CKAN resource views.
+ """A factory class for creating CKAN resource views.
Note: if you use this factory, you need to load the `image_view` plugin
on your test class (and unload it later), otherwise you will get an error.
Example::
- class TestSomethingWithResourceViews(object):
- @classmethod
- def setup_class(cls):
- if not p.plugin_loaded('image_view'):
- p.load('image_view')
+ @pytest.mark.ckan_config("ckan.plugins", "image_view")
+ @pytest.mark.usefixtures("with_plugins")
+ def test_resource_view_factory():
+ ...
- @classmethod
- def teardown_class(cls):
- p.unload('image_view')
-
- '''
+ """
FACTORY_FOR = ckan.model.ResourceView
- title = factory.Sequence(lambda n: 'test_resource_view_{0:02d}'.format(n))
- description = 'Just another test resource view.'
- view_type = 'image_view'
- resource_id = factory.LazyAttribute(lambda _: Resource()['id'])
+ title = factory.Sequence(lambda n: "test_resource_view_{0:02d}".format(n))
+ description = "Just another test resource view."
+ view_type = "image_view"
+ resource_id = factory.LazyAttribute(lambda _: Resource()["id"])
@classmethod
def _build(cls, target_class, *args, **kwargs):
@@ -198,23 +194,24 @@ def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- context = {'user': _get_action_user_name(kwargs)}
+ context = {"user": _get_action_user_name(kwargs)}
- resource_dict = helpers.call_action('resource_view_create',
- context=context, **kwargs)
+ resource_dict = helpers.call_action(
+ "resource_view_create", context=context, **kwargs
+ )
return resource_dict
class Sysadmin(factory.Factory):
- '''A factory class for creating sysadmin users.'''
+ """A factory class for creating sysadmin users."""
FACTORY_FOR = ckan.model.User
- fullname = 'Mr. Test Sysadmin'
- password = 'RandomPassword123'
- about = 'Just another test sysadmin.'
+ fullname = "Mr. Test Sysadmin"
+ password = "RandomPassword123"
+ about = "Just another test sysadmin."
- name = factory.Sequence(lambda n: 'test_sysadmin_{0:02d}'.format(n))
+ name = factory.Sequence(lambda n: "test_sysadmin_{0:02d}".format(n))
email = factory.LazyAttribute(_generate_email)
sysadmin = True
@@ -237,22 +234,24 @@ def _create(cls, target_class, *args, **kwargs):
# to get one. We pass the user's name in the context because we want
# the API key and other sensitive data to be returned in the user
# dict.
- user_dict = helpers.call_action('user_show', id=user.id,
- context={'user': user.name})
+ user_dict = helpers.call_action(
+ "user_show", id=user.id, context={"user": user.name}
+ )
return user_dict
class Group(factory.Factory):
- '''A factory class for creating CKAN groups.'''
+ """A factory class for creating CKAN groups."""
FACTORY_FOR = ckan.model.Group
- name = factory.Sequence(lambda n: 'test_group_{0:02d}'.format(n))
+ name = factory.Sequence(lambda n: "test_group_{0:02d}".format(n))
title = factory.LazyAttribute(_generate_group_title)
- description = 'A test description for this test group.'
+ description = "A test description for this test group."
- user = factory.LazyAttribute(lambda _:
- helpers.call_action('get_site_user'))
+ user = factory.LazyAttribute(
+ lambda _: helpers.call_action("get_site_user")
+ )
@classmethod
def _build(cls, target_class, *args, **kwargs):
@@ -263,16 +262,16 @@ def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- context = {'user': _get_action_user_name(kwargs)}
+ context = {"user": _get_action_user_name(kwargs)}
- group_dict = helpers.call_action('group_create',
- context=context,
- **kwargs)
+ group_dict = helpers.call_action(
+ "group_create", context=context, **kwargs
+ )
return group_dict
class Organization(factory.Factory):
- '''A factory class for creating CKAN organizations.'''
+ """A factory class for creating CKAN organizations."""
# This is the class that OrganizationFactory will create and return
# instances of.
@@ -282,12 +281,12 @@ class Organization(factory.Factory):
# organizations.
is_organization = True
- title = 'Test Organization'
- description = 'Just another test organization.'
- image_url = 'http://placekitten.com/g/200/100'
+ title = "Test Organization"
+ description = "Just another test organization."
+ image_url = "http://placekitten.com/g/200/100"
# Generate a different group name param for each user that gets created.
- name = factory.Sequence(lambda n: 'test_org_{0:02d}'.format(n))
+ name = factory.Sequence(lambda n: "test_org_{0:02d}".format(n))
@classmethod
def _build(cls, target_class, *args, **kwargs):
@@ -298,27 +297,27 @@ def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- context = {'user': _get_action_user_name(kwargs)}
+ context = {"user": _get_action_user_name(kwargs)}
- kwargs.setdefault('type', 'organization')
+ kwargs.setdefault("type", "organization")
- group_dict = helpers.call_action('organization_create',
- context=context,
- **kwargs)
+ group_dict = helpers.call_action(
+ "organization_create", context=context, **kwargs
+ )
return group_dict
class Dataset(factory.Factory):
- '''A factory class for creating CKAN datasets.'''
+ """A factory class for creating CKAN datasets."""
FACTORY_FOR = ckan.model.Package
# These are the default params that will be used to create new groups.
- title = 'Test Dataset'
- notes = 'Just another test dataset.'
+ title = "Test Dataset"
+ notes = "Just another test dataset."
# Generate a different group name param for each user that gets created.
- name = factory.Sequence(lambda n: 'test_dataset_{0:02d}'.format(n))
+ name = factory.Sequence(lambda n: "test_dataset_{0:02d}".format(n))
@classmethod
def _build(cls, target_class, *args, **kwargs):
@@ -329,23 +328,23 @@ def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- context = {'user': _get_action_user_name(kwargs)}
+ context = {"user": _get_action_user_name(kwargs)}
- dataset_dict = helpers.call_action('package_create',
- context=context,
- **kwargs)
+ dataset_dict = helpers.call_action(
+ "package_create", context=context, **kwargs
+ )
return dataset_dict
class MockUser(factory.Factory):
- '''A factory class for creating mock CKAN users using the mock library.'''
+ """A factory class for creating mock CKAN users using the mock library."""
FACTORY_FOR = mock.MagicMock
- fullname = 'Mr. Mock User'
- password = 'pass'
- about = 'Just another mock user.'
- name = factory.Sequence(lambda n: 'mock_user_{0:02d}'.format(n))
+ fullname = "Mr. Mock User"
+ password = "pass"
+ about = "Just another mock user."
+ name = factory.Sequence(lambda n: "mock_user_{0:02d}".format(n))
email = factory.LazyAttribute(_generate_email)
reset_key = factory.LazyAttribute(_generate_reset_key)
id = factory.LazyAttribute(_generate_user_id)
@@ -365,12 +364,12 @@ def _create(cls, target_class, *args, **kwargs):
class SystemInfo(factory.Factory):
- '''A factory class for creating SystemInfo objects (config objects
- stored in the DB).'''
+ """A factory class for creating SystemInfo objects (config objects
+ stored in the DB)."""
FACTORY_FOR = ckan.model.SystemInfo
- key = factory.Sequence(lambda n: 'test_config_{0:02d}'.format(n))
+ key = factory.Sequence(lambda n: "test_config_{0:02d}".format(n))
value = _generate_random_string()
@classmethod
@@ -382,35 +381,37 @@ def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- ckan.model.system_info.set_system_info(kwargs['key'],
- kwargs['value'])
- obj = ckan.model.Session.query(ckan.model.system_info.SystemInfo) \
- .filter_by(key=kwargs['key']).first()
+ ckan.model.system_info.set_system_info(kwargs["key"], kwargs["value"])
+ obj = (
+ ckan.model.Session.query(ckan.model.system_info.SystemInfo)
+ .filter_by(key=kwargs["key"])
+ .first()
+ )
return obj
def validator_data_dict():
- '''Return a data dict with some arbitrary data in it, suitable to be passed
+ """Return a data dict with some arbitrary data in it, suitable to be passed
to validator functions for testing.
- '''
- return {('other key',): 'other value'}
+ """
+ return {("other key",): "other value"}
def validator_errors_dict():
- '''Return an errors dict with some arbitrary errors in it, suitable to be
+ """Return an errors dict with some arbitrary errors in it, suitable to be
passed to validator functions for testing.
- '''
- return {('other key',): ['other error']}
+ """
+ return {("other key",): ["other error"]}
class Vocabulary(factory.Factory):
- '''A factory class for creating tag vocabularies.'''
+ """A factory class for creating tag vocabularies."""
FACTORY_FOR = ckan.model.Vocabulary
- name = factory.Sequence(lambda n: 'test_vocabulary_{0:02d}'.format(n))
+ name = factory.Sequence(lambda n: "test_vocabulary_{0:02d}".format(n))
@classmethod
def _build(cls, target_class, *args, **kwargs):
@@ -420,11 +421,11 @@ def _build(cls, target_class, *args, **kwargs):
def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- return helpers.call_action('vocabulary_create', **kwargs)
+ return helpers.call_action("vocabulary_create", **kwargs)
class Activity(factory.Factory):
- '''A factory class for creating CKAN activity objects.'''
+ """A factory class for creating CKAN activity objects."""
FACTORY_FOR = ckan.model.Activity
@@ -436,4 +437,4 @@ def _build(cls, target_class, *args, **kwargs):
def _create(cls, target_class, *args, **kwargs):
if args:
assert False, "Positional args aren't supported, use keyword args."
- return helpers.call_action('activity_create', **kwargs)
+ return helpers.call_action("activity_create", **kwargs)
diff --git a/ckan/tests/helpers.py b/ckan/tests/helpers.py
index 2302674a9c1..3d316ca46c2 100644
--- a/ckan/tests/helpers.py
+++ b/ckan/tests/helpers.py
@@ -1,11 +1,10 @@
# encoding: utf-8
-'''This is a collection of helper functions for use in tests.
+"""This is a collection of helper functions for use in tests.
We want to avoid sharing test helper functions between test modules as
-much as possible, and we definitely don't want to share test fixtures between
-test modules, or to introduce a complex hierarchy of test class subclasses,
-etc.
+much as possible, and we definitely don't want to introduce a complex
+hierarchy of test class subclasses, etc.
We want to reduce the amount of "travel" that a reader needs to undertake to
understand a test method -- reducing the number of other files they need to go
@@ -16,9 +15,12 @@
and make writing tests so much easier, that it's worth having them despite the
potential drawbacks.
+Consider using :ref:`fixtures` whenever is possible for setting up initial
+state of a test or creating related objects.
+
This module is reserved for these very useful functions.
-'''
+"""
import collections
import contextlib
@@ -41,9 +43,9 @@
def reset_db():
- '''Reset CKAN's database.
+ """Reset CKAN's database.
- If a test class uses the database, then it should call this function in its
+ If a test class uses the database, then it may call this function in its
``setup()`` method to make sure that it has a clean database to start with
(nothing left over from other test classes or from previous test runs).
@@ -52,7 +54,7 @@ def reset_db():
:returns: ``None``
- '''
+ """
# Close any database connections that have been left open.
# This prevents CKAN from hanging waiting for some unclosed connection.
model.Session.close_all()
@@ -61,7 +63,7 @@ def reset_db():
def call_action(action_name, context=None, **kwargs):
- '''Call the named ``ckan.logic.action`` function and return the result.
+ """Call the named ``ckan.logic.action`` function and return the result.
This is just a nicer way for user code to call action functions, nicer than
either calling the action function directly or via
@@ -98,16 +100,16 @@ def call_action(action_name, context=None, **kwargs):
:type context: dict
:returns: the dict or other value that the action function returns
- '''
+ """
if context is None:
context = {}
- context.setdefault('user', '127.0.0.1')
- context.setdefault('ignore_auth', True)
+ context.setdefault("user", "127.0.0.1")
+ context.setdefault("ignore_auth", True)
return logic.get_action(action_name)(context=context, data_dict=kwargs)
def call_auth(auth_name, context, **kwargs):
- '''Call the named ``ckan.logic.auth`` function and return the result.
+ """Call the named ``ckan.logic.auth`` function and return the result.
This is just a convenience function for tests in
:py:mod:`ckan.tests.logic.auth` to use.
@@ -132,50 +134,52 @@ def call_auth(auth_name, context, **kwargs):
or just ``{'success': False}``
:rtype: dict
- '''
- assert 'user' in context, ('Test methods must put a user name in the '
- 'context dict')
- assert 'model' in context, ('Test methods must put a model in the '
- 'context dict')
+ """
+ assert "user" in context, (
+ "Test methods must put a user name in the " "context dict"
+ )
+ assert "model" in context, (
+ "Test methods must put a model in the " "context dict"
+ )
return logic.check_access(auth_name, context, data_dict=kwargs)
class CKANTestApp(webtest.TestApp):
- '''A wrapper around webtest.TestApp
+ """A wrapper around webtest.TestApp
It adds some convenience methods for CKAN
- '''
+ """
_flask_app = None
@property
def flask_app(self):
if not self._flask_app:
- self._flask_app = self.app.apps['flask_app']._wsgi_app
+ self._flask_app = self.app.apps["flask_app"]._wsgi_app
return self._flask_app
def post(self, url, *args, **kwargs):
- url = url.encode('utf8') # or maybe it should be url_encoded?
+ url = url.encode("utf8") # or maybe it should be url_encoded?
return super(CKANTestApp, self).post(url, *args, **kwargs)
def _get_test_app():
- '''Return a webtest.TestApp for CKAN, with legacy templates disabled.
+ """Return a webtest.TestApp for CKAN, with legacy templates disabled.
For functional tests that need to request CKAN pages or post to the API.
Unit tests shouldn't need this.
- '''
- config['ckan.legacy_templates'] = False
- config['testing'] = True
- app = ckan.config.middleware.make_app(config['global_conf'], **config)
+ """
+ config["ckan.legacy_templates"] = False
+ config["testing"] = True
+ app = ckan.config.middleware.make_app(config["global_conf"], **config)
app = CKANTestApp(app)
return app
class FunctionalTestBase(object):
- '''A base class for functional test classes to inherit from.
+ """A base class for functional test classes to inherit from.
Allows configuration changes by overriding _apply_config_changes and
resetting the CKAN config after your test class has run. It creates a
@@ -187,23 +191,25 @@ class FunctionalTestBase(object):
and teardown_class(), make sure to use super() to call this class's methods
at the top of yours!
- '''
+ """
+
@classmethod
def _get_test_app(cls): # leading _ because nose is terrible
# FIXME: remove this method and switch to using helpers.get_test_app
# in each test once the old functional tests are fixed or removed
- if not hasattr(cls, '_test_app'):
+ if not hasattr(cls, "_test_app"):
cls._test_app = _get_test_app()
return cls._test_app
@classmethod
def setup_class(cls):
import ckan.plugins as p
+
# Make a copy of the Pylons config, so we can restore it in teardown.
cls._original_config = dict(config)
cls._apply_config_changes(config)
try:
- config['ckan.plugins'] = ' '.join(cls._load_plugins)
+ config["ckan.plugins"] = " ".join(cls._load_plugins)
del cls._test_app # reload with the new plugins
except AttributeError:
pass
@@ -214,16 +220,17 @@ def _apply_config_changes(cls, cfg):
pass
def setup(self):
- '''Reset the database and clear the search indexes.'''
+ """Reset the database and clear the search indexes."""
reset_db()
- if hasattr(self, '_test_app'):
+ if hasattr(self, "_test_app"):
self._test_app.reset()
search.clear_all()
@classmethod
def teardown_class(cls):
import ckan.plugins as p
- for plugin in reversed(getattr(cls, '_load_plugins', [])):
+
+ for plugin in reversed(getattr(cls, "_load_plugins", [])):
p.unload(plugin)
# Restore the Pylons config to its original values, in case any tests
# changed any config settings.
@@ -232,13 +239,14 @@ def teardown_class(cls):
class RQTestBase(object):
- '''
+ """
Base class for tests of RQ functionality.
- '''
+ """
+
def setup(self):
- u'''
+ u"""
Delete all RQ queues and jobs.
- '''
+ """
# See https://github.com/nvie/rq/issues/731
redis_conn = connect_to_redis()
for queue in rq.Queue.all(connection=redis_conn):
@@ -247,9 +255,9 @@ def setup(self):
redis_conn.delete(queue._key)
def all_jobs(self):
- u'''
+ u"""
Get a list of all RQ jobs.
- '''
+ """
jobs = []
redis_conn = connect_to_redis()
for queue in rq.Queue.all(connection=redis_conn):
@@ -257,39 +265,49 @@ def all_jobs(self):
return jobs
def enqueue(self, job=None, *args, **kwargs):
- u'''
+ u"""
Enqueue a test job.
- '''
+ """
if job is None:
job = jobs.test_job
return jobs.enqueue(job, *args, **kwargs)
class FunctionalRQTestBase(FunctionalTestBase, RQTestBase):
- '''
+ """
Base class for functional tests of RQ functionality.
- '''
+ """
+
def setup(self):
FunctionalTestBase.setup(self)
RQTestBase.setup(self)
-def submit_and_follow(app, form, extra_environ=None, name=None,
- value=None, **args):
- '''
+def submit_and_follow(
+ app, form, extra_environ=None, name=None, value=None, **args
+):
+ """
Call webtest_submit with name/value passed expecting a redirect
and return the response from following that redirect.
- '''
- response = webtest_submit(form, name, value=value, status=302,
- extra_environ=extra_environ, **args)
- return app.get(url=response.headers['Location'],
- extra_environ=extra_environ)
+ """
+ response = webtest_submit(
+ form,
+ name,
+ value=value,
+ status=302,
+ extra_environ=extra_environ,
+ **args
+ )
+ return app.get(
+ url=response.headers["Location"], extra_environ=extra_environ
+ )
# FIXME: remove webtest_* functions below when we upgrade webtest
+
def webtest_submit(form, name=None, index=None, value=None, **args):
- '''
+ """
backported version of webtest.Form.submit that actually works
for submitting with different submit buttons.
@@ -297,20 +315,22 @@ def webtest_submit(form, name=None, index=None, value=None, **args):
on an old version of webob because we're stuck on an old version
of Pylons. This prolongs our suffering, but on the bright side
it lets us have functional tests that work.
- '''
+ """
fields = webtest_submit_fields(form, name, index=index, submit_value=value)
if form.method.upper() != "GET":
args.setdefault("content_type", form.enctype)
- return form.response.goto(form.action, method=form.method,
- params=fields, **args)
+ return form.response.goto(
+ form.action, method=form.method, params=fields, **args
+ )
def webtest_submit_fields(form, name=None, index=None, submit_value=None):
- '''
+ """
backported version of webtest.Form.submit_fields that actually works
for submitting with different submit buttons.
- '''
+ """
from webtest.app import File
+
submit = []
# Use another name here so we can keep function param the same for BWC.
submit_name = name
@@ -329,8 +349,10 @@ def webtest_submit_fields(form, name=None, index=None, submit_value=None):
if submit_name is not None and name == submit_name:
if index is not None and current_index == index:
submit.append((name, field.value_if_submitted()))
- if submit_value is not None and \
- field.value_if_submitted() == submit_value:
+ if (
+ submit_value is not None
+ and field.value_if_submitted() == submit_value
+ ):
submit.append((name, field.value_if_submitted()))
current_index += 1
else:
@@ -366,7 +388,7 @@ def webtest_maybe_follow(response, **kw):
def change_config(key, value):
- '''Decorator to temporarily change CKAN's config to a new value
+ """Decorator to temporarily change CKAN's config to a new value
This allows you to easily create tests that need specific config values to
be set, making sure it'll be reverted to what it was originally, after your
@@ -385,19 +407,22 @@ def test_ckan_site_title(self):
:type value: string
.. seealso:: The context manager :py:func:`changed_config`
- '''
+ """
+
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
with changed_config(key, value):
return func(*args, **kwargs)
+
return wrapper
+
return decorator
@contextlib.contextmanager
def changed_config(key, value):
- '''
+ """
Context manager for temporarily changing a config value.
Allows you to temporarily change the value of a CKAN configuration
@@ -410,7 +435,7 @@ def changed_config(key, value):
assert config[u'ckan.site_title'] == u'My Test CKAN'
.. seealso:: The decorator :py:func:`change_config`
- '''
+ """
_original_config = config.copy()
config[key] = value
try:
@@ -421,7 +446,7 @@ def changed_config(key, value):
def mock_auth(auth_function_path):
- '''
+ """
Decorator to easily mock a CKAN auth method in the context of a test
function
@@ -448,7 +473,7 @@ def test_mock_package_create(self, mock_package_create):
e.g. ``ckan.logic.auth.create.package_create``
:type action_name: string
- '''
+ """
from ckan.authz import clear_auth_functions_cache
def decorator(func):
@@ -464,11 +489,12 @@ def wrapper(*args, **kwargs):
return return_value
return nose.tools.make_decorator(func)(wrapper)
+
return decorator
def mock_action(action_name):
- '''
+ """
Decorator to easily mock a CKAN action in the context of a test function
It adds a mock object for the provided action as a parameter to the test
@@ -494,7 +520,8 @@ def test_mock_user_list(self, mock_user_list):
e.g. ``package_create``
:type action_name: string
- '''
+ """
+
def decorator(func):
def wrapper(*args, **kwargs):
mock_action = mock.MagicMock()
@@ -506,10 +533,13 @@ def side_effect(called_action_name):
return mock_action
else:
return original_get_action(called_action_name)
+
try:
- with mock.patch('ckan.logic.get_action') as mock_get_action, \
- mock.patch('ckan.plugins.toolkit.get_action') \
- as mock_get_action_toolkit:
+ with mock.patch(
+ "ckan.logic.get_action"
+ ) as mock_get_action, mock.patch(
+ "ckan.plugins.toolkit.get_action"
+ ) as mock_get_action_toolkit:
mock_get_action.side_effect = side_effect
mock_get_action_toolkit.side_effect = side_effect
@@ -521,11 +551,12 @@ def side_effect(called_action_name):
return return_value
return nose.tools.make_decorator(func)(wrapper)
+
return decorator
def set_extra_environ(key, value):
- '''Decorator to temporarily changes a single request environemnt value
+ """Decorator to temporarily changes a single request environemnt value
Create a new test app and use the a side effect of making a request
to set an extra_environ value. Reset the value to '' after the test.
@@ -541,26 +572,33 @@ def test_ckan_thing_affected_by_script_name(self):
:param value: the new extra_environ key's value, e.g. ``'/myscript'``
:type value: string
- '''
+ """
+
def decorator(func):
def wrapper(*args, **kwargs):
app = _get_test_app()
- app.get('/', extra_environ={key: value})
+ app.get("/", extra_environ={key: value})
try:
return_value = func(*args, **kwargs)
finally:
- app.get('/', extra_environ={key: ''})
+ app.get("/", extra_environ={key: ""})
return return_value
+
return nose.tools.make_decorator(func)(wrapper)
+
return decorator
@contextlib.contextmanager
-def recorded_logs(logger=None, level=logging.DEBUG,
- override_disabled=True, override_global_level=True):
- u'''
+def recorded_logs(
+ logger=None,
+ level=logging.DEBUG,
+ override_disabled=True,
+ override_global_level=True,
+):
+ u"""
Context manager for recording log messages.
:param logger: The logger to record messages from. Can either be a
@@ -600,7 +638,7 @@ def recorded_logs(logger=None, level=logging.DEBUG,
logger.info(u'Hello, world!')
logs.assert_log(u'info', u'world')
- '''
+ """
if logger is None:
logger = logging.getLogger()
elif not isinstance(logger, logging.Logger):
@@ -629,7 +667,7 @@ def recorded_logs(logger=None, level=logging.DEBUG,
class RecordingLogHandler(logging.Handler):
- u'''
+ u"""
Log handler that records log messages for later inspection.
You can inspect the recorded messages via the ``messages`` attribute
@@ -638,7 +676,8 @@ class RecordingLogHandler(logging.Handler):
This class is rarely useful on its own, instead use
:py:func:`recorded_logs` to temporarily record log messages.
- '''
+ """
+
def __init__(self, *args, **kwargs):
super(RecordingLogHandler, self).__init__(*args, **kwargs)
self.clear()
@@ -647,7 +686,7 @@ def emit(self, record):
self.messages[record.levelname.lower()].append(record.getMessage())
def assert_log(self, level, pattern, msg=None):
- u'''
+ u"""
Assert that a certain message has been logged.
:param string pattern: A regex which the message has to match.
@@ -659,24 +698,28 @@ def assert_log(self, level, pattern, msg=None):
log message was not logged.
:raises AssertionError: If the expected message was not logged.
- '''
+ """
compiled_pattern = re.compile(pattern)
for log_msg in self.messages[level]:
if compiled_pattern.search(log_msg):
return
if not msg:
if self.messages[level]:
- lines = u'\n '.join(self.messages[level])
- msg = (u'Pattern "{}" was not found in the log messages for '
- + u'level "{}":\n {}').format(pattern, level, lines)
+ lines = u"\n ".join(self.messages[level])
+ msg = (
+ u'Pattern "{}" was not found in the log messages for '
+ + u'level "{}":\n {}'
+ ).format(pattern, level, lines)
else:
- msg = (u'Pattern "{}" was not found in the log messages for '
- + u'level "{}" (no messages were recorded for that '
- + u'level).').format(pattern, level)
+ msg = (
+ u'Pattern "{}" was not found in the log messages for '
+ + u'level "{}" (no messages were recorded for that '
+ + u"level)."
+ ).format(pattern, level)
raise AssertionError(msg)
def clear(self):
- u'''
+ u"""
Clear all captured log messages.
- '''
+ """
self.messages = collections.defaultdict(list)
diff --git a/ckan/tests/i18n/test_check_po_files.py b/ckan/tests/i18n/test_check_po_files.py
index 5243aeeaecd..82d38046d5c 100644
--- a/ckan/tests/i18n/test_check_po_files.py
+++ b/ckan/tests/i18n/test_check_po_files.py
@@ -1,16 +1,13 @@
# encoding: utf-8
-import nose
-
-from ckan.i18n.check_po_files import (check_po_file,
- simple_conv_specs,
- mapping_keys,
- replacement_fields)
-
-eq_ = nose.tools.eq_
-
-
-PO_OK = '''
+from ckan.i18n.check_po_files import (
+ check_po_file,
+ simple_conv_specs,
+ mapping_keys,
+ replacement_fields,
+)
+
+PO_OK = """
#: ckan/lib/formatters.py:57
msgid "November"
msgstr "Noiembrie"
@@ -18,108 +15,107 @@
#: ckan/lib/formatters.py:61
msgid "December"
msgstr "Decembrie"
-'''
+"""
-PO_WRONG = '''
+PO_WRONG = """
#: ckan/templates/snippets/search_result_text.html:15
msgid "{number} dataset found for {query}"
msgstr "צביר נתונים אחד נמצא עבור {query}"
-'''
+"""
-PO_PLURALS_OK = '''
+PO_PLURALS_OK = """
#: ckan/lib/formatters.py:114
msgid "{hours} hour ago"
msgid_plural "{hours} hours ago"
msgstr[0] "Fa {hours} hora"
msgstr[1] "Fa {hours} hores"
-'''
+"""
-PO_WRONG_PLURALS = '''
+PO_WRONG_PLURALS = """
#: ckan/lib/formatters.py:114
msgid "{hours} hour ago"
msgid_plural "{hours} hours ago"
msgstr[0] "o oră în urmă"
msgstr[1] "cîteva ore în urmă"
msgstr[2] "{hours} ore în urmă"
-'''
-
-
-class TestCheckPoFiles(object):
-
- def test_basic(self):
-
- errors = check_po_file(PO_OK)
-
- eq_(errors, [])
-
- def test_wrong(self):
-
- errors = check_po_file(PO_WRONG)
-
- eq_(len(errors), 1)
-
- eq_(errors[0][0], '{number} dataset found for {query}')
-
- def test_plurals_ok(self):
-
- errors = check_po_file(PO_PLURALS_OK)
-
- eq_(errors, [])
-
- def test_wrong_plurals(self):
-
- errors = check_po_file(PO_WRONG_PLURALS)
-
- eq_(len(errors), 2)
-
- for error in errors:
- assert error[0] in ('{hours} hour ago', '{hours} hours ago')
-
-
-class TestValidators(object):
-
- def test_simple_conv_specs(self):
- eq_(simple_conv_specs("Authorization function not found: %s"),
- (['%s']))
- eq_(simple_conv_specs("Problem purging revision %s: %s"),
- (['%s', '%s']))
- eq_(simple_conv_specs("Cannot create new entity of this type: %s %s"),
- ['%s', '%s'])
- eq_(simple_conv_specs("Could not read parameters: %r"), ['%r'])
- eq_(simple_conv_specs("User %r not authorized to edit %r"),
- (['%r', '%r']))
- eq_(simple_conv_specs(
- "Please update your profile and add your email "
- "address and your full name. "
- "%s uses your email address if you need to reset your password."),
- (['%s', '%s']))
- eq_(simple_conv_specs("You can use %sMarkdown formatting%s here."),
- ['%s', '%s'])
- eq_(simple_conv_specs("Name must be a maximum of %i characters long"),
- ['%i'])
- eq_(simple_conv_specs("Blah blah %s blah %(key)s blah %i"),
- (['%s', '%i']))
-
- def test_replacement_fields(self):
- eq_(replacement_fields(
- "{actor} added the tag {object} to the dataset {target}"),
- (['{actor}', '{object}', '{target}']))
- eq_(replacement_fields("{actor} updated their profile"), ['{actor}'])
-
- def test_mapping_keys(self):
- eq_(mapping_keys(
- "You have requested your password on %(site_title)s to be reset.\n"
- "\n"
- "Please click the following link to confirm this request:\n"
- "\n"
- " %(reset_link)s\n"),
- ['%(reset_link)s', '%(site_title)s'])
- eq_(mapping_keys(
- "The input field %(name)s was not expected."),
- ['%(name)s'])
- eq_(mapping_keys(
- "[1:You searched for \"%(query)s\". ]%(number_of_results)s "
- "datasets found."),
- ['%(number_of_results)s', '%(query)s'])
- eq_(mapping_keys("Blah blah %s blah %(key)s blah %i"),
- (['%(key)s']), mapping_keys("Blah blah %s blah %(key)s blah %i"))
+"""
+
+
+def test_basic():
+ errors = check_po_file(PO_OK)
+ assert errors == []
+
+
+def test_wrong():
+ errors = check_po_file(PO_WRONG)
+ assert len(errors) == 1
+ assert errors[0][0] == "{number} dataset found for {query}"
+
+
+def test_plurals_ok():
+ errors = check_po_file(PO_PLURALS_OK)
+ assert errors == []
+
+
+def test_wrong_plurals():
+ errors = check_po_file(PO_WRONG_PLURALS)
+ assert len(errors) == 2
+
+ for error in errors:
+ assert error[0] in ("{hours} hour ago", "{hours} hours ago")
+
+
+def test_simple_conv_specs():
+ assert simple_conv_specs("Authorization function not found: %s") == (
+ ["%s"]
+ )
+ assert simple_conv_specs("Problem purging revision %s: %s") == (
+ ["%s", "%s"]
+ )
+ assert simple_conv_specs(
+ "Cannot create new entity of this type: %s %s"
+ ) == ["%s", "%s"]
+ assert simple_conv_specs("Could not read parameters: %r") == ["%r"]
+ assert simple_conv_specs("User %r not authorized to edit %r") == (
+ ["%r", "%r"]
+ )
+ assert simple_conv_specs(
+ 'Please update your profile and add your email '
+ "address and your full name. "
+ "%s uses your email address if you need to reset your password."
+ ) == (["%s", "%s"])
+ assert simple_conv_specs("You can use %sMarkdown formatting%s here.") == [
+ "%s",
+ "%s",
+ ]
+ assert simple_conv_specs(
+ "Name must be a maximum of %i characters long"
+ ) == ["%i"]
+ assert simple_conv_specs("Blah blah %s blah %(key)s blah %i") == (
+ ["%s", "%i"]
+ )
+
+
+def test_replacement_fields():
+ assert replacement_fields(
+ "{actor} added the tag {object} to the dataset {target}"
+ ) == (["{actor}", "{object}", "{target}"])
+ assert replacement_fields("{actor} updated their profile") == ["{actor}"]
+
+
+def test_mapping_keys():
+ assert mapping_keys(
+ "You have requested your password on %(site_title)s to be reset.\n"
+ "\n"
+ "Please click the following link to confirm this request:\n"
+ "\n"
+ " %(reset_link)s\n"
+ ) == ["%(reset_link)s", "%(site_title)s"]
+ assert mapping_keys("The input field %(name)s was not expected.") == [
+ "%(name)s"
+ ]
+ assert mapping_keys(
+ '[1:You searched for "%(query)s". ]%(number_of_results)s '
+ "datasets found."
+ ) == ["%(number_of_results)s", "%(query)s"]
+ assert mapping_keys("Blah blah %s blah %(key)s blah %i") == (["%(key)s"])
diff --git a/ckan/tests/legacy/__init__.py b/ckan/tests/legacy/__init__.py
index 4e8340db074..0da06b7d2af 100644
--- a/ckan/tests/legacy/__init__.py
+++ b/ckan/tests/legacy/__init__.py
@@ -35,42 +35,46 @@
# evil hack as url_for is passed out
url_for = h.url_for
-__all__ = ['url_for',
- 'TestController',
- 'CreateTestData',
- 'TestSearchIndexer',
- 'CheckMethods',
- 'CommonFixtureMethods',
- 'TestCase',
- 'SkipTest',
- 'CkanServerCase',
- 'call_action_api',
- 'BaseCase',
- 'here_dir',
- 'conf_dir',
- 'is_datastore_supported',
- ]
+__all__ = [
+ "url_for",
+ "TestController",
+ "CreateTestData",
+ "TestSearchIndexer",
+ "CheckMethods",
+ "CommonFixtureMethods",
+ "TestCase",
+ "SkipTest",
+ "CkanServerCase",
+ "call_action_api",
+ "BaseCase",
+ "here_dir",
+ "conf_dir",
+ "is_datastore_supported",
+]
here_dir = os.path.dirname(os.path.abspath(__file__))
conf_dir = os.path.dirname(os.path.dirname(here_dir))
# Invoke websetup with the current config file
-SetupCommand('setup-app').run([config['__file__']])
+# SetupCommand('setup-app').run([config['__file__']])
# monkey patch paste.fixtures.TestRespose
# webtest (successor library) already has this
# http://pythonpaste.org/webtest/#parsing-the-body
def _getjson(self):
return json.loads(self.body)
+
+
paste.fixture.TestResponse.json = property(_getjson)
# Check config is correct for sqlite
if model.engine_is_sqlite():
- assert ckan_nose_plugin.CkanNose.settings.is_ckan, \
- 'You forgot the "--ckan" nosetest setting - see doc/test.rst'
+ assert (
+ ckan_nose_plugin.CkanNose.settings.is_ckan
+ ), 'You forgot the "--ckan" nosetest setting - see doc/test.rst'
-class BaseCase(object):
+class BaseCase(object):
def setup(self):
pass
@@ -80,18 +84,18 @@ def teardown(self):
@staticmethod
def _system(cmd):
import commands
+
(status, output) = commands.getstatusoutput(cmd)
if status:
raise Exception("Couldn't execute cmd: %s: %s" % (cmd, output))
@classmethod
def _paster(cls, cmd, config_path_rel):
- config_path = os.path.join(config['here'], config_path_rel)
- cls._system('paster --plugin ckan %s --config=%s' % (cmd, config_path))
+ config_path = os.path.join(config["here"], config_path_rel)
+ cls._system("paster --plugin ckan %s --config=%s" % (cmd, config_path))
class CommonFixtureMethods(BaseCase):
-
@classmethod
def create_package(self, data={}, **kwds):
# Todo: A simpler method for just creating a package.
@@ -99,7 +103,7 @@ def create_package(self, data={}, **kwds):
@classmethod
def create_user(cls, **kwds):
- user = model.User(name=kwds['name'])
+ user = model.User(name=kwds["name"])
model.Session.add(user)
model.Session.commit()
model.Session.remove()
@@ -137,7 +141,9 @@ def purge_packages(cls, pkg_names):
@classmethod
def purge_all_packages(self):
- all_pkg_names = [pkg.name for pkg in model.Session.query(model.Package)]
+ all_pkg_names = [
+ pkg.name for pkg in model.Session.query(model.Package)
+ ]
self.purge_packages(all_pkg_names)
def purge_group_by_name(self, group_name):
@@ -148,42 +154,50 @@ def purge_group_by_name(self, group_name):
@classmethod
def clear_all_tst_ratings(self):
- ratings = model.Session.query(model.Rating).filter_by(package=model.Package.by_name(u'annakarenina')).all()
- ratings += model.Session.query(model.Rating).filter_by(package=model.Package.by_name(u'warandpeace')).all()
+ ratings = (
+ model.Session.query(model.Rating)
+ .filter_by(package=model.Package.by_name(u"annakarenina"))
+ .all()
+ )
+ ratings += (
+ model.Session.query(model.Rating)
+ .filter_by(package=model.Package.by_name(u"warandpeace"))
+ .all()
+ )
for rating in ratings[:]:
model.Session.delete(rating)
model.repo.commit_and_remove()
@property
def war(self):
- return self.get_package_by_name(u'warandpeace')
+ return self.get_package_by_name(u"warandpeace")
@property
def anna(self):
- return self.get_package_by_name(u'annakarenina')
+ return self.get_package_by_name(u"annakarenina")
@property
def roger(self):
- return self.get_group_by_name(u'roger')
+ return self.get_group_by_name(u"roger")
@property
def david(self):
- return self.get_group_by_name(u'david')
+ return self.get_group_by_name(u"david")
@property
def russian(self):
- return self.get_tag_by_name(u'russian')
+ return self.get_tag_by_name(u"russian")
@property
def tolstoy(self):
- return self.get_tag_by_name(u'tolstoy')
+ return self.get_tag_by_name(u"tolstoy")
@property
def flexible_tag(self):
- return self.get_tag_by_name(u'Flexible \u30a1')
+ return self.get_tag_by_name(u"Flexible \u30a1")
-class CheckMethods(BaseCase):
+class CheckMethods(BaseCase):
def assert_true(self, value):
assert value, "Not true: '%s'" % value
@@ -191,10 +205,12 @@ def assert_false(self, value):
assert not value, "Not false: '%s'" % value
def assert_equal(self, value1, value2):
- assert value1 == value2, 'Not equal: %s' % ((value1, value2),)
+ assert value1 == value2, "Not equal: %s" % ((value1, value2),)
def assert_isinstance(self, value, check):
- assert isinstance(value, check), 'Not an instance: %s' % ((value, check),)
+ assert isinstance(value, check), "Not an instance: %s" % (
+ (value, check),
+ )
def assert_raises(self, exception_class, callable, *args, **kwds):
try:
@@ -202,19 +218,34 @@ def assert_raises(self, exception_class, callable, *args, **kwds):
except exception_class:
pass
else:
- assert False, "Didn't raise '%s' when calling: %s with %s" % (exception_class, callable, (args, kwds))
+ assert False, "Didn't raise '%s' when calling: %s with %s" % (
+ exception_class,
+ callable,
+ (args, kwds),
+ )
def assert_contains(self, sequence, item):
- assert item in sequence, "Sequence %s does not contain item: %s" % (sequence, item)
+ assert item in sequence, "Sequence %s does not contain item: %s" % (
+ sequence,
+ item,
+ )
def assert_missing(self, sequence, item):
- assert item not in sequence, "Sequence %s does contain item: %s" % (sequence, item)
+ assert item not in sequence, "Sequence %s does contain item: %s" % (
+ sequence,
+ item,
+ )
def assert_len(self, sequence, count):
- assert len(sequence) == count, "Length of sequence %s was not %s." % (sequence, count)
+ assert len(sequence) == count, "Length of sequence %s was not %s." % (
+ sequence,
+ count,
+ )
def assert_isinstance(self, object, kind):
- assert isinstance(object, kind), "Object %s is not an instance of %s." % (object, kind)
+ assert isinstance(
+ object, kind
+ ), "Object %s is not an instance of %s." % (object, kind)
class TestCase(CommonFixtureMethods, CheckMethods, BaseCase):
@@ -228,8 +259,8 @@ def teardown(self):
class WsgiAppCase(BaseCase):
- wsgiapp = pylonsapp
- assert wsgiapp, 'You need to run nose with --with-pylons'
+ # wsgiapp = pylonsapp
+ # assert wsgiapp, 'You need to run nose with --with-pylons'
# Either that, or this file got imported somehow before the tests started
# running, meaning the pylonsapp wasn't setup yet (which is done in
# pylons.test.py:begin())
@@ -238,25 +269,27 @@ class WsgiAppCase(BaseCase):
def config_abspath(file_path):
- if os.path.isabs(file_path):
- return file_path
- return os.path.join(conf_dir, file_path)
+ if os.path.isabs(file_path):
+ return file_path
+ return os.path.join(conf_dir, file_path)
+
class CkanServerCase(BaseCase):
@classmethod
def _recreate_ckan_server_testdata(cls, config_path):
- cls._paster('db clean', config_path)
- cls._paster('db init', config_path)
- cls._paster('create-test-data', config_path)
- cls._paster('search-index rebuild', config_path)
+ cls._paster("db clean", config_path)
+ cls._paster("db init", config_path)
+ cls._paster("create-test-data", config_path)
+ cls._paster("search-index rebuild", config_path)
@staticmethod
def _start_ckan_server(config_file=None):
if not config_file:
- config_file = config['__file__']
+ config_file = config["__file__"]
config_path = config_abspath(config_file)
import subprocess
- process = subprocess.Popen(['paster', 'serve', config_path])
+
+ process = subprocess.Popen(["paster", "serve", config_path])
return process
@staticmethod
@@ -264,11 +297,14 @@ def _stop_ckan_server(process):
pid = process.pid
pid = int(pid)
if os.system("kill -9 %d" % pid):
- raise Exception("Can't kill foreign CKAN instance (pid: %d)." % pid)
-
+ raise Exception(
+ "Can't kill foreign CKAN instance (pid: %d)." % pid
+ )
-class TestController(CommonFixtureMethods, CkanServerCase, WsgiAppCase, BaseCase):
+class TestController(
+ CommonFixtureMethods, CkanServerCase, WsgiAppCase, BaseCase
+):
def assert_equal(self, *args, **kwds):
assert_equal(*args, **kwds)
@@ -280,20 +316,21 @@ def clear_language_setting(self):
class TestSearchIndexer:
- '''
+ """
Tests which use search can use this object to provide indexing
Usage:
self.tsi = TestSearchIndexer()
(create packages)
self.tsi.index()
(do searching)
- '''
+ """
def __init__(self):
from ckan import plugins
+
if not is_search_supported():
raise SkipTest("Search not supported")
- plugins.load('synchronous_search')
+ plugins.load("synchronous_search")
@classmethod
def index(cls):
@@ -301,45 +338,58 @@ def index(cls):
@classmethod
def list(cls):
- return [model.Package.get(pkg_index.package_id).name for pkg_index in model.Session.query(model.PackageSearch)]
+ return [
+ model.Package.get(pkg_index.package_id).name
+ for pkg_index in model.Session.query(model.PackageSearch)
+ ]
+
def setup_test_search_index():
- #from ckan import plugins
+ # from ckan import plugins
if not is_search_supported():
raise SkipTest("Search not supported")
search.clear_all()
- #plugins.load('synchronous_search')
+ # plugins.load('synchronous_search')
+
def is_search_supported():
is_supported_db = not model.engine_is_sqlite()
return is_supported_db
+
def are_foreign_keys_supported():
return not model.engine_is_sqlite()
+
def is_regex_supported():
is_supported_db = not model.engine_is_sqlite()
return is_supported_db
+
def is_migration_supported():
is_supported_db = not model.engine_is_sqlite()
return is_supported_db
+
def is_datastore_supported():
# we assume that the datastore uses the same db engine that ckan uses
is_supported_db = model.engine_is_pg()
return is_supported_db
+
def regex_related(test):
def skip_test(*args):
raise SkipTest("Regex not supported")
+
if not is_regex_supported():
return make_decorator(test)(skip_test)
return test
+
def clear_flash(res=None):
messages = h._flash.pop_messages()
+
class StatusCodes:
STATUS_200_OK = 200
STATUS_201_CREATED = 201
@@ -350,7 +400,7 @@ class StatusCodes:
def call_action_api(app, action, apikey=None, status=200, **kwargs):
- '''POST an HTTP request to the CKAN API and return the result.
+ """POST an HTTP request to the CKAN API and return the result.
Any additional keyword arguments that you pass to this function as **kwargs
are posted as params to the API.
@@ -396,16 +446,22 @@ def call_action_api(app, action, apikey=None, status=200, **kwargs):
:returns: the 'result' or 'error' dictionary from the CKAN API response
:rtype: dictionary
- '''
+ """
params = json.dumps(kwargs)
- response = app.post('/api/action/{0}'.format(action), params=params,
- extra_environ={'Authorization': str(apikey)}, status=status)
- assert '/api/3/action/help_show?name={0}'.format(action) \
- in response.json['help']
+ response = app.post(
+ "/api/action/{0}".format(action),
+ params=params,
+ extra_environ={"Authorization": str(apikey)},
+ status=status,
+ )
+ assert (
+ "/api/3/action/help_show?name={0}".format(action)
+ in response.json["help"]
+ )
if status in (200,):
- assert response.json['success'] is True
- return response.json['result']
+ assert response.json["success"] is True
+ return response.json["result"]
else:
- assert response.json['success'] is False
- return response.json['error']
+ assert response.json["success"] is False
+ return response.json["error"]
diff --git a/ckan/tests/legacy/ckantestplugins.py b/ckan/tests/legacy/ckantestplugins.py
index a2cc8fa2472..7380e649a63 100644
--- a/ckan/tests/legacy/ckantestplugins.py
+++ b/ckan/tests/legacy/ckantestplugins.py
@@ -12,17 +12,20 @@ class MapperPlugin(p.SingletonPlugin):
def __init__(self, *args, **kw):
self.calls = []
+ def _get_instance_name(self, instance):
+ return getattr(instance, "name", None)
+
def before_insert(self, mapper, conn, instance):
- self.calls.append(('before_insert', instance.name))
+ self.calls.append(("before_insert", self._get_instance_name(instance)))
def after_insert(self, mapper, conn, instance):
- self.calls.append(('after_insert', instance.name))
+ self.calls.append(("after_insert", self._get_instance_name(instance)))
def before_delete(self, mapper, conn, instance):
- self.calls.append(('before_delete', instance.name))
+ self.calls.append(("before_delete", self._get_instance_name(instance)))
def after_delete(self, mapper, conn, instance):
- self.calls.append(('after_delete', instance.name))
+ self.calls.append(("after_delete", self._get_instance_name(instance)))
class MapperPlugin2(MapperPlugin):
@@ -42,6 +45,7 @@ def before_insert(self, mapper, conn, instance):
def before_delete(self, mapper, conn, instance):
self.deleted.append(instance)
+
class RoutesPlugin(p.SingletonPlugin):
p.implements(p.IRoutes, inherit=True)
@@ -49,28 +53,31 @@ def __init__(self, *args, **kw):
self.calls_made = []
def before_map(self, map):
- self.calls_made.append('before_map')
+ self.calls_made.append("before_map")
return map
def after_map(self, map):
- self.calls_made.append('after_map')
+ self.calls_made.append("after_map")
return map
class PluginObserverPlugin(mock_plugin.MockSingletonPlugin):
p.implements(p.IPluginObserver)
+
class ActionPlugin(p.SingletonPlugin):
p.implements(p.IActions)
def get_actions(self):
- return {'status_show': lambda context, data_dict: {}}
+ return {"status_show": lambda context, data_dict: {}}
+
class AuthPlugin(p.SingletonPlugin):
p.implements(p.IAuthFunctions)
def get_auth_functions(self):
- return {'package_list': lambda context, data_dict: {}}
+ return {"package_list": lambda context, data_dict: {}}
+
class MockGroupControllerPlugin(p.SingletonPlugin):
p.implements(p.IGroupController)
@@ -79,19 +86,19 @@ def __init__(self, *args, **kw):
self.calls = defaultdict(int)
def read(self, entity):
- self.calls['read'] += 1
+ self.calls["read"] += 1
def create(self, entity):
- self.calls['create'] += 1
+ self.calls["create"] += 1
def edit(self, entity):
- self.calls['edit'] += 1
+ self.calls["edit"] += 1
def delete(self, entity):
- self.calls['delete'] += 1
+ self.calls["delete"] += 1
def before_view(self, data_dict):
- self.calls['before_view'] += 1
+ self.calls["before_view"] += 1
return data_dict
@@ -102,56 +109,55 @@ def __init__(self, *args, **kw):
self.calls = defaultdict(int)
def read(self, entity):
- self.calls['read'] += 1
+ self.calls["read"] += 1
def create(self, entity):
- self.calls['create'] += 1
+ self.calls["create"] += 1
def edit(self, entity):
- self.calls['edit'] += 1
+ self.calls["edit"] += 1
def delete(self, entity):
- self.calls['delete'] += 1
+ self.calls["delete"] += 1
def before_search(self, search_params):
- self.calls['before_search'] += 1
+ self.calls["before_search"] += 1
return search_params
def after_search(self, search_results, search_params):
- self.calls['after_search'] += 1
+ self.calls["after_search"] += 1
return search_results
def before_index(self, data_dict):
- self.calls['before_index'] += 1
+ self.calls["before_index"] += 1
return data_dict
def before_view(self, data_dict):
- self.calls['before_view'] += 1
+ self.calls["before_view"] += 1
return data_dict
def after_create(self, context, data_dict):
- self.calls['after_create'] += 1
- self.id_in_dict = 'id' in data_dict
+ self.calls["after_create"] += 1
+ self.id_in_dict = "id" in data_dict
return data_dict
def after_update(self, context, data_dict):
- self.calls['after_update'] += 1
+ self.calls["after_update"] += 1
return data_dict
def after_delete(self, context, data_dict):
- self.calls['after_delete'] += 1
+ self.calls["after_delete"] += 1
return data_dict
def after_show(self, context, data_dict):
- self.calls['after_show'] += 1
+ self.calls["after_show"] += 1
return data_dict
def update_facet_titles(self, facet_titles):
return facet_titles
-
class MockResourcePreviewExtension(mock_plugin.MockSingletonPlugin):
p.implements(p.IResourcePreview)
@@ -159,22 +165,22 @@ def __init__(self, *args, **kw):
self.calls = defaultdict(int)
def setup_template_variables(self, context, data_dict):
- self.calls['setup_template_variables'] += 1
+ self.calls["setup_template_variables"] += 1
def can_preview(self, data_dict):
- assert(isinstance(data_dict['resource'], dict))
- assert(isinstance(data_dict['package'], dict))
- assert('on_same_domain' in data_dict['resource'])
+ assert isinstance(data_dict["resource"], dict)
+ assert isinstance(data_dict["package"], dict)
+ assert "on_same_domain" in data_dict["resource"]
- self.calls['can_preview'] += 1
- return data_dict['resource']['format'].lower() == 'mock'
+ self.calls["can_preview"] += 1
+ return data_dict["resource"]["format"].lower() == "mock"
def preview_template(self, context, data_dict):
- assert(isinstance(data_dict['resource'], dict))
- assert(isinstance(data_dict['package'], dict))
+ assert isinstance(data_dict["resource"], dict)
+ assert isinstance(data_dict["package"], dict)
- self.calls['preview_templates'] += 1
- return 'tests/mock_resource_preview_template.html'
+ self.calls["preview_templates"] += 1
+ return "tests/mock_resource_preview_template.html"
class JsonMockResourcePreviewExtension(mock_plugin.MockSingletonPlugin):
@@ -184,17 +190,17 @@ def __init__(self, *args, **kw):
self.calls = defaultdict(int)
def setup_template_variables(self, context, data_dict):
- self.calls['setup_template_variables'] += 1
+ self.calls["setup_template_variables"] += 1
def can_preview(self, data_dict):
- self.calls['can_preview'] += 1
- return data_dict['resource']['format'].lower() == 'json'
+ self.calls["can_preview"] += 1
+ return data_dict["resource"]["format"].lower() == "json"
def preview_template(self, context, data_dict):
- self.calls['preview_templates'] += 1
- return 'tests/mock_json_resource_preview_template.html'
+ self.calls["preview_templates"] += 1
+ return "tests/mock_json_resource_preview_template.html"
# importing this file loads all these extensions by default
# so clean up the extensions
-p.plugins_update()
+# p.plugins_update()
diff --git a/ckan/tests/legacy/functional/api/__init__.py b/ckan/tests/legacy/functional/api/__init__.py
index d0a6e636d32..0589c3ffce0 100644
--- a/ckan/tests/legacy/functional/api/__init__.py
+++ b/ckan/tests/legacy/functional/api/__init__.py
@@ -1,18 +1,17 @@
# encoding: utf-8
-from nose.tools import assert_equal
import copy
def change_lists_to_sets(iterable):
- '''Convert any lists or tuples in `iterable` into sets.
+ """Convert any lists or tuples in `iterable` into sets.
Recursively drill down into iterable and convert any list or tuples to
sets.
Does not work for dictionaries in lists.
- '''
+ """
if isinstance(iterable, dict):
for key in iterable:
if isinstance(iterable[key], (list, tuple)):
@@ -21,26 +20,26 @@ def change_lists_to_sets(iterable):
except TypeError:
# e.g. unhashable
pass
- elif getattr(iterable[key], '__iter__', False):
+ elif getattr(iterable[key], "__iter__", False):
change_lists_to_sets(iterable[key])
elif isinstance(iterable, (list, tuple)):
for item in iterable:
if isinstance(item, (list, tuple)):
iterable.pop(item)
iterable.append(set(item))
- elif getattr(item, '__iter__', False):
+ elif getattr(item, "__iter__", False):
change_lists_to_sets(item)
else:
raise NotImplementedError
def assert_dicts_equal_ignoring_ordering(dict1, dict2):
- '''Assert that dict1 and dict2 are equal.
+ """Assert that dict1 and dict2 are equal.
Assumes that the ordering of any lists in the dicts is unimportant.
- '''
+ """
dicts = [copy.deepcopy(dict1), copy.deepcopy(dict2)]
for d in dicts:
d = change_lists_to_sets(d)
- assert_equal(dicts[0], dicts[1])
+ assert dicts[0] == dicts[1]
diff --git a/ckan/tests/legacy/functional/api/base.py b/ckan/tests/legacy/functional/api/base.py
index 287750cad78..e853d36beb2 100644
--- a/ckan/tests/legacy/functional/api/base.py
+++ b/ckan/tests/legacy/functional/api/base.py
@@ -1,6 +1,5 @@
# encoding: utf-8
-from nose.tools import assert_equal
from paste.fixture import TestRequest
from six.moves.urllib.parse import quote
@@ -13,6 +12,7 @@
ACCESS_DENIED = [403]
+
class ApiTestCase(object):
STATUS_200_OK = 200
@@ -27,12 +27,13 @@ class ApiTestCase(object):
api_version = None
- ref_package_by = ''
- ref_group_by = ''
+ ref_package_by = ""
+ ref_group_by = ""
def get(self, offset, status=[200]):
- response = self.app.get(offset, status=status,
- extra_environ=self.get_extra_environ())
+ response = self.app.get(
+ offset, status=status, extra_environ=self.get_extra_environ()
+ )
return response
def post(self, offset, data, status=[200,201], *args, **kwds):
@@ -43,15 +44,16 @@ def post(self, offset, data, status=[200,201], *args, **kwds):
extra_environ=self.get_extra_environ())
return response
- def app_delete(self, offset, status=[200,201], *args, **kwds):
- response = self.app.delete(offset, status=status,
- extra_environ=self.get_extra_environ())
+ def app_delete(self, offset, status=[200, 201], *args, **kwds):
+ response = self.app.delete(
+ offset, status=status, extra_environ=self.get_extra_environ()
+ )
return response
def get_extra_environ(self):
extra_environ = {}
- for (key,value) in self.extra_environ.items():
- if key == 'Authorization':
+ for (key, value) in self.extra_environ.items():
+ if key == "Authorization":
if self.send_authorization_header == True:
extra_environ[key] = value
else:
@@ -74,65 +76,80 @@ def offset(self, path):
[1] http://www.w3.org/International/articles/idn-and-iri/
"""
assert self.api_version != None, "API version is missing."
- base = '/api'
+ base = "/api"
if self.api_version:
- base += '/%s' % self.api_version
- utf8_encoded = (u'%s%s' % (base, path)).encode('utf8')
+ base += "/%s" % self.api_version
+ utf8_encoded = (u"%s%s" % (base, path)).encode("utf8")
url_encoded = quote(utf8_encoded)
return url_encoded
def assert_msg_represents_anna(self, msg):
- assert 'annakarenina' in msg, msg
+ assert "annakarenina" in msg, msg
data = self.loads(msg)
- self.assert_equal(data['name'], 'annakarenina')
- self.assert_equal(data['license_id'], 'other-open')
+ assert data["name"] == "annakarenina"
+ assert data["license_id"] == "other-open"
assert '"license_id": "other-open"' in msg, str(msg)
- assert 'russian' in msg, msg
- assert 'tolstoy' in msg, msg
+ assert "russian" in msg, msg
+ assert "tolstoy" in msg, msg
assert '"extras": {' in msg, msg
assert '"genre": "romantic novel"' in msg, msg
assert '"original media": "book"' in msg, msg
- assert 'datahub.io/download' in msg, msg
+ assert "datahub.io/download" in msg, msg
assert '"plain text"' in msg, msg
assert '"Index of the novel"' in msg, msg
assert '"id": "%s"' % self.anna.id in msg, msg
expected = '"groups": ['
assert expected in msg, (expected, msg)
- expected = self.group_ref_from_name('roger')
+ expected = self.group_ref_from_name("roger")
assert expected in msg, (expected, msg)
- expected = self.group_ref_from_name('david')
+ expected = self.group_ref_from_name("david")
assert expected in msg, (expected, msg)
# Todo: What is the deal with ckan_url? And should this use IDs rather than names?
- assert 'ckan_url' in msg
- assert '"ckan_url": "http://test.ckan.net/dataset/annakarenina"' in msg, msg
+ assert "ckan_url" in msg
+ assert (
+ '"ckan_url": "http://test.ckan.net/dataset/annakarenina"' in msg
+ ), msg
- assert 'tags' in data, "Expected a tags list in json payload"
- assert self.russian.name in data['tags'], data['tags']
- assert self.tolstoy.name in data['tags'], data['tags']
- assert self.flexible_tag.name in data['tags'], data['tags']
+ assert "tags" in data, "Expected a tags list in json payload"
+ assert self.russian.name in data["tags"], data["tags"]
+ assert self.tolstoy.name in data["tags"], data["tags"]
+ assert self.flexible_tag.name in data["tags"], data["tags"]
def assert_msg_represents_roger(self, msg):
- assert 'roger' in msg, msg
+ assert "roger" in msg, msg
data = self.loads(msg)
keys = set(data.keys())
- expected_keys = set(['id', 'name', 'title', 'description', 'created',
- 'state', 'packages'])
+ expected_keys = set(
+ [
+ "id",
+ "name",
+ "title",
+ "description",
+ "created",
+ "state",
+ "packages",
+ ]
+ )
missing_keys = expected_keys - keys
assert not missing_keys, missing_keys
- assert_equal(data['name'], 'roger')
- assert_equal(data['title'], 'Roger\'s books')
- assert_equal(data['description'], 'Roger likes these books.')
- assert_equal(data['state'], 'active')
- assert_equal(data['packages'], [self._ref_package(self.anna)])
+ assert data["name"] == "roger"
+ assert data["title"] == "Roger's books"
+ assert data["description"] == "Roger likes these books."
+ assert data["state"] == "active"
+ assert data["packages"] == [self._ref_package(self.anna)]
def assert_msg_represents_russian(self, msg):
data = self.loads(msg)
pkgs = set(data)
- expected_pkgs = set([self.package_ref_from_name('annakarenina'),
- self.package_ref_from_name('warandpeace')])
+ expected_pkgs = set(
+ [
+ self.package_ref_from_name("annakarenina"),
+ self.package_ref_from_name("warandpeace"),
+ ]
+ )
differences = expected_pkgs ^ pkgs
- assert not differences, '%r != %r' % (pkgs, expected_pkgs)
+ assert not differences, "%r != %r" % (pkgs, expected_pkgs)
def assert_msg_represents_flexible_tag(self, msg):
"""
@@ -142,10 +159,14 @@ def assert_msg_represents_flexible_tag(self, msg):
"""
data = self.loads(msg)
pkgs = set(data)
- expected_pkgs = set([self.package_ref_from_name('annakarenina'),
- self.package_ref_from_name('warandpeace')])
+ expected_pkgs = set(
+ [
+ self.package_ref_from_name("annakarenina"),
+ self.package_ref_from_name("warandpeace"),
+ ]
+ )
differences = expected_pkgs ^ pkgs
- assert not differences, '%r != %r' % (pkgs, expected_pkgs)
+ assert not differences, "%r != %r" % (pkgs, expected_pkgs)
def data_from_res(self, res):
return self.loads(res.body)
@@ -165,7 +186,7 @@ def package_id_from_ref(self, package_name):
return self.ref_package(package)
def ref_package(self, package):
- assert self.ref_package_by in ['id', 'name']
+ assert self.ref_package_by in ["id", "name"]
return getattr(package, self.ref_package_by)
def get_expected_api_version(self):
@@ -181,73 +202,72 @@ def loads(self, chars):
raise Exception("Couldn't loads string '%s': %s" % (chars, inst))
def assert_json_response(self, res, expected_in_body=None):
- content_type = res.headers.get('Content-Type')
- assert 'application/json' in content_type, content_type
+ content_type = res.headers.get("Content-Type")
+ assert "application/json" in content_type, content_type
res_json = self.loads(res.body)
if expected_in_body:
- assert expected_in_body in res_json or \
- expected_in_body in str(res_json), \
- 'Expected to find %r in JSON response %r' % \
- (expected_in_body, res_json)
+ assert expected_in_body in res_json or expected_in_body in str(
+ res_json
+ ), (
+ "Expected to find %r in JSON response %r"
+ % (expected_in_body, res_json)
+ )
class Api3TestCase(ApiTestCase):
api_version = 3
- ref_package_by = 'name'
- ref_group_by = 'name'
- ref_tag_by = 'name'
+ ref_package_by = "name"
+ ref_group_by = "name"
+ ref_tag_by = "name"
def assert_msg_represents_anna(self, msg):
super(ApiTestCase, self).assert_msg_represents_anna(msg)
- assert 'download_url' not in msg, msg
+ assert "download_url" not in msg, msg
class BaseModelApiTestCase(ApiTestCase, ControllerTestCase):
- testpackage_license_id = u'gpl-3.0'
+ testpackage_license_id = u"gpl-3.0"
package_fixture_data = {
- 'name':
- u'testpkg',
- 'title':
- u'Some Title',
- 'url':
- u'http://blahblahblah.mydomain',
- 'resources': [{
- u'url': u'http://blah.com/file.xml',
- u'format': u'XML',
- u'description': u'Main file',
- u'hash': u'abc123',
- u'alt_url': u'alt_url',
- u'size_extra': u'200',
- }, {
- u'url': u'http://blah.com/file2.xml',
- u'format': u'XML',
- u'description': u'Second file',
- u'hash': u'def123',
- u'alt_url': u'alt_url',
- u'size_extra': u'200',
- }],
- 'tags': [u'russion', u'novel'],
- 'license_id':
- testpackage_license_id,
- 'extras': {
- 'genre': u'horror',
- 'media': u'dvd',
- },
+ "name": u"testpkg",
+ "title": u"Some Title",
+ "url": u"http://blahblahblah.mydomain",
+ "resources": [
+ {
+ u"url": u"http://blah.com/file.xml",
+ u"format": u"XML",
+ u"description": u"Main file",
+ u"hash": u"abc123",
+ u"alt_url": u"alt_url",
+ u"size_extra": u"200",
+ },
+ {
+ u"url": u"http://blah.com/file2.xml",
+ u"format": u"XML",
+ u"description": u"Second file",
+ u"hash": u"def123",
+ u"alt_url": u"alt_url",
+ u"size_extra": u"200",
+ },
+ ],
+ "tags": [u"russion", u"novel"],
+ "license_id": testpackage_license_id,
+ "extras": {"genre": u"horror", "media": u"dvd"},
}
testgroupvalues = {
- 'name' : u'testgroup',
- 'title' : u'Some Group Title',
- 'description' : u'Great group!',
- 'packages' : [u'annakarenina', u'warandpeace'],
+ "name": u"testgroup",
+ "title": u"Some Group Title",
+ "description": u"Great group!",
+ "packages": [u"annakarenina", u"warandpeace"],
}
- user_name = u'myrandom'
+ user_name = u"myrandom"
def setup(self):
super(BaseModelApiTestCase, self).setup()
-# self.conditional_create_common_fixtures()
-# self.init_extra_environ()
+
+ # self.conditional_create_common_fixtures()
+ # self.init_extra_environ()
def teardown(self):
model.Session.remove()
@@ -260,51 +280,64 @@ def init_extra_environ(cls, user_name):
# called elsewhere in this class are run with the specified
# user logged in.
cls.user = model.User.by_name(user_name)
- cls.extra_environ={'Authorization' : str(cls.user.apikey)}
- cls.adminuser = model.User.by_name('testsysadmin')
- cls.admin_extra_environ={'Authorization' : str(cls.adminuser.apikey)}
+ cls.extra_environ = {"Authorization": str(cls.user.apikey)}
+ cls.adminuser = model.User.by_name("testsysadmin")
+ cls.admin_extra_environ = {"Authorization": str(cls.adminuser.apikey)}
def post_json(self, offset, data, status=None, extra_environ=None):
- ''' Posts data in the body in application/json format, used by
+ """ Posts data in the body in application/json format, used by
javascript libraries.
(rather than Paste Fixture\'s default format of
application/x-www-form-urlencoded)
- '''
- return self.http_request(offset, data, content_type='application/json',
- request_method='POST',
- content_length=len(data),
- status=status, extra_environ=extra_environ)
+ """
+ return self.http_request(
+ offset,
+ data,
+ content_type="application/json",
+ request_method="POST",
+ content_length=len(data),
+ status=status,
+ extra_environ=extra_environ,
+ )
def delete_request(self, offset, status=None, extra_environ=None):
- ''' Sends a delete request. Similar to the paste.delete but it
+ """ Sends a delete request. Similar to the paste.delete but it
does not send the content type or content length.
- '''
- return self.http_request(offset, data='', content_type=None,
- request_method='DELETE',
- content_length=None,
- status=status,
- extra_environ=extra_environ)
-
- def http_request(self, offset, data,
- content_type='application/json',
- request_method='POST',
- content_length=None,
- status=None,
- extra_environ=None):
- ''' Posts data in the body in a user-specified format.
+ """
+ return self.http_request(
+ offset,
+ data="",
+ content_type=None,
+ request_method="DELETE",
+ content_length=None,
+ status=status,
+ extra_environ=extra_environ,
+ )
+
+ def http_request(
+ self,
+ offset,
+ data,
+ content_type="application/json",
+ request_method="POST",
+ content_length=None,
+ status=None,
+ extra_environ=None,
+ ):
+ """ Posts data in the body in a user-specified format.
(rather than Paste Fixture\'s default Content-Type of
application/x-www-form-urlencoded)
- '''
+ """
environ = self.app._make_environ()
if content_type:
- environ['CONTENT_TYPE'] = content_type
+ environ["CONTENT_TYPE"] = content_type
if content_length is not None:
- environ['CONTENT_LENGTH'] = str(content_length)
- environ['REQUEST_METHOD'] = request_method
- environ['QUERY_STRING'] = '' # avoids a warning
- environ['wsgi.input'] = StringIO(data)
+ environ["CONTENT_LENGTH"] = str(content_length)
+ environ["REQUEST_METHOD"] = request_method
+ environ["QUERY_STRING"] = "" # avoids a warning
+ environ["wsgi.input"] = StringIO(data)
if extra_environ:
environ.update(extra_environ)
self.app._set_headers({}, environ)
@@ -312,6 +345,6 @@ def http_request(self, offset, data,
return self.app.do_request(req, status=status)
def set_env(self, extra_environ):
- ''' used to reset env when admin has been forced etc '''
+ """ used to reset env when admin has been forced etc """
environ = self.app._make_environ()
environ.update(extra_environ)
diff --git a/ckan/tests/legacy/functional/api/model/test_group.py b/ckan/tests/legacy/functional/api/model/test_group.py
index 689b58dabfd..0bc6dd9900f 100644
--- a/ckan/tests/legacy/functional/api/model/test_group.py
+++ b/ckan/tests/legacy/functional/api/model/test_group.py
@@ -6,18 +6,16 @@
from ckan.lib.create_test_data import CreateTestData
from ckan.lib import search
-from nose.tools import assert_equal
from ckan.tests.legacy.functional.api.base import BaseModelApiTestCase
class GroupsTestCase(BaseModelApiTestCase):
-
@classmethod
def setup_class(cls):
search.clear_all()
CreateTestData.create()
- cls.user_name = u'russianfan' # created in CreateTestData
+ cls.user_name = u"russianfan" # created in CreateTestData
cls.init_extra_environ(cls.user_name)
@classmethod
@@ -25,7 +23,7 @@ def teardown_class(cls):
model.repo.rebuild_db()
def teardown(self):
- self.purge_group_by_name(self.testgroupvalues['name'])
+ self.purge_group_by_name(self.testgroupvalues["name"])
def test_register_get_ok(self):
offset = self.group_offset()
@@ -35,21 +33,30 @@ def test_register_get_ok(self):
def test_register_post_ok(self):
data = self.testgroupvalues
- postparams = '%s=1' % self.dumps(data)
+ postparams = "%s=1" % self.dumps(data)
offset = self.group_offset()
- res = self.app.post(offset, params=postparams,
- status=self.STATUS_201_CREATED,
- extra_environ=self.extra_environ)
+ res = self.app.post(
+ offset,
+ params=postparams,
+ status=self.STATUS_201_CREATED,
+ extra_environ=self.extra_environ,
+ )
# check group object
- group = self.get_group_by_name(self.testgroupvalues['name'])
+ group = self.get_group_by_name(self.testgroupvalues["name"])
assert group
- assert group.title == self.testgroupvalues['title'], group
- assert group.description == self.testgroupvalues['description'], group
+ assert group.title == self.testgroupvalues["title"], group
+ assert group.description == self.testgroupvalues["description"], group
pkg_ids = [member.table_id for member in group.member_all]
- pkgs = model.Session.query(model.Package).filter(model.Package.id.in_(pkg_ids)).all()
+ pkgs = (
+ model.Session.query(model.Package)
+ .filter(model.Package.id.in_(pkg_ids))
+ .all()
+ )
pkg_names = [pkg.name for pkg in pkgs]
- assert set(pkg_names) == set(('annakarenina', 'warandpeace')), pkg_names
+ assert set(pkg_names) == set(
+ ("annakarenina", "warandpeace")
+ ), pkg_names
# check register updated
res = self.app.get(offset, status=self.STATUS_200_OK)
@@ -58,32 +65,36 @@ def test_register_post_ok(self):
assert self._ref_group(group) in data, data
# check entity
- offset = self.group_offset(self.testgroupvalues['name'])
+ offset = self.group_offset(self.testgroupvalues["name"])
res = self.app.get(offset, status=self.STATUS_200_OK)
group = self.loads(res.body)
expected_group = copy.deepcopy(self.testgroupvalues)
- expected_group['packages'] = \
- sorted(self.ref_package(self.get_package_by_name(pkg_name))
- for pkg_name in expected_group['packages'])
+ expected_group["packages"] = sorted(
+ self.ref_package(self.get_package_by_name(pkg_name))
+ for pkg_name in expected_group["packages"]
+ )
for expected_key, expected_value in expected_group.items():
- assert_equal(group.get(expected_key), expected_value)
+ assert group.get(expected_key) == expected_value
# Test Group Register Post 409 (conflict - create duplicate group).
offset = self.group_offset()
- postparams = '%s=1' % self.dumps(self.testgroupvalues)
- res = self.app.post(offset, params=postparams,
- status=self.STATUS_409_CONFLICT,
- extra_environ=self.extra_environ)
- self.assert_json_response(res, 'Group name already exists')
+ postparams = "%s=1" % self.dumps(self.testgroupvalues)
+ res = self.app.post(
+ offset,
+ params=postparams,
+ status=self.STATUS_409_CONFLICT,
+ extra_environ=self.extra_environ,
+ )
+ self.assert_json_response(res, "Group name already exists")
def test_entity_get_ok(self):
offset = self.group_offset(self.roger.name)
res = self.app.get(offset, status=self.STATUS_200_OK)
self.assert_msg_represents_roger(msg=res.body)
- assert self.package_ref_from_name('annakarenina') in res, res
- assert self.group_ref_from_name('roger') in res, res
- assert not self.package_ref_from_name('warandpeace') in res, res
+ assert self.package_ref_from_name("annakarenina") in res, res
+ assert self.group_ref_from_name("roger") in res, res
+ assert not self.package_ref_from_name("warandpeace") in res, res
def test_entity_get_then_post(self):
# (ticket 662) Ensure an entity you 'get' from a register can be
@@ -91,26 +102,29 @@ def test_entity_get_then_post(self):
offset = self.group_offset(self.david.name)
res = self.app.get(offset, status=self.STATUS_200_OK)
data = self.loads(res.body)
- postparams = '%s=1' % self.dumps(data)
- res = self.app.post(offset, params=postparams,
- status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
+ postparams = "%s=1" % self.dumps(data)
+ res = self.app.post(
+ offset,
+ params=postparams,
+ status=self.STATUS_200_OK,
+ extra_environ=self.admin_extra_environ,
+ )
res = self.set_env(self.extra_environ)
def test_10_edit_group_name_duplicate(self):
# create a group with testgroupvalues
- if not model.Group.by_name(self.testgroupvalues['name']):
+ if not model.Group.by_name(self.testgroupvalues["name"]):
group = model.Group()
model.Session.add(group)
- group.name = self.testgroupvalues['name']
+ group.name = self.testgroupvalues["name"]
model.Session.commit()
- group = model.Group.by_name(self.testgroupvalues['name'])
+ group = model.Group.by_name(self.testgroupvalues["name"])
model.repo.commit_and_remove()
- assert model.Group.by_name(self.testgroupvalues['name'])
+ assert model.Group.by_name(self.testgroupvalues["name"])
# create a group with name 'dupname'
- dupname = u'dupname'
+ dupname = u"dupname"
if not model.Group.by_name(dupname):
group = model.Group()
model.Session.add(group)
@@ -119,61 +133,76 @@ def test_10_edit_group_name_duplicate(self):
assert model.Group.by_name(dupname)
# edit first group to have dupname
- group_vals = {'name':dupname}
- offset = self.group_offset(self.testgroupvalues['name'])
- postparams = '%s=1' % self.dumps(group_vals)
- res = self.app.post(offset, params=postparams, status=[409],
- extra_environ=self.admin_extra_environ)
- self.assert_json_response(res, 'Group name already exists')
+ group_vals = {"name": dupname}
+ offset = self.group_offset(self.testgroupvalues["name"])
+ postparams = "%s=1" % self.dumps(group_vals)
+ res = self.app.post(
+ offset,
+ params=postparams,
+ status=[409],
+ extra_environ=self.admin_extra_environ,
+ )
+ self.assert_json_response(res, "Group name already exists")
res = self.set_env(self.extra_environ)
def test_11_delete_group(self):
# Test Groups Entity Delete 200.
# create a group with testgroupvalues
- group = model.Group.by_name(self.testgroupvalues['name'])
+ group = model.Group.by_name(self.testgroupvalues["name"])
if not group:
group = model.Group()
model.Session.add(group)
- group.name = self.testgroupvalues['name']
+ group.name = self.testgroupvalues["name"]
model.repo.commit_and_remove()
- group = model.Group.by_name(self.testgroupvalues['name'])
+ group = model.Group.by_name(self.testgroupvalues["name"])
model.repo.commit_and_remove()
assert group
user = model.User.by_name(self.user_name)
# delete it
- offset = self.group_offset(self.testgroupvalues['name'])
- res = self.app.delete(offset, status=[200],
- extra_environ=self.admin_extra_environ)
+ offset = self.group_offset(self.testgroupvalues["name"])
+ res = self.app.delete(
+ offset, status=[200], extra_environ=self.admin_extra_environ
+ )
res = self.set_env(self.extra_environ)
- group = model.Group.by_name(self.testgroupvalues['name'])
+ group = model.Group.by_name(self.testgroupvalues["name"])
assert group
- assert group.state == 'deleted', group.state
+ assert group.state == "deleted", group.state
# Anyone can see groups especially sysadmins
# maybe we want to do something different with
# deleted groups but that would be a new requirement
- #res = self.app.get(offset, status=[403])
- #self.assert_json_response(res, 'Access denied')
- res = self.app.get(offset, status=[200],
- extra_environ=self.admin_extra_environ)
+ # res = self.app.get(offset, status=[403])
+ # self.assert_json_response(res, 'Access denied')
+ res = self.app.get(
+ offset, status=[200], extra_environ=self.admin_extra_environ
+ )
res = self.set_env(self.extra_environ)
def test_12_get_group_404(self):
# Test Package Entity Get 404.
- assert not model.Session.query(model.Group).filter_by(name=self.testgroupvalues['name']).count()
- offset = self.group_offset(self.testgroupvalues['name'])
+ assert (
+ not model.Session.query(model.Group)
+ .filter_by(name=self.testgroupvalues["name"])
+ .count()
+ )
+ offset = self.group_offset(self.testgroupvalues["name"])
res = self.app.get(offset, status=404)
- self.assert_json_response(res, 'Not found')
+ self.assert_json_response(res, "Not found")
def test_13_delete_group_404(self):
# Test Packages Entity Delete 404.
- assert not model.Session.query(model.Group).filter_by(name=self.testgroupvalues['name']).count()
- offset = self.group_offset(self.testgroupvalues['name'])
- res = self.app.delete(offset, status=[404],
- extra_environ=self.extra_environ)
- self.assert_json_response(res, 'not found')
+ assert (
+ not model.Session.query(model.Group)
+ .filter_by(name=self.testgroupvalues["name"])
+ .count()
+ )
+ offset = self.group_offset(self.testgroupvalues["name"])
+ res = self.app.delete(
+ offset, status=[404], extra_environ=self.extra_environ
+ )
+ self.assert_json_response(res, "not found")
diff --git a/ckan/tests/legacy/functional/api/model/test_package.py b/ckan/tests/legacy/functional/api/model/test_package.py
deleted file mode 100644
index 27e3064a757..00000000000
--- a/ckan/tests/legacy/functional/api/model/test_package.py
+++ /dev/null
@@ -1,564 +0,0 @@
-# encoding: utf-8
-
-from __future__ import print_function
-
-import copy
-
-from nose.tools import assert_equal, assert_raises
-
-from ckan.lib.create_test_data import CreateTestData
-import ckan.lib.search as search
-from ckan.lib.search.common import SolrSettings
-
-from ckan.tests.legacy.functional.api.base import BaseModelApiTestCase
-
-import ckan.tests.legacy as tests
-
-# Todo: Remove this ckan.model stuff.
-import ckan.model as model
-
-class PackagesTestCase(BaseModelApiTestCase):
-
- @classmethod
- def setup_class(cls):
- CreateTestData.create()
- cls.user_name = u'annafan' # created in CreateTestData
- cls.init_extra_environ(cls.user_name)
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
-
- def teardown(self):
- self.purge_package_by_name(self.package_fixture_data['name'])
-
- def get_groups_identifiers(self, test_groups, users=[]):
- groups = []
- for grp in test_groups:
- group = model.Group.get(grp)
- if self.get_expected_api_version() == 1:
- groups.append(group.name)
- else:
- groups.append(group.id)
- return groups
-
- def test_register_get_ok(self):
- offset = self.package_offset()
- res = self.app.get(offset, status=self.STATUS_200_OK)
- assert self.ref_package(self.anna) in res, res
- assert self.ref_package(self.war) in res, res
-
- def test_register_post_ok(self):
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
- postparams = '%s=1' % self.dumps(self.package_fixture_data)
- res = self.app.post(offset, params=postparams,
- status=self.STATUS_201_CREATED,
- extra_environ=self.admin_extra_environ)
-
- # Check the returned package is as expected
- pkg = self.loads(res.body)
- assert_equal(pkg['name'], self.package_fixture_data['name'])
- assert_equal(pkg['title'], self.package_fixture_data['title'])
- assert_equal(set(pkg['tags']), set(self.package_fixture_data['tags']))
- assert_equal(len(pkg['resources']), len(self.package_fixture_data['resources']))
- assert_equal(pkg['extras'], self.package_fixture_data['extras'])
-
- # Check the value of the Location header.
- location = res.headers.get('Location')
-
- assert offset in location
- res = self.app.get(location, status=self.STATUS_200_OK)
- # Check the database record.
- model.Session.remove()
- package = self.get_package_by_name(self.package_fixture_data['name'])
- assert package
- self.assert_equal(package.title, self.package_fixture_data['title'])
- self.assert_equal(package.url, self.package_fixture_data['url'])
- self.assert_equal(package.license_id, self.testpackage_license_id)
- self.assert_equal(len(package.get_tags()), 2)
- self.assert_equal(len(package.extras), 2)
- for key, value in self.package_fixture_data['extras'].items():
- self.assert_equal(package.extras[key], value)
- self.assert_equal(len(package.resources), len(self.package_fixture_data['resources']))
- for (i, expected_resource) in enumerate(self.package_fixture_data['resources']):
- package_resource = package.resources[i]
- for key in expected_resource.keys():
- if key == 'extras':
- package_resource_extras = getattr(package_resource, key)
- expected_resource_extras = expected_resource[key].items()
- for expected_extras_key, expected_extras_value in expected_resource_extras:
- package_resource_value = package_resource_extras[expected_extras_key],\
- 'Package:%r Extras:%r Expected_extras:%r' % \
- (self.package_fixture_data['name'],
- package_resource_extras, expected_resource)
- else:
- package_resource_value = getattr(package_resource, key, None)
- if not package_resource_value:
- package_resource_value = package_resource.extras[key]
-
- expected_resource_value = expected_resource[key]
- self.assert_equal(package_resource_value, expected_resource_value)
-
- # Test Package Entity Get 200.
- offset = self.package_offset(self.package_fixture_data['name'])
- res = self.app.get(offset, status=self.STATUS_200_OK)
- # Todo: Instead loads() the data and then check actual values.
- assert self.package_fixture_data['name'] in res, res
- assert '"license_id": "%s"' % self.package_fixture_data['license_id'] in res, res
- assert self.package_fixture_data['tags'][0] in res, res
- assert self.package_fixture_data['tags'][1] in res, res
- assert '"extras": {' in res, res
- for key, value in self.package_fixture_data['extras'].items():
- assert '"%s": "%s"' % (key, value) in res, res
-
- model.Session.remove()
-
- # Test Packages Register Post 409 (conflict - create duplicate package).
- offset = self.package_offset()
- postparams = '%s=1' % self.dumps(self.package_fixture_data)
- res = self.app.post(offset, params=postparams, status=self.STATUS_409_CONFLICT,
- extra_environ=self.admin_extra_environ)
- model.Session.remove()
-
- def test_register_post_with_group(self):
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
-
- test_groups = [u'david']
- user = model.User.by_name(u'testsysadmin')
-
- groups = self.get_groups_identifiers(test_groups,[user])
-
- package_fixture_data = self.package_fixture_data
- package_fixture_data['groups'] = groups
- data = self.dumps(package_fixture_data)
- res = self.post_json(offset, data, status=self.STATUS_201_CREATED,
- extra_environ={'Authorization':str(user.apikey)})
-
- # Check the database record.
- model.Session.remove()
- package = self.get_package_by_name(self.package_fixture_data['name'])
- assert package
- pkg_groups = model.Session.query(model.Group).\
- join(model.Member, model.Member.group_id == model.Group.id).\
- filter(model.Member.table_id == package.id).all()
- if self.get_expected_api_version() == 1:
- self.assert_equal([g.name for g in pkg_groups], groups)
- else:
- self.assert_equal([g.id for g in pkg_groups], groups)
- del package_fixture_data['groups']
-
- def test_register_post_with_group_not_authorized(self):
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
-
- test_groups = [u'david']
- groups = self.get_groups_identifiers(test_groups)
-
- package_fixture_data = self.package_fixture_data
- package_fixture_data['groups'] = groups
- data = self.dumps(package_fixture_data)
- res = self.post_json(offset, data, status=self.STATUS_403_ACCESS_DENIED,
- extra_environ=self.extra_environ)
- del package_fixture_data['groups']
-
- def test_register_post_with_group_not_found(self):
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
-
- test_groups = [u'this-group-does-not-exist']
- groups = test_groups
-
- package_fixture_data = self.package_fixture_data
- package_fixture_data['groups'] = groups
- data = self.dumps(package_fixture_data)
- res = self.post_json(offset, data, status=self.STATUS_404_NOT_FOUND,
- extra_environ=self.extra_environ)
- del package_fixture_data['groups']
-
- def test_register_post_with_group_sysadmin(self):
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
- user = model.User.by_name(u'testsysadmin')
- test_groups = [u'david']
- groups = self.get_groups_identifiers(test_groups)
-
- package_fixture_data = self.package_fixture_data
- package_fixture_data['groups'] = groups
- data = self.dumps(package_fixture_data)
- res = self.post_json(offset, data, status=self.STATUS_201_CREATED,
- extra_environ={'Authorization':str(user.apikey)})
- # Check the database record.
- model.Session.remove()
- package = self.get_package_by_name(self.package_fixture_data['name'])
- assert package
- pkg_groups = model.Session.query(model.Group).\
- join(model.Member, model.Member.group_id == model.Group.id).\
- filter(model.Member.table_id == package.id).all()
- if self.get_expected_api_version() == 1:
- self.assert_equal([g.name for g in pkg_groups], groups)
- else:
- self.assert_equal([g.id for g in pkg_groups], groups)
-
- del package_fixture_data['groups']
-
- def test_register_post_json(self):
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
- data = self.dumps(self.package_fixture_data)
- res = self.post_json(offset, data, status=self.STATUS_201_CREATED,
- extra_environ=self.admin_extra_environ)
- # Check the database record.
- model.Session.remove()
- package = self.get_package_by_name(self.package_fixture_data['name'])
- assert package
- self.assert_equal(package.title, self.package_fixture_data['title'])
-
- def test_register_post_indexerror(self):
- """
- Test that we can't add a package if Solr is down.
- """
- bad_solr_url = 'http://example.com/badsolrurl'
- original_settings = SolrSettings.get()[0]
- try:
- SolrSettings.init(bad_solr_url)
-
- assert not self.get_package_by_name(self.package_fixture_data['name'])
- offset = self.package_offset()
- data = self.dumps(self.package_fixture_data)
-
- self.post_json(offset, data, status=500, extra_environ=self.admin_extra_environ)
- model.Session.remove()
- finally:
- SolrSettings.init(original_settings)
-
- def test_register_post_tag_too_long(self):
- pkg = {'name': 'test_tag_too_long',
- 'tags': ['tagok', 't'*101]}
- assert not self.get_package_by_name(pkg['name'])
- offset = self.package_offset()
- data = self.dumps(pkg)
- res = self.post_json(offset, data, status=self.STATUS_409_CONFLICT,
- extra_environ=self.admin_extra_environ)
- assert 'length is more than maximum 100' in res.body, res.body
- assert 'tagok' not in res.body
-
- def test_entity_get_ok_jsonp(self):
- offset = self.anna_offset(postfix='?callback=jsoncallback')
- res = self.app.get(offset, status=self.STATUS_200_OK)
- import re
- assert re.match('jsoncallback\(.*\);', res.body), res
- # Unwrap JSONP callback (we want to look at the data).
- msg = res.body[len('jsoncallback')+1:-2]
- self.assert_msg_represents_anna(msg=msg)
-
- def test_entity_get_then_post(self):
- # (ticket 662) Ensure an entity you 'get' from a register can be
- # returned by posting it back
- offset = self.package_offset(self.war.name)
- res = self.app.get(offset, status=self.STATUS_200_OK)
- data = self.loads(res.body)
-
- postparams = '%s=1' % self.dumps(data)
- res = self.app.post(offset, params=postparams,
- status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
- data_returned = self.loads(res.body)
- assert_equal(data['name'], data_returned['name'])
- assert_equal(data['license_id'], data_returned['license_id'])
-
- def test_entity_get_then_post_new(self):
- offset = self.package_offset(self.war.name)
- res = self.app.get(offset, status=self.STATUS_200_OK)
- data = self.loads(res.body)
-
- # change name and create a new package
- data['name'] = u'newpkg'
- data['id'] = None # ensure this doesn't clash or you get 409 error
- postparams = '%s=1' % self.dumps(data)
- # use russianfan now because he has rights to add this package to
- # the 'david' group.
- extra_environ = {'REMOTE_USER': 'testsysadmin'}
- res = self.app.post(self.package_offset(), params=postparams,
- status=self.STATUS_201_CREATED,
- extra_environ=extra_environ)
- try:
- data_returned = self.loads(res.body)
- assert_equal(data['name'], data_returned['name'])
- assert_equal(data['license_id'], data_returned['license_id'])
- finally:
- self.purge_package_by_name(data['name'])
-
- def test_entity_post_changed_readonly(self):
- # (ticket 662) Edit a readonly field gives error
- offset = self.package_offset(self.war.name)
- res = self.app.get(offset, status=self.STATUS_200_OK)
- data = self.loads(res.body)
- data['id'] = 'illegally changed value'
- postparams = '%s=1' % self.dumps(data)
- res = self.app.post(offset, params=postparams,
- status=self.STATUS_409_CONFLICT,
- extra_environ=self.admin_extra_environ)
- assert "Cannot change value of key from" in res.body, res.body
- assert "to illegally changed value. This key is read-only" in res.body, res.body
-
- def test_entity_update_denied(self):
- offset = self.anna_offset()
- postparams = '%s=1' % self.dumps(self.package_fixture_data)
- res = self.app.post(offset, params=postparams, status=self.STATUS_403_ACCESS_DENIED)
-
- def test_entity_delete_denied(self):
- offset = self.anna_offset()
- res = self.app.delete(offset, status=self.STATUS_403_ACCESS_DENIED)
-
- def create_package_with_admin_user(self, package_data):
- '''Creates a package with self.user as admin and provided package_data.
- '''
- self.create_package(data=package_data)
-
- def test_package_update_ok_by_id(self):
- self.assert_package_update_ok('id', 'post')
-
- def test_entity_update_ok_by_name(self):
- self.assert_package_update_ok('name', 'post')
-
- def test_package_update_ok_by_id_by_put(self):
- self.assert_package_update_ok('id', 'put')
-
- def test_entity_update_ok_by_name_by_put(self):
- self.assert_package_update_ok('name', 'put')
-
- def test_package_update_delete_last_extra(self):
- old_fixture_data = {
- 'name': self.package_fixture_data['name'],
- 'extras': {
- u'key1': u'val1',
- },
- }
- new_fixture_data = {
- 'name':u'somethingnew',
- 'extras': {
- u'key1': None,
- },
- }
- self.create_package_with_admin_user(old_fixture_data)
- offset = self.package_offset(old_fixture_data['name'])
- params = '%s=1' % self.dumps(new_fixture_data)
- res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
-
- try:
- # Check the returned package is as expected
- pkg = self.loads(res.body)
- assert_equal(pkg['name'], new_fixture_data['name'])
- expected_extras = copy.deepcopy(new_fixture_data['extras'])
- del expected_extras['key1']
- assert_equal(pkg['extras'], expected_extras)
-
- # Check extra was deleted
- model.Session.remove()
- package = self.get_package_by_name(new_fixture_data['name'])
- # - title
- self.assert_equal(package.extras, {})
- finally:
- self.purge_package_by_name(new_fixture_data['name'])
-
- def test_package_update_do_not_delete_last_extra(self):
- old_fixture_data = {
- 'name': self.package_fixture_data['name'],
- 'extras': {
- u'key1': u'val1',
- },
- }
- new_fixture_data = {
- 'name':u'somethingnew',
- 'extras': {}, # no extras specified, but existing
- # ones should be left alone
- }
- self.create_package_with_admin_user(old_fixture_data)
- offset = self.package_offset(old_fixture_data['name'])
- params = '%s=1' % self.dumps(new_fixture_data)
- res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
-
- try:
- # Check the returned package is as expected
- pkg = self.loads(res.body)
- assert_equal(pkg['name'], new_fixture_data['name'])
- expected_extras = {u'key1': u'val1'} # should not be deleted
- assert_equal(pkg['extras'], expected_extras)
-
- # Check extra was not deleted
- model.Session.remove()
- package = self.get_package_by_name(new_fixture_data['name'])
- # - title
- assert len(package.extras) == 1, package.extras
- finally:
- self.purge_package_by_name(new_fixture_data['name'])
-
- def test_entity_update_readd_tag(self):
- name = self.package_fixture_data['name']
- old_fixture_data = {
- 'name': name,
- 'tags': ['tag 1.', 'tag2']
- }
- new_fixture_data = {
- 'name': name,
- 'tags': ['tag 1.']
- }
- self.create_package_with_admin_user(old_fixture_data)
- offset = self.package_offset(name)
- params = '%s=1' % self.dumps(new_fixture_data)
- res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
-
- # Check the returned package is as expected
- pkg = self.loads(res.body)
- assert_equal(pkg['name'], new_fixture_data['name'])
- assert_equal(pkg['tags'], ['tag 1.'])
-
- package = self.get_package_by_name(new_fixture_data['name'])
- assert len(package.get_tags()) == 1, package.get_tags()
-
- # now reinstate the tag
- params = '%s=1' % self.dumps(old_fixture_data)
- res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
- pkg = self.loads(res.body)
- assert_equal(pkg['tags'], ['tag 1.', 'tag2'])
-
- def test_entity_update_conflict(self):
- package1_name = self.package_fixture_data['name']
- package1_data = {'name': package1_name}
- package1 = self.create_package_with_admin_user(package1_data)
- package2_name = u'somethingnew'
- package2_data = {'name': package2_name}
- package2 = self.create_package_with_admin_user(package2_data)
- try:
- package1_offset = self.package_offset(package1_name)
- # trying to rename package 1 to package 2's name
- print(package1_offset, package2_data)
- self.post(package1_offset, package2_data, self.STATUS_409_CONFLICT, extra_environ=self.admin_extra_environ)
- finally:
- self.purge_package_by_name(package2_name)
-
- def test_entity_update_empty(self):
- package1_name = self.package_fixture_data['name']
- package1_data = {'name': package1_name}
- package1 = self.create_package_with_admin_user(package1_data)
- package2_data = '' # this is the error
- package1_offset = self.package_offset(package1_name)
- self.app.put(package1_offset, package2_data,
- status=self.STATUS_400_BAD_REQUEST)
-
- def test_entity_update_indexerror(self):
- """
- Test that we can't update a package if Solr is down.
- """
- bad_solr_url = 'http://example.com/badsolrurl'
- original_settings = SolrSettings.get()[0]
- try:
- SolrSettings.init(bad_solr_url)
-
- assert_raises(
- search.SearchIndexError, self.assert_package_update_ok, 'name', 'post'
- )
- finally:
- SolrSettings.init(original_settings)
-
- def test_package_update_delete_resource(self):
- old_fixture_data = {
- 'name': self.package_fixture_data['name'],
- 'resources': [{
- u'url':u'http://blah.com/file2.xml',
- u'format':u'XML',
- u'description':u'Appendix 1',
- u'hash':u'def123',
- u'alt_url':u'alt123',
- },{
- u'url':u'http://blah.com/file3.xml',
- u'format':u'XML',
- u'description':u'Appenddic 2',
- u'hash':u'ghi123',
- u'alt_url':u'alt123',
- }],
- }
- new_fixture_data = {
- 'name':u'somethingnew',
- 'resources': [],
- }
- self.create_package_with_admin_user(old_fixture_data)
- offset = self.package_offset(old_fixture_data['name'])
- params = '%s=1' % self.dumps(new_fixture_data)
- res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
-
- try:
- # Check the returned package is as expected
- pkg = self.loads(res.body)
- assert_equal(pkg['name'], new_fixture_data['name'])
- assert_equal(pkg['resources'], [])
-
- # Check resources were deleted
- model.Session.remove()
- package = self.get_package_by_name(new_fixture_data['name'])
- self.assert_equal(len(package.resources), 0)
- finally:
- self.purge_package_by_name(new_fixture_data['name'])
-
- def test_entity_delete_ok(self):
- # create a package with package_fixture_data
- if not self.get_package_by_name(self.package_fixture_data['name']):
- self.create_package(name=self.package_fixture_data['name'])
- assert self.get_package_by_name(self.package_fixture_data['name'])
- # delete it
- offset = self.package_offset(self.package_fixture_data['name'])
- res = self.app.delete(offset, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
- package = self.get_package_by_name(self.package_fixture_data['name'])
- self.assert_equal(package.state, 'deleted')
- model.Session.remove()
-
- def test_entity_delete_ok_without_request_headers(self):
- # create a package with package_fixture_data
- if not self.get_package_by_name(self.package_fixture_data['name']):
- self.create_package(name=self.package_fixture_data['name'])
- assert self.get_package_by_name(self.package_fixture_data['name'])
- # delete it
- offset = self.package_offset(self.package_fixture_data['name'])
- res = self.delete_request(offset, status=self.STATUS_200_OK,
- extra_environ=self.admin_extra_environ)
- package = self.get_package_by_name(self.package_fixture_data['name'])
- self.assert_equal(package.state, 'deleted')
- model.Session.remove()
-
- def test_create_private_package_with_no_organization(self):
- '''Test that private packages with no organization cannot be created.
-
- '''
- testsysadmin = model.User.by_name('testsysadmin')
- result = tests.call_action_api(self.app, 'package_create', name='test',
- private=True, apikey=testsysadmin.apikey, status=409)
- assert result == {'__type': 'Validation Error',
- 'private': ["Datasets with no organization can't be private."]}
-
- def test_create_public_package_with_no_organization(self):
- '''Test that public packages with no organization can be created.'''
- testsysadmin = model.User.by_name('testsysadmin')
- tests.call_action_api(self.app, 'package_create', name='test',
- private=False, apikey=testsysadmin.apikey)
-
- def test_make_package_with_no_organization_private(self):
- '''Test that private packages with no organization cannot be created
- by package_update.
-
- '''
- testsysadmin = model.User.by_name('testsysadmin')
- package = tests.call_action_api(self.app, 'package_create',
- name='test_2', private=False, apikey=testsysadmin.apikey)
- package['private'] = True
- result = tests.call_action_api(self.app, 'package_update',
- apikey=testsysadmin.apikey, status=409, **package)
- assert result == {'__type': 'Validation Error',
- 'private': ["Datasets with no organization can't be private."]}
diff --git a/ckan/tests/legacy/functional/api/model/test_ratings.py b/ckan/tests/legacy/functional/api/model/test_ratings.py
deleted file mode 100644
index 2edca6a45a2..00000000000
--- a/ckan/tests/legacy/functional/api/model/test_ratings.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# encoding: utf-8
-
-from ckan import model
-from ckan.lib.create_test_data import CreateTestData
-
-from ckan.tests.legacy.functional.api.base import BaseModelApiTestCase
-
-
-class RatingsTestCase(BaseModelApiTestCase):
-
- @classmethod
- def setup_class(cls):
- CreateTestData.create()
- cls.testsysadmin = model.User.by_name(u'testsysadmin')
- cls.comment = u'Comment umlaut: \xfc.'
- cls.user_name = u'annafan' # created in CreateTestData
- cls.init_extra_environ(cls.user_name)
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
-
- def test_register_post(self):
- # Test Rating Register Post 200.
- self.clear_all_tst_ratings()
- offset = self.rating_offset()
- rating_opts = {'package':u'warandpeace',
- 'rating':5}
- pkg_name = rating_opts['package']
- postparams = '%s=1' % self.dumps(rating_opts)
- res = self.app.post(offset, params=postparams, status=[201],
- extra_environ=self.extra_environ)
- model.Session.remove()
- pkg = self.get_package_by_name(pkg_name)
- assert pkg
- assert len(pkg.ratings) == 1
- assert pkg.ratings[0].rating == rating_opts['rating'], pkg.ratings
-
- # Get package to see rating
- offset = self.package_offset(pkg_name)
- res = self.app.get(offset, status=[200])
- assert pkg_name in res, res
- assert '"ratings_average": %s.0' % rating_opts['rating'] in res, res
- assert '"ratings_count": 1' in res, res
-
- model.Session.remove()
-
- # Rerate package
- offset = self.rating_offset()
- postparams = '%s=1' % self.dumps(rating_opts)
- res = self.app.post(offset, params=postparams, status=[201],
- extra_environ=self.extra_environ)
- model.Session.remove()
- pkg = self.get_package_by_name(pkg_name)
- assert pkg
- assert len(pkg.ratings) == 1
- assert pkg.ratings[0].rating == rating_opts['rating'], pkg.ratings
-
- def test_entity_post_invalid(self):
- self.clear_all_tst_ratings()
- offset = self.rating_offset()
- rating_opts = {'package':u'warandpeace',
- 'rating':0}
- postparams = '%s=1' % self.dumps(rating_opts)
- res = self.app.post(offset, params=postparams, status=[409],
- extra_environ=self.extra_environ)
- self.assert_json_response(res, 'rating')
- model.Session.remove()
- pkg = self.get_package_by_name(rating_opts['package'])
- assert pkg
- assert len(pkg.ratings) == 0
diff --git a/ckan/tests/legacy/functional/api/model/test_tag.py b/ckan/tests/legacy/functional/api/model/test_tag.py
deleted file mode 100644
index a46a5f172fb..00000000000
--- a/ckan/tests/legacy/functional/api/model/test_tag.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# encoding: utf-8
-
-from ckan import model
-from ckan.lib.create_test_data import CreateTestData
-import ckan.lib.search as search
-
-from ckan.tests.legacy.functional.api.base import BaseModelApiTestCase
-
-
-class TagsTestCase(BaseModelApiTestCase):
-
- @classmethod
- def setup_class(cls):
- search.clear_all()
- CreateTestData.create()
- cls.testsysadmin = model.User.by_name(u'testsysadmin')
- cls.comment = u'Comment umlaut: \xfc.'
- cls.user_name = u'annafan' # created in CreateTestData
- cls.init_extra_environ(cls.user_name)
-
- @classmethod
- def teardown_class(cls):
- search.clear_all()
- model.repo.rebuild_db()
-
- def test_register_get_ok(self):
- offset = self.tag_offset()
- res = self.app.get(offset, status=self.STATUS_200_OK)
- results = self.loads(res.body)
- assert self.russian.name in results, results
- assert self.tolstoy.name in results, results
- assert self.flexible_tag.name in results, results
-
- def test_entity_get_ok(self):
- offset = self.tag_offset(self.russian.name)
- res = self.app.get(offset, status=self.STATUS_200_OK)
- self.assert_msg_represents_russian(msg=res.body)
-
- def test_entity_get_ok_flexible_tag(self):
- """
- Asserts that searching for a tag name with spaces and punctuation works.
-
- The tag name is u'Flexible \u30a1', and both the 'warandpeace'
- and 'annakarenina' packages should be returned.
- """
- offset = self.tag_offset(self.flexible_tag.name)
- res = self.app.get(offset, status=self.STATUS_200_OK)
- self.assert_msg_represents_flexible_tag(msg=res.body)
-
- def test_entity_get_not_found(self):
- offset = self.tag_offset('doesntexist')
- res = self.app.get(offset, status=404)
- self.assert_json_response(res, 'Not found')
diff --git a/ckan/tests/legacy/functional/api/model/test_vocabulary.py b/ckan/tests/legacy/functional/api/model/test_vocabulary.py
index 373f8b6d8b6..924ed0e8d5f 100644
--- a/ckan/tests/legacy/functional/api/model/test_vocabulary.py
+++ b/ckan/tests/legacy/functional/api/model/test_vocabulary.py
@@ -4,22 +4,15 @@
import ckan.lib.helpers as helpers
import ckan.tests.helpers as h
import ckan.lib.dictization.model_dictize as model_dictize
+import pytest
class TestVocabulary(object):
-
- @classmethod
- def setup_class(self):
- self.app = h._get_test_app()
-
- @classmethod
- def teardown_class(self):
- ckan.model.repo.rebuild_db()
-
- def setup(self):
- self.clean_vocab()
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db, app):
+ self.app = app
model = ckan.model
- context = {'model': model}
+ context = {"model": model}
genre = model.Vocabulary("Genre")
time_period = ckan.model.Vocabulary("Time Period")
@@ -27,1099 +20,1218 @@ def setup(self):
model.Session.add_all([genre, time_period, composers])
self.genre_vocab = model_dictize.vocabulary_dictize(genre, context)
- self.timeperiod_vocab = model_dictize.vocabulary_dictize(time_period,
- context)
- self.composers_vocab = model_dictize.vocabulary_dictize(composers,
- context)
+ self.timeperiod_vocab = model_dictize.vocabulary_dictize(
+ time_period, context
+ )
+ self.composers_vocab = model_dictize.vocabulary_dictize(
+ composers, context
+ )
ckan.model.Session.commit()
- self.sysadmin_user = ckan.model.User.get('admin')
- self.normal_user = ckan.model.User.get('normal')
+ self.sysadmin_user = ckan.model.User.get("admin")
+ self.normal_user = ckan.model.User.get("normal")
if not self.sysadmin_user:
- normal_user = ckan.model.User(name=u'normal', password=u'annafan')
- sysadmin_user = ckan.model.User(name=u'admin',
- password=u'testsysadmin')
+ normal_user = ckan.model.User(name=u"normal", password=u"annafan")
+ sysadmin_user = ckan.model.User(
+ name=u"admin", password=u"testsysadmin"
+ )
sysadmin_user.sysadmin = True
ckan.model.Session.add(normal_user)
ckan.model.Session.add(sysadmin_user)
ckan.model.Session.commit()
- self.sysadmin_user = ckan.model.User.get('admin')
- self.normal_user = ckan.model.User.get('normal')
+ self.sysadmin_user = ckan.model.User.get("admin")
+ self.normal_user = ckan.model.User.get("normal")
self.sysadmin_apikey = self.sysadmin_user.apikey
- def clean_vocab(self):
- ckan.model.Session.execute('delete from package_tag_revision')
- ckan.model.Session.execute('delete from package_tag')
- ckan.model.Session.execute('delete from tag')
- ckan.model.Session.execute('delete from vocabulary')
- ckan.model.Session.commit()
-
- @classmethod
def _post(self, url, params=None, extra_environ=None):
if params is None:
params = {}
param_string = helpers.json.dumps(params)
- response = self.app.post(url, params=param_string,
- extra_environ=extra_environ)
+ response = self.app.post(
+ url, params=param_string, extra_environ=extra_environ
+ )
assert not response.errors
return response.json
- @classmethod
def _create_vocabulary(self, vocab_name=None, user=None):
# Create a new vocabulary.
- params = {'name': vocab_name}
+ params = {"name": vocab_name}
if user:
- extra_environ = {'Authorization': str(user.apikey)}
+ extra_environ = {"Authorization": str(user.apikey)}
else:
extra_environ = None
- response = self._post('/api/action/vocabulary_create', params=params,
- extra_environ=extra_environ)
+ response = self._post(
+ "/api/action/vocabulary_create",
+ params=params,
+ extra_environ=extra_environ,
+ )
# Check the values of the response.
- assert response['success'] is True
- assert response['result']
- created_vocab = response['result']
- assert created_vocab['name'] == vocab_name
- assert created_vocab['id']
+ assert response["success"] is True
+ assert response["result"]
+ created_vocab = response["result"]
+ assert created_vocab["name"] == vocab_name
+ assert created_vocab["id"]
# Get the list of vocabularies.
- response = self._post('/api/action/vocabulary_list')
+ response = self._post("/api/action/vocabulary_list")
# Check that the vocabulary we created is in the list.
- assert response['success'] is True
- assert response['result']
- assert response['result'].count(created_vocab) == 1
+ assert response["success"] is True
+ assert response["result"]
+ assert response["result"].count(created_vocab) == 1
# Get the created vocabulary.
- params = {'id': created_vocab['id']}
- response = self._post('/api/action/vocabulary_show', params)
+ params = {"id": created_vocab["id"]}
+ response = self._post("/api/action/vocabulary_show", params)
# Check that retrieving the vocab by name gives the same result.
- by_name_params = {'id': created_vocab['name']}
- assert response == self._post('/api/action/vocabulary_show',
- by_name_params)
+ by_name_params = {"id": created_vocab["name"]}
+ assert response == self._post(
+ "/api/action/vocabulary_show", by_name_params
+ )
# Check that it matches what we created.
- assert response['success'] is True
- assert response['result'] == created_vocab
+ assert response["success"] is True
+ assert response["result"] == created_vocab
return created_vocab
def _update_vocabulary(self, params, user=None):
if user:
- extra_environ = {'Authorization': str(user.apikey)}
+ extra_environ = {"Authorization": str(user.apikey)}
else:
extra_environ = None
- original_vocab = self._post('/api/action/vocabulary_show',
- {'id': params.get('id') or params.get('name')})['result']
+ original_vocab = self._post(
+ "/api/action/vocabulary_show",
+ {"id": params.get("id") or params.get("name")},
+ )["result"]
- response = self._post('/api/action/vocabulary_update', params=params,
- extra_environ=extra_environ)
+ response = self._post(
+ "/api/action/vocabulary_update",
+ params=params,
+ extra_environ=extra_environ,
+ )
# Check the values of the response.
- assert response['success'] is True
- assert response['result']
- updated_vocab = response['result']
+ assert response["success"] is True
+ assert response["result"]
+ updated_vocab = response["result"]
# id should never change.
- assert updated_vocab['id'] == original_vocab['id']
- if 'id' in params:
- assert updated_vocab['id'] == params['id']
+ assert updated_vocab["id"] == original_vocab["id"]
+ if "id" in params:
+ assert updated_vocab["id"] == params["id"]
# name should change only if given in params.
- if 'name' in params:
- assert updated_vocab['name'] == params['name']
+ if "name" in params:
+ assert updated_vocab["name"] == params["name"]
else:
- assert updated_vocab['name'] == original_vocab['name']
+ assert updated_vocab["name"] == original_vocab["name"]
# tags should change only if given in params.
- if 'tags' in params:
- assert sorted(tag['name'] for tag in params['tags']) \
- == sorted(tag['name'] for tag in updated_vocab['tags'])
+
+ if "tags" in params:
+ assert sorted([tag["name"] for tag in params["tags"]]) == sorted(
+ [tag["name"] for tag in updated_vocab["tags"]]
+ )
else:
- assert updated_vocab['tags'] == original_vocab['tags']
+ assert updated_vocab["tags"] == original_vocab["tags"]
# Get the list of vocabularies.
- response = self._post('/api/action/vocabulary_list')
+ response = self._post("/api/action/vocabulary_list")
# Check that the vocabulary we created is in the list.
- assert response['success'] is True
- assert response['result']
- assert response['result'].count(updated_vocab) == 1
+ assert response["success"] is True
+ assert response["result"]
+ assert response["result"].count(updated_vocab) == 1
# Get the created vocabulary.
- params = {'id': updated_vocab['id']}
- response = self._post('/api/action/vocabulary_show', params)
+ params = {"id": updated_vocab["id"]}
+ response = self._post("/api/action/vocabulary_show", params)
# Check that retrieving the vocab by name gives the same result.
- by_name_params = {'id': updated_vocab['name']}
- assert response == self._post('/api/action/vocabulary_show',
- by_name_params)
+ by_name_params = {"id": updated_vocab["name"]}
+ assert response == self._post(
+ "/api/action/vocabulary_show", by_name_params
+ )
# Check that it matches what we created.
- assert response['success'] is True
- assert response['result'] == updated_vocab
+ assert response["success"] is True
+ assert response["result"] == updated_vocab
return updated_vocab
- def _delete_vocabulary(self, vocab_id, user=None):
- if user:
- extra_environ = {'Authorization': str(user.apikey)}
- else:
- extra_environ = None
- params = {'id': vocab_id}
- response = self._post('/api/action/vocabulary_delete', params=params,
- extra_environ=extra_environ)
-
- # Check the values of the response.
- assert response['success'] is True
- assert response['result'] is None
- response['result']
-
- # Get the list of vocabularies.
- response = self._post('/api/action/vocabulary_list')
- assert response['success'] is True
- assert response['result']
- # Check that the vocabulary we deleted is not in the list.
- assert vocab_id not in [vocab['id'] for vocab in response['result']]
-
- # Check that the deleted vocabulary can no longer be retrieved.
- response = self.app.post('/api/action/vocabulary_show',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
-
def _list_tags(self, vocabulary=None, user=None):
params = {}
if vocabulary:
- params['vocabulary_id'] = vocabulary['id']
+ params["vocabulary_id"] = vocabulary["id"]
if user:
- extra_environ = {'Authorization': str(user.apikey)}
+ extra_environ = {"Authorization": str(user.apikey)}
else:
extra_environ = None
- response = self._post('/api/action/tag_list', params=params,
- extra_environ=extra_environ)
- assert response['success'] is True
- return response['result']
+ response = self._post(
+ "/api/action/tag_list", params=params, extra_environ=extra_environ
+ )
+ assert response["success"] is True
+ return response["result"]
def _create_tag(self, user, tag_name, vocabulary=None):
- tag_dict = {'name': tag_name}
+ tag_dict = {"name": tag_name}
if vocabulary:
- tag_dict['vocabulary_id'] = vocabulary['id']
+ tag_dict["vocabulary_id"] = vocabulary["id"]
if user:
- extra_environ = {'Authorization': str(user.apikey)}
+ extra_environ = {"Authorization": str(user.apikey)}
else:
extra_environ = None
- response = self._post('/api/action/tag_create', params=tag_dict,
- extra_environ=extra_environ)
- assert response['success'] is True
- return response['result']
+ response = self._post(
+ "/api/action/tag_create",
+ params=tag_dict,
+ extra_environ=extra_environ,
+ )
+ assert response["success"] is True
+ return response["result"]
def _delete_tag(self, user, tag_id_or_name, vocab_id_or_name=None):
- params = {'id': tag_id_or_name}
+ params = {"id": tag_id_or_name}
if vocab_id_or_name:
- params['vocabulary_id'] = vocab_id_or_name
+ params["vocabulary_id"] = vocab_id_or_name
if user:
- extra_environ = {'Authorization': str(user.apikey)}
+ extra_environ = {"Authorization": str(user.apikey)}
else:
extra_environ = None
- response = self._post('/api/action/tag_delete', params=params,
- extra_environ=extra_environ)
- assert response['success'] is True
- return response['result']
+ response = self._post(
+ "/api/action/tag_delete",
+ params=params,
+ extra_environ=extra_environ,
+ )
+ assert response["success"] is True
+ return response["result"]
def test_vocabulary_create(self):
- '''Test adding a new vocabulary to a CKAN instance via the action
+ """Test adding a new vocabulary to a CKAN instance via the action
API.
- '''
- self._create_vocabulary(vocab_name="My cool vocab",
- user=self.sysadmin_user)
+ """
+ self._create_vocabulary(
+ vocab_name="My cool vocab", user=self.sysadmin_user
+ )
def test_vocabulary_create_with_tags(self):
- '''Test adding a new vocabulary with some tags.
-
- '''
- params = {'name': 'foobar'}
- tag1 = {'name': 'foo'}
- tag2 = {'name': 'bar'}
- params['tags'] = [tag1, tag2]
- response = self._post('/api/action/vocabulary_create',
- params=params,
- extra_environ={'Authorization': str(self.sysadmin_apikey)})
- assert response['success'] is True
- assert response['result']
- created_vocab = response['result']
- assert created_vocab['name'] == 'foobar'
- assert created_vocab['id']
+ """Test adding a new vocabulary with some tags.
+
+ """
+ params = {"name": "foobar"}
+ tag1 = {"name": "foo"}
+ tag2 = {"name": "bar"}
+ params["tags"] = [tag1, tag2]
+ response = self._post(
+ "/api/action/vocabulary_create",
+ params=params,
+ extra_environ={"Authorization": str(self.sysadmin_apikey)},
+ )
+ assert response["success"] is True
+ assert response["result"]
+ created_vocab = response["result"]
+ assert created_vocab["name"] == "foobar"
+ assert created_vocab["id"]
# Get the list of vocabularies.
- response = self._post('/api/action/vocabulary_list')
+ response = self._post("/api/action/vocabulary_list")
# Check that the vocabulary we created is in the list.
- assert response['success'] is True
- assert response['result']
- assert response['result'].count(created_vocab) == 1
+ assert response["success"] is True
+ assert response["result"]
+ assert response["result"].count(created_vocab) == 1
# Get the created vocabulary.
- params = {'id': created_vocab['id']}
- response = self._post('/api/action/vocabulary_show', params)
+ params = {"id": created_vocab["id"]}
+ response = self._post("/api/action/vocabulary_show", params)
# Check that retrieving the vocab by name gives the same result.
- by_name_params = {'id': created_vocab['name']}
- assert response == self._post('/api/action/vocabulary_show',
- by_name_params)
+ by_name_params = {"id": created_vocab["name"]}
+ assert response == self._post(
+ "/api/action/vocabulary_show", by_name_params
+ )
# Check that it matches what we created.
- assert response['success'] is True
- assert response['result'] == created_vocab
+ assert response["success"] is True
+ assert response["result"] == created_vocab
# Get the list of tags for the vocabulary.
tags = self._list_tags(created_vocab)
assert len(tags) == 2
- assert tags.count('foo') == 1
- assert tags.count('bar') == 1
+ assert tags.count("foo") == 1
+ assert tags.count("bar") == 1
- def test_vocabulary_create_bad_tags(self):
- '''Test creating new vocabularies with invalid tags.
+ def test_vocabulary_create_bad_tags(self, app):
+ """Test creating new vocabularies with invalid tags.
- '''
+ """
for tags in (
- [{'id': 'xxx'}, {'name': 'foo'}],
- [{'name': 'foo'}, {'name': None}],
- [{'name': 'foo'}, {'name': ''}],
- [{'name': 'foo'}, {'name': 'f'}],
- [{'name': 'f' * 200}, {'name': 'foo'}],
- [{'name': 'Invalid!'}, {'name': 'foo'}],
- ):
- params = {'name': 'foobar', 'tags': tags}
- response = self.app.post('/api/action/vocabulary_create',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization': str(self.sysadmin_apikey)},
- status=409)
- assert response.json['success'] is False
- assert 'tags' in response.json['error']
- assert len(response.json['error']) == 2
-
- def test_vocabulary_create_none_tags(self):
- '''Test creating new vocabularies with None for 'tags'.
-
- '''
- params = {'name': 'foobar', 'tags': None}
- response = self.app.post('/api/action/vocabulary_create',
+ [{"id": "xxx"}, {"name": "foo"}],
+ [{"name": "foo"}, {"name": None}],
+ [{"name": "foo"}, {"name": ""}],
+ [{"name": "foo"}, {"name": "f"}],
+ [{"name": "f" * 200}, {"name": "foo"}],
+ [{"name": "Invalid!"}, {"name": "foo"}],
+ ):
+ params = {"name": "foobar", "tags": tags}
+ response = app.post(
+ "/api/action/vocabulary_create",
params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=400)
+ extra_environ={"Authorization": str(self.sysadmin_apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert "tags" in response.json["error"]
+ assert len(response.json["error"]) == 2
+
+ def test_vocabulary_create_none_tags(self, app):
+ """Test creating new vocabularies with None for 'tags'.
+
+ """
+ params = {"name": "foobar", "tags": None}
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=400,
+ )
assert "Integrity Error" in response.body
- def test_vocabulary_create_empty_tags(self):
- '''Test creating new vocabularies with [] for 'tags'.
-
- '''
- params = {'name': 'foobar', 'tags': []}
- response = self.app.post('/api/action/vocabulary_create',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=200)
- assert response.json['success'] is True
- assert response.json['result']
- created_vocab = response.json['result']
- assert created_vocab['name'] == 'foobar'
- assert created_vocab['id']
- assert created_vocab['tags'] == []
- params = {'id': created_vocab['id']}
- response = self._post('/api/action/vocabulary_show', params)
- assert response['success'] is True
- assert response['result'] == created_vocab
+ def test_vocabulary_create_empty_tags(self, app):
+ """Test creating new vocabularies with [] for 'tags'.
+
+ """
+ params = {"name": "foobar", "tags": []}
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=200,
+ )
+ assert response.json["success"] is True
+ assert response.json["result"]
+ created_vocab = response.json["result"]
+ assert created_vocab["name"] == "foobar"
+ assert created_vocab["id"]
+ assert created_vocab["tags"] == []
+ params = {"id": created_vocab["id"]}
+ response = self._post("/api/action/vocabulary_show", params)
+ assert response["success"] is True
+ assert response["result"] == created_vocab
tags = self._list_tags(created_vocab)
assert tags == []
- def test_vocabulary_create_id(self):
- '''Test error response when user tries to supply their own ID when
+ def test_vocabulary_create_id(self, app):
+ """Test error response when user tries to supply their own ID when
creating a vocabulary.
- '''
- params = {'id': 'xxx', 'name': 'foobar'}
+ """
+ params = {"id": "xxx", "name": "foobar"}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_create',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['id'] == [u'The input field id was '
- 'not expected.']
-
- def test_vocabulary_create_no_name(self):
- '''Test error response when user tries to create a vocab without a
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["id"] == [
+ u"The input field id was " "not expected."
+ ]
+
+ def test_vocabulary_create_no_name(self, app):
+ """Test error response when user tries to create a vocab without a
name.
- '''
+ """
params = {}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_create',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['name'] == [u'Missing value']
-
- def test_vocabulary_create_invalid_name(self):
- '''Test error response when user tries to create a vocab with an
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["name"] == [u"Missing value"]
+
+ def test_vocabulary_create_invalid_name(self, app):
+ """Test error response when user tries to create a vocab with an
invalid name.
- '''
- for name in (None, '', 'a', 'foobar' * 100):
- params = {'name': name}
+ """
+ for name in (None, "", "a", "foobar" * 100):
+ params = {"name": name}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_create',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['name']
-
- def test_vocabulary_create_exists(self):
- '''Test error response when user tries to create a vocab that already
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["name"]
+
+ def test_vocabulary_create_exists(self, app):
+ """Test error response when user tries to create a vocab that already
exists.
- '''
- params = {'name': self.genre_vocab['name']}
+ """
+ params = {"name": self.genre_vocab["name"]}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_create',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['name'] == [u'That vocabulary name is '
- 'already in use.']
-
- def test_vocabulary_create_not_logged_in(self):
- '''Test that users who are not logged in cannot create vocabularies.'''
-
- params = {'name':
- "Spam Vocabulary: SpamCo Duck Rental: Rent Your Ducks From Us!"}
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["name"] == [
+ u"That vocabulary name is " "already in use."
+ ]
+
+ def test_vocabulary_create_not_logged_in(self, app):
+ """Test that users who are not logged in cannot create vocabularies."""
+
+ params = {
+ "name": "Spam Vocabulary: SpamCo Duck Rental: Rent Your Ducks From Us!"
+ }
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_create',
- params=param_string,
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
+ response = app.post(
+ "/api/action/vocabulary_create", params=param_string, status=403
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
- def test_vocabulary_create_not_authorized(self):
- '''Test that users who are not authorized cannot create vocabs.'''
+ def test_vocabulary_create_not_authorized(self, app):
+ """Test that users who are not authorized cannot create vocabs."""
- params = {'name': 'My Unauthorised Vocabulary'}
+ params = {"name": "My Unauthorised Vocabulary"}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_create',
- params=param_string,
- extra_environ={'Authorization':
- str(self.normal_user.apikey)},
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
+ response = app.post(
+ "/api/action/vocabulary_create",
+ params=param_string,
+ extra_environ={"Authorization": str(self.normal_user.apikey)},
+ status=403,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
def test_vocabulary_update_id_only(self):
- self._update_vocabulary({'id': self.genre_vocab['id']},
- self.sysadmin_user)
+ self._update_vocabulary(
+ {"id": self.genre_vocab["id"]}, self.sysadmin_user
+ )
def test_vocabulary_update_id_and_same_name(self):
- self._update_vocabulary({'id': self.genre_vocab['id'],
- 'name': self.genre_vocab['name']}, self.sysadmin_user)
+ self._update_vocabulary(
+ {"id": self.genre_vocab["id"], "name": self.genre_vocab["name"]},
+ self.sysadmin_user,
+ )
def test_vocabulary_update_id_and_new_name(self):
- self._update_vocabulary({'id': self.genre_vocab['id'],
- 'name': 'new name'}, self.sysadmin_user)
+ self._update_vocabulary(
+ {"id": self.genre_vocab["id"], "name": "new name"},
+ self.sysadmin_user,
+ )
def test_vocabulary_update_id_and_same_tags(self):
- self._update_vocabulary({'id': self.genre_vocab['id'],
- 'tags': self.genre_vocab['tags']}, self.sysadmin_user)
+ self._update_vocabulary(
+ {"id": self.genre_vocab["id"], "tags": self.genre_vocab["tags"]},
+ self.sysadmin_user,
+ )
def test_vocabulary_update_id_and_new_tags(self):
tags = [
- {'name': 'new test tag one'},
- {'name': 'new test tag two'},
- {'name': 'new test tag three'},
- ]
- self._update_vocabulary({'id': self.genre_vocab['id'], 'tags': tags},
- self.sysadmin_user)
+ {"name": "new test tag one"},
+ {"name": "new test tag two"},
+ {"name": "new test tag three"},
+ ]
+ self._update_vocabulary(
+ {"id": self.genre_vocab["id"], "tags": tags}, self.sysadmin_user
+ )
def test_vocabulary_update_id_same_name_and_same_tags(self):
- self._update_vocabulary({'id': self.genre_vocab['id'],
- 'name': self.genre_vocab['name'],
- 'tags': self.genre_vocab['tags']}, self.sysadmin_user)
+ self._update_vocabulary(
+ {
+ "id": self.genre_vocab["id"],
+ "name": self.genre_vocab["name"],
+ "tags": self.genre_vocab["tags"],
+ },
+ self.sysadmin_user,
+ )
def test_vocabulary_update_id_same_name_and_new_tags(self):
tags = [
- {'name': 'new test tag one'},
- {'name': 'new test tag two'},
- {'name': 'new test tag three'},
- ]
- self._update_vocabulary({'id': self.genre_vocab['id'],
- 'name': self.genre_vocab['name'],
- 'tags': tags}, self.sysadmin_user)
+ {"name": "new test tag one"},
+ {"name": "new test tag two"},
+ {"name": "new test tag three"},
+ ]
+ self._update_vocabulary(
+ {
+ "id": self.genre_vocab["id"],
+ "name": self.genre_vocab["name"],
+ "tags": tags,
+ },
+ self.sysadmin_user,
+ )
def test_vocabulary_update_id_new_name_and_same_tags(self):
- self._update_vocabulary({'id': self.genre_vocab['id'],
- 'name': 'new name',
- 'tags': self.genre_vocab['tags']}, self.sysadmin_user)
-
- def test_vocabulary_update_not_exists(self):
- '''Test the error response given when a user tries to update a
+ self._update_vocabulary(
+ {
+ "id": self.genre_vocab["id"],
+ "name": "new name",
+ "tags": self.genre_vocab["tags"],
+ },
+ self.sysadmin_user,
+ )
+
+ def test_vocabulary_update_not_exists(self, app):
+ """Test the error response given when a user tries to update a
vocabulary that doesn't exist.
- '''
- params = {'id': 'xxxxxxx', 'name': 'updated_name'}
+ """
+ params = {"id": "xxxxxxx", "name": "updated_name"}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_update',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- assert response.json['error']['message'].startswith('Not found: ')
-
- def test_vocabulary_update_no_id(self):
- params = {'name': 'bagel radio'}
+ response = app.post(
+ "/api/action/vocabulary_update",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=404,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["message"].startswith("Not found: ")
+
+ def test_vocabulary_update_no_id(self, app):
+ params = {"name": "bagel radio"}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_update',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert 'id' in response.json['error']
- assert response.json['error']['id'] == 'id not in data'
-
- def test_vocabulary_update_not_logged_in(self):
- '''Test that users who are not logged in cannot update vocabularies.'''
- params = {'id': self.genre_vocab['id']}
+ response = app.post(
+ "/api/action/vocabulary_update",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert "id" in response.json["error"]
+ assert response.json["error"]["id"] == "id not in data"
+
+ def test_vocabulary_update_not_logged_in(self, app):
+ """Test that users who are not logged in cannot update vocabularies."""
+ params = {"id": self.genre_vocab["id"]}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_update',
- params=param_string,
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
+ response = app.post(
+ "/api/action/vocabulary_update", params=param_string, status=403
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
def test_vocabulary_update_with_tags(self):
tags = [
- {'name': 'drone'},
- {'name': 'noise'},
- {'name': 'fuzz'},
- {'name': 'field recordings'},
- {'name': 'hypnagogia'},
- {'name': 'textures without rhythm'},
- ]
+ {"name": "drone"},
+ {"name": "noise"},
+ {"name": "fuzz"},
+ {"name": "field recordings"},
+ {"name": "hypnagogia"},
+ {"name": "textures without rhythm"},
+ ]
self._update_vocabulary(
- {
- 'id': self.genre_vocab['id'],
- 'name': self.genre_vocab['name'],
- 'tags': tags
- },
- self.sysadmin_user)
-
- params = {'id': self.genre_vocab['id']}
- response = self._post('/api/action/vocabulary_show', params)
+ {
+ "id": self.genre_vocab["id"],
+ "name": self.genre_vocab["name"],
+ "tags": tags,
+ },
+ self.sysadmin_user,
+ )
+
+ params = {"id": self.genre_vocab["id"]}
+ response = self._post("/api/action/vocabulary_show", params)
# Check that retrieving the vocab by name gives the same result.
- assert len(response['result']['tags']) == len(tags)
+ assert len(response["result"]["tags"]) == len(tags)
- def test_vocabulary_update_not_authorized(self):
- '''Test that users who are not authorized cannot update vocabs.'''
- params = {'id': self.genre_vocab['id']}
+ def test_vocabulary_update_not_authorized(self, app):
+ """Test that users who are not authorized cannot update vocabs."""
+ params = {"id": self.genre_vocab["id"]}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_update',
- params=param_string,
- extra_environ={'Authorization':
- str(self.normal_user.apikey)},
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['message'] == 'Access denied'
-
- def test_vocabulary_update_bad_tags(self):
- '''Test updating vocabularies with invalid tags.
-
- '''
+ response = app.post(
+ "/api/action/vocabulary_update",
+ params=param_string,
+ extra_environ={"Authorization": str(self.normal_user.apikey)},
+ status=403,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["message"] == "Access denied"
+
+ def test_vocabulary_update_bad_tags(self, app):
+ """Test updating vocabularies with invalid tags.
+
+ """
apikey = str(self.sysadmin_user.apikey)
for tags in (
- [{'id': 'xxx'}, {'name': 'foo'}],
- [{'name': 'foo'}, {'name': None}],
- [{'name': 'foo'}, {'name': ''}],
- [{'name': 'foo'}, {'name': 'f'}],
- [{'name': 'f' * 200}, {'name': 'foo'}],
- [{'name': 'Invalid!'}, {'name': 'foo'}],
- ):
- params = {'id': self.genre_vocab['name'], 'tags': tags}
- response = self.app.post('/api/action/vocabulary_update',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization': apikey},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['tags']
-
- def test_vocabulary_update_none_tags(self):
- '''Test updating vocabularies with None for 'tags'.
-
- '''
- params = {'id': self.genre_vocab['id'], 'tags': None}
- response = self.app.post('/api/action/vocabulary_update',
+ [{"id": "xxx"}, {"name": "foo"}],
+ [{"name": "foo"}, {"name": None}],
+ [{"name": "foo"}, {"name": ""}],
+ [{"name": "foo"}, {"name": "f"}],
+ [{"name": "f" * 200}, {"name": "foo"}],
+ [{"name": "Invalid!"}, {"name": "foo"}],
+ ):
+ params = {"id": self.genre_vocab["name"], "tags": tags}
+ response = app.post(
+ "/api/action/vocabulary_update",
params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=400)
+ extra_environ={"Authorization": apikey},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["tags"]
+
+ def test_vocabulary_update_none_tags(self, app):
+ """Test updating vocabularies with None for 'tags'.
+
+ """
+ params = {"id": self.genre_vocab["id"], "tags": None}
+ response = app.post(
+ "/api/action/vocabulary_update",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=400,
+ )
assert "Integrity Error" in response.body, response.body
- def test_vocabulary_update_empty_tags(self):
- '''Test updating vocabularies with [] for 'tags'.
-
- '''
- params = {'id': self.genre_vocab['id'], 'tags': []}
- response = self.app.post('/api/action/vocabulary_update',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=200)
- assert response.json['success'] is True
- assert response.json['result']
- updated_vocab = response.json['result']
- assert updated_vocab['name'] == self.genre_vocab['name']
- assert updated_vocab['id'] == self.genre_vocab['id']
- assert updated_vocab['tags'] == []
- params = {'id': updated_vocab['id']}
- response = self._post('/api/action/vocabulary_show', params)
- assert response['success'] is True
- assert response['result'] == updated_vocab
+ def test_vocabulary_update_empty_tags(self, app):
+ """Test updating vocabularies with [] for 'tags'.
+
+ """
+ params = {"id": self.genre_vocab["id"], "tags": []}
+ response = app.post(
+ "/api/action/vocabulary_update",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=200,
+ )
+ assert response.json["success"] is True
+ assert response.json["result"]
+ updated_vocab = response.json["result"]
+ assert updated_vocab["name"] == self.genre_vocab["name"]
+ assert updated_vocab["id"] == self.genre_vocab["id"]
+ assert updated_vocab["tags"] == []
+ params = {"id": updated_vocab["id"]}
+ response = self._post("/api/action/vocabulary_show", params)
+ assert response["success"] is True
+ assert response["result"] == updated_vocab
tags = self._list_tags(updated_vocab)
assert tags == []
- def test_vocabulary_delete(self):
- self._delete_vocabulary(self.genre_vocab['id'], self.sysadmin_user)
+ def test_vocabulary_delete(self, app):
+ vocab_id = self.genre_vocab["id"]
+ user = self.sysadmin_user
+ if user:
+ extra_environ = {"Authorization": str(user.apikey)}
+ else:
+ extra_environ = None
+ params = {"id": vocab_id}
+ response = self._post(
+ "/api/action/vocabulary_delete",
+ params=params,
+ extra_environ=extra_environ,
+ )
+
+ # Check the values of the response.
+ assert response["success"] is True
+ assert response["result"] is None
+ response["result"]
+
+ # Get the list of vocabularies.
+ response = self._post("/api/action/vocabulary_list")
+ assert response["success"] is True
+ assert response["result"]
+ # Check that the vocabulary we deleted is not in the list.
+ assert vocab_id not in [vocab["id"] for vocab in response["result"]]
- def test_vocabulary_delete_not_exists(self):
- '''Test the error response given when a user tries to delete a
+ # Check that the deleted vocabulary can no longer be retrieved.
+ response = app.post(
+ "/api/action/vocabulary_show",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=404,
+ )
+ assert response.json["success"] is False
+
+ def test_vocabulary_delete_not_exists(self, app):
+ """Test the error response given when a user tries to delete a
vocabulary that doesn't exist.
- '''
- params = {'id': 'xxxxxxx'}
+ """
+ params = {"id": "xxxxxxx"}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_delete',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- assert response.json['error']['message'].startswith('Not found: '
- 'Could not find vocabulary')
-
- def test_vocabulary_delete_no_id(self):
- '''Test the error response given when a user tries to delete a
+ response = app.post(
+ "/api/action/vocabulary_delete",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=404,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["message"].startswith(
+ "Not found: " "Could not find vocabulary"
+ )
+
+ def test_vocabulary_delete_no_id(self, app):
+ """Test the error response given when a user tries to delete a
vocabulary without giving the vocabulary id.
- '''
+ """
params = {}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_delete',
- params=param_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert 'id' in response.json['error']
- assert response.json['error']['id'] == 'id not in data'
-
- def test_vocabulary_delete_not_logged_in(self):
- '''Test that users who are not logged in cannot delete vocabularies.'''
- params = {'id': self.genre_vocab['id']}
+ response = app.post(
+ "/api/action/vocabulary_delete",
+ params=param_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert "id" in response.json["error"]
+ assert response.json["error"]["id"] == "id not in data"
+
+ def test_vocabulary_delete_not_logged_in(self, app):
+ """Test that users who are not logged in cannot delete vocabularies."""
+ params = {"id": self.genre_vocab["id"]}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_delete',
- params=param_string,
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
-
- def test_vocabulary_delete_not_authorized(self):
- '''Test that users who are not authorized cannot delete vocabs.'''
- params = {'id': self.genre_vocab['id']}
+ response = app.post(
+ "/api/action/vocabulary_delete", params=param_string, status=403
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
+
+ def test_vocabulary_delete_not_authorized(self, app):
+ """Test that users who are not authorized cannot delete vocabs."""
+ params = {"id": self.genre_vocab["id"]}
param_string = helpers.json.dumps(params)
- response = self.app.post('/api/action/vocabulary_delete',
- params=param_string,
- extra_environ={'Authorization':
- str(self.normal_user.apikey)},
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
+ response = app.post(
+ "/api/action/vocabulary_delete",
+ params=param_string,
+ extra_environ={"Authorization": str(self.normal_user.apikey)},
+ status=403,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
def test_add_tag_to_vocab(self):
- '''Test that a tag can be added to and then retrieved from a vocab.'''
+ """Test that a tag can be added to and then retrieved from a vocab."""
vocab = self.genre_vocab
tags_before = self._list_tags(vocab)
- tag_created = self._create_tag(self.sysadmin_user, 'noise', vocab)
+ tag_created = self._create_tag(self.sysadmin_user, "noise", vocab)
tags_after = self._list_tags(vocab)
- new_tag_names = [tag_name for tag_name in tags_after if tag_name not in
- tags_before]
+ new_tag_names = [
+ tag_name for tag_name in tags_after if tag_name not in tags_before
+ ]
assert len(new_tag_names) == 1
- assert tag_created['name'] in new_tag_names
+ assert tag_created["name"] in new_tag_names
- def test_add_tag_no_vocab(self):
- '''Test the error response when a user tries to create a tag without
+ def test_add_tag_no_vocab(self, app):
+ """Test the error response when a user tries to create a tag without
specifying a vocab.
- '''
- tag_dict = {'name': 'noise'}
+ """
+ tag_dict = {"name": "noise"}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['vocabulary_id'] == ['Missing value']
-
- def test_add_tag_vocab_not_exists(self):
- '''Test the error response when a user tries to add a tag to a vocab
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["vocabulary_id"] == ["Missing value"]
+
+ def test_add_tag_vocab_not_exists(self, app):
+ """Test the error response when a user tries to add a tag to a vocab
that doesn't exist.
- '''
- tag_dict = {'name': 'noise', 'vocabulary_id': 'does not exist'}
+ """
+ tag_dict = {"name": "noise", "vocabulary_id": "does not exist"}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['vocabulary_id'] == [
- 'Tag vocabulary was not found.']
-
- def test_add_tag_already_added(self):
- '''Test the error response when a user tries to add a tag to a vocab
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["vocabulary_id"] == [
+ "Tag vocabulary was not found."
+ ]
+
+ def test_add_tag_already_added(self, app):
+ """Test the error response when a user tries to add a tag to a vocab
that already has a tag with the same name.
- '''
+ """
self.test_add_tag_to_vocab()
vocab = self.genre_vocab
- tag_dict = {'name': 'noise', 'vocabulary_id': vocab['id']}
+ tag_dict = {"name": "noise", "vocabulary_id": vocab["id"]}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['vocabulary_id'][0].startswith(
- 'Tag noise already belongs to vocabulary')
-
- def test_add_tag_with_id(self):
- '''Test the error response when a user tries to specify the tag ID when
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["vocabulary_id"][0].startswith(
+ "Tag noise already belongs to vocabulary"
+ )
+
+ def test_add_tag_with_id(self, app):
+ """Test the error response when a user tries to specify the tag ID when
adding a tag to a vocab.
- '''
+ """
tag_dict = {
- 'id': 'dsagdsgsgsd',
- 'name': 'noise',
- 'vocabulary_id': self.genre_vocab['id']
- }
+ "id": "dsagdsgsgsd",
+ "name": "noise",
+ "vocabulary_id": self.genre_vocab["id"],
+ }
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['id'] == [u'The input field id was not '
- 'expected.']
-
- def test_add_tag_without_name(self):
- '''Test the error response when a user tries to create a tag without a
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["id"] == [
+ u"The input field id was not " "expected."
+ ]
+
+ def test_add_tag_without_name(self, app):
+ """Test the error response when a user tries to create a tag without a
name.
- '''
- tag_dict = {
- 'vocabulary_id': self.genre_vocab['id']
- }
+ """
+ tag_dict = {"vocabulary_id": self.genre_vocab["id"]}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['name'] == [u'Missing value']
-
- def test_add_tag_invalid_name(self):
- for name in ('Not a valid tag name!', '', None):
- tag_dict = {
- 'name': name,
- 'vocabulary_id': self.genre_vocab['id']
- }
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["name"] == [u"Missing value"]
+
+ def test_add_tag_invalid_name(self, app):
+ for name in ("Not a valid tag name!", "", None):
+ tag_dict = {"name": name, "vocabulary_id": self.genre_vocab["id"]}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['name']
-
- def test_add_tag_invalid_vocab_id(self):
- tag_dict = {
- 'name': 'noise',
- 'vocabulary_id': 'xxcxzczxczxc',
- }
- tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
+ response = app.post(
+ "/api/action/tag_create",
params=tag_string,
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert response.json['error']['vocabulary_id'] == [
- u'Tag vocabulary was not found.']
-
- def test_add_tag_not_logged_in(self):
- tag_dict = {
- 'name': 'noise',
- 'vocabulary_id': self.genre_vocab['id']
- }
+ extra_environ={"Authorization": str(self.sysadmin_apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["name"]
+
+ def test_add_tag_invalid_vocab_id(self, app):
+ tag_dict = {"name": "noise", "vocabulary_id": "xxcxzczxczxc"}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
-
- def test_add_tag_not_authorized(self):
- tag_dict = {
- 'name': 'noise',
- 'vocabulary_id': self.genre_vocab['id']
- }
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["vocabulary_id"] == [
+ u"Tag vocabulary was not found."
+ ]
+
+ def test_add_tag_not_logged_in(self, app):
+ tag_dict = {"name": "noise", "vocabulary_id": self.genre_vocab["id"]}
tag_string = helpers.json.dumps(tag_dict)
- response = self.app.post('/api/action/tag_create',
- params=tag_string,
- extra_environ={'Authorization':
- str(self.normal_user.apikey)},
- status=403)
- assert response.json['success'] is False
- assert response.json['error']['__type'] == 'Authorization Error'
+ response = app.post(
+ "/api/action/tag_create", params=tag_string, status=403
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
+
+ def test_add_tag_not_authorized(self, app):
+ tag_dict = {"name": "noise", "vocabulary_id": self.genre_vocab["id"]}
+ tag_string = helpers.json.dumps(tag_dict)
+ response = app.post(
+ "/api/action/tag_create",
+ params=tag_string,
+ extra_environ={"Authorization": str(self.normal_user.apikey)},
+ status=403,
+ )
+ assert response.json["success"] is False
+ assert response.json["error"]["__type"] == "Authorization Error"
def test_add_vocab_tag_to_dataset(self):
- '''Test that a tag belonging to a vocab can be added to a dataset,
- retrieved from the dataset, and then removed from the dataset.'''
+ """Test that a tag belonging to a vocab can be added to a dataset,
+ retrieved from the dataset, and then removed from the dataset."""
- ckan.model.repo.rebuild_db()
- self.setup()
ckan.tests.legacy.CreateTestData.create()
# First add a tag to the vocab.
vocab = self.genre_vocab
- tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
+ tag = self._create_tag(self.sysadmin_user, "noise", vocab)
# Get a package from the API.
- package = (self._post('/api/action/package_show',
- {'id': self._post('/api/action/package_list')['result'][0]})
- ['result'])
+ package = self._post(
+ "/api/action/package_show",
+ {"id": self._post("/api/action/package_list")["result"][0]},
+ )["result"]
# Add the new vocab tag to the package.
- package['tags'].append(tag)
+ package["tags"].append(tag)
- updated_package = self._post('/api/action/package_update',
- params={'id': package['id'], 'tags': package['tags']},
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)})['result']
+ updated_package = self._post(
+ "/api/action/package_update",
+ params={"id": package["id"], "tags": package["tags"]},
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ )["result"]
# Test that the new vocab tag was added to the package.
- tags_in_pkg = [tag_in_pkg for tag_in_pkg in updated_package['tags'] if
- tag_in_pkg['name'] == tag['name'] and
- tag_in_pkg['vocabulary_id'] == tag['vocabulary_id']]
+ tags_in_pkg = [
+ tag_in_pkg
+ for tag_in_pkg in updated_package["tags"]
+ if tag_in_pkg["name"] == tag["name"]
+ and tag_in_pkg["vocabulary_id"] == tag["vocabulary_id"]
+ ]
assert len(tags_in_pkg) == 1
# Test that the package appears in tag_show.
- noise_tag = self._post('/api/action/tag_show',
- params={'id': 'noise',
- 'vocabulary_id': vocab['id'],
- 'include_datasets': True}
- )['result']
- assert len([p for p in noise_tag['packages'] if
- p['id'] == updated_package['id']]) == 1
+ noise_tag = self._post(
+ "/api/action/tag_show",
+ params={
+ "id": "noise",
+ "vocabulary_id": vocab["id"],
+ "include_datasets": True,
+ },
+ )["result"]
+ assert (
+ len(
+ [
+ p
+ for p in noise_tag["packages"]
+ if p["id"] == updated_package["id"]
+ ]
+ )
+ == 1
+ )
# Remove the new vocab tag from the package.
- package['tags'].remove(tag)
- updated_package = self._post('/api/action/package_update',
- params={'id': package['id'], 'tags': package['tags']},
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)})['result']
+ package["tags"].remove(tag)
+ updated_package = self._post(
+ "/api/action/package_update",
+ params={"id": package["id"], "tags": package["tags"]},
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ )["result"]
# Test that the tag no longer appears in the list of tags for the
# package.
- package = (self._post('/api/action/package_show',
- {'id': self._post('/api/action/package_list')['result'][0]})
- ['result'])
- tags_in_pkg = [tag_in_pkg for tag_in_pkg in package['tags'] if
- tag_in_pkg['name'] == tag['name'] and
- tag_in_pkg['vocabulary_id'] == tag['vocabulary_id']]
+ package = self._post(
+ "/api/action/package_show",
+ {"id": self._post("/api/action/package_list")["result"][0]},
+ )["result"]
+ tags_in_pkg = [
+ tag_in_pkg
+ for tag_in_pkg in package["tags"]
+ if tag_in_pkg["name"] == tag["name"]
+ and tag_in_pkg["vocabulary_id"] == tag["vocabulary_id"]
+ ]
assert len(tags_in_pkg) == 0
def test_delete_tag_from_vocab(self):
- '''Test that a tag can be deleted from a vocab.'''
+ """Test that a tag can be deleted from a vocab."""
- ckan.model.repo.rebuild_db()
- self.setup()
ckan.tests.legacy.CreateTestData.create()
vocab = self.genre_vocab
# First add some tags to the vocab.
- noise_tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
- ragga_tag = self._create_tag(self.sysadmin_user, 'ragga', vocab)
- grunge_tag = self._create_tag(self.sysadmin_user, 'grunge', vocab)
- funk_tag = self._create_tag(self.sysadmin_user, 'funk', vocab)
+ noise_tag = self._create_tag(self.sysadmin_user, "noise", vocab)
+ ragga_tag = self._create_tag(self.sysadmin_user, "ragga", vocab)
+ grunge_tag = self._create_tag(self.sysadmin_user, "grunge", vocab)
+ funk_tag = self._create_tag(self.sysadmin_user, "funk", vocab)
tags = (noise_tag, ragga_tag, grunge_tag, funk_tag)
# Get a package from the API.
- package = (self._post('/api/action/package_show',
- {'id': self._post('/api/action/package_list')['result'][0]})
- ['result'])
+ package = self._post(
+ "/api/action/package_show",
+ {"id": self._post("/api/action/package_list")["result"][0]},
+ )["result"]
# Add the new vocab tags to the package.
for tag in tags:
- package['tags'].append(tag)
+ package["tags"].append(tag)
- updated_package = self._post('/api/action/package_update',
- params={'id': package['id'], 'tags': package['tags']},
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)})['result']
+ updated_package = self._post(
+ "/api/action/package_update",
+ params={"id": package["id"], "tags": package["tags"]},
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ )["result"]
# Test that the new vocab tags were added to the package.
for tag in tags:
- tags_in_pkg = [tag_in_pkg for tag_in_pkg in
- updated_package['tags'] if tag_in_pkg['name'] ==
- tag['name'] and tag_in_pkg['vocabulary_id'] ==
- tag['vocabulary_id']]
+ tags_in_pkg = [
+ tag_in_pkg
+ for tag_in_pkg in updated_package["tags"]
+ if tag_in_pkg["name"] == tag["name"]
+ and tag_in_pkg["vocabulary_id"] == tag["vocabulary_id"]
+ ]
assert len(tags_in_pkg) == 1
# Now delete the tags from the vocab.
tags_before = self._list_tags(vocab)
- self._delete_tag(self.sysadmin_user, noise_tag['name'], vocab['name'])
- self._delete_tag(self.sysadmin_user, ragga_tag['id'], vocab['name'])
- self._delete_tag(self.sysadmin_user, grunge_tag['id'], vocab['id'])
- self._delete_tag(self.sysadmin_user, funk_tag['name'], vocab['id'])
+ self._delete_tag(self.sysadmin_user, noise_tag["name"], vocab["name"])
+ self._delete_tag(self.sysadmin_user, ragga_tag["id"], vocab["name"])
+ self._delete_tag(self.sysadmin_user, grunge_tag["id"], vocab["id"])
+ self._delete_tag(self.sysadmin_user, funk_tag["name"], vocab["id"])
# Test that the tags no longer appear in the list of tags for the
# vocab.
tags_after = self._list_tags(vocab)
assert len(tags_after) == len(tags_before) - 4
- assert tag['name'] not in tags_after
- difference = [tag_name for tag_name in tags_before if tag_name not in
- tags_after]
- assert sorted(difference) == sorted(tag['name'] for tag in tags)
+ assert tag["name"] not in tags_after
+ difference = [
+ tag_name for tag_name in tags_before if tag_name not in tags_after
+ ]
+ assert sorted(difference) == sorted([tag["name"] for tag in tags])
# Test that the tags no longer appear in the list of tags for the
# package.
- package = (self._post('/api/action/package_show',
- {'id': self._post('/api/action/package_list')['result'][0]})
- ['result'])
+ package = self._post(
+ "/api/action/package_show",
+ {"id": self._post("/api/action/package_list")["result"][0]},
+ )["result"]
for tag in tags:
- tags_in_pkg = [tag_in_pkg for tag_in_pkg in package['tags'] if
- tag_in_pkg['name'] == tag['name'] and
- tag_in_pkg['vocabulary_id'] == tag['vocabulary_id']]
+ tags_in_pkg = [
+ tag_in_pkg
+ for tag_in_pkg in package["tags"]
+ if tag_in_pkg["name"] == tag["name"]
+ and tag_in_pkg["vocabulary_id"] == tag["vocabulary_id"]
+ ]
assert len(tags_in_pkg) == 0
def test_delete_free_tag(self):
- '''Test that a free tag can be deleted via the API, and is
+ """Test that a free tag can be deleted via the API, and is
automatically removed from datasets.
- '''
- ckan.model.repo.rebuild_db()
- self.setup()
+ """
ckan.tests.legacy.CreateTestData.create()
# Get a package from the API.
- package = (self._post('/api/action/package_show',
- {'id': self._post('/api/action/package_list')['result'][0]})
- ['result'])
- package_id = package['id']
+ package = self._post(
+ "/api/action/package_show",
+ {"id": self._post("/api/action/package_list")["result"][0]},
+ )["result"]
+ package_id = package["id"]
# Add some new free tags to the package.
- tags = package['tags']
- tags.append({'name': 'ducks'})
- tags.append({'name': 'birds'})
- self._post('/api/action/package_update',
- params={'id': package['id'], 'tags': tags},
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)})
+ tags = package["tags"]
+ tags.append({"name": "ducks"})
+ tags.append({"name": "birds"})
+ self._post(
+ "/api/action/package_update",
+ params={"id": package["id"], "tags": tags},
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ )
# Test that the new tags appear in the list of tags.
tags = self._list_tags()
- assert [tag for tag in tags].count('ducks') == 1
- assert [tag for tag in tags].count('birds') == 1
+ assert [tag for tag in tags].count("ducks") == 1
+ assert [tag for tag in tags].count("birds") == 1
# Test that the new tags appear in the package's list of tags.
- package = (self._post('/api/action/package_show',
- {'id': package_id})['result'])
- packages_tags = [tag['name'] for tag in package['tags']]
- assert [tag for tag in packages_tags].count('ducks') == 1
- assert [tag for tag in packages_tags].count('birds') == 1
+ package = self._post("/api/action/package_show", {"id": package_id})[
+ "result"
+ ]
+ packages_tags = [tag["name"] for tag in package["tags"]]
+ assert [tag for tag in packages_tags].count("ducks") == 1
+ assert [tag for tag in packages_tags].count("birds") == 1
# Now delete the tags.
- self._delete_tag(self.sysadmin_user, 'ducks')
- birds_tag_id = self._post('/api/action/tag_show',
- {'id': 'birds'})['result']['id']
+ self._delete_tag(self.sysadmin_user, "ducks")
+ birds_tag_id = self._post("/api/action/tag_show", {"id": "birds"})[
+ "result"
+ ]["id"]
self._delete_tag(self.sysadmin_user, birds_tag_id)
# Test that the tags no longer appear in the list of tags.
tags = self._list_tags()
- assert [tag for tag in tags].count('ducks') == 0
- assert [tag for tag in tags].count('birds') == 0
+ assert [tag for tag in tags].count("ducks") == 0
+ assert [tag for tag in tags].count("birds") == 0
# Test that the tags no longer appear in the package's list of tags.
- package = (self._post('/api/action/package_show',
- {'id': package_id})['result'])
- packages_tags = [tag['name'] for tag in package['tags']]
- assert [tag for tag in packages_tags].count('ducks') == 0
- assert [tag for tag in packages_tags].count('birds') == 0
-
- def test_delete_tag_no_id(self):
- '''Test the error response when a user tries to delete a tag without
+ package = self._post("/api/action/package_show", {"id": package_id})[
+ "result"
+ ]
+ packages_tags = [tag["name"] for tag in package["tags"]]
+ assert [tag for tag in packages_tags].count("ducks") == 0
+ assert [tag for tag in packages_tags].count("birds") == 0
+
+ def test_delete_tag_no_id(self, app):
+ """Test the error response when a user tries to delete a tag without
giving the tag id.
- '''
+ """
vocab = self.genre_vocab
- self._create_tag(self.sysadmin_user, 'noise', vocab)
+ self._create_tag(self.sysadmin_user, "noise", vocab)
- for tag_id in ('missing', '', None):
+ for tag_id in ("missing", "", None):
# Now try to delete the tag from the vocab.
- params = {'vocabulary_id': vocab['name']}
- if tag_id != 'missing':
- params['id'] = tag_id
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=409)
- assert response.json['success'] is False
- assert 'id' in response.json['error']
- assert response.json['error']['id'] == 'id not in data'
-
- def test_delete_tag_no_vocab(self):
- '''Test the error response when a user tries to delete a vocab tag
+ params = {"vocabulary_id": vocab["name"]}
+ if tag_id != "missing":
+ params["id"] = tag_id
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ extra_environ={
+ "Authorization": str(self.sysadmin_user.apikey)
+ },
+ status=409,
+ )
+ assert response.json["success"] is False
+ assert "id" in response.json["error"]
+ assert response.json["error"]["id"] == "id not in data"
+
+ def test_delete_tag_no_vocab(self, app):
+ """Test the error response when a user tries to delete a vocab tag
without giving the vocab name.
- '''
+ """
vocab = self.genre_vocab
- tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
+ tag = self._create_tag(self.sysadmin_user, "noise", vocab)
# Now try to delete the tag from the vocab.
- for vocab_name in ('', None, 'missing'):
- params = {'id': tag['name']}
- if vocab_name != 'missing':
- params['vocabulary_id'] = vocab_name
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- msg = response.json['error']['message']
+ for vocab_name in ("", None, "missing"):
+ params = {"id": tag["name"]}
+ if vocab_name != "missing":
+ params["vocabulary_id"] = vocab_name
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ extra_environ={
+ "Authorization": str(self.sysadmin_user.apikey)
+ },
+ status=404,
+ )
+ assert response.json["success"] is False
+ msg = response.json["error"]["message"]
assert msg == u'Not found: Could not find tag "{0}"'.format(
- tag['name']), msg
+ tag["name"]
+ ), msg
- def test_delete_tag_not_exists(self):
- '''Test the error response when a user tries to delete a from a vocab
+ def test_delete_tag_not_exists(self, app):
+ """Test the error response when a user tries to delete a from a vocab
but there is no tag with that name in the vocab.
- '''
+ """
vocab = self.genre_vocab
- self._create_tag(self.sysadmin_user, 'noise', vocab)
-
- params = {'id': 'nonexistent',
- 'vocabulary_id': self.genre_vocab['name']}
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- msg = response.json['error']['message']
- assert msg == u'Not found: Could not find tag "%s"' % 'nonexistent', \
- msg
-
- def test_delete_tag_vocab_not_exists(self):
- '''Test the error response when a user tries to delete a from a vocab
+ self._create_tag(self.sysadmin_user, "noise", vocab)
+
+ params = {
+ "id": "nonexistent",
+ "vocabulary_id": self.genre_vocab["name"],
+ }
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=404,
+ )
+ assert response.json["success"] is False
+ msg = response.json["error"]["message"]
+ assert (
+ msg == u'Not found: Could not find tag "%s"' % "nonexistent"
+ ), msg
+
+ def test_delete_tag_vocab_not_exists(self, app):
+ """Test the error response when a user tries to delete a from a vocab
but there is no vocab with that name.
- '''
+ """
vocab = self.genre_vocab
- tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
-
- params = {'id': tag['name'],
- 'vocabulary_id': 'nonexistent'}
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- msg = response.json['error']['message']
- assert msg == u"Not found: could not find vocabulary 'nonexistent'", \
- msg
-
- def test_delete_tag_invalid_tag(self):
- '''Test the error response when a user tries to delete a tag but gives
+ tag = self._create_tag(self.sysadmin_user, "noise", vocab)
+
+ params = {"id": tag["name"], "vocabulary_id": "nonexistent"}
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ status=404,
+ )
+ assert response.json["success"] is False
+ msg = response.json["error"]["message"]
+ assert (
+ msg == u"Not found: could not find vocabulary 'nonexistent'"
+ ), msg
+
+ def test_delete_tag_invalid_tag(self, app):
+ """Test the error response when a user tries to delete a tag but gives
an invalid tag name.
- '''
+ """
vocab = self.genre_vocab
- self._create_tag(self.sysadmin_user, 'noise', vocab)
-
- for tag_name in ('Invalid!', ' '):
- params = {'id': tag_name,
- 'vocabulary_id': self.genre_vocab['name']}
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- msg = response.json['error']['message']
+ self._create_tag(self.sysadmin_user, "noise", vocab)
+
+ for tag_name in ("Invalid!", " "):
+ params = {
+ "id": tag_name,
+ "vocabulary_id": self.genre_vocab["name"],
+ }
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ extra_environ={
+ "Authorization": str(self.sysadmin_user.apikey)
+ },
+ status=404,
+ )
+ assert response.json["success"] is False
+ msg = response.json["error"]["message"]
assert msg == u'Not found: Could not find tag "%s"' % tag_name, msg
- def test_delete_tag_invalid_vocab(self):
- '''Test the error response when a user tries to delete a tag but gives
+ def test_delete_tag_invalid_vocab(self, app):
+ """Test the error response when a user tries to delete a tag but gives
an invalid vocab name.
- '''
- vocab = self.genre_vocab
- tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
-
- for vocab_name in ('Invalid!', ' '):
- params = {'id': tag['name'], 'vocabulary_id': vocab_name}
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.sysadmin_user.apikey)},
- status=404)
- assert response.json['success'] is False
- msg = response.json['error']['message']
- assert msg == u"Not found: could not find vocabulary '%s'" \
- % vocab_name, msg
-
- def test_delete_tag_not_logged_in(self):
+ """
vocab = self.genre_vocab
- tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
+ tag = self._create_tag(self.sysadmin_user, "noise", vocab)
- params = {'id': tag['name'],
- 'vocabulary_id': self.genre_vocab['name']}
- response = self.app.post('/api/action/tag_delete',
+ for vocab_name in ("Invalid!", " "):
+ params = {"id": tag["name"], "vocabulary_id": vocab_name}
+ response = app.post(
+ "/api/action/tag_delete",
params=helpers.json.dumps(params),
- status=403)
- assert response.json['success'] is False
- error = response.json['error']['__type']
- assert error == u"Authorization Error", error
+ extra_environ={
+ "Authorization": str(self.sysadmin_user.apikey)
+ },
+ status=404,
+ )
+ assert response.json["success"] is False
+ msg = response.json["error"]["message"]
+ assert (
+ msg
+ == u"Not found: could not find vocabulary '%s'" % vocab_name
+ ), msg
- def test_delete_tag_not_authorized(self):
+ def test_delete_tag_not_logged_in(self, app):
vocab = self.genre_vocab
- tag = self._create_tag(self.sysadmin_user, 'noise', vocab)
+ tag = self._create_tag(self.sysadmin_user, "noise", vocab)
+
+ params = {"id": tag["name"], "vocabulary_id": self.genre_vocab["name"]}
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ status=403,
+ )
+ assert response.json["success"] is False
+ error = response.json["error"]["__type"]
+ assert error == u"Authorization Error", error
- params = {'id': tag['name'],
- 'vocabulary_id': self.genre_vocab['name']}
- response = self.app.post('/api/action/tag_delete',
- params=helpers.json.dumps(params),
- extra_environ={'Authorization':
- str(self.normal_user.apikey)},
- status=403)
- assert response.json['success'] is False
- msg = response.json['error']['__type']
+ def test_delete_tag_not_authorized(self, app):
+ vocab = self.genre_vocab
+ tag = self._create_tag(self.sysadmin_user, "noise", vocab)
+
+ params = {"id": tag["name"], "vocabulary_id": self.genre_vocab["name"]}
+ response = app.post(
+ "/api/action/tag_delete",
+ params=helpers.json.dumps(params),
+ extra_environ={"Authorization": str(self.normal_user.apikey)},
+ status=403,
+ )
+ assert response.json["success"] is False
+ msg = response.json["error"]["__type"]
assert msg == u"Authorization Error"
diff --git a/ckan/tests/legacy/functional/api/test_api.py b/ckan/tests/legacy/functional/api/test_api.py
index 04bbdef63f3..d0e9c310bb8 100644
--- a/ckan/tests/legacy/functional/api/test_api.py
+++ b/ckan/tests/legacy/functional/api/test_api.py
@@ -1,51 +1,50 @@
# encoding: utf-8
-from nose.tools import assert_in
-from ckan.tests.legacy.functional.api.base import *
+from ckan.tests.legacy.functional.api.base import (
+ ApiTestCase,
+ ControllerTestCase,
+ Api3TestCase,
+)
class ApiTestCase(ApiTestCase, ControllerTestCase):
-
- def test_get_api(self):
- offset = self.offset('')
- res = self.app.get(offset, status=[200])
+ def test_get_api(self, app):
+ offset = self.offset("")
+ res = app.get(offset, status=[200])
self.assert_version_data(res)
def assert_version_data(self, res):
data = self.data_from_res(res)
- assert 'version' in data, data
+ assert "version" in data, data
expected_version = self.get_expected_api_version()
- self.assert_equal(data['version'], expected_version)
+ assert data["version"] == expected_version
-class TestApi3(Api3TestCase, ApiTestCase):
- def test_readonly_is_get_able_with_normal_url_params(self):
- '''Test that a read-only action is GET-able
+class TestApi3(Api3TestCase, ApiTestCase):
+ def test_readonly_is_get_able_with_normal_url_params(self, app):
+ """Test that a read-only action is GET-able
Picks an action within `get.py` and checks that it works if it's
invoked with a http GET request. The action's data_dict is
populated from the url parameters.
- '''
- offset = self.offset('/action/package_search')
- params = {'q': 'russian'}
- res = self.app.get(offset, params=params, status=[200])
+ """
+ offset = self.offset("/action/package_search")
+ params = {"q": "russian"}
+ res = app.get(offset, params=params, status=[200])
- def test_sideeffect_action_is_not_get_able(self):
- '''Test that a non-readonly action is not GET-able.
+ def test_sideeffect_action_is_not_get_able(self, app):
+ """Test that a non-readonly action is not GET-able.
Picks an action outside of `get.py`, and checks that it 400s if an
attempt to invoke with a http GET request is made.
- '''
- offset = self.offset('/action/package_create')
- data_dict = {
- 'type': 'dataset',
- 'name': 'a-name'
- }
- res = self.app.get(offset,
- params=data_dict,
- status=[400],
- expect_errors=True)
- assert_in('Bad request - JSON Error: Invalid request.'\
- ' Please use POST method for your request',
- res.body)
+ """
+ offset = self.offset("/action/package_create")
+ data_dict = {"type": "dataset", "name": "a-name"}
+ res = app.get(
+ offset, params=data_dict, status=[400], expect_errors=True
+ )
+ assert (
+ "Bad request - JSON Error: Invalid request."
+ " Please use POST method for your request" in res.body
+ )
diff --git a/ckan/tests/legacy/functional/api/test_email_notifications.py b/ckan/tests/legacy/functional/api/test_email_notifications.py
index 26b9147472c..9f46b59a3fd 100644
--- a/ckan/tests/legacy/functional/api/test_email_notifications.py
+++ b/ckan/tests/legacy/functional/api/test_email_notifications.py
@@ -9,453 +9,609 @@
from ckan.tests.legacy import TestController as ControllerTestCase
-class TestEmailNotifications(mock_mail_server.SmtpServerHarness, ControllerTestCase):
-
+class TestEmailNotifications(
+ mock_mail_server.SmtpServerHarness, ControllerTestCase
+):
@classmethod
def setup_class(cls):
+ model.repo.rebuild_db()
+
mock_mail_server.SmtpServerHarness.setup_class()
tests.CreateTestData.create()
cls.app = helpers._get_test_app()
- joeadmin = model.User.get('joeadmin')
- cls.joeadmin = {'id': joeadmin.id,
- 'apikey': joeadmin.apikey,
- }
- testsysadmin = model.User.get('testsysadmin')
- cls.testsysadmin = {'id': testsysadmin.id,
- 'apikey': testsysadmin.apikey,
- }
- annafan = model.User.get('annafan')
- cls.annafan = {'id': annafan.id,
- 'apikey': annafan.apikey,
- }
+ joeadmin = model.User.get("joeadmin")
+ cls.joeadmin = {"id": joeadmin.id, "apikey": joeadmin.apikey}
+ testsysadmin = model.User.get("testsysadmin")
+ cls.testsysadmin = {
+ "id": testsysadmin.id,
+ "apikey": testsysadmin.apikey,
+ }
+ annafan = model.User.get("annafan")
+ cls.annafan = {"id": annafan.id, "apikey": annafan.apikey}
- @classmethod
- def teardown_class(cls):
- mock_mail_server.SmtpServerHarness.teardown_class()
- model.repo.rebuild_db()
+ # Register a new user.
+ cls.sara = tests.call_action_api(
+ cls.app,
+ "user_create",
+ apikey=cls.testsysadmin["apikey"],
+ name="sara",
+ email="sara@sararollins.com",
+ password="TestPassword1",
+ fullname="Sara Rollins",
+ activity_streams_email_notifications=True,
+ )
def check_email(self, email, address, name, subject):
- assert email[1] == 'info@test.ckan.net'
+ assert email[1] == "info@test.ckan.net"
assert email[2] == [address]
- encoded_subject = 'Subject: =?utf-8?q?{subject}'.format(
- subject=subject.replace(' ', '_'))
+ encoded_subject = "Subject: =?utf-8?q?{subject}".format(
+ subject=subject.replace(" ", "_")
+ )
assert encoded_subject in email[3]
# TODO: Check that body contains link to dashboard and email prefs.
def test_00_send_email_notifications_not_logged_in(self):
- '''Not-logged-in users shouldn't be able to send email notifications.
+ """Not-logged-in users shouldn't be able to send email notifications.
- '''
- tests.call_action_api(self.app, 'send_email_notifications',
- status=403)
+ """
+ tests.call_action_api(self.app, "send_email_notifications", status=403)
- def test_00_send_email_notifications_not_authorized(self):
- '''Unauthorized users shouldn't be able to send email notifications.
+ # def test_00_send_email_notifications_not_authorized(self):
+ """Unauthorized users shouldn't be able to send email notifications.
- '''
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.annafan['apikey'], status=403)
+ """
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.annafan["apikey"],
+ status=403,
+ )
- def test_01_no_email_notifications_after_registration(self):
- '''A new user who isn't following anything shouldn't get any emails.'''
+ # def test_01_no_email_notifications_after_registration(self):
+ """A new user who isn't following anything shouldn't get any emails."""
# Clear any emails already sent due to CreateTestData.create().
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
self.clear_smtp_messages()
- # Register a new user.
- sara = tests.call_action_api(self.app, 'user_create',
- apikey=self.testsysadmin['apikey'], name='sara',
- email='sara@sararollins.com', password='TestPassword1',
- fullname='Sara Rollins',
- activity_streams_email_notifications=True)
-
- # Save the user for later tests to use.
- TestEmailNotifications.sara = sara
-
# No notification emails should be sent to anyone at this point.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
- def test_02_one_new_activity(self):
- '''A user with one new activity should get one email.'''
+ # def test_02_one_new_activity(self):
+ """A user with one new activity should get one email."""
# Make Sara follow something, have to do this to get new activity.
- tests.call_action_api(self.app, 'follow_dataset',
- apikey=self.sara['apikey'], id='warandpeace')
+ tests.call_action_api(
+ self.app,
+ "follow_dataset",
+ apikey=self.sara["apikey"],
+ id="warandpeace",
+ )
# Make someone else update the dataset Sara's following, this should
# create a new activity on Sara's dashboard.
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], name='warandpeace',
- notes='updated')
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ name="warandpeace",
+ notes="updated",
+ )
# Run the email notifier job, it should send one notification email
# to Sara.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 1
email = self.get_smtp_messages()[0]
- self.check_email(email, 'sara@sararollins.com', 'Sara Rollins',
- '1 new activity from CKAN')
+ self.check_email(
+ email,
+ "sara@sararollins.com",
+ "Sara Rollins",
+ "1 new activity from CKAN",
+ )
self.clear_smtp_messages()
- def test_03_multiple_new_activities(self):
- '''Test that a user with multiple new activities gets just one email.
+ # def test_03_multiple_new_activities(self):
+ """Test that a user with multiple new activities gets just one email.
- '''
+ """
# Make someone else update the dataset Sara's following three times,
# this should create three new activities on Sara's dashboard.
for i in range(1, 4):
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], name='warandpeace',
- notes='updated {0} times'.format(i))
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ name="warandpeace",
+ notes="updated {0} times".format(i),
+ )
# Run the email notifier job, it should send one notification email
# to Sara.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 1
email = self.get_smtp_messages()[0]
- self.check_email(email, 'sara@sararollins.com', 'Sara Rollins',
- '3 new activities from CKAN')
+ self.check_email(
+ email,
+ "sara@sararollins.com",
+ "Sara Rollins",
+ "3 new activities from CKAN",
+ )
self.clear_smtp_messages()
- def test_04_no_repeat_email_notifications(self):
- '''Test that a user does not get a second email notification for the
+ # def test_04_no_repeat_email_notifications(self):
+ """Test that a user does not get a second email notification for the
same new activity.
- '''
+ """
# TODO: Assert that Sara has some new activities and has already had
# an email about them.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
- def test_05_no_email_if_seen_on_dashboard(self):
- '''Test that emails are not sent for activities already seen on dash.
+ # def test_05_no_email_if_seen_on_dashboard(self):
+ """Test that emails are not sent for activities already seen on dash.
If a user gets some new activities in her dashboard activity stream,
then views her dashboard activity stream, then she should not got any
email notifications about these new activities.
- '''
+ """
# Make someone else update the dataset Sara's following, this should
# create a new activity on Sara's dashboard.
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], name='warandpeace',
- notes='updated by test_05_no_email_if_seen_on_dashboard')
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ name="warandpeace",
+ notes="updated by test_05_no_email_if_seen_on_dashboard",
+ )
# At this point Sara should have a new activity on her dashboard.
- num_new_activities = tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey'])
+ num_new_activities = tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
assert num_new_activities > 0, num_new_activities
# View Sara's dashboard.
- tests.call_action_api(self.app, 'dashboard_mark_activities_old',
- apikey=self.sara['apikey'])
+ tests.call_action_api(
+ self.app,
+ "dashboard_mark_activities_old",
+ apikey=self.sara["apikey"],
+ )
# No email should be sent.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
- def test_05_no_email_notifications_when_disabled_site_wide(self):
- '''Users should not get email notifications when the feature is
- disabled site-wide by a sysadmin.'''
+ # def test_05_no_email_notifications_when_disabled_site_wide(self):
+ """Users should not get email notifications when the feature is
+ disabled site-wide by a sysadmin."""
- def test_06_enable_email_notifications_sitewide(self):
- '''When a sysadamin enables email notifications site wide, users
+ # def test_06_enable_email_notifications_sitewide(self):
+ """When a sysadamin enables email notifications site wide, users
should not get emails for new activities from before email
notifications were enabled.
- '''
+ """
# It's just easier to separate these tests into their own test class.
class TestEmailNotificationsUserPreference(
- mock_mail_server.SmtpServerHarness,
- ControllerTestCase):
- '''Tests for the email notifications (on/off) user preference.'''
+ mock_mail_server.SmtpServerHarness, ControllerTestCase
+):
+ """Tests for the email notifications (on/off) user preference."""
@classmethod
def setup_class(cls):
+ model.repo.rebuild_db()
mock_mail_server.SmtpServerHarness.setup_class()
tests.CreateTestData.create()
cls.app = helpers._get_test_app()
- joeadmin = model.User.get('joeadmin')
- cls.joeadmin = {'id': joeadmin.id,
- 'apikey': joeadmin.apikey,
- }
- testsysadmin = model.User.get('testsysadmin')
- cls.testsysadmin = {'id': testsysadmin.id,
- 'apikey': testsysadmin.apikey,
- }
-
- @classmethod
- def teardown_class(self):
- mock_mail_server.SmtpServerHarness.teardown_class()
- model.repo.rebuild_db()
+ joeadmin = model.User.get("joeadmin")
+ cls.joeadmin = {"id": joeadmin.id, "apikey": joeadmin.apikey}
+
+ testsysadmin = model.User.get("testsysadmin")
+ cls.testsysadmin = {
+ "id": testsysadmin.id,
+ "apikey": testsysadmin.apikey,
+ }
+ cls.sara = tests.call_action_api(
+ cls.app,
+ "user_create",
+ apikey=cls.testsysadmin["apikey"],
+ name="sara",
+ email="sara@sararollins.com",
+ password="TestPassword1",
+ fullname="Sara Rollins",
+ )
def test_00_email_notifications_disabled_by_default(self):
- '''Email notifications should be disabled for new users.'''
-
- # Register a new user.
- sara = tests.call_action_api(self.app, 'user_create',
- apikey=self.testsysadmin['apikey'], name='sara',
- email='sara@sararollins.com', password='TestPassword1',
- fullname='Sara Rollins')
-
- # Save the user for later tests to use.
- TestEmailNotificationsUserPreference.sara = sara
-
- # Email notifications should be disabled for the new user.
- assert sara['activity_streams_email_notifications'] is False
- assert (tests.call_action_api(self.app, 'user_show',
- apikey=self.sara['apikey'], id='sara')[
- 'activity_streams_email_notifications'] is False)
-
- def test_01_no_email_notifications_when_disabled(self):
- '''Users with email notifications turned off should not get emails.'''
+ """Email notifications should be disabled for new users."""
+ assert self.sara["activity_streams_email_notifications"] is False
+ assert (
+ tests.call_action_api(
+ self.app, "user_show", apikey=self.sara["apikey"], id="sara"
+ )["activity_streams_email_notifications"]
+ is False
+ )
+
+ # def test_01_no_email_notifications_when_disabled(self):
+ """Users with email notifications turned off should not get emails."""
# First make Sara follow something so she gets some new activity in
# her dashboard activity stream.
- tests.call_action_api(self.app, 'follow_dataset',
- apikey=self.sara['apikey'], id='warandpeace')
+ tests.call_action_api(
+ self.app,
+ "follow_dataset",
+ apikey=self.sara["apikey"],
+ id="warandpeace",
+ )
# Now make someone else update the dataset so Sara gets a new activity.
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], id='warandpeace',
- notes='updated')
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ id="warandpeace",
+ notes="updated",
+ )
# Test that Sara has a new activity, just to make sure.
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ > 0
+ )
# No email notifications should be sent to Sara.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
- def test_02_enable_email_notifications(self):
- '''Users should be able to turn email notifications on.'''
+ # def test_02_enable_email_notifications(self):
+ """Users should be able to turn email notifications on."""
# Mark all Sara's new activities as old, just to get a fresh start.
- tests.call_action_api(self.app, 'dashboard_mark_activities_old',
- apikey=self.sara['apikey'])
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) == 0
+ tests.call_action_api(
+ self.app,
+ "dashboard_mark_activities_old",
+ apikey=self.sara["apikey"],
+ )
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ == 0
+ )
# Update the followed dataset a few times so Sara gets a few new
# activities.
for i in range(1, 4):
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], id='warandpeace',
- notes='updated {0} times'.format(i))
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ id="warandpeace",
+ notes="updated {0} times".format(i),
+ )
# Now Sara should have new activities.
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) == 3
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ == 3
+ )
# Run the email notifier job.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
# Enable email notifications for Sara.
- self.sara['activity_streams_email_notifications'] = True
- tests.call_action_api(self.app, 'user_update', **self.sara)
-
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
- assert len(self.get_smtp_messages()) == 0, ("After a user enables "
+ self.sara["activity_streams_email_notifications"] = True
+ tests.call_action_api(self.app, "user_update", **self.sara)
+
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert len(self.get_smtp_messages()) == 0, (
+ "After a user enables "
"email notifications she should _not_ get emails about activities "
"that happened before she enabled them, even if those activities "
- "are still marked as 'new' on her dashboard.")
+ "are still marked as 'new' on her dashboard."
+ )
# Update the package to generate another new activity.
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], id='warandpeace',
- notes='updated yet again')
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ id="warandpeace",
+ notes="updated yet again",
+ )
# Check that Sara has a new activity.
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) == 4
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ == 4
+ )
# Run the email notifier job, this time Sara should get one email.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 1
self.clear_smtp_messages()
- def test_03_disable_email_notifications(self):
- '''Users should be able to turn email notifications off.'''
-
- self.sara['activity_streams_email_notifications'] = False
- tests.call_action_api(self.app, 'user_update', **self.sara)
-
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], id='warandpeace',
- notes='updated yet again')
-
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
-
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ # def test_03_disable_email_notifications(self):
+ """Users should be able to turn email notifications off."""
+
+ self.sara["activity_streams_email_notifications"] = False
+ tests.call_action_api(self.app, "user_update", **self.sara)
+
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ id="warandpeace",
+ notes="updated yet again",
+ )
+
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ > 0
+ )
+
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
class TestEmailNotificationsIniSetting(
- mock_mail_server.SmtpServerHarness, ControllerTestCase):
- '''Tests for the ckan.activity_streams_email_notifications config setting.
+ mock_mail_server.SmtpServerHarness, ControllerTestCase
+):
+ """Tests for the ckan.activity_streams_email_notifications config setting.
+
+ """
- '''
@classmethod
def setup_class(cls):
# Disable the email notifications feature.
cls.app = helpers._get_test_app()
-
+ model.repo.rebuild_db()
mock_mail_server.SmtpServerHarness.setup_class()
tests.CreateTestData.create()
- joeadmin = model.User.get('joeadmin')
- cls.joeadmin = {'id': joeadmin.id,
- 'apikey': joeadmin.apikey,
- }
- testsysadmin = model.User.get('testsysadmin')
- cls.testsysadmin = {'id': testsysadmin.id,
- 'apikey': testsysadmin.apikey,
- }
+ joeadmin = model.User.get("joeadmin")
+ cls.joeadmin = {"id": joeadmin.id, "apikey": joeadmin.apikey}
+ testsysadmin = model.User.get("testsysadmin")
+ cls.testsysadmin = {
+ "id": testsysadmin.id,
+ "apikey": testsysadmin.apikey,
+ }
- @classmethod
- def teardown_class(cls):
- mock_mail_server.SmtpServerHarness.teardown_class()
- model.repo.rebuild_db()
-
- @helpers.change_config('ckan.activity_streams_email_notifications', False)
+ @helpers.change_config("ckan.activity_streams_email_notifications", False)
def test_00_send_email_notifications_feature_disabled(self):
- '''Send_email_notifications API should error when feature disabled.'''
+ """Send_email_notifications API should error when feature disabled."""
# Register a new user.
- sara = tests.call_action_api(self.app, 'user_create',
- apikey=self.testsysadmin['apikey'], name='sara',
- email='sara@sararollins.com', password='TestPassword1',
- fullname='Sara Rollins')
+ sara = tests.call_action_api(
+ self.app,
+ "user_create",
+ apikey=self.testsysadmin["apikey"],
+ name="sara",
+ email="sara@sararollins.com",
+ password="TestPassword1",
+ fullname="Sara Rollins",
+ )
# Save the user for later tests to use.
TestEmailNotificationsIniSetting.sara = sara
# Enable the new user's email notifications preference.
- sara['activity_streams_email_notifications'] = True
- tests.call_action_api(self.app, 'user_update', **sara)
- assert (tests.call_action_api(self.app, 'user_show',
- apikey=self.sara['apikey'], id='sara')[
- 'activity_streams_email_notifications']
- is True)
+ sara["activity_streams_email_notifications"] = True
+ tests.call_action_api(self.app, "user_update", **sara)
+ assert (
+ tests.call_action_api(
+ self.app, "user_show", apikey=self.sara["apikey"], id="sara"
+ )["activity_streams_email_notifications"]
+ is True
+ )
# Make Sara follow something so she gets some new activity in her
# dashboard activity stream.
- tests.call_action_api(self.app, 'follow_dataset',
- apikey=self.sara['apikey'], id='warandpeace')
+ tests.call_action_api(
+ self.app,
+ "follow_dataset",
+ apikey=self.sara["apikey"],
+ id="warandpeace",
+ )
# Now make someone else update the dataset so Sara gets a new activity.
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], id='warandpeace',
- notes='updated')
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ id="warandpeace",
+ notes="updated",
+ )
# Test that Sara has a new activity, just to make sure.
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ > 0
+ )
# We expect an error when trying to call the send_email_notifications
# API, because the feature is disabled by the ini file setting.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'], status=409)
-
- @helpers.change_config('ckan.activity_streams_email_notifications', False)
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ status=409,
+ )
+
+ @helpers.change_config("ckan.activity_streams_email_notifications", False)
def test_01_no_emails_sent_if_turned_off(self):
- '''No emails should be sent if the feature is disabled site-wide.'''
+ """No emails should be sent if the feature is disabled site-wide."""
# No emails should have been sent by the last test.
assert len(self.get_smtp_messages()) == 0
class TestEmailNotificationsSinceIniSetting(
- mock_mail_server.SmtpServerHarness,
- ControllerTestCase):
- '''Tests for the ckan.email_notifications_since config setting.'''
+ mock_mail_server.SmtpServerHarness, ControllerTestCase
+):
+ """Tests for the ckan.email_notifications_since config setting."""
@classmethod
def setup_class(cls):
cls.app = helpers._get_test_app()
+ model.repo.rebuild_db()
mock_mail_server.SmtpServerHarness.setup_class()
tests.CreateTestData.create()
- joeadmin = model.User.get('joeadmin')
- cls.joeadmin = {'id': joeadmin.id,
- 'apikey': joeadmin.apikey,
- }
- testsysadmin = model.User.get('testsysadmin')
- cls.testsysadmin = {'id': testsysadmin.id,
- 'apikey': testsysadmin.apikey,
- }
-
- @classmethod
- def teardown_class(self):
- mock_mail_server.SmtpServerHarness.teardown_class()
- model.repo.rebuild_db()
+ joeadmin = model.User.get("joeadmin")
+ cls.joeadmin = {"id": joeadmin.id, "apikey": joeadmin.apikey}
+ testsysadmin = model.User.get("testsysadmin")
+ cls.testsysadmin = {
+ "id": testsysadmin.id,
+ "apikey": testsysadmin.apikey,
+ }
# Don't send email notifications for activities older than 1
# microsecond
- @helpers.change_config('ckan.email_notifications_since', '.000001')
+ @helpers.change_config("ckan.email_notifications_since", ".000001")
def test_00_email_notifications_since(self):
- '''No emails should be sent for activities older than
+ """No emails should be sent for activities older than
email_notifications_since.
- '''
+ """
# Register a new user.
- sara = tests.call_action_api(self.app, 'user_create',
- apikey=self.testsysadmin['apikey'], name='sara',
- email='sara@sararollins.com', password='TestPassword1',
- fullname='Sara Rollins')
+ sara = tests.call_action_api(
+ self.app,
+ "user_create",
+ apikey=self.testsysadmin["apikey"],
+ name="sara",
+ email="sara@sararollins.com",
+ password="TestPassword1",
+ fullname="Sara Rollins",
+ )
# Save the user for later tests to use.
TestEmailNotificationsSinceIniSetting.sara = sara
# Enable the new user's email notifications preference.
- sara['activity_streams_email_notifications'] = True
- tests.call_action_api(self.app, 'user_update', **sara)
- assert (tests.call_action_api(self.app, 'user_show',
- apikey=self.sara['apikey'], id='sara')[
- 'activity_streams_email_notifications']
- is True)
+ sara["activity_streams_email_notifications"] = True
+ tests.call_action_api(self.app, "user_update", **sara)
+ assert (
+ tests.call_action_api(
+ self.app, "user_show", apikey=self.sara["apikey"], id="sara"
+ )["activity_streams_email_notifications"]
+ is True
+ )
# Make Sara follow something so she gets some new activity in her
# dashboard activity stream.
- tests.call_action_api(self.app, 'follow_dataset',
- apikey=self.sara['apikey'], id='warandpeace')
+ tests.call_action_api(
+ self.app,
+ "follow_dataset",
+ apikey=self.sara["apikey"],
+ id="warandpeace",
+ )
# Now make someone else update the dataset so Sara gets a new activity.
- tests.call_action_api(self.app, 'package_update',
- apikey=self.joeadmin['apikey'], id='warandpeace',
- notes='updated')
+ tests.call_action_api(
+ self.app,
+ "package_update",
+ apikey=self.joeadmin["apikey"],
+ id="warandpeace",
+ notes="updated",
+ )
# Test that Sara has a new activity, just to make sure.
- assert tests.call_action_api(self.app,
- 'dashboard_new_activities_count', apikey=self.sara['apikey']) > 0
+ assert (
+ tests.call_action_api(
+ self.app,
+ "dashboard_new_activities_count",
+ apikey=self.sara["apikey"],
+ )
+ > 0
+ )
# Wait 1 microsecond, just to make sure we're passed the 'since' time.
time.sleep(0.000001)
# No emails should be sent.
- tests.call_action_api(self.app, 'send_email_notifications',
- apikey=self.testsysadmin['apikey'])
+ tests.call_action_api(
+ self.app,
+ "send_email_notifications",
+ apikey=self.testsysadmin["apikey"],
+ )
assert len(self.get_smtp_messages()) == 0
diff --git a/ckan/tests/legacy/functional/api/test_follow.py b/ckan/tests/legacy/functional/api/test_follow.py
index 3db56545773..b7ff86f7b70 100644
--- a/ckan/tests/legacy/functional/api/test_follow.py
+++ b/ckan/tests/legacy/functional/api/test_follow.py
@@ -1,6 +1,6 @@
# encoding: utf-8
-'''Test for the follower API.
+"""Test for the follower API.
This module tests following, unfollowing, getting a list of what you're
following or the number of things you're following, getting a list of who's
@@ -11,60 +11,85 @@
activities from everything you're following), that is tested in
test_dashboard.py.
-'''
+"""
import datetime
import ckan
-from ckan.tests.legacy import are_foreign_keys_supported, SkipTest, CreateTestData, call_action_api
-import ckan.tests.helpers as helpers
+import pytest
+from ckan.tests.legacy import (
+ are_foreign_keys_supported,
+ SkipTest,
+ CreateTestData,
+ call_action_api,
+)
+
def datetime_from_string(s):
- '''Return a standard datetime.datetime object initialised from a string in
+ """Return a standard datetime.datetime object initialised from a string in
the same format used for timestamps in dictized activities (the format
produced by datetime.datetime.isoformat())
- '''
- return datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
+ """
+ return datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%S.%f")
+
def follow(func):
- '''Return a wrapper function for a follow_* function.
+ """Return a wrapper function for a follow_* function.
The wrapper functions test the `followee_list` and `followee_count` API
calls, in addition to any tests carried out by the wrapped function.
- '''
- def wrapped_func(app, follower_id, apikey, object_id, object_arg,
- sysadmin_apikey):
- followee_count_before = call_action_api(app,
- 'followee_count', id=follower_id)
- followees_before = call_action_api(app, 'followee_list',
- id=follower_id, apikey=sysadmin_apikey)
+ """
+
+ def wrapped_func(
+ app, follower_id, apikey, object_id, object_arg, sysadmin_apikey
+ ):
+ followee_count_before = call_action_api(
+ app, "followee_count", id=follower_id
+ )
+ followees_before = call_action_api(
+ app, "followee_list", id=follower_id, apikey=sysadmin_apikey
+ )
func(app, follower_id, apikey, object_id, object_arg, sysadmin_apikey)
- followee_count_after = call_action_api(app,
- 'followee_count', id=follower_id)
- followees_after = call_action_api(app, 'followee_list',
- id=follower_id, apikey=sysadmin_apikey)
+ followee_count_after = call_action_api(
+ app, "followee_count", id=follower_id
+ )
+ followees_after = call_action_api(
+ app, "followee_list", id=follower_id, apikey=sysadmin_apikey
+ )
assert followee_count_after == followee_count_before + 1, (
- "After a user follows an object, the user's `followee_count` "
- "should increase by 1")
+ "After a user follows an object, the user's `followee_count` "
+ "should increase by 1"
+ )
assert len(followees_after) == len(followees_before) + 1, (
- "After a user follows an object, the object should appear in "
- "the user's `followee_list`")
- assert len([followee for followee in followees_after
- if followee['dict']['id'] == object_id]) == 1, (
- "After a user follows an object, the object should appear in "
- "the user's `followee_list`")
+ "After a user follows an object, the object should appear in "
+ "the user's `followee_list`"
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees_after
+ if followee["dict"]["id"] == object_id
+ ]
+ )
+ == 1
+ ), (
+ "After a user follows an object, the object should appear in "
+ "the user's `followee_list`"
+ )
return wrapped_func
@follow
-def follow_user(app, follower_id, apikey, object_id, object_arg,
- sysadmin_apikey):
- '''Test a user starting to follow another user via the API.
+def follow_user(
+ app, follower_id, apikey, object_id, object_arg, sysadmin_apikey
+):
+ """Test a user starting to follow another user via the API.
:param follower_id: id of the user that will be following something.
:param apikey: API key of the user that will be following something.
@@ -72,62 +97,86 @@ def follow_user(app, follower_id, apikey, object_id, object_arg,
:param object_arg: the argument to pass to follow_user as the id of
the object that will be followed, could be the object's id or name.
- '''
+ """
# Record the object's followers count before.
- follower_count_before = call_action_api(app,
- 'user_follower_count', id=object_id)
+ follower_count_before = call_action_api(
+ app, "user_follower_count", id=object_id
+ )
# Record the follower's followees count before.
- followee_count_before = call_action_api(app,
- 'user_followee_count', id=follower_id)
+ followee_count_before = call_action_api(
+ app, "user_followee_count", id=follower_id
+ )
# Check that the user is not already following the object.
- result = call_action_api(app, 'am_following_user',
- id=object_id, apikey=apikey)
+ result = call_action_api(
+ app, "am_following_user", id=object_id, apikey=apikey
+ )
assert result is False
# Make the user start following the object.
before = datetime.datetime.now()
- follower = call_action_api(app, 'follow_user', id=object_arg,
- apikey=apikey)
+ follower = call_action_api(
+ app, "follow_user", id=object_arg, apikey=apikey
+ )
after = datetime.datetime.now()
- assert follower['follower_id'] == follower_id
- assert follower['object_id'] == object_id
- timestamp = datetime_from_string(follower['datetime'])
- assert (timestamp >= before and timestamp <= after), str(timestamp)
+ assert follower["follower_id"] == follower_id
+ assert follower["object_id"] == object_id
+ timestamp = datetime_from_string(follower["datetime"])
+ assert timestamp >= before and timestamp <= after, str(timestamp)
# Check that am_following_user now returns True.
- result = call_action_api(app, 'am_following_user',
- id=object_id, apikey=apikey)
+ result = call_action_api(
+ app, "am_following_user", id=object_id, apikey=apikey
+ )
assert result is True
# Check that the follower appears in the object's list of followers.
- followers = call_action_api(app, 'user_follower_list',
- id=object_id, apikey=sysadmin_apikey)
+ followers = call_action_api(
+ app, "user_follower_list", id=object_id, apikey=sysadmin_apikey
+ )
assert len(followers) == follower_count_before + 1
- assert len([follower for follower in followers if follower['id'] == follower_id]) == 1
+ assert (
+ len(
+ [
+ follower
+ for follower in followers
+ if follower["id"] == follower_id
+ ]
+ )
+ == 1
+ )
# Check that the object appears in the follower's list of followees.
- followees = call_action_api(app, 'user_followee_list',
- apikey=sysadmin_apikey, id=follower_id)
+ followees = call_action_api(
+ app, "user_followee_list", apikey=sysadmin_apikey, id=follower_id
+ )
assert len(followees) == followee_count_before + 1
- assert len([followee for followee in followees if followee['id'] == object_id]) == 1
+ assert (
+ len(
+ [followee for followee in followees if followee["id"] == object_id]
+ )
+ == 1
+ )
# Check that the object's follower count has increased by 1.
- follower_count_after = call_action_api(app,
- 'user_follower_count', id=object_id)
+ follower_count_after = call_action_api(
+ app, "user_follower_count", id=object_id
+ )
assert follower_count_after == follower_count_before + 1
# Check that the follower's followee count has increased by 1.
- followee_count_after = call_action_api(app,
- 'user_followee_count', id=follower_id)
+ followee_count_after = call_action_api(
+ app, "user_followee_count", id=follower_id
+ )
assert followee_count_after == followee_count_before + 1
@follow
-def follow_dataset(app, follower_id, apikey, dataset_id, dataset_arg,
- sysadmin_apikey):
- '''Test a user starting to follow a dataset via the API.
+def follow_dataset(
+ app, follower_id, apikey, dataset_id, dataset_arg, sysadmin_apikey
+):
+ """Test a user starting to follow a dataset via the API.
:param follower_id: id of the user.
:param apikey: API key of the user.
@@ -135,61 +184,88 @@ def follow_dataset(app, follower_id, apikey, dataset_id, dataset_arg,
:param dataset_arg: the argument to pass to follow_dataset as the id of
the dataset that will be followed, could be the dataset's id or name.
- '''
+ """
# Record the dataset's followers count before.
- follower_count_before = call_action_api(app,
- 'dataset_follower_count', id=dataset_id)
+ follower_count_before = call_action_api(
+ app, "dataset_follower_count", id=dataset_id
+ )
# Record the follower's followees count before.
- followee_count_before = call_action_api(app,
- 'dataset_followee_count', id=follower_id)
+ followee_count_before = call_action_api(
+ app, "dataset_followee_count", id=follower_id
+ )
# Check that the user is not already following the dataset.
- result = call_action_api(app, 'am_following_dataset',
- id=dataset_id, apikey=apikey)
+ result = call_action_api(
+ app, "am_following_dataset", id=dataset_id, apikey=apikey
+ )
assert result is False
# Make the user start following the dataset.
before = datetime.datetime.now()
- follower = call_action_api(app, 'follow_dataset',
- id=dataset_arg, apikey=apikey)
+ follower = call_action_api(
+ app, "follow_dataset", id=dataset_arg, apikey=apikey
+ )
after = datetime.datetime.now()
- assert follower['follower_id'] == follower_id
- assert follower['object_id'] == dataset_id
- timestamp = datetime_from_string(follower['datetime'])
- assert (timestamp >= before and timestamp <= after), str(timestamp)
+ assert follower["follower_id"] == follower_id
+ assert follower["object_id"] == dataset_id
+ timestamp = datetime_from_string(follower["datetime"])
+ assert timestamp >= before and timestamp <= after, str(timestamp)
# Check that am_following_dataset now returns True.
- result = call_action_api(app, 'am_following_dataset',
- id=dataset_id, apikey=apikey)
+ result = call_action_api(
+ app, "am_following_dataset", id=dataset_id, apikey=apikey
+ )
assert result is True
# Check that the follower appears in the dataset's list of followers.
- followers = call_action_api(app, 'dataset_follower_list',
- id=dataset_id, apikey=sysadmin_apikey)
+ followers = call_action_api(
+ app, "dataset_follower_list", id=dataset_id, apikey=sysadmin_apikey
+ )
assert len(followers) == follower_count_before + 1
- assert len([follower for follower in followers if follower['id'] == follower_id]) == 1
+ assert (
+ len(
+ [
+ follower
+ for follower in followers
+ if follower["id"] == follower_id
+ ]
+ )
+ == 1
+ )
# Check that the dataset appears in the follower's list of followees.
- followees = call_action_api(app, 'dataset_followee_list',
- apikey=sysadmin_apikey, id=follower_id)
+ followees = call_action_api(
+ app, "dataset_followee_list", apikey=sysadmin_apikey, id=follower_id
+ )
assert len(followees) == followee_count_before + 1
- assert len([followee for followee in followees if followee['id'] == dataset_id]) == 1
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["id"] == dataset_id
+ ]
+ )
+ == 1
+ )
# Check that the dataset's follower count has increased by 1.
- follower_count_after = call_action_api(app,
- 'dataset_follower_count', id=dataset_id)
+ follower_count_after = call_action_api(
+ app, "dataset_follower_count", id=dataset_id
+ )
assert follower_count_after == follower_count_before + 1
# Check that the follower's followee count has increased by 1.
- followee_count_after = call_action_api(app,
- 'dataset_followee_count', id=follower_id)
+ followee_count_after = call_action_api(
+ app, "dataset_followee_count", id=follower_id
+ )
assert followee_count_after == followee_count_before + 1
@follow
def follow_group(app, user_id, apikey, group_id, group_arg, sysadmin_apikey):
- '''Test a user starting to follow a group via the API.
+ """Test a user starting to follow a group via the API.
:param user_id: id of the user
:param apikey: API key of the user
@@ -197,718 +273,1030 @@ def follow_group(app, user_id, apikey, group_id, group_arg, sysadmin_apikey):
:param group_arg: the argument to pass to follow_group as the id of
the group that will be followed, could be the group's id or name
- '''
+ """
# Record the group's followers count before.
- follower_count_before = call_action_api(app,
- 'group_follower_count', id=group_id)
+ follower_count_before = call_action_api(
+ app, "group_follower_count", id=group_id
+ )
# Record the user's followees count before.
- followee_count_before = call_action_api(app,
- 'group_followee_count', id=user_id)
+ followee_count_before = call_action_api(
+ app, "group_followee_count", id=user_id
+ )
# Check that the user is not already following the group.
- result = call_action_api(app, 'am_following_group',
- id=group_id, apikey=apikey)
+ result = call_action_api(
+ app, "am_following_group", id=group_id, apikey=apikey
+ )
assert result is False
# Make the user start following the group.
before = datetime.datetime.now()
- follower = call_action_api(app, 'follow_group', id=group_id,
- apikey=apikey)
+ follower = call_action_api(app, "follow_group", id=group_id, apikey=apikey)
after = datetime.datetime.now()
- assert follower['follower_id'] == user_id
- assert follower['object_id'] == group_id
- timestamp = datetime_from_string(follower['datetime'])
- assert (timestamp >= before and timestamp <= after), str(timestamp)
+ assert follower["follower_id"] == user_id
+ assert follower["object_id"] == group_id
+ timestamp = datetime_from_string(follower["datetime"])
+ assert timestamp >= before and timestamp <= after, str(timestamp)
# Check that am_following_group now returns True.
- result = call_action_api(app, 'am_following_group',
- id=group_id, apikey=apikey)
+ result = call_action_api(
+ app, "am_following_group", id=group_id, apikey=apikey
+ )
assert result is True
# Check that the user appears in the group's list of followers.
- followers = call_action_api(app, 'group_follower_list',
- id=group_id, apikey=sysadmin_apikey)
+ followers = call_action_api(
+ app, "group_follower_list", id=group_id, apikey=sysadmin_apikey
+ )
assert len(followers) == follower_count_before + 1
- assert len([follower for follower in followers
- if follower['id'] == user_id]) == 1
+ assert (
+ len([follower for follower in followers if follower["id"] == user_id])
+ == 1
+ )
# Check that the group appears in the user's list of followees.
- followees = call_action_api(app, 'group_followee_list',
- apikey=sysadmin_apikey, id=user_id)
+ followees = call_action_api(
+ app, "group_followee_list", apikey=sysadmin_apikey, id=user_id
+ )
assert len(followees) == followee_count_before + 1
- assert len([followee for followee in followees
- if followee['id'] == group_id]) == 1
+ assert (
+ len([followee for followee in followees if followee["id"] == group_id])
+ == 1
+ )
# Check that the group's follower count has increased by 1.
- follower_count_after = call_action_api(app,
- 'group_follower_count', id=group_id)
+ follower_count_after = call_action_api(
+ app, "group_follower_count", id=group_id
+ )
assert follower_count_after == follower_count_before + 1
# Check that the user's followee count has increased by 1.
- followee_count_after = call_action_api(app,
- 'group_followee_count', id=user_id)
+ followee_count_after = call_action_api(
+ app, "group_followee_count", id=user_id
+ )
assert followee_count_after == followee_count_before + 1
class TestFollow(object):
- '''Tests for the follower API.'''
+ """Tests for the follower API."""
- @classmethod
- def setup_class(self):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db, app):
CreateTestData.create()
+ self.app = app
self.testsysadmin = {
- 'id': ckan.model.User.get('testsysadmin').id,
- 'apikey': ckan.model.User.get('testsysadmin').apikey,
- 'name': ckan.model.User.get('testsysadmin').name,
- }
+ "id": ckan.model.User.get("testsysadmin").id,
+ "apikey": ckan.model.User.get("testsysadmin").apikey,
+ "name": ckan.model.User.get("testsysadmin").name,
+ }
self.annafan = {
- 'id': ckan.model.User.get('annafan').id,
- 'apikey': ckan.model.User.get('annafan').apikey,
- 'name': ckan.model.User.get('annafan').name,
- }
+ "id": ckan.model.User.get("annafan").id,
+ "apikey": ckan.model.User.get("annafan").apikey,
+ "name": ckan.model.User.get("annafan").name,
+ }
self.russianfan = {
- 'id': ckan.model.User.get('russianfan').id,
- 'apikey': ckan.model.User.get('russianfan').apikey,
- 'name': ckan.model.User.get('russianfan').name,
- }
+ "id": ckan.model.User.get("russianfan").id,
+ "apikey": ckan.model.User.get("russianfan").apikey,
+ "name": ckan.model.User.get("russianfan").name,
+ }
self.joeadmin = {
- 'id': ckan.model.User.get('joeadmin').id,
- 'apikey': ckan.model.User.get('joeadmin').apikey,
- 'name': ckan.model.User.get('joeadmin').name,
- }
+ "id": ckan.model.User.get("joeadmin").id,
+ "apikey": ckan.model.User.get("joeadmin").apikey,
+ "name": ckan.model.User.get("joeadmin").name,
+ }
self.warandpeace = {
- 'id': ckan.model.Package.get('warandpeace').id,
- 'name': ckan.model.Package.get('warandpeace').name,
- }
+ "id": ckan.model.Package.get("warandpeace").id,
+ "name": ckan.model.Package.get("warandpeace").name,
+ }
self.annakarenina = {
- 'id': ckan.model.Package.get('annakarenina').id,
- 'name': ckan.model.Package.get('annakarenina').name,
- }
+ "id": ckan.model.Package.get("annakarenina").id,
+ "name": ckan.model.Package.get("annakarenina").name,
+ }
self.rogers_group = {
- 'id': ckan.model.Group.get('roger').id,
- 'name': ckan.model.Group.get('roger').name,
- }
+ "id": ckan.model.Group.get("roger").id,
+ "name": ckan.model.Group.get("roger").name,
+ }
self.davids_group = {
- 'id': ckan.model.Group.get('david').id,
- 'name': ckan.model.Group.get('david').name,
- }
- self.app = helpers._get_test_app()
-
- @classmethod
- def teardown_class(self):
- ckan.model.repo.rebuild_db()
-
- def test_00_visitor_cannot_get_user_follower_list(self):
- call_action_api(self.app, 'user_follower_list',
- id=self.russianfan['id'], status=403)
-
- def test_00_user_cannot_get_user_follower_list(self):
- call_action_api(self.app, 'user_follower_list',
- id=self.russianfan['id'], status=403,
- apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_user_follower_list(self):
- call_action_api(self.app, 'user_follower_list',
- id=self.russianfan['id'], status=200,
- apikey=self.testsysadmin['apikey'])
-
- def test_00_visitor_cannot_get_dataset_follower_list(self):
- call_action_api(self.app, 'dataset_follower_list',
- id='warandpeace', status=403)
-
- def test_00_user_cannot_get_dataset_follower_list(self):
- call_action_api(self.app, 'dataset_follower_list',
- id='warandpeace', status=403, apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_dataset_follower_list(self):
- call_action_api(self.app, 'dataset_follower_list',
- id='warandpeace', status=200,
- apikey=self.testsysadmin['apikey'])
-
- def test_00_visitor_cannot_get_group_follower_list(self):
- call_action_api(self.app, 'group_follower_list',
- id='roger', status=403)
-
- def test_00_user_cannot_get_group_follower_list(self):
- call_action_api(self.app, 'group_follower_list',
- id='roger', status=403, apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_group_follower_list(self):
- call_action_api(self.app, 'group_follower_list',
- id='roger', status=200, apikey=self.testsysadmin['apikey'])
-
- def test_00_visitor_cannot_get_followee_list(self):
- call_action_api(self.app, 'followee_list',
- id=self.russianfan['id'], status=403)
-
- def test_00_user_cannot_get_followee_list(self):
- call_action_api(self.app, 'followee_list',
- id=self.russianfan['id'], status=403,
- apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_followee_list(self):
- call_action_api(self.app, 'followee_list',
- id=self.russianfan['id'], status=200,
- apikey=self.testsysadmin['apikey'])
-
- def test_00_visitor_cannot_get_user_followee_list(self):
- '''A visitor cannot see what users a user is following.'''
- call_action_api(self.app, 'user_followee_list',
- id=self.russianfan['id'], status=403)
-
- def test_00_user_cannot_get_user_followee_list(self):
- '''A user cannot see what users another user is following.'''
- call_action_api(self.app, 'user_followee_list',
- id=self.russianfan['id'], status=403,
- apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_user_followee_list(self):
- '''A sysadmin can see what users another user is following.'''
- call_action_api(self.app, 'user_followee_list',
- id=self.russianfan['id'], status=200,
- apikey=self.testsysadmin['apikey'])
-
- def test_00_user_can_get_own_user_followee_list(self):
- '''A user can see what users she herself is following.'''
- call_action_api(self.app, 'user_followee_list',
- id=self.russianfan['id'], status=200,
- apikey=self.russianfan['apikey'])
-
- def test_00_visitor_cannot_get_dataset_followee_list(self):
- '''A visitor cannot see what datasets a user is following.'''
- call_action_api(self.app, 'dataset_followee_list',
- id=self.russianfan['id'], status=403)
-
- def test_00_user_cannot_get_dataset_followee_list(self):
- '''A user cannot see what datasets another user is following.'''
- call_action_api(self.app, 'dataset_followee_list',
- id='russianfan', status=403, apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_dataset_followee_list(self):
- '''A sysadmin can see what datasets another user is following.'''
- call_action_api(self.app, 'dataset_followee_list',
- id='russianfan', status=200,
- apikey=self.testsysadmin['apikey'])
-
- def test_00_user_can_get_own_dataset_followee_list(self):
- '''A user can see what datasets she herself is following.'''
- call_action_api(self.app, 'dataset_followee_list',
- id=self.russianfan['id'], status=200,
- apikey=self.russianfan['apikey'])
-
- def test_00_visitor_cannot_get_group_followee_list(self):
- '''A visitor cannot see what groups a user is following.'''
- call_action_api(self.app, 'group_followee_list',
- id='roger', status=403)
-
- def test_00_user_cannot_get_group_followee_list(self):
- '''A user cannot see what groups another user is following.'''
- call_action_api(self.app, 'group_followee_list',
- id='roger', status=403, apikey=self.annafan['apikey'])
-
- def test_00_sysadmin_can_get_group_followee_list(self):
- '''A sysadmin can see what groups another user is following.'''
- call_action_api(self.app, 'group_followee_list',
- id=self.annafan['id'], status=200,
- apikey=self.testsysadmin['apikey'])
-
- def test_00_user_can_get_own_group_followee_list(self):
- '''A user can see what groups she herself is following.'''
- call_action_api(self.app, 'group_followee_list',
- id=self.russianfan['id'], status=200,
- apikey=self.russianfan['apikey'])
-
- def test_01_user_follow_user_bad_apikey(self):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
- error = call_action_api(self.app, 'follow_user',
- id=self.russianfan['id'], apikey=apikey,
- status=403)
- assert error['__type'] == 'Authorization Error'
-
- def test_01_user_follow_dataset_bad_apikey(self):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
- error = call_action_api(self.app, 'follow_dataset',
- id=self.warandpeace['id'], apikey=apikey,
- status=403)
- assert error['__type'] == 'Authorization Error'
-
- def test_01_user_follow_group_bad_apikey(self):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
- error = call_action_api(self.app, 'follow_group',
- id=self.rogers_group['id'], apikey=apikey,
- status=403)
- assert error['__type'] == 'Authorization Error'
-
- def test_01_user_follow_user_missing_apikey(self):
- error = call_action_api(self.app, 'follow_user',
- id=self.russianfan['id'], status=403)
- assert error['__type'] == 'Authorization Error'
-
- def test_01_user_follow_dataset_missing_apikey(self):
- error = call_action_api(self.app, 'follow_dataset',
- id=self.warandpeace['id'], status=403)
- assert error['__type'] == 'Authorization Error'
-
- def test_01_user_follow_group_missing_apikey(self):
- error = call_action_api(self.app, 'follow_group',
- id=self.rogers_group['id'], status=403)
- assert error['__type'] == 'Authorization Error'
-
- def test_01_follow_bad_object_id(self):
- for action in ('follow_user', 'follow_dataset', 'follow_group'):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx'):
- error = call_action_api(self.app, action,
- id=object_id,
- apikey=self.annafan['apikey'], status=409)
- assert error['id'][0].startswith('Not found')
-
- def test_01_follow_empty_object_id(self):
- for action in ('follow_user', 'follow_dataset', 'follow_group'):
- for object_id in ('', None):
- error = call_action_api(self.app, action,
- id=object_id,
- apikey=self.annafan['apikey'], status=409)
- assert error['id'] == ['Missing value']
-
- def test_01_follow_missing_object_id(self):
- for action in ('follow_user', 'follow_dataset', 'follow_group'):
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409)
- assert error['id'] == ['Missing value']
-
- def test_02_user_follow_user_by_id(self):
- follow_user(self.app, self.annafan['id'], self.annafan['apikey'],
- self.russianfan['id'], self.russianfan['id'],
- self.testsysadmin['apikey'])
-
- def test_02_user_follow_dataset_by_id(self):
- follow_dataset(self.app, self.annafan['id'], self.annafan['apikey'],
- self.warandpeace['id'], self.warandpeace['id'],
- self.testsysadmin['apikey'])
-
- def test_02_user_follow_group_by_id(self):
- follow_group(self.app, self.annafan['id'], self.annafan['apikey'],
- self.rogers_group['id'], self.rogers_group['id'],
- self.testsysadmin['apikey'])
-
- def test_02_user_follow_user_by_name(self):
- follow_user(self.app, self.annafan['id'], self.annafan['apikey'],
- self.testsysadmin['id'], self.testsysadmin['name'],
- self.testsysadmin['apikey'])
-
- def test_02_user_follow_dataset_by_name(self):
- follow_dataset(self.app, self.joeadmin['id'], self.joeadmin['apikey'],
- self.warandpeace['id'], self.warandpeace['name'],
- self.testsysadmin['apikey'])
-
- def test_02_user_follow_group_by_name(self):
- follow_group(self.app, self.joeadmin['id'], self.joeadmin['apikey'],
- self.rogers_group['id'], self.rogers_group['name'],
- self.testsysadmin['apikey'])
-
- 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']):
- error = call_action_api(self.app, 'follow_user',
- id=object_id, apikey=self.annafan['apikey'],
- status=409)
- assert error['message'].startswith('You are already following ')
-
- def test_03_user_follow_dataset_already_following(self):
- for object_id in (self.warandpeace['id'], self.warandpeace['name']):
- error = call_action_api(self.app, 'follow_dataset',
- id=object_id, apikey=self.annafan['apikey'],
- status=409)
- assert error['message'].startswith('You are already following ')
-
- def test_03_user_follow_group_already_following(self):
- for group_id in (self.rogers_group['id'], self.rogers_group['name']):
- error = call_action_api(self.app, 'follow_group',
- id=group_id, apikey=self.annafan['apikey'],
- status=409)
- assert error['message'].startswith('You are already following ')
-
- def test_03_user_cannot_follow_herself(self):
- error = call_action_api(self.app, 'follow_user',
- apikey=self.annafan['apikey'], status=409,
- id=self.annafan['id'])
- assert error['message'] == 'You cannot follow yourself'
-
- def test_04_follower_count_bad_id(self):
- for action in ('user_follower_count', 'dataset_follower_count',
- 'group_follower_count'):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
- error = call_action_api(self.app, action,
- status=409, id=object_id)
- assert 'id' in error
-
- def test_04_follower_count_missing_id(self):
- for action in ('user_follower_count', 'dataset_follower_count',
- 'group_follower_count'):
- error = call_action_api(self.app, action, status=409)
- assert error['id'] == ['Missing value']
-
- def test_04_user_follower_count_no_followers(self):
- follower_count = call_action_api(self.app,
- 'user_follower_count', id=self.annafan['id'])
- assert follower_count == 0
-
- def test_04_dataset_follower_count_no_followers(self):
- follower_count = call_action_api(self.app,
- 'dataset_follower_count', id=self.annakarenina['id'])
- assert follower_count == 0
-
- def test_04_group_follower_count_no_followers(self):
- follower_count = call_action_api(self.app,
- 'group_follower_count', id=self.davids_group['id'])
- assert follower_count == 0
+ "id": ckan.model.Group.get("david").id,
+ "name": ckan.model.Group.get("david").name,
+ }
+
+ def test_00_visitor_cannot_get_user_follower_list(self, app):
+ call_action_api(
+ app, "user_follower_list", id=self.russianfan["id"], status=403
+ )
+
+ # def test_00_user_cannot_get_user_follower_list(self):
+ call_action_api(
+ app,
+ "user_follower_list",
+ id=self.russianfan["id"],
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_user_follower_list(self):
+ call_action_api(
+ app,
+ "user_follower_list",
+ id=self.russianfan["id"],
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_visitor_cannot_get_dataset_follower_list(self):
+ call_action_api(
+ app, "dataset_follower_list", id="warandpeace", status=403
+ )
+
+ # def test_00_user_cannot_get_dataset_follower_list(self):
+ call_action_api(
+ app,
+ "dataset_follower_list",
+ id="warandpeace",
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_dataset_follower_list(self):
+ call_action_api(
+ app,
+ "dataset_follower_list",
+ id="warandpeace",
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_visitor_cannot_get_group_follower_list(self):
+ call_action_api(app, "group_follower_list", id="roger", status=403)
+
+ # def test_00_user_cannot_get_group_follower_list(self):
+ call_action_api(
+ app,
+ "group_follower_list",
+ id="roger",
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_group_follower_list(self):
+ call_action_api(
+ app,
+ "group_follower_list",
+ id="roger",
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_visitor_cannot_get_followee_list(self):
+ call_action_api(
+ app, "followee_list", id=self.russianfan["id"], status=403
+ )
+
+ # def test_00_user_cannot_get_followee_list(self):
+ call_action_api(
+ app,
+ "followee_list",
+ id=self.russianfan["id"],
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_followee_list(self):
+ call_action_api(
+ app,
+ "followee_list",
+ id=self.russianfan["id"],
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_visitor_cannot_get_user_followee_list(self):
+ """A visitor cannot see what users a user is following."""
+ call_action_api(
+ app, "user_followee_list", id=self.russianfan["id"], status=403
+ )
+
+ # def test_00_user_cannot_get_user_followee_list(self):
+ """A user cannot see what users another user is following."""
+ call_action_api(
+ app,
+ "user_followee_list",
+ id=self.russianfan["id"],
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_user_followee_list(self):
+ """A sysadmin can see what users another user is following."""
+ call_action_api(
+ app,
+ "user_followee_list",
+ id=self.russianfan["id"],
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_user_can_get_own_user_followee_list(self):
+ """A user can see what users she herself is following."""
+ call_action_api(
+ app,
+ "user_followee_list",
+ id=self.russianfan["id"],
+ status=200,
+ apikey=self.russianfan["apikey"],
+ )
+
+ # def test_00_visitor_cannot_get_dataset_followee_list(self):
+ """A visitor cannot see what datasets a user is following."""
+ call_action_api(
+ app, "dataset_followee_list", id=self.russianfan["id"], status=403
+ )
+
+ # def test_00_user_cannot_get_dataset_followee_list(self):
+ """A user cannot see what datasets another user is following."""
+ call_action_api(
+ app,
+ "dataset_followee_list",
+ id="russianfan",
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_dataset_followee_list(self):
+ """A sysadmin can see what datasets another user is following."""
+ call_action_api(
+ app,
+ "dataset_followee_list",
+ id="russianfan",
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_user_can_get_own_dataset_followee_list(self):
+ """A user can see what datasets she herself is following."""
+ call_action_api(
+ app,
+ "dataset_followee_list",
+ id=self.russianfan["id"],
+ status=200,
+ apikey=self.russianfan["apikey"],
+ )
+
+ # def test_00_visitor_cannot_get_group_followee_list(self):
+ """A visitor cannot see what groups a user is following."""
+ call_action_api(app, "group_followee_list", id="roger", status=403)
+
+ # def test_00_user_cannot_get_group_followee_list(self):
+ """A user cannot see what groups another user is following."""
+ call_action_api(
+ app,
+ "group_followee_list",
+ id="roger",
+ status=403,
+ apikey=self.annafan["apikey"],
+ )
+
+ # def test_00_sysadmin_can_get_group_followee_list(self):
+ """A sysadmin can see what groups another user is following."""
+ call_action_api(
+ app,
+ "group_followee_list",
+ id=self.annafan["id"],
+ status=200,
+ apikey=self.testsysadmin["apikey"],
+ )
+
+ # def test_00_user_can_get_own_group_followee_list(self):
+ """A user can see what groups she herself is following."""
+ call_action_api(
+ app,
+ "group_followee_list",
+ id=self.russianfan["id"],
+ status=200,
+ apikey=self.russianfan["apikey"],
+ )
+
+ def test_01_user_follow_user_bad_apikey(self, app):
+ for apikey in ("bad api key", "", " ", "None", "3", "35.7", "xxx"):
+ error = call_action_api(
+ app,
+ "follow_user",
+ id=self.russianfan["id"],
+ apikey=apikey,
+ status=403,
+ )
+ assert error["__type"] == "Authorization Error"
+
+ # def test_01_user_follow_dataset_bad_apikey(self):
+ for apikey in ("bad api key", "", " ", "None", "3", "35.7", "xxx"):
+ error = call_action_api(
+ app,
+ "follow_dataset",
+ id=self.warandpeace["id"],
+ apikey=apikey,
+ status=403,
+ )
+ assert error["__type"] == "Authorization Error"
+
+ # def test_01_user_follow_group_bad_apikey(self):
+ for apikey in ("bad api key", "", " ", "None", "3", "35.7", "xxx"):
+ error = call_action_api(
+ app,
+ "follow_group",
+ id=self.rogers_group["id"],
+ apikey=apikey,
+ status=403,
+ )
+ assert error["__type"] == "Authorization Error"
+
+ # def test_01_user_follow_user_missing_apikey(self):
+ error = call_action_api(
+ app, "follow_user", id=self.russianfan["id"], status=403
+ )
+ assert error["__type"] == "Authorization Error"
+
+ # def test_01_user_follow_dataset_missing_apikey(self):
+ error = call_action_api(
+ app, "follow_dataset", id=self.warandpeace["id"], status=403
+ )
+ assert error["__type"] == "Authorization Error"
+
+ # def test_01_user_follow_group_missing_apikey(self):
+ error = call_action_api(
+ app, "follow_group", id=self.rogers_group["id"], status=403
+ )
+ assert error["__type"] == "Authorization Error"
+
+ # def test_01_follow_bad_object_id(self):
+ for action in ("follow_user", "follow_dataset", "follow_group"):
+ for object_id in ("bad id", " ", 3, 35.7, "xxx"):
+ error = call_action_api(
+ app,
+ action,
+ id=object_id,
+ apikey=self.annafan["apikey"],
+ status=409,
+ )
+ assert error["id"][0].startswith("Not found")
+
+ # def test_01_follow_empty_object_id(self):
+ for action in ("follow_user", "follow_dataset", "follow_group"):
+ for object_id in ("", None):
+ error = call_action_api(
+ app,
+ action,
+ id=object_id,
+ apikey=self.annafan["apikey"],
+ status=409,
+ )
+ assert error["id"] == ["Missing value"]
+
+ # def test_01_follow_missing_object_id(self):
+ for action in ("follow_user", "follow_dataset", "follow_group"):
+ error = call_action_api(
+ app, action, apikey=self.annafan["apikey"], status=409
+ )
+ assert error["id"] == ["Missing value"]
+
+ def test_02_user_follow_user_by_id(self, app):
+ follow_user(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.russianfan["id"],
+ self.russianfan["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ # def test_02_user_follow_dataset_by_id(self):
+ follow_dataset(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ # def test_02_user_follow_group_by_id(self):
+ follow_group(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.rogers_group["id"],
+ self.rogers_group["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ # def test_02_user_follow_user_by_name(self):
+ follow_user(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.testsysadmin["id"],
+ self.testsysadmin["name"],
+ self.testsysadmin["apikey"],
+ )
+
+ # def test_02_user_follow_dataset_by_name(self):
+ follow_dataset(
+ app,
+ self.joeadmin["id"],
+ self.joeadmin["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["name"],
+ self.testsysadmin["apikey"],
+ )
+
+ # def test_02_user_follow_group_by_name(self):
+ follow_group(
+ app,
+ self.joeadmin["id"],
+ self.joeadmin["apikey"],
+ self.rogers_group["id"],
+ self.rogers_group["name"],
+ self.testsysadmin["apikey"],
+ )
+
+ # 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"],
+ ):
+ error = call_action_api(
+ app,
+ "follow_user",
+ id=object_id,
+ apikey=self.annafan["apikey"],
+ status=409,
+ )
+ assert error["message"].startswith("You are already following ")
+
+ # def test_03_user_follow_dataset_already_following(self):
+ for object_id in (self.warandpeace["id"], self.warandpeace["name"]):
+ error = call_action_api(
+ app,
+ "follow_dataset",
+ id=object_id,
+ apikey=self.annafan["apikey"],
+ status=409,
+ )
+ assert error["message"].startswith("You are already following ")
+
+ # def test_03_user_follow_group_already_following(self):
+ for group_id in (self.rogers_group["id"], self.rogers_group["name"]):
+ error = call_action_api(
+ app,
+ "follow_group",
+ id=group_id,
+ apikey=self.annafan["apikey"],
+ status=409,
+ )
+ assert error["message"].startswith("You are already following ")
+
+ # def test_03_user_cannot_follow_herself(self):
+ error = call_action_api(
+ app,
+ "follow_user",
+ apikey=self.annafan["apikey"],
+ status=409,
+ id=self.annafan["id"],
+ )
+ assert error["message"] == "You cannot follow yourself"
def _followee_count_bad_id(self, action):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
- error = call_action_api(self.app, action,
- status=409, id=object_id)
- assert 'id' in error
-
- def test_04_followee_count_bad_id(self):
- self._followee_count_bad_id('followee_count')
-
- def test_04_user_followee_count_bad_id(self):
- self._followee_count_bad_id('user_followee_count')
-
- def test_04_dataset_followee_count_bad_id(self):
- self._followee_count_bad_id('dataset_followee_count')
-
- def test_04_group_followee_count_bad_id(self):
- self._followee_count_bad_id('group_followee_count')
+ for object_id in ("bad id", " ", 3, 35.7, "xxx", ""):
+ error = call_action_api(self.app, action, status=409, id=object_id)
+ assert "id" in error
def _followee_count_missing_id(self, action):
error = call_action_api(self.app, action, status=409)
- assert error['id'] == ['Missing value']
-
- def test_04_followee_count_missing_id(self):
- self._followee_count_missing_id('followee_count')
-
- def test_04_user_followee_count_missing_id(self):
- self._followee_count_missing_id('user_followee_count')
-
- def test_04_dataset_followee_count_missing_id(self):
- self._followee_count_missing_id('dataset_followee_count')
-
- def test_04_group_followee_count_missing_id(self):
- self._followee_count_missing_id('group_followee_count')
+ assert error["id"] == ["Missing value"]
def _followee_count_not_following_anything(self, action):
- followee_count = call_action_api(self.app, action,
- id=self.russianfan['id'])
+ followee_count = call_action_api(
+ self.app, action, id=self.russianfan["id"]
+ )
assert followee_count == 0
- def test_04_followee_count_not_following_anything(self):
- self._followee_count_not_following_anything('followee_count')
-
- def test_04_user_followee_count_not_following_anything(self):
- self._followee_count_not_following_anything('user_followee_count')
-
- def test_04_dataset_followee_count_not_following_anything(self):
- self._followee_count_not_following_anything('dataset_followee_count')
-
- def test_04_group_followee_count_not_following_anything(self):
- self._followee_count_not_following_anything('group_followee_count')
-
- def test_04_follower_list_bad_id(self):
- for action in ('user_follower_list', 'dataset_follower_list',
- 'group_follower_list'):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
- error = call_action_api(self.app, action,
- status=409, id=object_id,
- apikey=self.testsysadmin['apikey'])
- assert error['id']
-
- def test_04_follower_list_missing_id(self):
- for action in ('user_follower_list', 'dataset_follower_list',
- 'group_follower_list'):
- error = call_action_api(self.app, action, status=409,
- apikey=self.testsysadmin['apikey'])
- assert error['id'] == ['Missing value']
-
- def test_04_user_follower_list_no_followers(self):
- followers = call_action_api(self.app, 'user_follower_list',
- id=self.annafan['id'], apikey=self.testsysadmin['apikey'])
- assert followers == []
-
- def test_04_dataset_follower_list_no_followers(self):
- followers = call_action_api(self.app,
- 'dataset_follower_list', id=self.annakarenina['id'],
- apikey=self.testsysadmin['apikey'])
- assert followers == []
-
- def test_04_group_follower_list_no_followers(self):
- followers = call_action_api(self.app, 'group_follower_list',
- id=self.davids_group['id'], apikey=self.testsysadmin['apikey'])
- assert followers == []
-
def _followee_list_bad_id(self, action):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx', ''):
- error = call_action_api(self.app, action,
- status=409, id=object_id,
- apikey=self.testsysadmin['apikey'])
- assert error['id']
-
- def test_04_followee_list_bad_id(self):
- self._followee_list_bad_id('followee_list')
+ for object_id in ("bad id", " ", 3, 35.7, "xxx", ""):
+ error = call_action_api(
+ self.app,
+ action,
+ status=409,
+ id=object_id,
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert error["id"]
- def test_04_user_followee_list_bad_id(self):
- self._followee_list_bad_id('user_followee_list')
-
- def test_04_dataset_followee_list_bad_id(self):
- self._followee_list_bad_id('dataset_followee_list')
+ def _followee_list_missing_id(self, action):
+ error = call_action_api(
+ self.app, action, status=409, apikey=self.testsysadmin["apikey"]
+ )
+ assert error["id"] == ["Missing value"]
- def test_04_group_followee_list_bad_id(self):
- self._followee_list_bad_id('group_followee_list')
+ def _followee_list_not_following_anything(self, action):
+ followees = call_action_api(
+ self.app,
+ action,
+ id=self.russianfan["id"],
+ apikey=self.russianfan["apikey"],
+ )
+ assert followees == []
- def _followee_list_missing_id(self, action):
- error = call_action_api(self.app, action, status=409,
- apikey=self.testsysadmin['apikey'])
- assert error['id'] == ['Missing value']
+ def test_04_follower_count_bad_id(self, app):
+ for action in (
+ "user_follower_count",
+ "dataset_follower_count",
+ "group_follower_count",
+ ):
+ for object_id in ("bad id", " ", 3, 35.7, "xxx", ""):
+ error = call_action_api(app, action, status=409, id=object_id)
+ assert "id" in error
+
+ # def test_04_follower_count_missing_id(self):
+ for action in (
+ "user_follower_count",
+ "dataset_follower_count",
+ "group_follower_count",
+ ):
+ error = call_action_api(app, action, status=409)
+ assert error["id"] == ["Missing value"]
+
+ # def test_04_user_follower_count_no_followers(self):
+ follower_count = call_action_api(
+ app, "user_follower_count", id=self.annafan["id"]
+ )
+ assert follower_count == 0
- def test_04_followee_list_missing_id(self):
- self._followee_list_missing_id('followee_list')
+ # def test_04_dataset_follower_count_no_followers(self):
+ follower_count = call_action_api(
+ app, "dataset_follower_count", id=self.annakarenina["id"]
+ )
+ assert follower_count == 0
- def test_04_user_followee_list_missing_id(self):
- self._followee_list_missing_id('user_followee_list')
+ # def test_04_group_follower_count_no_followers(self):
+ follower_count = call_action_api(
+ app, "group_follower_count", id=self.davids_group["id"]
+ )
+ assert follower_count == 0
- def test_04_dataset_followee_missing_bad_id(self):
- self._followee_list_missing_id('dataset_followee_list')
+ # def test_04_followee_count_bad_id(self):
+ self._followee_count_bad_id("followee_count")
+
+ # def test_04_user_followee_count_bad_id(self):
+ self._followee_count_bad_id("user_followee_count")
+
+ # def test_04_dataset_followee_count_bad_id(self):
+ self._followee_count_bad_id("dataset_followee_count")
+
+ # def test_04_group_followee_count_bad_id(self):
+ self._followee_count_bad_id("group_followee_count")
+
+ # def test_04_followee_count_missing_id(self):
+ self._followee_count_missing_id("followee_count")
+
+ # def test_04_user_followee_count_missing_id(self):
+ self._followee_count_missing_id("user_followee_count")
+
+ # def test_04_dataset_followee_count_missing_id(self):
+ self._followee_count_missing_id("dataset_followee_count")
+
+ # def test_04_group_followee_count_missing_id(self):
+ self._followee_count_missing_id("group_followee_count")
+
+ # def test_04_followee_count_not_following_anything(self):
+ self._followee_count_not_following_anything("followee_count")
+
+ # def test_04_user_followee_count_not_following_anything(self):
+ self._followee_count_not_following_anything("user_followee_count")
+
+ # def test_04_dataset_followee_count_not_following_anything(self):
+ self._followee_count_not_following_anything("dataset_followee_count")
+
+ # def test_04_group_followee_count_not_following_anything(self):
+ self._followee_count_not_following_anything("group_followee_count")
+
+ # def test_04_follower_list_bad_id(self):
+ for action in (
+ "user_follower_list",
+ "dataset_follower_list",
+ "group_follower_list",
+ ):
+ for object_id in ("bad id", " ", 3, 35.7, "xxx", ""):
+ error = call_action_api(
+ app,
+ action,
+ status=409,
+ id=object_id,
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert error["id"]
+
+ # def test_04_follower_list_missing_id(self):
+ for action in (
+ "user_follower_list",
+ "dataset_follower_list",
+ "group_follower_list",
+ ):
+ error = call_action_api(
+ app, action, status=409, apikey=self.testsysadmin["apikey"]
+ )
+ assert error["id"] == ["Missing value"]
+
+ # def test_04_user_follower_list_no_followers(self):
+ followers = call_action_api(
+ app,
+ "user_follower_list",
+ id=self.annafan["id"],
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert followers == []
- def test_04_group_followee_missing_bad_id(self):
- self._followee_list_missing_id('group_followee_list')
+ # def test_04_dataset_follower_list_no_followers(self):
+ followers = call_action_api(
+ app,
+ "dataset_follower_list",
+ id=self.annakarenina["id"],
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert followers == []
- def _followee_list_not_following_anything(self, action):
- followees = call_action_api(self.app, action,
- id=self.russianfan['id'], apikey=self.russianfan['apikey'])
- assert followees == []
+ # def test_04_group_follower_list_no_followers(self):
+ followers = call_action_api(
+ app,
+ "group_follower_list",
+ id=self.davids_group["id"],
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert followers == []
- def test_04_followee_list_not_following_anything(self):
- self._followee_list_not_following_anything('followee_list')
-
- def test_04_user_followee_list_not_following_anything(self):
- self._followee_list_not_following_anything('user_followee_list')
-
- def test_04_dataset_followee_not_following_anything(self):
- self._followee_list_not_following_anything('dataset_followee_list')
-
- def test_04_group_followee_not_following_anything(self):
- self._followee_list_not_following_anything('group_followee_list')
-
- def test_04_am_following_bad_id(self):
- for action in ('am_following_dataset', 'am_following_user',
- 'am_following_group'):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx'):
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409, id=object_id)
- assert error['id'][0].startswith('Not found: ')
-
- def test_04_am_following_missing_id(self):
- for action in ('am_following_dataset', 'am_following_user',
- 'am_following_group'):
- for id in ('missing', None, ''):
- if id == 'missing':
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409)
+ # def test_04_followee_list_bad_id(self):
+ self._followee_list_bad_id("followee_list")
+
+ # def test_04_user_followee_list_bad_id(self):
+ self._followee_list_bad_id("user_followee_list")
+
+ # def test_04_dataset_followee_list_bad_id(self):
+ self._followee_list_bad_id("dataset_followee_list")
+
+ # def test_04_group_followee_list_bad_id(self):
+ self._followee_list_bad_id("group_followee_list")
+
+ # def test_04_followee_list_missing_id(self):
+ self._followee_list_missing_id("followee_list")
+
+ # def test_04_user_followee_list_missing_id(self):
+ self._followee_list_missing_id("user_followee_list")
+
+ # def test_04_dataset_followee_missing_bad_id(self):
+ self._followee_list_missing_id("dataset_followee_list")
+
+ # def test_04_group_followee_missing_bad_id(self):
+ self._followee_list_missing_id("group_followee_list")
+
+ # def test_04_followee_list_not_following_anything(self):
+ self._followee_list_not_following_anything("followee_list")
+
+ # def test_04_user_followee_list_not_following_anything(self):
+ self._followee_list_not_following_anything("user_followee_list")
+
+ # def test_04_dataset_followee_not_following_anything(self):
+ self._followee_list_not_following_anything("dataset_followee_list")
+
+ # def test_04_group_followee_not_following_anything(self):
+ self._followee_list_not_following_anything("group_followee_list")
+
+ # def test_04_am_following_bad_id(self):
+ for action in (
+ "am_following_dataset",
+ "am_following_user",
+ "am_following_group",
+ ):
+ for object_id in ("bad id", " ", 3, 35.7, "xxx"):
+ error = call_action_api(
+ app,
+ action,
+ apikey=self.annafan["apikey"],
+ status=409,
+ id=object_id,
+ )
+ assert error["id"][0].startswith("Not found: ")
+
+ # def test_04_am_following_missing_id(self):
+ for action in (
+ "am_following_dataset",
+ "am_following_user",
+ "am_following_group",
+ ):
+ for id in ("missing", None, ""):
+ if id == "missing":
+ error = call_action_api(
+ app, action, apikey=self.annafan["apikey"], status=409
+ )
else:
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409, id=id)
- assert error['id'] == [u'Missing value']
-
- def test_04_am_following_dataset_bad_apikey(self):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
- error = call_action_api(self.app,
- 'am_following_dataset', apikey=apikey, status=403,
- id=self.warandpeace['id'])
- assert error['message'] == 'Access denied'
-
- def test_04_am_following_dataset_missing_apikey(self):
- error = call_action_api(self.app, 'am_following_dataset',
- status=403, id=self.warandpeace['id'])
- assert error['message'] == 'Access denied'
-
- def test_04_am_following_user_bad_apikey(self):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
- error = call_action_api(self.app, 'am_following_user',
- apikey=apikey, status=403, id=self.annafan['id'])
- assert error['message'] == 'Access denied'
-
- def test_04_am_following_user_missing_apikey(self):
- error = call_action_api(self.app, 'am_following_user',
- status=403, id=self.annafan['id'])
- assert error['message'] == 'Access denied'
-
- def test_04_am_following_group_bad_apikey(self):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7', 'xxx'):
- error = call_action_api(self.app, 'am_following_group',
- apikey=apikey, status=403, id=self.rogers_group['id'])
- assert error['message'] == 'Access denied'
-
- def test_04_am_following_group_missing_apikey(self):
- error = call_action_api(self.app, 'am_following_group',
- status=403, id=self.rogers_group['id'])
- assert error['message'] == 'Access denied'
+ error = call_action_api(
+ app,
+ action,
+ apikey=self.annafan["apikey"],
+ status=409,
+ id=id,
+ )
+ assert error["id"] == [u"Missing value"]
+
+ # def test_04_am_following_dataset_bad_apikey(self):
+ for apikey in ("bad api key", "", " ", "None", "3", "35.7", "xxx"):
+ error = call_action_api(
+ app,
+ "am_following_dataset",
+ apikey=apikey,
+ status=403,
+ id=self.warandpeace["id"],
+ )
+ assert error["message"] == "Access denied"
+
+ # def test_04_am_following_dataset_missing_apikey(self):
+ error = call_action_api(
+ app, "am_following_dataset", status=403, id=self.warandpeace["id"]
+ )
+ assert error["message"] == "Access denied"
+
+ # def test_04_am_following_user_bad_apikey(self):
+ for apikey in ("bad api key", "", " ", "None", "3", "35.7", "xxx"):
+ error = call_action_api(
+ app,
+ "am_following_user",
+ apikey=apikey,
+ status=403,
+ id=self.annafan["id"],
+ )
+ assert error["message"] == "Access denied"
+
+ # def test_04_am_following_user_missing_apikey(self):
+ error = call_action_api(
+ app, "am_following_user", status=403, id=self.annafan["id"]
+ )
+ assert error["message"] == "Access denied"
+
+ # def test_04_am_following_group_bad_apikey(self):
+ for apikey in ("bad api key", "", " ", "None", "3", "35.7", "xxx"):
+ error = call_action_api(
+ app,
+ "am_following_group",
+ apikey=apikey,
+ status=403,
+ id=self.rogers_group["id"],
+ )
+ assert error["message"] == "Access denied"
+
+ # def test_04_am_following_group_missing_apikey(self):
+ error = call_action_api(
+ app, "am_following_group", status=403, id=self.rogers_group["id"]
+ )
+ assert error["message"] == "Access denied"
class TestFollowerDelete(object):
- '''Tests for the unfollow_* APIs.'''
+ """Tests for the unfollow_* APIs."""
- @classmethod
- def setup_class(self):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, app, clean_db):
CreateTestData.create()
+ self.app = app
self.tester = {
- 'id': ckan.model.User.get('tester').id,
- 'apikey': ckan.model.User.get('tester').apikey,
- 'name': ckan.model.User.get('tester').name,
- }
+ "id": ckan.model.User.get("tester").id,
+ "apikey": ckan.model.User.get("tester").apikey,
+ "name": ckan.model.User.get("tester").name,
+ }
self.testsysadmin = {
- 'id': ckan.model.User.get('testsysadmin').id,
- 'apikey': ckan.model.User.get('testsysadmin').apikey,
- 'name': ckan.model.User.get('testsysadmin').name,
- }
+ "id": ckan.model.User.get("testsysadmin").id,
+ "apikey": ckan.model.User.get("testsysadmin").apikey,
+ "name": ckan.model.User.get("testsysadmin").name,
+ }
self.annafan = {
- 'id': ckan.model.User.get('annafan').id,
- 'apikey': ckan.model.User.get('annafan').apikey,
- 'name': ckan.model.User.get('annafan').name,
- }
+ "id": ckan.model.User.get("annafan").id,
+ "apikey": ckan.model.User.get("annafan").apikey,
+ "name": ckan.model.User.get("annafan").name,
+ }
self.russianfan = {
- 'id': ckan.model.User.get('russianfan').id,
- 'apikey': ckan.model.User.get('russianfan').apikey,
- 'name': ckan.model.User.get('russianfan').name,
- }
+ "id": ckan.model.User.get("russianfan").id,
+ "apikey": ckan.model.User.get("russianfan").apikey,
+ "name": ckan.model.User.get("russianfan").name,
+ }
self.joeadmin = {
- 'id': ckan.model.User.get('joeadmin').id,
- 'apikey': ckan.model.User.get('joeadmin').apikey,
- 'name': ckan.model.User.get('joeadmin').name,
- }
+ "id": ckan.model.User.get("joeadmin").id,
+ "apikey": ckan.model.User.get("joeadmin").apikey,
+ "name": ckan.model.User.get("joeadmin").name,
+ }
self.warandpeace = {
- 'id': ckan.model.Package.get('warandpeace').id,
- 'name': ckan.model.Package.get('warandpeace').name,
- }
+ "id": ckan.model.Package.get("warandpeace").id,
+ "name": ckan.model.Package.get("warandpeace").name,
+ }
self.annakarenina = {
- 'id': ckan.model.Package.get('annakarenina').id,
- 'name': ckan.model.Package.get('annakarenina').name,
- }
+ "id": ckan.model.Package.get("annakarenina").id,
+ "name": ckan.model.Package.get("annakarenina").name,
+ }
self.rogers_group = {
- 'id': ckan.model.Group.get('roger').id,
- 'name': ckan.model.Group.get('roger').name,
- }
+ "id": ckan.model.Group.get("roger").id,
+ "name": ckan.model.Group.get("roger").name,
+ }
self.davids_group = {
- 'id': ckan.model.Group.get('david').id,
- 'name': ckan.model.Group.get('david').name,
- }
- self.app = helpers._get_test_app()
- follow_user(self.app, self.testsysadmin['id'],
- self.testsysadmin['apikey'], self.joeadmin['id'],
- self.joeadmin['id'], self.testsysadmin['apikey'])
- follow_user(self.app, self.tester['id'], self.tester['apikey'],
- self.joeadmin['id'], self.joeadmin['id'],
- self.testsysadmin['apikey'])
- follow_user(self.app, self.russianfan['id'], self.russianfan['apikey'],
- self.joeadmin['id'], self.joeadmin['id'],
- self.testsysadmin['apikey'])
- follow_user(self.app, self.annafan['id'], self.annafan['apikey'],
- self.joeadmin['id'], self.joeadmin['id'],
- self.testsysadmin['apikey'])
- follow_user(self.app, self.annafan['id'], self.annafan['apikey'],
- self.tester['id'], self.tester['id'],
- self.testsysadmin['apikey'])
- follow_dataset(self.app, self.testsysadmin['id'],
- self.testsysadmin['apikey'], self.warandpeace['id'],
- self.warandpeace['id'], self.testsysadmin['apikey'])
- follow_dataset(self.app, self.tester['id'], self.tester['apikey'],
- self.warandpeace['id'], self.warandpeace['id'],
- self.testsysadmin['apikey'])
- follow_dataset(self.app, self.russianfan['id'], self.russianfan['apikey'],
- self.warandpeace['id'], self.warandpeace['id'],
- self.testsysadmin['apikey'])
- follow_dataset(self.app, self.annafan['id'], self.annafan['apikey'],
- self.warandpeace['id'], self.warandpeace['id'],
- self.testsysadmin['apikey'])
- follow_group(self.app, self.annafan['id'], self.annafan['apikey'],
- self.davids_group['id'], self.davids_group['id'],
- self.testsysadmin['apikey'])
-
- @classmethod
- def teardown_class(self):
- ckan.model.repo.rebuild_db()
-
- def test_01_unfollow_user_not_exists(self):
- '''Test the error response when a user tries to unfollow a user that
+ "id": ckan.model.Group.get("david").id,
+ "name": ckan.model.Group.get("david").name,
+ }
+
+ follow_user(
+ app,
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ self.joeadmin["id"],
+ self.joeadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_user(
+ app,
+ self.tester["id"],
+ self.tester["apikey"],
+ self.joeadmin["id"],
+ self.joeadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_user(
+ app,
+ self.russianfan["id"],
+ self.russianfan["apikey"],
+ self.joeadmin["id"],
+ self.joeadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_user(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.joeadmin["id"],
+ self.joeadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_user(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.tester["id"],
+ self.tester["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_dataset(
+ app,
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_dataset(
+ app,
+ self.tester["id"],
+ self.tester["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_dataset(
+ app,
+ self.russianfan["id"],
+ self.russianfan["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_dataset(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_group(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.davids_group["id"],
+ self.davids_group["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ def test_01_unfollow_user_not_exists(self, app):
+ """Test the error response when a user tries to unfollow a user that
she is not following.
- '''
- error = call_action_api(self.app, 'unfollow_user',
- apikey=self.annafan['apikey'], status=404,
- id=self.russianfan['id'])
- assert error['message'].startswith('Not found: You are not following ')
-
- def test_01_unfollow_dataset_not_exists(self):
- '''Test the error response when a user tries to unfollow a dataset that
+ """
+ error = call_action_api(
+ app,
+ "unfollow_user",
+ apikey=self.annafan["apikey"],
+ status=404,
+ id=self.russianfan["id"],
+ )
+ assert error["message"].startswith("Not found: You are not following ")
+
+ def test_01_unfollow_dataset_not_exists(self, app):
+ """Test the error response when a user tries to unfollow a dataset that
she is not following.
- '''
- error = call_action_api(self.app, 'unfollow_dataset',
- apikey=self.annafan['apikey'], status=404,
- id=self.annakarenina['id'])
- assert error['message'].startswith('Not found: You are not following')
-
- def test_01_unfollow_group_not_exists(self):
- '''Test the error response when a user tries to unfollow a group that
+ """
+ error = call_action_api(
+ app,
+ "unfollow_dataset",
+ apikey=self.annafan["apikey"],
+ status=404,
+ id=self.annakarenina["id"],
+ )
+ assert error["message"].startswith("Not found: You are not following")
+
+ def test_01_unfollow_group_not_exists(self, app):
+ """Test the error response when a user tries to unfollow a group that
she is not following.
- '''
- error = call_action_api(self.app, 'unfollow_group',
- apikey=self.annafan['apikey'], status=404,
- id=self.rogers_group['id'])
- assert error['message'].startswith('Not found: You are not following')
-
- def test_01_unfollow_bad_apikey(self):
- '''Test the error response when a user tries to unfollow something
+ """
+ error = call_action_api(
+ app,
+ "unfollow_group",
+ apikey=self.annafan["apikey"],
+ status=404,
+ id=self.rogers_group["id"],
+ )
+ assert error["message"].startswith("Not found: You are not following")
+
+ def test_01_unfollow_bad_apikey(self, app):
+ """Test the error response when a user tries to unfollow something
but provides a bad API key.
- '''
- for action in ('unfollow_user', 'unfollow_dataset', 'unfollow_group'):
- for apikey in ('bad api key', '', ' ', 'None', '3', '35.7',
- 'xxx'):
- error = call_action_api(self.app, action,
- apikey=apikey, status=403, id=self.joeadmin['id'])
- assert error['__type'] == 'Authorization Error'
-
- def test_01_unfollow_missing_apikey(self):
- '''Test error response when calling unfollow_* without api key.'''
- for action in ('unfollow_user', 'unfollow_dataset', 'unfollow_group'):
- error = call_action_api(self.app, action, status=403,
- id=self.joeadmin['id'])
- assert error['__type'] == 'Authorization Error'
-
- def test_01_unfollow_bad_object_id(self):
- '''Test error response when calling unfollow_* with bad object id.'''
- for action in ('unfollow_user', 'unfollow_dataset', 'unfollow_group'):
- for object_id in ('bad id', ' ', 3, 35.7, 'xxx'):
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409,
- id=object_id)
- assert error['id'][0].startswith('Not found')
-
- def test_01_unfollow_missing_object_id(self):
- for action in ('unfollow_user', 'unfollow_dataset', 'unfollow_group'):
- for id in ('missing', None, ''):
- if id == 'missing':
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409)
+ """
+ for action in ("unfollow_user", "unfollow_dataset", "unfollow_group"):
+ for apikey in (
+ "bad api key",
+ "",
+ " ",
+ "None",
+ "3",
+ "35.7",
+ "xxx",
+ ):
+ error = call_action_api(
+ app,
+ action,
+ apikey=apikey,
+ status=403,
+ id=self.joeadmin["id"],
+ )
+ assert error["__type"] == "Authorization Error"
+
+ def test_01_unfollow_missing_apikey(self, app):
+ """Test error response when calling unfollow_* without api key."""
+ for action in ("unfollow_user", "unfollow_dataset", "unfollow_group"):
+ error = call_action_api(
+ app, action, status=403, id=self.joeadmin["id"]
+ )
+ assert error["__type"] == "Authorization Error"
+
+ def test_01_unfollow_bad_object_id(self, app):
+ """Test error response when calling unfollow_* with bad object id."""
+ for action in ("unfollow_user", "unfollow_dataset", "unfollow_group"):
+ for object_id in ("bad id", " ", 3, 35.7, "xxx"):
+ error = call_action_api(
+ app,
+ action,
+ apikey=self.annafan["apikey"],
+ status=409,
+ id=object_id,
+ )
+ assert error["id"][0].startswith("Not found")
+
+ def test_01_unfollow_missing_object_id(self, app):
+ for action in ("unfollow_user", "unfollow_dataset", "unfollow_group"):
+ for id in ("missing", None, ""):
+ if id == "missing":
+ error = call_action_api(
+ app, action, apikey=self.annafan["apikey"], status=409
+ )
else:
- error = call_action_api(self.app, action,
- apikey=self.annafan['apikey'], status=409, id=id)
- assert error['id'] == [u'Missing value']
+ error = call_action_api(
+ app,
+ action,
+ apikey=self.annafan["apikey"],
+ status=409,
+ id=id,
+ )
+ assert error["id"] == [u"Missing value"]
def _unfollow_user(self, follower_id, apikey, object_id, object_arg):
- '''Test a user unfollowing a user via the API.
+ """Test a user unfollowing a user via the API.
:param follower_id: id of the follower.
:param apikey: API key of the follower.
@@ -916,61 +1304,100 @@ def _unfollow_user(self, follower_id, apikey, object_id, object_arg):
:param object_arg: the argument to pass to unfollow_user as the id of
the object to unfollow, could be the object's id or name.
- '''
+ """
# Record the user's number of followers before.
- count_before = call_action_api(self.app,
- 'user_follower_count', id=object_id)
- followee_count_before = call_action_api(self.app,
- 'followee_count', id=follower_id)
- user_followee_count_before = call_action_api(self.app,
- 'user_followee_count', id=follower_id)
+ count_before = call_action_api(
+ self.app, "user_follower_count", id=object_id
+ )
+ followee_count_before = call_action_api(
+ self.app, "followee_count", id=follower_id
+ )
+ user_followee_count_before = call_action_api(
+ self.app, "user_followee_count", id=follower_id
+ )
# Check that the user is following the object.
- am_following = call_action_api(self.app,
- 'am_following_user', apikey=apikey, id=object_id)
+ am_following = call_action_api(
+ self.app, "am_following_user", apikey=apikey, id=object_id
+ )
assert am_following is True
# Make the user unfollow the object.
- call_action_api(self.app, 'unfollow_user', apikey=apikey,
- id=object_arg)
+ call_action_api(
+ self.app, "unfollow_user", apikey=apikey, id=object_arg
+ )
# Check that am_following_user now returns False.
- am_following = call_action_api(self.app,
- 'am_following_user', apikey=apikey, id=object_id)
+ am_following = call_action_api(
+ self.app, "am_following_user", apikey=apikey, id=object_id
+ )
assert am_following is False
# Check that the user doesn't appear in the object's list of followers.
- followers = call_action_api(self.app, 'user_follower_list',
- id=object_id, apikey=self.testsysadmin['apikey'])
- assert len([follower for follower in followers if follower['id'] ==
- follower_id]) == 0
+ followers = call_action_api(
+ self.app,
+ "user_follower_list",
+ id=object_id,
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert (
+ len(
+ [
+ follower
+ for follower in followers
+ if follower["id"] == follower_id
+ ]
+ )
+ == 0
+ )
# Check that the object's follower count has decreased by 1.
- count_after = call_action_api(self.app,
- 'user_follower_count', id=object_id)
+ count_after = call_action_api(
+ self.app, "user_follower_count", id=object_id
+ )
assert count_after == count_before - 1
# Check that the user doesn't appear in the subject's list of
# followees.
- followees = call_action_api(self.app, 'followee_list',
- id=follower_id, apikey=apikey)
- assert len([followee for followee in followees
- if followee['dict']['id'] == object_id]) == 0
- followees = call_action_api(self.app, 'user_followee_list',
- id=follower_id, apikey=apikey)
- assert len([followee for followee in followees
- if followee['id'] == object_id]) == 0
+ followees = call_action_api(
+ self.app, "followee_list", id=follower_id, apikey=apikey
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["dict"]["id"] == object_id
+ ]
+ )
+ == 0
+ )
+ followees = call_action_api(
+ self.app, "user_followee_list", id=follower_id, apikey=apikey
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["id"] == object_id
+ ]
+ )
+ == 0
+ )
# Check the the subject's followee cont has decreased by 1.
- count_after = call_action_api(self.app, 'followee_count',
- id=follower_id)
+ count_after = call_action_api(
+ self.app, "followee_count", id=follower_id
+ )
assert count_after == followee_count_before - 1
- count_after = call_action_api(self.app,
- 'user_followee_count', id=follower_id)
+ count_after = call_action_api(
+ self.app, "user_followee_count", id=follower_id
+ )
assert count_after == user_followee_count_before - 1
def _unfollow_dataset(self, user_id, apikey, dataset_id, dataset_arg):
- '''Test a user unfollowing a dataset via the API.
+ """Test a user unfollowing a dataset via the API.
:param user_id: id of the follower.
:param apikey: API key of the follower.
@@ -978,63 +1405,99 @@ def _unfollow_dataset(self, user_id, apikey, dataset_id, dataset_arg):
:param dataset_arg: the argument to pass to unfollow_dataset as the id
of the object to unfollow, could be the object's id or name.
- '''
+ """
# Record the dataset's number of followers before.
- count_before = call_action_api(self.app,
- 'dataset_follower_count', id=dataset_id)
- followee_count_before = call_action_api(self.app,
- 'followee_count', id=user_id)
- dataset_followee_count_before = call_action_api(self.app,
- 'dataset_followee_count', id=user_id)
+ count_before = call_action_api(
+ self.app, "dataset_follower_count", id=dataset_id
+ )
+ followee_count_before = call_action_api(
+ self.app, "followee_count", id=user_id
+ )
+ dataset_followee_count_before = call_action_api(
+ self.app, "dataset_followee_count", id=user_id
+ )
# Check that the user is following the dataset.
- am_following = call_action_api(self.app,
- 'am_following_dataset', apikey=apikey, id=dataset_id)
+ am_following = call_action_api(
+ self.app, "am_following_dataset", apikey=apikey, id=dataset_id
+ )
assert am_following is True
# Make the user unfollow the dataset.
- call_action_api(self.app, 'unfollow_dataset', apikey=apikey,
- id=dataset_arg)
+ call_action_api(
+ self.app, "unfollow_dataset", apikey=apikey, id=dataset_arg
+ )
# Check that am_following_dataset now returns False.
- am_following = call_action_api(self.app,
- 'am_following_dataset', apikey=apikey, id=dataset_id)
+ am_following = call_action_api(
+ self.app, "am_following_dataset", apikey=apikey, id=dataset_id
+ )
assert am_following is False
# Check that the user doesn't appear in the dataset's list of
# followers.
- followers = call_action_api(self.app,
- 'dataset_follower_list', id=dataset_id,
- apikey=self.testsysadmin['apikey'])
- assert len([follower for follower in followers if follower['id'] ==
- user_id]) == 0
+ followers = call_action_api(
+ self.app,
+ "dataset_follower_list",
+ id=dataset_id,
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert (
+ len(
+ [
+ follower
+ for follower in followers
+ if follower["id"] == user_id
+ ]
+ )
+ == 0
+ )
# Check that the dataset's follower count has decreased by 1.
- count_after = call_action_api(self.app,
- 'dataset_follower_count', id=dataset_id)
+ count_after = call_action_api(
+ self.app, "dataset_follower_count", id=dataset_id
+ )
assert count_after == count_before - 1
# Check that the dataset doesn't appear in the user's list of
# followees.
- followees = call_action_api(self.app, 'followee_list',
- id=user_id, apikey=apikey)
- assert len([followee for followee in followees
- if followee['dict']['id'] == dataset_id]) == 0
- followees = call_action_api(self.app,
- 'dataset_followee_list', id=user_id, apikey=apikey)
- assert len([followee for followee in followees
- if followee['id'] == dataset_id]) == 0
+ followees = call_action_api(
+ self.app, "followee_list", id=user_id, apikey=apikey
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["dict"]["id"] == dataset_id
+ ]
+ )
+ == 0
+ )
+ followees = call_action_api(
+ self.app, "dataset_followee_list", id=user_id, apikey=apikey
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["id"] == dataset_id
+ ]
+ )
+ == 0
+ )
# Check the the user's followee count has decreased by 1.
- count_after = call_action_api(self.app, 'followee_count',
- id=user_id)
+ count_after = call_action_api(self.app, "followee_count", id=user_id)
assert count_after == followee_count_before - 1
- count_after = call_action_api(self.app,
- 'dataset_followee_count', id=user_id)
+ count_after = call_action_api(
+ self.app, "dataset_followee_count", id=user_id
+ )
assert count_after == dataset_followee_count_before - 1
def _unfollow_group(self, user_id, apikey, group_id, group_arg):
- '''Test a user unfollowing a group via the API.
+ """Test a user unfollowing a group via the API.
:param user_id: id of the user
:param apikey: API key of the user
@@ -1042,275 +1505,448 @@ def _unfollow_group(self, user_id, apikey, group_id, group_arg):
:param group_arg: the argument to pass to unfollow_group as the id
of the group, could be the group's id or name.
- '''
+ """
# Record the group's number of followers before.
- count_before = call_action_api(self.app,
- 'group_follower_count', id=group_id)
- followee_count_before = call_action_api(self.app,
- 'followee_count', id=user_id)
- group_followee_count_before = call_action_api(self.app,
- 'group_followee_count', id=user_id)
+ count_before = call_action_api(
+ self.app, "group_follower_count", id=group_id
+ )
+ followee_count_before = call_action_api(
+ self.app, "followee_count", id=user_id
+ )
+ group_followee_count_before = call_action_api(
+ self.app, "group_followee_count", id=user_id
+ )
# Check that the user is following the group.
- am_following = call_action_api(self.app,
- 'am_following_group', apikey=apikey, id=group_id)
+ am_following = call_action_api(
+ self.app, "am_following_group", apikey=apikey, id=group_id
+ )
assert am_following is True
# Make the user unfollow the group.
- call_action_api(self.app, 'unfollow_group', apikey=apikey,
- id=group_arg)
+ call_action_api(
+ self.app, "unfollow_group", apikey=apikey, id=group_arg
+ )
# Check that am_following_group now returns False.
- am_following = call_action_api(self.app,
- 'am_following_group', apikey=apikey, id=group_id)
+ am_following = call_action_api(
+ self.app, "am_following_group", apikey=apikey, id=group_id
+ )
assert am_following is False
# Check that the user doesn't appear in the group's list of
# followers.
- followers = call_action_api(self.app, 'group_follower_list',
- id=group_id, apikey=self.testsysadmin['apikey'])
- assert len([follower for follower in followers if follower['id'] ==
- user_id]) == 0
+ followers = call_action_api(
+ self.app,
+ "group_follower_list",
+ id=group_id,
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert (
+ len(
+ [
+ follower
+ for follower in followers
+ if follower["id"] == user_id
+ ]
+ )
+ == 0
+ )
# Check that the group's follower count has decreased by 1.
- count_after = call_action_api(self.app,
- 'group_follower_count', id=group_id)
+ count_after = call_action_api(
+ self.app, "group_follower_count", id=group_id
+ )
assert count_after == count_before - 1
# Check that the group doesn't appear in the user's list of
# followees.
- followees = call_action_api(self.app, 'followee_list',
- id=user_id, apikey=apikey)
- assert len([followee for followee in followees
- if followee['dict']['id'] == group_id]) == 0
- followees = call_action_api(self.app,
- 'group_followee_list', id=user_id,
- apikey=self.testsysadmin['apikey'])
- assert len([followee for followee in followees
- if followee['id'] == group_id]) == 0
+ followees = call_action_api(
+ self.app, "followee_list", id=user_id, apikey=apikey
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["dict"]["id"] == group_id
+ ]
+ )
+ == 0
+ )
+ followees = call_action_api(
+ self.app,
+ "group_followee_list",
+ id=user_id,
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert (
+ len(
+ [
+ followee
+ for followee in followees
+ if followee["id"] == group_id
+ ]
+ )
+ == 0
+ )
# Check the the user's followee count has decreased by 1.
- count_after = call_action_api(self.app, 'followee_count',
- id=user_id)
+ count_after = call_action_api(self.app, "followee_count", id=user_id)
assert count_after == followee_count_before - 1
- count_after = call_action_api(self.app,
- 'group_followee_count', id=user_id)
+ count_after = call_action_api(
+ self.app, "group_followee_count", id=user_id
+ )
assert count_after == group_followee_count_before - 1
def test_02_follower_delete_by_id(self):
- self._unfollow_user(self.annafan['id'], self.annafan['apikey'],
- self.joeadmin['id'], self.joeadmin['id'])
- self._unfollow_dataset(self.annafan['id'], self.annafan['apikey'],
- self.warandpeace['id'], self.warandpeace['id'])
- self._unfollow_group(self.annafan['id'], self.annafan['apikey'],
- self.davids_group['id'], self.davids_group['id'])
+ self._unfollow_user(
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.joeadmin["id"],
+ self.joeadmin["id"],
+ )
+ self._unfollow_dataset(
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ )
+ self._unfollow_group(
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.davids_group["id"],
+ self.davids_group["id"],
+ )
+
class TestFollowerCascade(object):
- '''Tests for on delete cascade of follower table rows.'''
+ """Tests for on delete cascade of follower table rows."""
- @classmethod
- def setup_class(self):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db, app):
CreateTestData.create()
+ self.app = app
self.tester = {
- 'id': ckan.model.User.get('tester').id,
- 'apikey': ckan.model.User.get('tester').apikey,
- 'name': ckan.model.User.get('tester').name,
- }
+ "id": ckan.model.User.get("tester").id,
+ "apikey": ckan.model.User.get("tester").apikey,
+ "name": ckan.model.User.get("tester").name,
+ }
self.testsysadmin = {
- 'id': ckan.model.User.get('testsysadmin').id,
- 'apikey': ckan.model.User.get('testsysadmin').apikey,
- 'name': ckan.model.User.get('testsysadmin').name,
- }
+ "id": ckan.model.User.get("testsysadmin").id,
+ "apikey": ckan.model.User.get("testsysadmin").apikey,
+ "name": ckan.model.User.get("testsysadmin").name,
+ }
self.annafan = {
- 'id': ckan.model.User.get('annafan').id,
- 'apikey': ckan.model.User.get('annafan').apikey,
- 'name': ckan.model.User.get('annafan').name,
- }
+ "id": ckan.model.User.get("annafan").id,
+ "apikey": ckan.model.User.get("annafan").apikey,
+ "name": ckan.model.User.get("annafan").name,
+ }
self.russianfan = {
- 'id': ckan.model.User.get('russianfan').id,
- 'apikey': ckan.model.User.get('russianfan').apikey,
- 'name': ckan.model.User.get('russianfan').name,
- }
+ "id": ckan.model.User.get("russianfan").id,
+ "apikey": ckan.model.User.get("russianfan").apikey,
+ "name": ckan.model.User.get("russianfan").name,
+ }
self.joeadmin = {
- 'id': ckan.model.User.get('joeadmin').id,
- 'apikey': ckan.model.User.get('joeadmin').apikey,
- 'name': ckan.model.User.get('joeadmin').name,
- }
+ "id": ckan.model.User.get("joeadmin").id,
+ "apikey": ckan.model.User.get("joeadmin").apikey,
+ "name": ckan.model.User.get("joeadmin").name,
+ }
self.warandpeace = {
- 'id': ckan.model.Package.get('warandpeace').id,
- 'name': ckan.model.Package.get('warandpeace').name,
- }
+ "id": ckan.model.Package.get("warandpeace").id,
+ "name": ckan.model.Package.get("warandpeace").name,
+ }
self.annakarenina = {
- 'id': ckan.model.Package.get('annakarenina').id,
- 'name': ckan.model.Package.get('annakarenina').name,
- }
+ "id": ckan.model.Package.get("annakarenina").id,
+ "name": ckan.model.Package.get("annakarenina").name,
+ }
self.rogers_group = {
- 'id': ckan.model.Group.get('roger').id,
- 'name': ckan.model.Group.get('roger').name,
- }
+ "id": ckan.model.Group.get("roger").id,
+ "name": ckan.model.Group.get("roger").name,
+ }
self.davids_group = {
- 'id': ckan.model.Group.get('david').id,
- 'name': ckan.model.Group.get('david').name,
- }
- self.app = helpers._get_test_app()
-
- follow_user(self.app, self.joeadmin['id'], self.joeadmin['apikey'],
- self.testsysadmin['id'], self.testsysadmin['id'],
- self.testsysadmin['apikey'])
-
- follow_user(self.app, self.annafan['id'], self.annafan['apikey'],
- self.testsysadmin['id'], self.testsysadmin['id'],
- self.testsysadmin['apikey'])
- follow_user(self.app, self.russianfan['id'], self.russianfan['apikey'],
- self.testsysadmin['id'], self.testsysadmin['id'],
- self.testsysadmin['apikey'])
-
- follow_dataset(self.app, self.joeadmin['id'], self.joeadmin['apikey'],
- self.annakarenina['id'], self.annakarenina['id'],
- self.testsysadmin['apikey'])
-
- follow_dataset(self.app, self.annafan['id'], self.annafan['apikey'],
- self.annakarenina['id'], self.annakarenina['id'],
- self.testsysadmin['apikey'])
- follow_dataset(self.app, self.russianfan['id'], self.russianfan['apikey'],
- self.annakarenina['id'], self.annakarenina['id'],
- self.testsysadmin['apikey'])
-
- follow_user(self.app, self.tester['id'], self.tester['apikey'],
- self.joeadmin['id'], self.joeadmin['id'],
- self.testsysadmin['apikey'])
-
- follow_dataset(self.app, self.testsysadmin['id'],
- self.testsysadmin['apikey'], self.warandpeace['id'],
- self.warandpeace['id'], self.testsysadmin['apikey'])
-
- follow_group(self.app, self.testsysadmin['id'],
- self.testsysadmin['apikey'], self.davids_group['id'],
- self.davids_group['id'], self.testsysadmin['apikey'])
+ "id": ckan.model.Group.get("david").id,
+ "name": ckan.model.Group.get("david").name,
+ }
+
+ follow_user(
+ app,
+ self.joeadmin["id"],
+ self.joeadmin["apikey"],
+ self.testsysadmin["id"],
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ follow_user(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.testsysadmin["id"],
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_user(
+ app,
+ self.russianfan["id"],
+ self.russianfan["apikey"],
+ self.testsysadmin["id"],
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ follow_dataset(
+ app,
+ self.joeadmin["id"],
+ self.joeadmin["apikey"],
+ self.annakarenina["id"],
+ self.annakarenina["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ follow_dataset(
+ app,
+ self.annafan["id"],
+ self.annafan["apikey"],
+ self.annakarenina["id"],
+ self.annakarenina["id"],
+ self.testsysadmin["apikey"],
+ )
+ follow_dataset(
+ app,
+ self.russianfan["id"],
+ self.russianfan["apikey"],
+ self.annakarenina["id"],
+ self.annakarenina["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ follow_user(
+ app,
+ self.tester["id"],
+ self.tester["apikey"],
+ self.joeadmin["id"],
+ self.joeadmin["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ follow_dataset(
+ app,
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ self.warandpeace["id"],
+ self.warandpeace["id"],
+ self.testsysadmin["apikey"],
+ )
+
+ follow_group(
+ app,
+ self.testsysadmin["id"],
+ self.testsysadmin["apikey"],
+ self.davids_group["id"],
+ self.davids_group["id"],
+ self.testsysadmin["apikey"],
+ )
session = ckan.model.Session()
- session.delete(ckan.model.User.get('joeadmin'))
+ session.delete(ckan.model.User.get("joeadmin"))
session.commit()
- session.delete(ckan.model.Package.get('warandpeace'))
+ session.delete(ckan.model.Package.get("warandpeace"))
session.commit()
- session.delete(ckan.model.Group.get('david'))
+ session.delete(ckan.model.Group.get("david"))
session.commit()
- @classmethod
- def teardown_class(self):
- ckan.model.repo.rebuild_db()
-
- def test_01_on_delete_cascade_api(self):
- '''
+ def test_01_on_delete_cascade_api(self, app):
+ """
Test that UserFollowingUser and UserFollowingDataset rows cascade.
- '''
+ """
# It should no longer be possible to get joeadmin's follower list.
- error = call_action_api(self.app, 'user_follower_list',
- status=409, id='joeadmin', apikey=self.testsysadmin['apikey'])
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "user_follower_list",
+ status=409,
+ id="joeadmin",
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert "id" in error
# It should no longer be possible to get joeadmin's followee lists.
- for action in ('followee_list', 'user_followee_list',
- 'dataset_followee_list', 'group_followee_list'):
- error = call_action_api(self.app, action, status=409,
- id='joeadmin', apikey=self.testsysadmin['apikey'])
- assert 'id' in error
+ for action in (
+ "followee_list",
+ "user_followee_list",
+ "dataset_followee_list",
+ "group_followee_list",
+ ):
+ error = call_action_api(
+ app,
+ action,
+ status=409,
+ id="joeadmin",
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert "id" in error
# It should no longer be possible to get warandpeace's follower list.
- error = call_action_api(self.app, 'dataset_follower_list',
- status=409, id='warandpeace', apikey=self.testsysadmin['apikey'])
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "dataset_follower_list",
+ status=409,
+ id="warandpeace",
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert "id" in error
# It should no longer be possible to get david's follower list.
- error = call_action_api(self.app, 'group_follower_list',
- status=409, id='david', apikey=self.testsysadmin['apikey'])
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "group_follower_list",
+ status=409,
+ id="david",
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert "id" in error
# It should no longer be possible to get joeadmin's follower count.
- error = call_action_api(self.app, 'user_follower_count',
- status=409, id='joeadmin')
- assert 'id' in error
+ error = call_action_api(
+ app, "user_follower_count", status=409, id="joeadmin"
+ )
+ assert "id" in error
# It should no longer be possible to get joeadmin's followee counts.
- for action in ('followee_count', 'user_followee_count',
- 'dataset_followee_count', 'group_followee_count'):
- error = call_action_api(self.app, action, status=409,
- id='joeadmin')
- assert 'id' in error
+ for action in (
+ "followee_count",
+ "user_followee_count",
+ "dataset_followee_count",
+ "group_followee_count",
+ ):
+ error = call_action_api(app, action, status=409, id="joeadmin")
+ assert "id" in error
# It should no longer be possible to get warandpeace's follower count.
- error = call_action_api(self.app, 'dataset_follower_count',
- status=409, id='warandpeace')
- assert 'id' in error
+ error = call_action_api(
+ app, "dataset_follower_count", status=409, id="warandpeace"
+ )
+ assert "id" in error
# It should no longer be possible to get david's follower count.
- error = call_action_api(self.app, 'group_follower_count',
- status=409, id='david')
- assert 'id' in error
+ error = call_action_api(
+ app, "group_follower_count", status=409, id="david"
+ )
+ assert "id" in error
# It should no longer be possible to get am_following for joeadmin.
- error = call_action_api(self.app, 'am_following_user',
- apikey=self.testsysadmin['apikey'], status=409, id='joeadmin')
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "am_following_user",
+ apikey=self.testsysadmin["apikey"],
+ status=409,
+ id="joeadmin",
+ )
+ assert "id" in error
# It should no longer be possible to get am_following for warandpeace.
- error = call_action_api(self.app, 'am_following_dataset',
- apikey=self.testsysadmin['apikey'], status=409,
- id='warandpeace')
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "am_following_dataset",
+ apikey=self.testsysadmin["apikey"],
+ status=409,
+ id="warandpeace",
+ )
+ assert "id" in error
# It should no longer be possible to get am_following for david.
- error = call_action_api(self.app, 'am_following_group',
- apikey=self.testsysadmin['apikey'], status=409, id='david')
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "am_following_group",
+ apikey=self.testsysadmin["apikey"],
+ status=409,
+ id="david",
+ )
+ assert "id" in error
# It should no longer be possible to unfollow joeadmin.
- error = call_action_api(self.app, 'unfollow_user',
- apikey=self.tester['apikey'], status=409, id='joeadmin')
- assert error['id'] == ['Not found: User']
+ error = call_action_api(
+ app,
+ "unfollow_user",
+ apikey=self.tester["apikey"],
+ status=409,
+ id="joeadmin",
+ )
+ assert error["id"] == ["Not found: User"]
# It should no longer be possible to unfollow warandpeace.
- error = call_action_api(self.app, 'unfollow_dataset',
- apikey=self.testsysadmin['apikey'], status=409,
- id='warandpeace')
- assert error['id'] == ['Not found: Dataset']
+ error = call_action_api(
+ app,
+ "unfollow_dataset",
+ apikey=self.testsysadmin["apikey"],
+ status=409,
+ id="warandpeace",
+ )
+ assert error["id"] == ["Not found: Dataset"]
# It should no longer be possible to unfollow david.
- error = call_action_api(self.app, 'unfollow_group',
- apikey=self.testsysadmin['apikey'], status=409, id='david')
- assert error['id'] == ['Not found: Group']
+ error = call_action_api(
+ app,
+ "unfollow_group",
+ apikey=self.testsysadmin["apikey"],
+ status=409,
+ id="david",
+ )
+ assert error["id"] == ["Not found: Group"]
# It should no longer be possible to follow joeadmin.
- error = call_action_api(self.app, 'follow_user',
- apikey=self.annafan['apikey'], status=409, id='joeadmin')
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "follow_user",
+ apikey=self.annafan["apikey"],
+ status=409,
+ id="joeadmin",
+ )
+ assert "id" in error
# It should no longer be possible to follow warandpeace.
- error = call_action_api(self.app, 'follow_dataset',
- apikey=self.annafan['apikey'], status=409, id='warandpeace')
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "follow_dataset",
+ apikey=self.annafan["apikey"],
+ status=409,
+ id="warandpeace",
+ )
+ assert "id" in error
# It should no longer be possible to follow david.
- error = call_action_api(self.app, 'follow_group',
- apikey=self.annafan['apikey'], status=409, id='david')
- assert 'id' in error
+ error = call_action_api(
+ app,
+ "follow_group",
+ apikey=self.annafan["apikey"],
+ status=409,
+ id="david",
+ )
+ assert "id" in error
# Users who joeadmin was following should no longer have him in their
# follower list.
- followers = call_action_api(self.app, 'user_follower_list',
- id=self.testsysadmin['id'], apikey=self.testsysadmin['apikey'])
- assert 'joeadmin' not in [follower['name'] for follower in followers]
+ followers = call_action_api(
+ app,
+ "user_follower_list",
+ id=self.testsysadmin["id"],
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert "joeadmin" not in [follower["name"] for follower in followers]
# Datasets who joeadmin was following should no longer have him in
# their follower list.
- followers = call_action_api(self.app,
- 'dataset_follower_list', id=self.annakarenina['id'],
- apikey=self.testsysadmin['apikey'])
- assert 'joeadmin' not in [follower['name'] for follower in followers]
+ followers = call_action_api(
+ app,
+ "dataset_follower_list",
+ id=self.annakarenina["id"],
+ apikey=self.testsysadmin["apikey"],
+ )
+ assert "joeadmin" not in [follower["name"] for follower in followers]
def test_02_on_delete_cascade_db(self):
if not are_foreign_keys_supported():
@@ -1318,31 +1954,44 @@ def test_02_on_delete_cascade_db(self):
# After the previous test above there should be no rows with joeadmin's
# id in the UserFollowingUser or UserFollowingDataset tables.
- from ckan.model import UserFollowingUser, UserFollowingDataset, UserFollowingGroup
+ from ckan.model import (
+ UserFollowingUser,
+ UserFollowingDataset,
+ UserFollowingGroup,
+ )
+
session = ckan.model.Session()
query = session.query(UserFollowingUser)
- query = query.filter(UserFollowingUser.follower_id==self.joeadmin['id'])
+ query = query.filter(
+ UserFollowingUser.follower_id == self.joeadmin["id"]
+ )
assert query.count() == 0
query = session.query(UserFollowingUser)
- query = query.filter(UserFollowingUser.object_id==self.joeadmin['id'])
+ query = query.filter(
+ UserFollowingUser.object_id == self.joeadmin["id"]
+ )
assert query.count() == 0
query = session.query(UserFollowingDataset)
- query = query.filter(UserFollowingUser.follower_id==self.joeadmin['id'])
+ query = query.filter(
+ UserFollowingUser.follower_id == self.joeadmin["id"]
+ )
assert query.count() == 0
# There should be no rows with warandpeace's id in the
# UserFollowingDataset table.
query = session.query(UserFollowingDataset)
query = query.filter(
- UserFollowingDataset.object_id==self.warandpeace['id'])
+ UserFollowingDataset.object_id == self.warandpeace["id"]
+ )
assert query.count() == 0
# There should be no rows with david's id in the
# UserFollowingGroup table.
query = session.query(UserFollowingGroup)
query = query.filter(
- UserFollowingGroup.object_id==self.davids_group['id'])
+ UserFollowingGroup.object_id == self.davids_group["id"]
+ )
assert query.count() == 0
diff --git a/ckan/tests/legacy/functional/api/test_package_search.py b/ckan/tests/legacy/functional/api/test_package_search.py
index 55b73765925..02ca129c224 100644
--- a/ckan/tests/legacy/functional/api/test_package_search.py
+++ b/ckan/tests/legacy/functional/api/test_package_search.py
@@ -2,224 +2,237 @@
from six.moves.urllib.parse import quote
+import pytest
from dominate.util import escape
import ckan.lib.search as search
-from ckan.tests.legacy import setup_test_search_index
-from ckan.tests.legacy.functional.api.base import *
+from ckan.tests.legacy.functional.api.base import ApiTestCase, Api3TestCase
+from ckan.tests.legacy import setup_test_search_index, CreateTestData
from ckan.tests.legacy import TestController as ControllerTestCase
class PackageSearchApiTestCase(ApiTestCase, ControllerTestCase):
-
- @classmethod
- def setup_class(self):
- setup_test_search_index()
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db, clean_index):
CreateTestData.create()
self.package_fixture_data = {
- 'name' : u'testpkg',
- 'title': 'Some Title',
- 'url': u'http://blahblahblah.mydomain',
- 'resources': [{u'url':u'http://blahblahblah.mydomain',
- u'format':u'', u'description':''}],
- 'tags': ['russion', 'novel'],
- 'license_id': u'gpl-3.0',
- 'extras': {'national_statistic':'yes',
- 'geographic_coverage':'England, Wales'},
+ "name": u"testpkg",
+ "title": "Some Title",
+ "url": u"http://blahblahblah.mydomain",
+ "resources": [
+ {
+ u"url": u"http://blahblahblah.mydomain",
+ u"format": u"",
+ u"description": "",
+ }
+ ],
+ "tags": ["russion", "novel"],
+ "license_id": u"gpl-3.0",
+ "extras": {
+ "national_statistic": "yes",
+ "geographic_coverage": "England, Wales",
+ },
}
CreateTestData.create_arbitrary(self.package_fixture_data)
- self.base_url = self.offset('/action/package_search')
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
- search.clear_all()
+ self.base_url = self.offset("/action/package_search")
def assert_results(self, res_dict, expected_package_names):
- result = res_dict['result']['results'][0]
- assert_equal(result['name'], expected_package_names)
+ result = res_dict["result"]["results"][0]
+ assert result["name"] == expected_package_names
def test_01_uri_q(self):
- offset = self.base_url + '?q=%s' % self.package_fixture_data['name']
+ offset = self.base_url + "?q=%s" % self.package_fixture_data["name"]
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- self.assert_results(res_dict, 'testpkg')
- assert res_dict['result']['count'] == 1, res_dict['result']['count']
+ self.assert_results(res_dict, "testpkg")
+ assert res_dict["result"]["count"] == 1, res_dict["result"]["count"]
def test_02_post_q(self):
offset = self.base_url
- query = {'q':'testpkg'}
+ query = {"q": "testpkg"}
res = self.app.post(offset, params=query, status=200)
res_dict = self.data_from_res(res)
- self.assert_results(res_dict, 'testpkg')
- assert res_dict['result']['count'] == 1, res_dict['result']['count']
+ self.assert_results(res_dict, "testpkg")
+ assert res_dict["result"]["count"] == 1, res_dict["result"]["count"]
def test_04_post_json(self):
- query = {'q': self.package_fixture_data['name']}
+ query = {"q": self.package_fixture_data["name"]}
json_query = self.dumps(query)
offset = self.base_url
res = self.app.post(offset, params=json_query, status=200)
res_dict = self.data_from_res(res)
- self.assert_results(res_dict, 'testpkg')
- assert res_dict['result']['count'] == 1, res_dict['result']['count']
+ self.assert_results(res_dict, "testpkg")
+ assert res_dict["result"]["count"] == 1, res_dict["result"]["count"]
def test_06_uri_q_tags(self):
query = escape('annakarenina tags:russian tags:tolstoy')
offset = self.base_url + '?q=%s' % query
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- self.assert_results(res_dict, 'annakarenina')
- assert res_dict['result']['count'] == 1, res_dict['count']
+ self.assert_results(res_dict, "annakarenina")
+ assert res_dict["result"]["count"] == 1, res_dict["count"]
def test_09_just_tags(self):
- offset = self.base_url + '?q=tags:russian'
+ offset = self.base_url + "?q=tags:russian"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 2, res_dict
+ assert res_dict["result"]["count"] == 2, res_dict
def test_10_multiple_tags(self):
- offset = self.base_url + '?q=tags:tolstoy tags:russian'
+ offset = self.base_url + "?q=tags:tolstoy tags:russian"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 1, res_dict
+ assert res_dict["result"]["count"] == 1, res_dict
def test_12_all_packages_q(self):
offset = self.base_url + '?q=""'
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert_equal(res_dict['result']['count'], 3)
+ assert res_dict["result"]["count"] == 3
def test_12_all_packages_no_q(self):
offset = self.base_url
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert_equal(res_dict['result']['count'], 3)
+ assert res_dict["result"]["count"] == 3
def test_12_filter_by_openness(self):
- offset = self.base_url + '?filter_by_openness=1'
- res = self.app.get(offset, status=400) # feature dropped in #1360
+ offset = self.base_url + "?filter_by_openness=1"
+ res = self.app.get(offset, status=400) # feature dropped in #1360
assert "'filter_by_openness'" in res.body, res.body
def test_12_filter_by_downloadable(self):
- offset = self.base_url + '?filter_by_downloadable=1'
- res = self.app.get(offset, status=400) # feature dropped in #1360
+ offset = self.base_url + "?filter_by_downloadable=1"
+ res = self.app.get(offset, status=400) # feature dropped in #1360
assert "'filter_by_downloadable'" in res.body, res.body
class LegacyOptionsTestCase(ApiTestCase, ControllerTestCase):
- '''Here are tests with URIs in the syntax they were in
- for API v1 and v2.'''
- @classmethod
- def setup_class(self):
- setup_test_search_index()
+ """Here are tests with URIs in the syntax they were in
+ for API v1 and v2."""
+
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db, clean_index):
CreateTestData.create()
self.package_fixture_data = {
- 'name' : u'testpkg',
- 'title': 'Some Title',
- 'url': u'http://blahblahblah.mydomain',
- 'resources': [{u'url':u'http://blahblahblah.mydomain',
- u'format':u'', u'description':''}],
- 'tags': ['russion', 'novel'],
- 'license_id': u'gpl-3.0',
- 'extras': {'national_statistic':'yes',
- 'geographic_coverage':'England, Wales'},
+ "name": u"testpkg",
+ "title": "Some Title",
+ "url": u"http://blahblahblah.mydomain",
+ "resources": [
+ {
+ u"url": u"http://blahblahblah.mydomain",
+ u"format": u"",
+ u"description": "",
+ }
+ ],
+ "tags": ["russion", "novel"],
+ "license_id": u"gpl-3.0",
+ "extras": {
+ "national_statistic": "yes",
+ "geographic_coverage": "England, Wales",
+ },
}
CreateTestData.create_arbitrary(self.package_fixture_data)
- self.base_url = self.offset('/search/dataset')
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
- search.clear_all()
+ self.base_url = self.offset("/search/dataset")
def test_08_all_fields_syntax_error(self):
- offset = self.base_url + '?all_fields=should_be_boolean' # invalid all_fields value
+ offset = (
+ self.base_url + "?all_fields=should_be_boolean"
+ ) # invalid all_fields value
res = self.app.get(offset, status=400)
- assert('boolean' in res.body)
- assert('all_fields' in res.body)
- self.assert_json_response(res, 'boolean')
+ assert "boolean" in res.body
+ assert "all_fields" in res.body
+ self.assert_json_response(res, "boolean")
def test_09_just_tags(self):
- offset = self.base_url + '?tags=tolstoy'
+ offset = self.base_url + "?tags=tolstoy"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['count'] == 1, res_dict
+ assert res_dict["count"] == 1, res_dict
def test_10_single_tag_with_plus(self):
- tagname = "Flexible+" + quote(u'\u30a1'.encode('utf8'))
- offset = self.base_url + "?tags=%s&all_fields=1"%tagname
+ tagname = "Flexible+" + quote(u"\u30a1".encode("utf8"))
+ offset = self.base_url + "?tags=%s&all_fields=1" % tagname
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['count'] == 2, res_dict
+ assert res_dict["count"] == 2, res_dict
def test_10_multi_tags_with_ampersand_including_a_multiword_tagame(self):
- tagname = "Flexible+" + quote(u'\u30a1'.encode('utf8'))
- offset = self.base_url + '?tags=tolstoy&tags=%s&all_fields=1' % tagname
+ tagname = "Flexible+" + quote(u"\u30a1".encode("utf8"))
+ offset = self.base_url + "?tags=tolstoy&tags=%s&all_fields=1" % tagname
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['count'] == 1, res_dict
+ assert res_dict["count"] == 1, res_dict
def test_10_multiple_tags_with_ampersand(self):
- offset = self.base_url + '?tags=tolstoy&tags=russian&all_fields=1'
+ offset = self.base_url + "?tags=tolstoy&tags=russian&all_fields=1"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['count'] == 1, res_dict
+ assert res_dict["count"] == 1, res_dict
def test_10_many_tags_with_ampersand(self):
- offset = self.base_url + '?tags=tolstoy&tags=russian&tags=tolstoy'
+ offset = self.base_url + "?tags=tolstoy&tags=russian&tags=tolstoy"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['count'] == 1, res_dict
+ assert res_dict["count"] == 1, res_dict
def test_13_just_groups(self):
- offset = self.base_url + '?groups=roger'
+ offset = self.base_url + "?groups=roger"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 1, res_dict
+ assert res_dict["result"]["count"] == 1, res_dict
def test_14_empty_parameter_ignored(self):
- offset = self.base_url + '?groups=roger&title='
+ offset = self.base_url + "?groups=roger&title="
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 1, res_dict
+ assert res_dict["result"]["count"] == 1, res_dict
class TestPackageSearchApi3(Api3TestCase, PackageSearchApiTestCase):
- '''Here are tests with URIs in specifically SOLR syntax.'''
+ """Here are tests with URIs in specifically SOLR syntax."""
+
def test_09_just_tags(self):
- offset = self.base_url + '?q=tags:russian&fl=*'
+ offset = self.base_url + "?q=tags:russian&fl=*"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 2, res_dict
+ assert res_dict["result"]["count"] == 2, res_dict
def test_11_pagination_limit(self):
- offset = self.base_url + '?fl=*&q=tags:russian&rows=1&sort=name asc'
+ offset = self.base_url + "?fl=*&q=tags:russian&rows=1&sort=name asc"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 2, res_dict
- assert len(res_dict['result']['results']) == 1, res_dict
- self.assert_results(res_dict, 'annakarenina')
+ assert res_dict["result"]["count"] == 2, res_dict
+ assert len(res_dict["result"]["results"]) == 1, res_dict
+ self.assert_results(res_dict, "annakarenina")
def test_11_pagination_offset_limit(self):
- offset = self.base_url + '?fl=*&q=tags:russian&start=1&rows=1&sort=name asc'
+ offset = (
+ self.base_url + "?fl=*&q=tags:russian&start=1&rows=1&sort=name asc"
+ )
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 2, res_dict
- assert len(res_dict['result']['results']) == 1, res_dict
- self.assert_results(res_dict, 'warandpeace')
+ assert res_dict["result"]["count"] == 2, res_dict
+ assert len(res_dict["result"]["results"]) == 1, res_dict
+ self.assert_results(res_dict, "warandpeace")
def test_11_pagination_validation_error(self):
- offset = self.base_url + '?fl=*&q=tags:russian&start=should_be_integer&rows=1&sort=name asc' # invalid offset value
+ offset = (
+ self.base_url
+ + "?fl=*&q=tags:russian&start=should_be_integer&rows=1&sort=name asc"
+ ) # invalid offset value
res = self.app.get(offset, status=409)
- assert('Validation Error' in res.body)
+ assert "Validation Error" in res.body
def test_12_v1_or_v2_syntax(self):
- offset = self.base_url + '?all_fields=1'
+ offset = self.base_url + "?all_fields=1"
res = self.app.get(offset, status=400)
- assert("Invalid search parameters: ['all_fields']" in res.body), res.body
+ assert (
+ "Invalid search parameters: ['all_fields']" in res.body
+ ), res.body
def test_13_just_groups(self):
- offset = self.base_url + '?q=groups:roger'
+ offset = self.base_url + "?q=groups:roger"
res = self.app.get(offset, status=200)
res_dict = self.data_from_res(res)
- assert res_dict['result']['count'] == 1, res_dict
+ assert res_dict["result"]["count"] == 1, res_dict
diff --git a/ckan/tests/legacy/functional/api/test_resource.py b/ckan/tests/legacy/functional/api/test_resource.py
index 5614a01cd3b..05c60246117 100644
--- a/ckan/tests/legacy/functional/api/test_resource.py
+++ b/ckan/tests/legacy/functional/api/test_resource.py
@@ -3,65 +3,71 @@
from ckan.tests.legacy.functional.api.base import ApiTestCase, CreateTestData
from ckan.tests.legacy import TestController as ControllerTestCase
from ckan import model
+import pytest
+
class TestResourceApi(ApiTestCase, ControllerTestCase):
- api_version = '2'
+ api_version = "2"
- @classmethod
- def setup_class(self):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- self.ab = 'http://site.com/a/b.txt'
- self.cd = 'http://site.com/c/d.txt'
+ self.ab = "http://site.com/a/b.txt"
+ self.cd = "http://site.com/c/d.txt"
self.package_fixture_data = {
- 'name' : u'testpkg',
- 'title': 'Some Title',
- 'url': u'http://blahblahblah.mydomain',
- 'resources':[
- {'url':self.ab,
- 'description':'This is site ab.',
- 'format':'Excel spreadsheet',
- 'alt_url':'alt',
- 'extras':{'size':'100'},
- 'hash':'abc-123'},
- {'url':self.cd,
- 'description':'This is site cd.',
- 'format':'CSV',
- 'alt_url':'alt',
- 'extras':{'size':'100'},
- 'hash':'qwe-456'},
- ],
- 'tags': ['russian', 'novel'],
- 'license_id': u'gpl-3.0',
- 'extras': {'national_statistic':'yes',
- 'geographic_coverage':'England, Wales'},
+ "name": u"testpkg",
+ "title": "Some Title",
+ "url": u"http://blahblahblah.mydomain",
+ "resources": [
+ {
+ "url": self.ab,
+ "description": "This is site ab.",
+ "format": "Excel spreadsheet",
+ "alt_url": "alt",
+ "extras": {"size": "100"},
+ "hash": "abc-123",
+ },
+ {
+ "url": self.cd,
+ "description": "This is site cd.",
+ "format": "CSV",
+ "alt_url": "alt",
+ "extras": {"size": "100"},
+ "hash": "qwe-456",
+ },
+ ],
+ "tags": ["russian", "novel"],
+ "license_id": u"gpl-3.0",
+ "extras": {
+ "national_statistic": "yes",
+ "geographic_coverage": "England, Wales",
+ },
}
CreateTestData.create_arbitrary(self.package_fixture_data)
- self.base_url = self.offset('/util/resource')
-
- @classmethod
- def teardown_class(self):
- model.repo.rebuild_db()
+ self.base_url = self.offset("/util/resource")
- def test_good_input(self):
- offset = self.base_url + '/format_autocomplete?incomplete=cs'
- result = self.app.get(offset, status=200)
- content_type = result.headers.get('Content-Type')
- assert 'application/json' in content_type, content_type
+ def test_good_input(self, app):
+ offset = self.base_url + "/format_autocomplete?incomplete=cs"
+ result = app.get(offset, status=200)
+ content_type = result.headers.get("Content-Type")
+ assert "application/json" in content_type, content_type
res_json = self.loads(result.body)
- assert 'ResultSet' in res_json, res_json
- assert 'Result' in res_json.get('ResultSet'), res_json
- result_json = res_json.get('ResultSet').get('Result')
+ assert "ResultSet" in res_json, res_json
+ assert "Result" in res_json.get("ResultSet"), res_json
+ result_json = res_json.get("ResultSet").get("Result")
assert len(result_json) == 1, result_json
- assert 'Format' in result_json[0], result_json
- assert result_json[0].get('Format') == 'csv'
+ assert "Format" in result_json[0], result_json
+ assert result_json[0].get("Format") == "csv"
- def test_missing_format(self):
- offset = self.base_url + '/format_autocomplete?incomplete=incorrectformat'
- result = self.app.get(offset, status=200)
- content_type = result.headers.get('Content-Type')
- assert 'application/json' in content_type, content_type
+ def test_missing_format(self, app):
+ offset = (
+ self.base_url + "/format_autocomplete?incomplete=incorrectformat"
+ )
+ result = app.get(offset, status=200)
+ content_type = result.headers.get("Content-Type")
+ assert "application/json" in content_type, content_type
res_json = self.loads(result.body)
- assert 'ResultSet' in res_json, res_json
- assert 'Result' in res_json.get('ResultSet'), res_json
- result_json = res_json.get('ResultSet').get('Result')
+ assert "ResultSet" in res_json, res_json
+ assert "Result" in res_json.get("ResultSet"), res_json
+ result_json = res_json.get("ResultSet").get("Result")
assert not result_json, result_json
diff --git a/ckan/tests/legacy/functional/api/test_resource_search.py b/ckan/tests/legacy/functional/api/test_resource_search.py
deleted file mode 100644
index 57d7ab58768..00000000000
--- a/ckan/tests/legacy/functional/api/test_resource_search.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# encoding: utf-8
-
-from ckan.tests.legacy.functional.api.base import *
-from ckan.tests.legacy import TestController as ControllerTestCase
-
-class ResourceSearchApiTestCase(ApiTestCase, ControllerTestCase):
-
- @classmethod
- def setup_class(self):
- CreateTestData.create()
- self.ab = 'http://site.com/a/b.txt'
- self.cd = 'http://site.com/c/d.txt'
- self.package_fixture_data = {
- 'name' : u'testpkg',
- 'title': 'Some Title',
- 'url': u'http://blahblahblah.mydomain',
- 'resources':[
- {'url':self.ab,
- 'description':'This is site ab.',
- 'format':'Excel spreadsheet',
- 'alt_url':'alt',
- 'extras':{'size':'100'},
- 'hash':'abc-123'},
- {'url':self.cd,
- 'description':'This is site cd.',
- 'format':'Office spreadsheet',
- 'alt_url':'alt',
- 'extras':{'size':'100'},
- 'hash':'qwe-456'},
- ],
- 'tags': ['russion', 'novel', 'Leo Tolstoy'],
- 'license_id': u'gpl-3.0',
- 'extras': {'national_statistic':'yes',
- 'geographic_coverage':'England, Wales'},
- }
- CreateTestData.create_arbitrary(self.package_fixture_data)
- self.base_url = self.offset('/search/resource')
-
- @classmethod
- def teardown_class(self):
- model.repo.rebuild_db()
-
- def assert_urls_in_search_results(self, offset, expected_urls):
- result = self.app.get(offset, status=200)
- result_dict = self.loads(result.body)
- resources = [model.Session.query(model.Resource).get(resource_id) for resource_id in result_dict['results']]
- urls = set([resource.url for resource in resources])
- assert urls == set(expected_urls), urls
-
- def test_01_url(self):
- offset = self.base_url + '?url=site'
- self.assert_urls_in_search_results(offset, [self.ab, self.cd])
-
- def test_02_url_qjson(self):
- query = {'url':'site'}
- json_query = self.dumps(query)
- offset = self.base_url + '?qjson=%s' % json_query
- self.assert_urls_in_search_results(offset, [self.ab, self.cd])
-
- def test_03_post_qjson(self):
- query = {'url':'site'}
- json_query = self.dumps(query)
- offset = self.base_url
- result = self.app.post(offset, params=json_query, status=200)
- expected_urls = [self.ab, self.cd]
- result_dict = self.loads(result.body)
- resources = [model.Session.query(model.Resource).get(resource_id) for resource_id in result_dict['results']]
- urls = set([resource.url for resource in resources])
- assert urls == set(expected_urls), urls
-
- def test_04_bad_option(self):
- offset = self.base_url + '?random=option'
- result = self.app.get(offset, status=400)
- self.assert_json_response(result, 'Bad request - Bad search option')
-
- def test_05_options(self):
- offset = self.base_url + '?url=site&all_fields=1&callback=mycallback'
- result = self.app.get(offset, status=200)
- assert re.match('^mycallback\(.*\);$', result.body), result.body
- assert 'package_id' in result.body, result.body
diff --git a/ckan/tests/legacy/functional/api/test_user.py b/ckan/tests/legacy/functional/api/test_user.py
index a7f5826da9a..98968c3063e 100644
--- a/ckan/tests/legacy/functional/api/test_user.py
+++ b/ckan/tests/legacy/functional/api/test_user.py
@@ -1,6 +1,5 @@
# encoding: utf-8
-from nose.tools import assert_equal
import ckan.logic as logic
from ckan import model
@@ -8,219 +7,185 @@
from ckan.tests.legacy import TestController as ControllerTestCase
from ckan.tests.legacy import url_for
from ckan.tests import helpers
-
+import pytest
from ckan.common import json
class TestUserApi(ControllerTestCase):
- @classmethod
- def setup_class(cls):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
-
def test_autocomplete(self):
response = self.app.get(
- url=url_for(controller='api', action='user_autocomplete', ver=2),
- params={
- 'q': u'sysadmin',
- },
+ url=url_for(controller="api", action="user_autocomplete", ver=2),
+ params={"q": u"sysadmin"},
status=200,
)
- print(response.json)
- assert set(response.json[0].keys()) == set(['id', 'name', 'fullname'])
- assert_equal(response.json[0]['name'], u'testsysadmin')
- assert_equal(response.headers.get('Content-Type'), 'application/json;charset=utf-8')
+ assert set(response.json[0].keys()) == set(["id", "name", "fullname"])
+ assert response.json[0]["name"] == u"testsysadmin"
+ assert (
+ response.headers.get("Content-Type")
+ == "application/json;charset=utf-8"
+ )
def test_autocomplete_multiple(self):
response = self.app.get(
- url=url_for(controller='api', action='user_autocomplete', ver=2),
- params={
- 'q': u'tes',
- },
+ url=url_for(controller="api", action="user_autocomplete", ver=2),
+ params={"q": u"tes"},
status=200,
)
- print(response.json)
- assert_equal(len(response.json), 2)
+ assert len(response.json) == 2
def test_autocomplete_limit(self):
response = self.app.get(
- url=url_for(controller='api', action='user_autocomplete', ver=2),
- params={
- 'q': u'tes',
- 'limit': 1
- },
+ url=url_for(controller="api", action="user_autocomplete", ver=2),
+ params={"q": u"tes", "limit": 1},
status=200,
)
print(response.json)
- assert_equal(len(response.json), 1)
+ assert len(response.json) == 1
-class TestCreateUserApiDisabled(ControllerTestCase):
- '''
+class TestCreateUserApiDisabled(object):
+ """
Tests for the creating user when create_user_via_api is disabled.
- '''
+ """
- @classmethod
- def setup_class(cls):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- cls.sysadmin_user = model.User.get('testsysadmin')
- cls.app = helpers._get_test_app()
+ self.sysadmin_user = model.User.get("testsysadmin")
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
-
- def test_user_create_api_enabled_sysadmin(self):
+ def test_user_create_api_enabled_sysadmin(self, app):
params = {
- 'name': 'testinganewusersysadmin',
- 'email': 'testinganewuser@ckan.org',
- 'password': 'TestPassword1',
+ "name": "testinganewusersysadmin",
+ "email": "testinganewuser@ckan.org",
+ "password": "TestPassword1",
}
- res = self.app.post(
- '/api/3/action/user_create',
+ res = app.post(
+ "/api/3/action/user_create",
json.dumps(params),
- extra_environ={'Authorization': str(self.sysadmin_user.apikey)},
- expect_errors=True)
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ expect_errors=True,
+ )
res_dict = res.json
- assert res_dict['success'] is True
+ assert res_dict["success"] is True
- def test_user_create_api_disabled_anon(self):
+ def test_user_create_api_disabled_anon(self, app):
params = {
- 'name': 'testinganewuseranon',
- 'email': 'testinganewuser@ckan.org',
- 'password': 'TestPassword1',
+ "name": "testinganewuseranon",
+ "email": "testinganewuser@ckan.org",
+ "password": "TestPassword1",
}
- res = self.app.post('/api/3/action/user_create', json.dumps(params),
- expect_errors=True)
+ res = app.post(
+ "/api/3/action/user_create", json.dumps(params), expect_errors=True
+ )
res_dict = res.json
- assert res_dict['success'] is False
+ assert res_dict["success"] is False
-class TestCreateUserApiEnabled(ControllerTestCase):
- '''
+class TestCreateUserApiEnabled(object):
+ """
Tests for the creating user when create_user_via_api is enabled.
- '''
+ """
- @classmethod
- def setup_class(cls):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- cls.sysadmin_user = model.User.get('testsysadmin')
- cls.app = helpers._get_test_app()
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
+ self.sysadmin_user = model.User.get("testsysadmin")
- def test_user_create_api_enabled_sysadmin(self):
+ def test_user_create_api_enabled_sysadmin(self, app):
params = {
- 'name': 'testinganewusersysadmin',
- 'email': 'testinganewuser@ckan.org',
- 'password': 'TestPassword1',
+ "name": "testinganewusersysadmin",
+ "email": "testinganewuser@ckan.org",
+ "password": "TestPassword1",
}
- res = self.app.post(
- '/api/3/action/user_create',
+ res = app.post(
+ "/api/3/action/user_create",
json.dumps(params),
- extra_environ={'Authorization': str(self.sysadmin_user.apikey)})
+ extra_environ={"Authorization": str(self.sysadmin_user.apikey)},
+ )
res_dict = res.json
- assert res_dict['success'] is True
+ assert res_dict["success"] is True
- @helpers.change_config('ckan.auth.create_user_via_api', True)
- def test_user_create_api_enabled_anon(self):
+ @pytest.mark.ckan_config("ckan.auth.create_user_via_api", True)
+ def test_user_create_api_enabled_anon(self, app):
params = {
- 'name': 'testinganewuseranon',
- 'email': 'testinganewuser@ckan.org',
- 'password': 'TestPassword1',
+ "name": "testinganewuseranon",
+ "email": "testinganewuser@ckan.org",
+ "password": "TestPassword1",
}
- res = self.app.post('/api/3/action/user_create', json.dumps(params))
+ res = app.post("/api/3/action/user_create", json.dumps(params))
res_dict = res.json
- assert res_dict['success'] is True
+ assert res_dict["success"] is True
-class TestCreateUserWebDisabled(ControllerTestCase):
- '''
+class TestCreateUserWebDisabled(object):
+ """
Tests for the creating user by create_user_via_web is disabled.
- '''
+ """
- @classmethod
- def setup_class(cls):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- cls.app = helpers._get_test_app()
- cls.sysadmin_user = model.User.get('testsysadmin')
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
+ self.sysadmin_user = model.User.get("testsysadmin")
- @helpers.change_config('ckan.auth.create_user_via_web', False)
- def test_user_create_api_disabled(self):
+ @pytest.mark.ckan_config("ckan.auth.create_user_via_web", False)
+ def test_user_create_api_disabled(self, app):
params = {
- 'name': 'testinganewuser',
- 'email': 'testinganewuser@ckan.org',
- 'password': 'TestPassword1',
+ "name": "testinganewuser",
+ "email": "testinganewuser@ckan.org",
+ "password": "TestPassword1",
}
- res = self.app.post('/api/3/action/user_create', json.dumps(params),
- expect_errors=True)
+ res = app.post(
+ "/api/3/action/user_create", json.dumps(params), expect_errors=True
+ )
res_dict = res.json
- assert res_dict['success'] is False
+ assert res_dict["success"] is False
-class TestCreateUserWebEnabled(ControllerTestCase):
- '''
+class TestCreateUserWebEnabled(object):
+ """
Tests for the creating user by create_user_via_web is enabled.
- '''
+ """
- @classmethod
- def setup_class(cls):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- cls.app = helpers._get_test_app()
- cls.sysadmin_user = model.User.get('testsysadmin')
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
+ self.sysadmin_user = model.User.get("testsysadmin")
- @helpers.change_config('ckan.auth.create_user_via_web', True)
- def test_user_create_api_disabled(self):
+ @pytest.mark.ckan_config("ckan.auth.create_user_via_web", True)
+ def test_user_create_api_disabled(self, app):
params = {
- 'name': 'testinganewuser',
- 'email': 'testinganewuser@ckan.org',
- 'password': 'TestPassword1',
+ "name": "testinganewuser",
+ "email": "testinganewuser@ckan.org",
+ "password": "TestPassword1",
}
- res = self.app.post('/api/3/action/user_create', json.dumps(params),
- expect_errors=True)
+ res = app.post(
+ "/api/3/action/user_create", json.dumps(params), expect_errors=True
+ )
res_dict = res.json
- assert res_dict['success'] is False
+ assert res_dict["success"] is False
class TestUserActions(object):
-
- @classmethod
- def setup_class(cls):
+ @pytest.fixture(autouse=True)
+ def initial_data(self, clean_db):
CreateTestData.create()
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
-
def test_user_create_simple(self):
- '''Simple creation of a new user by a non-sysadmin user.'''
- context = {
- 'model': model,
- 'session': model.Session,
- 'user': 'tester'
- }
+ """Simple creation of a new user by a non-sysadmin user."""
+ context = {"model": model, "session": model.Session, "user": "tester"}
data_dict = {
- 'name': 'a-new-user',
- 'email': 'a.person@example.com',
- 'password': 'TestPassword1',
+ "name": "a-new-user",
+ "email": "a.person@example.com",
+ "password": "TestPassword1",
}
- user_dict = logic.get_action('user_create')(context, data_dict)
+ user_dict = logic.get_action("user_create")(context, data_dict)
- assert_equal(user_dict['name'], 'a-new-user')
- assert 'email' in user_dict
- assert 'apikey' in user_dict
- assert 'password' not in user_dict
+ assert user_dict["name"] == "a-new-user"
+ assert "email" in user_dict
+ assert "apikey" in user_dict
+ assert "password" not in user_dict
diff --git a/ckan/tests/legacy/functional/api/test_util.py b/ckan/tests/legacy/functional/api/test_util.py
index dd7f7fc54d1..eb99c38335a 100644
--- a/ckan/tests/legacy/functional/api/test_util.py
+++ b/ckan/tests/legacy/functional/api/test_util.py
@@ -1,41 +1,41 @@
# encoding: utf-8
-from nose.tools import assert_equal
-
+import pytest
from ckan import model
from ckan.lib.create_test_data import CreateTestData
from ckan.tests.legacy import TestController as ControllerTestCase
from ckan.tests.legacy import url_for
-class TestUtil(ControllerTestCase):
- @classmethod
- def setup_class(cls):
- CreateTestData.create()
-
- @classmethod
- def teardown_class(cls):
- model.repo.rebuild_db()
-
- def test_munge_package_name(self):
- response = self.app.get(
- url=url_for(controller='api', action='munge_package_name', ver=2),
- params={'name': 'test name'},
- status=200,
- )
- assert_equal(response.body, '"test-name"')
-
- def test_munge_title_to_package_name(self):
- response = self.app.get(
- url=url_for(controller='api', action='munge_title_to_package_name', ver=2),
- params={'name': 'Test title'},
- status=200,
- )
- assert_equal(response.body, '"test-title"')
-
- def test_munge_tag(self):
- response = self.app.get(
- url=url_for(controller='api', action='munge_tag', ver=2),
- params={'name': 'Test subject'},
- status=200,
- )
- assert_equal(response.body, '"test-subject"')
+
+@pytest.fixture(autouse=True)
+def initial_data(clean_db):
+ CreateTestData.create()
+
+
+def test_munge_package_name(app):
+ response = app.get(
+ url=url_for(controller="api", action="munge_package_name", ver=2),
+ params={"name": "test name"},
+ status=200,
+ )
+ assert response.body == '"test-name"'
+
+
+def test_munge_title_to_package_name(app):
+ response = app.get(
+ url=url_for(
+ controller="api", action="munge_title_to_package_name", ver=2
+ ),
+ params={"name": "Test title"},
+ status=200,
+ )
+ assert response.body == '"test-title"'
+
+
+def test_munge_tag(app):
+ response = app.get(
+ url=url_for(controller="api", action="munge_tag", ver=2),
+ params={"name": "Test subject"},
+ status=200,
+ )
+ assert response.body == '"test-subject"'
diff --git a/ckan/tests/legacy/functional/base.py b/ckan/tests/legacy/functional/base.py
index 671a0d1d5e3..8c18d868550 100644
--- a/ckan/tests/legacy/functional/base.py
+++ b/ckan/tests/legacy/functional/base.py
@@ -3,5 +3,6 @@
from ckan.tests.legacy.html_check import HtmlCheckMethods
from ckan.tests.legacy import TestController as ControllerTestCase
+
class FunctionalTestCase(ControllerTestCase, HtmlCheckMethods):
pass
diff --git a/ckan/tests/legacy/functional/test_admin.py b/ckan/tests/legacy/functional/test_admin.py
index 74c79477653..32cf2d02341 100644
--- a/ckan/tests/legacy/functional/test_admin.py
+++ b/ckan/tests/legacy/functional/test_admin.py
@@ -1,27 +1,20 @@
# encoding: utf-8
+import pytest
import ckan.model as model
-from ckan.tests.legacy import url_for, CreateTestData, WsgiAppCase
+from ckan.tests.legacy import url_for, CreateTestData
-class TestAdminController(WsgiAppCase):
- @classmethod
- def setup_class(cls):
- # setup test data including testsysadmin user
- CreateTestData.create()
- @classmethod
- def teardown_class(self):
- model.repo.rebuild_db()
-
- #test that only sysadmins can access the /ckan-admin page
- def test_index(self):
- url = url_for('admin.index')
- response = self.app.get(url, status=[403])
- # random username
- response = self.app.get(url, status=[403],
- extra_environ={'REMOTE_USER': 'my-random-user-name'})
- # now test real access
- username = u'testsysadmin'.encode('utf8')
- response = self.app.get(url,
- extra_environ={'REMOTE_USER': username})
- assert 'Administration' in response, response
+@pytest.mark.usefixtures("clean_db")
+def test_index(app):
+ CreateTestData.create()
+ url = url_for("admin.index")
+ response = app.get(url, status=[403])
+ # random username
+ response = app.get(
+ url, status=[403], extra_environ={"REMOTE_USER": "my-random-user-name"}
+ )
+ # now test real access
+ username = u"testsysadmin".encode("utf8")
+ response = app.get(url, extra_environ={"REMOTE_USER": username})
+ assert "Administration" in response, response
diff --git a/ckan/tests/legacy/functional/test_error.py b/ckan/tests/legacy/functional/test_error.py
index a67a42da2fc..5fc3b38b61b 100644
--- a/ckan/tests/legacy/functional/test_error.py
+++ b/ckan/tests/legacy/functional/test_error.py
@@ -1,9 +1,7 @@
# encoding: utf-8
-from base import FunctionalTestCase
-class TestError(FunctionalTestCase):
- def test_without_redirect(self):
- # this is what a web bot might do
- res = self.app.get('/error/document')
- assert 'There is no error.' in str(res), str(res)
+def test_without_redirect(app):
+ # this is what a web bot might do
+ res = app.get("/error/document")
+ assert "There is no error." in str(res)
diff --git a/ckan/tests/legacy/functional/test_group.py b/ckan/tests/legacy/functional/test_group.py
index 8fdd156932c..6db14637adf 100644
--- a/ckan/tests/legacy/functional/test_group.py
+++ b/ckan/tests/legacy/functional/test_group.py
@@ -1,130 +1,107 @@
# encoding: utf-8
+import pytest
import mock
import ckan.model as model
-import ckan.lib.search as search
from ckan.lib.create_test_data import CreateTestData
from ckan.logic import get_action
-from ckan.tests.legacy import *
-from base import FunctionalTestCase
-
-
-class TestGroup(FunctionalTestCase):
-
- @classmethod
- def setup_class(self):
- search.clear_all()
- model.Session.remove()
- CreateTestData.create()
-
- @classmethod
- def teardown_class(self):
- model.repo.rebuild_db()
-
- def test_sorting(self):
- model.repo.rebuild_db()
-
- testsysadmin = model.User(name=u'testsysadmin')
- testsysadmin.sysadmin = True
- model.Session.add(testsysadmin)
-
- pkg1 = model.Package(name="pkg1")
- pkg2 = model.Package(name="pkg2")
- model.Session.add(pkg1)
- model.Session.add(pkg2)
- model.Session.commit()
-
- CreateTestData.create_groups([{'name': "alpha",
- 'title': "Alpha",
- 'packages': []},
- {'name': "beta",
- 'title': "Beta",
- 'packages': ["pkg1", "pkg2"]},
- {'name': "delta",
- 'title': 'Delta',
- 'packages': ["pkg1"]},
- {'name': "gamma",
- 'title': "Gamma",
- 'packages': []}],
- admin_user_name='testsysadmin')
-
- context = {'model': model, 'session': model.Session,
- 'user': 'testsysadmin', 'for_view': True,
- 'with_private': False}
- data_dict = {'all_fields': True}
- results = get_action('group_list')(context, data_dict)
- assert results[0]['name'] == u'alpha', results[0]['name']
- assert results[-1]['name'] == u'gamma', results[-1]['name']
-
- # Test title forward
- data_dict = {'all_fields': True, 'sort': 'title asc'}
- results = get_action('group_list')(context, data_dict)
- assert results[0]['name'] == u'alpha', results[0]['name']
- assert results[-1]['name'] == u'gamma', results[-1]['name']
-
- # Test title reverse
- data_dict = {'all_fields': True, 'sort': 'title desc'}
- results = get_action('group_list')(context, data_dict)
- assert results[0]['name'] == u'gamma', results[0]['name']
- assert results[-1]['name'] == u'alpha', results[-1]['name']
-
- # Test name reverse
- data_dict = {'all_fields': True, 'sort': 'name desc'}
- results = get_action('group_list')(context, data_dict)
- assert results[0]['name'] == u'gamma', results[0]['name']
- assert results[-1]['name'] == u'alpha', results[-1]['name']
-
- # Test packages reversed
- data_dict = {'all_fields': True, 'sort': 'package_count desc'}
- results = get_action('group_list')(context, data_dict)
- assert results[0]['name'] == u'beta', results[0]['name']
- assert results[1]['name'] == u'delta', results[1]['name']
-
- # Test packages forward
- data_dict = {'all_fields': True, 'sort': 'package_count asc'}
- results = get_action('group_list')(context, data_dict)
- assert results[-2]['name'] == u'delta', results[-2]['name']
- assert results[-1]['name'] == u'beta', results[-1]['name']
-
- # Default ordering for packages
- data_dict = {'all_fields': True, 'sort': 'package_count'}
- results = get_action('group_list')(context, data_dict)
- assert results[0]['name'] == u'beta', results[0]['name']
- assert results[1]['name'] == u'delta', results[1]['name']
-
- def test_read_non_existent(self):
- name = u'group_does_not_exist'
- offset = url_for(controller='group', action='read', id=name)
- res = self.app.get(offset, status=404)
-
-
-class TestMemberInvite(FunctionalTestCase):
- @classmethod
- def setup_class(self):
- model.Session.remove()
- model.repo.rebuild_db()
-
- def teardown(self):
- model.repo.rebuild_db()
-
- @mock.patch('ckan.lib.mailer.mail_user')
- def test_member_new_invites_user_if_received_email(self, mail_user):
- user = CreateTestData.create_user('a_user', sysadmin=True)
- group_name = 'a_group'
- CreateTestData.create_groups([{'name': group_name}], user.name)
- group = model.Group.get(group_name)
- url = url_for(controller='group', action='member_new', id=group.id)
- email = 'invited_user@mailinator.com'
- role = 'member'
-
- params = {'email': email, 'role': role}
- res = self.app.post(url, params,
- extra_environ={'REMOTE_USER': str(user.name)})
-
- users = model.User.by_email(email)
- assert len(users) == 1, users
- user = users[0]
- assert user.email == email, user
- assert group.id in user.get_group_ids(capacity=role)
+from ckan.lib.helpers import url_for
+import ckan.tests.factories as factories
+
+
+@pytest.mark.usefixtures("clean_db", "clean_index")
+def test_sorting():
+ testsysadmin = factories.Sysadmin(name=u"testsysadmin")
+
+ pkg1 = model.Package(name="pkg1")
+ pkg2 = model.Package(name="pkg2")
+ model.Session.add(pkg1)
+ model.Session.add(pkg2)
+
+ CreateTestData.create_groups(
+ [
+ {"name": "alpha", "title": "Alpha", "packages": []},
+ {"name": "beta", "title": "Beta", "packages": ["pkg1", "pkg2"]},
+ {"name": "delta", "title": "Delta", "packages": ["pkg1"]},
+ {"name": "gamma", "title": "Gamma", "packages": []},
+ ],
+ admin_user_name="testsysadmin",
+ )
+
+ context = {
+ "model": model,
+ "session": model.Session,
+ "user": "testsysadmin",
+ "for_view": True,
+ "with_private": False,
+ }
+ data_dict = {"all_fields": True}
+ results = get_action("group_list")(context, data_dict)
+ assert results[0]["name"] == u"alpha", results[0]["name"]
+ assert results[-1]["name"] == u"gamma", results[-1]["name"]
+
+ # Test title forward
+ data_dict = {"all_fields": True, "sort": "title asc"}
+ results = get_action("group_list")(context, data_dict)
+ assert results[0]["name"] == u"alpha", results[0]["name"]
+ assert results[-1]["name"] == u"gamma", results[-1]["name"]
+
+ # Test title reverse
+ data_dict = {"all_fields": True, "sort": "title desc"}
+ results = get_action("group_list")(context, data_dict)
+ assert results[0]["name"] == u"gamma", results[0]["name"]
+ assert results[-1]["name"] == u"alpha", results[-1]["name"]
+
+ # Test name reverse
+ data_dict = {"all_fields": True, "sort": "name desc"}
+ results = get_action("group_list")(context, data_dict)
+ assert results[0]["name"] == u"gamma", results[0]["name"]
+ assert results[-1]["name"] == u"alpha", results[-1]["name"]
+
+ # Test packages reversed
+ data_dict = {"all_fields": True, "sort": "package_count desc"}
+ results = get_action("group_list")(context, data_dict)
+ assert results[0]["name"] == u"beta", results[0]["name"]
+ assert results[1]["name"] == u"delta", results[1]["name"]
+
+ # Test packages forward
+ data_dict = {"all_fields": True, "sort": "package_count asc"}
+ results = get_action("group_list")(context, data_dict)
+ assert results[-2]["name"] == u"delta", results[-2]["name"]
+ assert results[-1]["name"] == u"beta", results[-1]["name"]
+
+ # Default ordering for packages
+ data_dict = {"all_fields": True, "sort": "package_count"}
+ results = get_action("group_list")(context, data_dict)
+ assert results[0]["name"] == u"beta", results[0]["name"]
+ assert results[1]["name"] == u"delta", results[1]["name"]
+
+
+@pytest.mark.usefixtures("clean_db")
+def test_read_non_existent(app):
+ name = u"group_does_not_exist"
+ offset = url_for(controller="group", action="read", id=name)
+ app.get(offset, status=404)
+
+
+@pytest.mark.usefixtures("clean_db")
+@mock.patch("ckan.lib.mailer.mail_user")
+def test_member_new_invites_user_if_received_email(_mail_user, app):
+ user = CreateTestData.create_user("a_user", sysadmin=True)
+ group_name = "a_group"
+ CreateTestData.create_groups([{"name": group_name}], user.name)
+ group = model.Group.get(group_name)
+ url = url_for(controller="group", action="member_new", id=group.id)
+ email = "invited_user@mailinator.com"
+ role = "member"
+
+ params = {"email": email, "role": role}
+ app.post(url, params, extra_environ={"REMOTE_USER": str(user.name)})
+
+ users = model.User.by_email(email)
+ assert len(users) == 1, users
+ user = users[0]
+ assert user.email == email, user
+ assert group.id in user.get_group_ids(capacity=role)
diff --git a/ckan/tests/legacy/functional/test_package.py b/ckan/tests/legacy/functional/test_package.py
index faf638cb31a..4530fc4308d 100644
--- a/ckan/tests/legacy/functional/test_package.py
+++ b/ckan/tests/legacy/functional/test_package.py
@@ -1,12 +1,12 @@
# encoding: utf-8
-from __future__ import print_function
+import pytest
+from six import string_types
from ckan.common import config
from difflib import unified_diff
-from nose.tools import assert_equal
-from ckan.tests.legacy import *
+from ckan.tests.legacy import url_for
import ckan.tests.legacy as tests
from ckan.tests.legacy.html_check import HtmlCheckMethods
from base import FunctionalTestCase
@@ -16,84 +16,93 @@
from ckan import plugins
from ckan.lib.search.common import SolrSettings
+existing_extra_html = (
+ '',
+ '',
+)
+class TestPackageBase(object):
+ key1 = u"key1 Less-than: < Umlaut: \xfc"
+ value1 = u"value1 Less-than: < Umlaut: \xfc"
-existing_extra_html = ('', '')
-
-
-class TestPackageBase(FunctionalTestCase):
- key1 = u'key1 Less-than: < Umlaut: \xfc'
- value1 = u'value1 Less-than: < Umlaut: \xfc'
# Note: Can't put a quotation mark in key1 or value1 because
# paste.fixture doesn't unescape the value in an input field
# on form submission. (But it works in real life.)
def _assert_form_errors(self, res):
- self.check_tag(res, '