From 25e67a6787237e97fef12e6428089cf75ae852c3 Mon Sep 17 00:00:00 2001 From: Eric Barbour Date: Jun 14 2016 16:16:43 +0000 Subject: [PATCH 1/3] Add fedmsg/markup route, and api tests --- diff --git a/hubs/app.py b/hubs/app.py index fe661ab..df33459 100755 --- a/hubs/app.py +++ b/hubs/app.py @@ -1,11 +1,15 @@ import datetime import functools +import json import logging import os +import uuid import flask import flask.json +import fmn.lib import munch +import pygments.formatters import six from flask.ext.openid import OpenID @@ -16,6 +20,10 @@ import hubs.widgets import datanommer.models from hubs.utils import username2avatar +from hubs.widgets.feed import ( + apply_markup, rehydrate_preference, + get_remote_preference +) app = flask.Flask(__name__) @@ -43,6 +51,7 @@ import fedmsg.config import fedmsg.meta fedmsg_config = fedmsg.config.load_config() fedmsg.meta.make_processors(**fedmsg_config) +PATHS = fmn.lib.load_rules(root='fmn.rules') session = hubs.models.init(fedmsg_config['hubs.sqlalchemy.uri']) datanommer.models.init(fedmsg_config['datanommer.sqlalchemy.uri']) @@ -628,3 +637,50 @@ def hub_leave(hub): return flask.abort(400) session.commit() return flask.redirect(flask.url_for('hub', name=hub.name)) + + +@app.route('/api/fedmsg/markup', methods=['GET']) +def markup_fedmsg(): + try: + data = flask.request.args['message'] + plugin = flask.request.args['plugin'] + except KeyError: + return flask.abort(400) + widget = hubs.models.Widget.by_plugin(session, plugin) + if not widget: + return flask.abort(400) + context = widget.config.get('fmn_context') + messages = [] + message = json.loads(data) + try: + nickname = flask.g.auth.nickname + except AttributeError: # Not logged in + return flask.abort(403) + preference = get_remote_preference(nickname, context) + if preference: + try: + preference = rehydrate_preference(preference) + except ImportError: + pass + recipients = fmn.lib.recipients( + [preference], message, PATHS, fedmsg_config) + if recipients: + messages.append(message) + matches = fedmsg.meta.conglomerate(messages, lexers=True, **fedmsg_config) + for match in matches: + match['markup'] = apply_markup(match) + for _, constituent in match['msg_ids'].items(): + constituent['markup'] = apply_markup(constituent) + if constituent['long_form'] != constituent['subtitle']: + if constituent.get('lexer'): + constituent['long_form'] = pygments.highlight( + constituent['long_form'], + constituent['lexer'], + pygments.formatters.HtmlFormatter(style='monokai'), + ) + else: + markup = u"
{long_form}
".format(**constituent) + constituent['long_form'] = markup + # And tack on a unique identifier for each top level entry. + match['dom_id'] = six.text_type(uuid.uuid4()) + return flask.jsonify(matches) diff --git a/hubs/models.py b/hubs/models.py index 1731076..32580a6 100755 --- a/hubs/models.py +++ b/hubs/models.py @@ -303,6 +303,10 @@ class Widget(BASE): def by_idx(cls, session, idx): return session.query(cls).filter_by(idx=idx).first() + @classmethod + def by_plugin(cls, session, plugin): + return session.query(cls).filter_by(plugin=plugin).first() + get = by_idx @property diff --git a/hubs/tests/__init__.py b/hubs/tests/__init__.py index 8dbca6c..7c9da28 100644 --- a/hubs/tests/__init__.py +++ b/hubs/tests/__init__.py @@ -88,6 +88,22 @@ class APPTest(unittest.TestCase): @contextmanager +def user_set(APP, user): + """ Set the provided user as fas_user in the provided application.""" + # Hack used to remove the before_request function set by + # flask.ext.fas_openid.FAS which otherwise kills our effort to set a + # flask.g.fas_user. + from flask import appcontext_pushed, g + + def handler(sender, **kwargs): + g.fas_user = user + g.fas_session_id = b'123' + + with appcontext_pushed.connected_to(handler, APP): + yield + + +@contextmanager def auth_set(APP, auth): """ Set the provided user as fas_user in the provided application.""" @@ -105,6 +121,7 @@ def auth_set(APP, auth): with appcontext_pushed.connected_to(handler, APP): yield + class FakeUser(object): """ Fake user used to test the fedocallib library. """ diff --git a/hubs/tests/test_api/test_fedmsg.py b/hubs/tests/test_api/test_fedmsg.py new file mode 100644 index 0000000..c708073 --- /dev/null +++ b/hubs/tests/test_api/test_fedmsg.py @@ -0,0 +1,330 @@ +import json + +import hubs.tests +import hubs.models + + +class TestFeed(hubs.tests.APPTest): + # TODO this test relies on a specific filter for the atelic user + # It would be better to fake preferences on FAS + user = hubs.tests.FakeAuthorization('atelic') + message_involved = { + 'timestamp': 1465567413.0, + 'topic': 'io.pagure.prod.pagure.issue.new', + 'msg_id': '2016-0490127f-473f-4d01-ASDF-a864a56dc302', + 'msg': { + 'action': 'created', + 'comment': { + 'body': + 'hm, there is something odd, the stackage page is being inconsistent, one time the version number for LTS is linked, one time it isn\'t.\r\n\r\nIt\'s as if there are 2 servers running 2 different versions of the application', + 'created_at': '2016-06-10T14:03:31Z', + 'html_url': + 'https://github.com/fedora-infra/anitya/issues/283#issuecomment-225190438', + 'id': 225190438, + 'updated_at': '2016-06-10T14:03:31Z', + 'url': + 'https://api.github.com/repos/fedora-infra/anitya/issues/comments/225190438', + 'user': { + 'gravatar_id': '', + 'html_url': 'https://github.com/pypingou', + 'id': 1240038, + 'login': 'pypingou', + 'site_admin': False, + 'type': 'User', + 'url': 'https://api.github.com/users/pypingou' + } + }, + 'fas_usernames': { + 'fedora-infra': 'github_org_fedora-infra', + 'pypingou': 'pingou' + }, + 'issue': { + 'assignee': None, + 'body': + '@juhp it seems that the stackage backend is broken: https://release-monitoring.org/projects/updates/failed?name=&log=stackage want to look at it?', + 'closed_at': '2016-04-29T14:53:10Z', + 'comments': 8, + 'created_at': '2016-04-15T16:15:57Z', + 'html_url': + 'https://github.com/fedora-infra/anitya/issues/283', + 'id': 148703615, + 'labels': [], + 'locked': False, + 'milestone': None, + 'number': 283, + 'state': 'closed', + 'title': 'stackage backend broken', + 'updated_at': '2016-06-10T14:03:31Z', + 'url': + 'https://api.github.com/repos/fedora-infra/anitya/issues/283', + 'user': { + 'gravatar_id': '', + 'html_url': 'https://github.com/pypingou', + 'id': 1240038, + 'login': 'pypingou', + 'site_admin': False, + 'type': 'User', + 'url': 'https://api.github.com/users/pypingou' + } + }, + 'organization': { + 'description': 'Fedora Infrastructure Team', + 'id': 3316637, + 'login': 'fedora-infra', + 'url': 'https://api.github.com/orgs/fedora-infra' + }, + 'repository': { + 'created_at': '2013-11-29T10:17:26Z', + 'default_branch': 'master', + 'description': 'A cross-distribution upstream release project', + 'fork': False, + 'forks': 33, + 'forks_count': 33, + 'full_name': 'fedora-infra/anitya', + 'has_downloads': True, + 'has_issues': True, + 'has_pages': False, + 'has_wiki': False, + 'homepage': 'https://release-monitoring.org', + 'html_url': 'https://github.com/fedora-infra/anitya', + 'id': 14798348, + 'language': 'Python', + 'name': 'anitya', + 'open_issues': 25, + 'open_issues_count': 25, + 'owner': { + 'gravatar_id': '', + 'html_url': 'https://github.com/fedora-infra', + 'id': 3316637, + 'login': 'fedora-infra', + 'site_admin': False, + 'type': 'Organization', + 'url': 'https://api.github.com/users/fedora-infra' + }, + 'private': False, + 'pushed_at': '2016-06-05T18:16:15Z', + 'size': 4364, + 'stargazers_count': 56, + 'updated_at': '2016-06-10T09:43:58Z', + 'url': 'https://api.github.com/repos/fedora-infra/anitya', + 'watchers': 56, + 'watchers_count': 56 + }, + 'sender': { + 'gravatar_id': '', + 'html_url': 'https://github.com/pypingou', + 'id': 1240038, + 'login': 'pypingou', + 'site_admin': False, + 'type': 'User', + 'url': 'https://api.github.com/users/pypingou' + } + }, + 'arguments': { + 'categories': [ + 'pagure' + ], + 'contains': [], + 'delta': 172800.0, + 'end': 1465839365.0, + 'grouped': False, + 'meta': [], + 'not_categories': [], + 'not_packages': [], + 'not_topics': [], + 'not_users': [], + 'order': 'desc', + 'packages': [], + 'page': 1, + 'rows_per_page': 1, + 'start': 1465666565.0, + 'topics': [], + 'users': [] + }, + 'count': 1, + 'pages': 225, + 'total': 225 + } + message_not_involved = { + 'topic': 'org.fedoraproject.prod.github.issue.comment', + 'i': 1, + 'msg': { + 'action': 'created', + 'comment': { + 'body': + 'hm, there is something odd, the stackage page is being inconsistent, one time the version number for LTS is linked, one time it isn\'t.\r\n\r\nIt\'s as if there are 2 servers running 2 different versions of the application', + 'created_at': '2016-06-10T14:03:31Z', + 'html_url': + 'https://github.com/fedora-infra/anitya/issues/283#issuecomment-225190438', + 'id': 225190438, + 'updated_at': '2016-06-10T14:03:31Z', + 'url': + 'https://api.github.com/repos/fedora-infra/anitya/issues/comments/225190438', + 'user': { + 'gravatar_id': '', + 'html_url': 'https://github.com/pypingou', + 'id': 1240038, + 'login': 'pypingou', + 'site_admin': False, + 'type': 'User', + 'url': 'https://api.github.com/users/pypingou' + } + }, + 'fas_usernames': { + 'fedora-infra': 'github_org_fedora-infra', + 'pypingou': 'pingou' + }, + 'issue': { + 'assignee': None, + 'body': + '@juhp it seems that the stackage backend is broken: https://release-monitoring.org/projects/updates/failed?name=&log=stackage want to look at it?', + 'closed_at': '2016-04-29T14:53:10Z', + 'comments': 8, + 'created_at': '2016-04-15T16:15:57Z', + 'html_url': + 'https://github.com/fedora-infra/anitya/issues/283', + 'id': 148703615, + 'labels': [], + 'locked': False, + 'milestone': None, + 'number': 283, + 'state': 'closed', + 'title': 'stackage backend broken', + 'updated_at': '2016-06-10T14:03:31Z', + 'url': + 'https://api.github.com/repos/fedora-infra/anitya/issues/283', + 'user': { + 'gravatar_id': '', + 'html_url': 'https://github.com/pypingou', + 'id': 1240038, + 'login': 'pypingou', + 'site_admin': False, + 'type': 'User', + 'url': 'https://api.github.com/users/pypingou' + } + }, + 'organization': { + 'description': 'Fedora Infrastructure Team', + 'id': 3316637, + 'login': 'fedora-infra', + 'url': 'https://api.github.com/orgs/fedora-infra' + }, + 'repository': { + 'created_at': '2013-11-29T10:17:26Z', + 'default_branch': 'master', + 'description': + 'A cross-distribution upstream release monitoring project', + 'fork': False, + 'forks': 33, + 'forks_count': 33, + 'full_name': 'fedora-infra/anitya', + 'has_downloads': True, + 'has_issues': True, + 'has_pages': False, + 'has_wiki': False, + 'homepage': 'https://release-monitoring.org', + 'html_url': 'https://github.com/fedora-infra/anitya', + 'id': 14798348, + 'language': 'Python', + 'name': 'anitya', + 'open_issues': 25, + 'open_issues_count': 25, + 'owner': { + 'gravatar_id': '', + 'html_url': 'https://github.com/fedora-infra', + 'id': 3316637, + 'login': 'fedora-infra', + 'site_admin': False, + 'type': 'Organization', + 'url': 'https://api.github.com/users/fedora-infra' + }, + 'private': False, + 'pushed_at': '2016-06-05T18:16:15Z', + 'size': 4364, + 'stargazers_count': 56, + 'updated_at': '2016-06-10T09:43:58Z', + 'url': 'https://api.github.com/repos/fedora-infra/anitya', + 'watchers': 56, + 'watchers_count': 56 + }, + 'sender': { + 'gravatar_id': '', + 'html_url': 'https://github.com/pypingou', + 'id': 1240038, + 'login': 'pypingou', + 'site_admin': False, + 'type': 'User', + 'url': 'https://api.github.com/users/pypingou' + } + }, + 'msg_id': '2016-0490127f-473f-4d01-8e3a-a864a56dc302', + 'signature': + 'MNpAVdrPW78dcSe94FOS+/6QFBYo/LkrV5ee9tQedkhurHY1BGpaFHlU5l8cNVEpB7rr/zhHgQ+V\nmE3zYPmW/aREgvUoQgz74TR5F6/nK4Q1cD97VkFgHCadxZC6kjXd4H3BahEYnD+erj1iaArcdZaI\nXyKLZUBJLYL4JiXlmec=\n', + 'source_name': 'datanommer', + 'source_version': '0.6.5', + 'timestamp': 1465567413.0, + 'topic': 'org.fedoraproject.prod.github.issue.comment' + } + + plugin = 'feed' + + def test_returns_400_when_no_message(self): + payload = {'plugin': 'feed'} + response = self.app.get('/api/fedmsg/markup', query_string=payload) + assert response.status_code == 400 + + def test_returns_400_when_no_plugin(self): + payload = {'message': json.dumps(self.message_involved)} + response = self.app.get('/api/fedmsg/markup', query_string=payload) + assert response.status_code == 400 + + def test_returns_400_when_bad_plugin_name(self): + payload = { + 'message': json.dumps(self.message_involved), + 'plugin': 'notarealplugin' + } + response = self.app.get('/api/fedmsg/markup', query_string=payload) + assert response.status_code == 400 + + def test_returns_403_when_not_logged_in(self): + payload = { + 'message': json.dumps(self.message_involved), + 'plugin': 'feed' + } + with hubs.tests.user_set(self.app, self.user): + response = self.app.get('/api/fedmsg/markup', query_string=payload) + + assert response.status_code == 403 + + def test_returns_match_if_involved(self): + payload = { + 'message': json.dumps(self.message_involved), + 'plugin': 'feed' + } + with self.app.session_transaction() as sess: + sess['openid'] = 'atelic@fedoraproject.org' + sess['nickname'] = 'atelic' + + with hubs.tests.user_set(self.app, self.user): + response = self.app.get('/api/fedmsg/markup', query_string=payload) + + assert response.status_code == 200, response.status_code + data = json.loads(response.data) + self.assertTrue(data) + assert isinstance(data[0], dict) + + def test_returns_no_match_if_not_involved(self): + payload = { + 'message': json.dumps(self.message_not_involved), + 'plugin': 'feed' + } + with self.app.session_transaction() as sess: + sess['openid'] = 'atelic@fedoraproject.org' + sess['nickname'] = 'atelic' + + with hubs.tests.user_set(self.app, self.user): + response = self.app.get('/api/fedmsg/markup', query_string=payload) + + assert response.status_code == 200, response.status_code + data = json.loads(response.data) + self.assertFalse(data) From d4fcd3f05604b98fe20b20e74b6d3a375f871c76 Mon Sep 17 00:00:00 2001 From: Eric Barbour Date: Jun 16 2016 14:42:05 +0000 Subject: [PATCH 2/3] Add tests for /api/hub/* Still skipping tests that check logged out behavior until issues can be worked out with testing redirecting --- diff --git a/hubs/app.py b/hubs/app.py index df33459..c283490 100755 --- a/hubs/app.py +++ b/hubs/app.py @@ -641,6 +641,12 @@ def hub_leave(hub): @app.route('/api/fedmsg/markup', methods=['GET']) def markup_fedmsg(): + ''' + This is a temporary endpoint to create a human-readable form of a message. + For now it serves as a development tool + + This route will be removed once its functionality is integrated into FMN + ''' try: data = flask.request.args['message'] plugin = flask.request.args['plugin'] diff --git a/hubs/tests/__init__.py b/hubs/tests/__init__.py index 7c9da28..bafe0a1 100644 --- a/hubs/tests/__init__.py +++ b/hubs/tests/__init__.py @@ -88,28 +88,16 @@ class APPTest(unittest.TestCase): @contextmanager -def user_set(APP, user): - """ Set the provided user as fas_user in the provided application.""" - # Hack used to remove the before_request function set by - # flask.ext.fas_openid.FAS which otherwise kills our effort to set a - # flask.g.fas_user. - from flask import appcontext_pushed, g - - def handler(sender, **kwargs): - g.fas_user = user - g.fas_session_id = b'123' - - with appcontext_pushed.connected_to(handler, APP): - yield - - -@contextmanager def auth_set(APP, auth): - """ Set the provided user as fas_user in the provided application.""" + """ + Set the provided user as g.auth in the provided application. + :param APP: A Flask instance. Cannot be a FlaskClient. + :param auth: A FakeAuthorization instance to set as g.auth. + """ # Hack used to remove the before_request function set by # flask.ext.fas_openid.FAS which otherwise kills our effort to set a - # flask.g.fas_user. + # flask.g.auth. from flask import appcontext_pushed, g APP.before_request_funcs[None] = [] @@ -123,7 +111,7 @@ def auth_set(APP, auth): class FakeUser(object): - """ Fake user used to test the fedocallib library. """ + """ Fake user to be attached to an Authorization. """ def __init__(self, username='username'): """ Constructor. @@ -131,7 +119,7 @@ class FakeUser(object): supposed to be. """ self.username = username - self.openid = username + 'id.fedoraproject.org' + self.openid = username + '.id.fedoraproject.org' self.booksmarks = [] def __getitem__(self, key): @@ -139,7 +127,7 @@ class FakeUser(object): class FakeAuthorization(object): - """ Fake user used to test the fedocallib library. """ + """ Fake Authorization used to set as flask.g.auth. """ def __init__(self, username='username'): """ Constructor. @@ -149,10 +137,11 @@ class FakeAuthorization(object): self.logged_in = True self.fullname = 'fullname: ' + username self.email = 'email: ' + username - self.openid = username + 'id.fedoraproject.org' + self.openid = username + '.id.fedoraproject.org' self.user = FakeUser(username) self.avatar = 'avatar_src_url' self.nickname = username + self.username = username def __getitem__(self, key): return self.dic[key] diff --git a/hubs/tests/test_api/test_fedmsg.py b/hubs/tests/test_api/test_fedmsg.py index c708073..ef3b6db 100644 --- a/hubs/tests/test_api/test_fedmsg.py +++ b/hubs/tests/test_api/test_fedmsg.py @@ -2,6 +2,7 @@ import json import hubs.tests import hubs.models +from hubs.app import app class TestFeed(hubs.tests.APPTest): @@ -271,12 +272,12 @@ class TestFeed(hubs.tests.APPTest): def test_returns_400_when_no_message(self): payload = {'plugin': 'feed'} response = self.app.get('/api/fedmsg/markup', query_string=payload) - assert response.status_code == 400 + self.assertEqual(response.status_code, 400) def test_returns_400_when_no_plugin(self): payload = {'message': json.dumps(self.message_involved)} response = self.app.get('/api/fedmsg/markup', query_string=payload) - assert response.status_code == 400 + self.assertEqual(response.status_code, 400) def test_returns_400_when_bad_plugin_name(self): payload = { @@ -284,17 +285,16 @@ class TestFeed(hubs.tests.APPTest): 'plugin': 'notarealplugin' } response = self.app.get('/api/fedmsg/markup', query_string=payload) - assert response.status_code == 400 + self.assertEqual(response.status_code, 400) def test_returns_403_when_not_logged_in(self): payload = { 'message': json.dumps(self.message_involved), 'plugin': 'feed' } - with hubs.tests.user_set(self.app, self.user): - response = self.app.get('/api/fedmsg/markup', query_string=payload) - assert response.status_code == 403 + response = self.app.get('/api/fedmsg/markup', query_string=payload) + self.assertEqual(response.status_code, 403) def test_returns_match_if_involved(self): payload = { @@ -305,13 +305,13 @@ class TestFeed(hubs.tests.APPTest): sess['openid'] = 'atelic@fedoraproject.org' sess['nickname'] = 'atelic' - with hubs.tests.user_set(self.app, self.user): + with hubs.tests.auth_set(app, self.user): response = self.app.get('/api/fedmsg/markup', query_string=payload) - assert response.status_code == 200, response.status_code + self.assertEqual(response.status_code, 200) data = json.loads(response.data) self.assertTrue(data) - assert isinstance(data[0], dict) + self.assertTrue(isinstance(data[0], dict)) def test_returns_no_match_if_not_involved(self): payload = { @@ -322,9 +322,9 @@ class TestFeed(hubs.tests.APPTest): sess['openid'] = 'atelic@fedoraproject.org' sess['nickname'] = 'atelic' - with hubs.tests.user_set(self.app, self.user): + with hubs.tests.auth_set(app, self.user): response = self.app.get('/api/fedmsg/markup', query_string=payload) - assert response.status_code == 200, response.status_code + self.assertEqual(response.status_code, 200) data = json.loads(response.data) self.assertFalse(data) diff --git a/hubs/tests/test_api/test_hub.py b/hubs/tests/test_api/test_hub.py new file mode 100644 index 0000000..ee749d9 --- /dev/null +++ b/hubs/tests/test_api/test_hub.py @@ -0,0 +1,150 @@ +import flask +import unittest + +import hubs.tests +import hubs.models +from hubs.app import app + + +def usernames(collection): return [u.username for u in collection] + + +class TestHubSubscribe(hubs.tests.APPTest): + user = hubs.tests.FakeAuthorization('decause') + + @unittest.skip('Need to handle redirects') + def test_subscribe_redirects_when_logged_out(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + resp = self.app.post('/api/hub/{}/subscribe'.format(hub.idx)) + self.assertEqual(resp.status_code, 302) + self.assertEqual(resp.location, flask.url_for('fedora.login')) + + def test_subscribe_when_logged_in(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + with hubs.tests.auth_set(app, self.user): + resp = self.app.post('/api/hub/{}/subscribe'.format(hub.name), + follow_redirects=True) + self.assertEqual(resp.status_code, 200) + # Need to find the Hub again to avoid DetachedInstanceError + h = hubs.models.Hub.by_name(self.session, 'infra') + self.assertTrue(self.user.username in usernames(h.subscribers)) + + +class TestHubUnsubscribe(hubs.tests.APPTest): + user = hubs.tests.FakeAuthorization('decause') + + @unittest.skip('Need to handle redirects') + def test_unsubscribe_redirects_when_logged_out(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + resp = self.app.post('/api/hub/{}/unsubscribe'.format(hub.idx)) + self.assertEqual(resp.status_code, 302) + self.assertEqual(resp.location, flask.url_for('fedora.login')) + + def test_unsubscribe_when_logged_in(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + # Need a real user model to subscribe to the hub + User = hubs.models.User.by_username(self.session, self.user.username) + hub.subscribe(self.session, User) + + self.assertTrue(self.user.username in usernames(hub.subscribers)) + + with hubs.tests.auth_set(app, self.user): + resp = self.app.post('/api/hub/{}/unsubscribe'.format(hub.name), + follow_redirects=True) + self.assertEqual(resp.status_code, 200) + h = hubs.models.Hub.by_name(self.session, 'infra') + self.assertTrue(self.user.username not in usernames(h.subscribers)) + + +class TestHubStar(hubs.tests.APPTest): + user = hubs.tests.FakeAuthorization('decause') + + @unittest.skip('Need to handle redirects') + def test_star_redirects_when_logged_out(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + resp = self.app.post('/api/hub/{}/star'.format(hub.idx)) + self.assertEqual(resp.status_code, 302) + self.assertEqual(resp.location, flask.url_for('fedora.login')) + + def test_star_when_logged_in(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + with hubs.tests.auth_set(app, self.user): + resp = self.app.post('/api/hub/{}/star'.format(hub.name), + follow_redirects=True) + + self.assertEqual(resp.status_code, 200) + h = hubs.models.Hub.by_name(self.session, 'infra') + self.assertTrue(self.user.username in usernames(h.stargazers)) + + +class TestHubUnstar(hubs.tests.APPTest): + user = hubs.tests.FakeAuthorization('decause') + + @unittest.skip('Need to handle redirects') + def test_unstar_redirects_when_logged_out(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + resp = self.app.post('/api/hub/{}/unstar'.format(hub.idx)) + self.assertEqual(resp.status_code, 302) + self.assertEqual(resp.location, flask.url_for('fedora.login')) + + def test_unstar_when_logged_in(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + # Need a real user model to subscribe to the hub + User = hubs.models.User.by_username(self.session, self.user.username) + hub.subscribe(self.session, User, role='stargazer') + + self.assertTrue(self.user.username in [u.username for + u in hub.stargazers]) + + with hubs.tests.auth_set(app, self.user): + resp = self.app.post('/api/hub/{}/unstar'.format(hub.name), + follow_redirects=True) + self.assertEqual(resp.status_code, 200) + h = hubs.models.Hub.by_name(self.session, 'infra') + self.assertTrue(self.user.username not in usernames(h.stargazers)) + + +class TestHubJoin(hubs.tests.APPTest): + user = hubs.tests.FakeAuthorization('decause') + + @unittest.skip('Need to handle redirects') + def test_join_redirects_when_logged_out(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + resp = self.app.post('/api/hub/{}/join'.format(hub.idx)) + self.assertEqual(resp.status_code, 302) + self.assertEqual(resp.location, flask.url_for('fedora.login')) + + def test_join_when_logged_in(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + with hubs.tests.auth_set(app, self.user): + resp = self.app.post('/api/hub/{}/join'.format(hub.name), + follow_redirects=True) + + self.assertEqual(resp.status_code, 200) + h = hubs.models.Hub.by_name(self.session, 'infra') + self.assertTrue(self.user.username in usernames(h.members)) + + +class TestHubLeave(hubs.tests.APPTest): + user = hubs.tests.FakeAuthorization('decause') + + @unittest.skip('Need to handle redirects') + def test_leave_redirects_when_logged_out(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + resp = self.app.post('/api/hub/{}/leave'.format(hub.idx)) + self.assertEqual(resp.status_code, 302) + self.assertEqual(resp.location, flask.url_for('fedora.login')) + + def test_star_when_logged_in(self): + hub = hubs.models.Hub.by_name(self.session, 'infra') + # Need a real user model to subscribe to the hub + User = hubs.models.User.by_username(self.session, self.user.username) + hub.subscribe(self.session, User, role='member') + + with hubs.tests.auth_set(app, self.user): + resp = self.app.post('/api/hub/{}/leave'.format(hub.name), + follow_redirects=True) + + self.assertEqual(resp.status_code, 200) + h = hubs.models.Hub.by_name(self.session, 'infra') + self.assertTrue(self.user.username not in usernames(h.members)) From eaa718781c8cbeadd90929820bd07c5871ec4a00 Mon Sep 17 00:00:00 2001 From: Eric Barbour Date: Jun 16 2016 15:54:14 +0000 Subject: [PATCH 3/3] Apply pep8 and move json data to their own files --- diff --git a/hubs/tests/__init__.py b/hubs/tests/__init__.py index bafe0a1..96379c2 100644 --- a/hubs/tests/__init__.py +++ b/hubs/tests/__init__.py @@ -1,6 +1,7 @@ from contextlib import contextmanager import json from datetime import datetime, timedelta +import os import munch from os.path import dirname @@ -12,6 +13,8 @@ import vcr import hubs.models cassette_dir = dirname(dirname(__file__)) + '/vcr-request-data/' +json_path = os.path.join( + os.path.join(os.path.dirname(os.path.abspath(__file__))), 'data/') class APPTest(unittest.TestCase): diff --git a/hubs/tests/data/message_involved.json b/hubs/tests/data/message_involved.json new file mode 100644 index 0000000..fdfd0db --- /dev/null +++ b/hubs/tests/data/message_involved.json @@ -0,0 +1,137 @@ +{ + "timestamp": 1465567413.0, + "topic": "io.pagure.prod.pagure.issue.new", + "msg_id": "2016-0490127f-473f-4d01-ASDF-a864a56dc302", + "msg": { + "action": "created", + "comment": { + "body": + "hm, there is something odd the stackage page is inconsistent", + "created_at": "2016-06-10T14:03:31Z", + "html_url": + "https://github.com/fedora-infra/anitya/issues/283#issuecomment-225190438", + "id": 225190438, + "updated_at": "2016-06-10T14:03:31Z", + "url": + "https://api.github.com/repos/fedora-infra/anitya/issues/comments/225190438", + "user": { + "gravatar_id": "", + "html_url": "https://github.com/pypingou", + "id": 1240038, + "login": "pypingou", + "site_admin": false, + "type": "User", + "url": "https://api.github.com/users/pypingou" + } + }, + "fas_usernames": { + "fedora-infra": "github_org_fedora-infra", + "pypingou": "pingou" + }, + "issue": { + "assignee": null, + "body": + "@juhp it seems that the stackage backend is broken:", + "closed_at": "2016-04-29T14:53:10Z", + "comments": 8, + "created_at": "2016-04-15T16:15:57Z", + "html_url": + "https://github.com/fedora-infra/anitya/issues/283", + "id": 148703615, + "labels": [], + "locked": false, + "milestone": null, + "number": 283, + "state": "closed", + "title": "stackage backend broken", + "updated_at": "2016-06-10T14:03:31Z", + "url": + "https://api.github.com/repos/fedora-infra/anitya/issues/283", + "user": { + "gravatar_id": "", + "html_url": "https://github.com/pypingou", + "id": 1240038, + "login": "pypingou", + "site_admin": false, + "type": "User", + "url": "https://api.github.com/users/pypingou" + } + }, + "organization": { + "description": "Fedora Infrastructure Team", + "id": 3316637, + "login": "fedora-infra", + "url": "https://api.github.com/orgs/fedora-infra" + }, + "repository": { + "created_at": "2013-11-29T10:17:26Z", + "default_branch": "master", + "description": "A cross-distribution upstream release project", + "fork": false, + "forks": 33, + "forks_count": 33, + "full_name": "fedora-infra/anitya", + "has_downloads": true, + "has_issues": true, + "has_pages": false, + "has_wiki": false, + "homepage": "https://release-monitoring.org", + "html_url": "https://github.com/fedora-infra/anitya", + "id": 14798348, + "language": "Python", + "name": "anitya", + "open_issues": 25, + "open_issues_count": 25, + "owner": { + "gravatar_id": "", + "html_url": "https://github.com/fedora-infra", + "id": 3316637, + "login": "fedora-infra", + "site_admin": false, + "type": "Organization", + "url": "https://api.github.com/users/fedora-infra" + }, + "private": false, + "pushed_at": "2016-06-05T18:16:15Z", + "size": 4364, + "stargazers_count": 56, + "updated_at": "2016-06-10T09:43:58Z", + "url": "https://api.github.com/repos/fedora-infra/anitya", + "watchers": 56, + "watchers_count": 56 + }, + "sender": { + "gravatar_id": "", + "html_url": "https://github.com/pypingou", + "id": 1240038, + "login": "pypingou", + "site_admin": false, + "type": "User", + "url": "https://api.github.com/users/pypingou" + } + }, + "arguments": { + "categories": [ + "pagure" + ], + "contains": [], + "delta": 172800.0, + "end": 1465839365.0, + "grouped": false, + "meta": [], + "not_categories": [], + "not_packages": [], + "not_topics": [], + "not_users": [], + "order": "desc", + "packages": [], + "page": 1, + "rows_per_page": 1, + "start": 1465666565.0, + "topics": [], + "users": [] + }, + "count": 1, + "pages": 225, + "total": 225 +} diff --git a/hubs/tests/data/message_not_involved.json b/hubs/tests/data/message_not_involved.json new file mode 100644 index 0000000..e72439a --- /dev/null +++ b/hubs/tests/data/message_not_involved.json @@ -0,0 +1,120 @@ +{ + "topic": "org.fedoraproject.prod.github.issue.comment", + "i": 1, + "msg": { + "action": "created", + "comment": { + "body": + "hm, there is something odd the stackage page is inconsistent", + "created_at": "2016-06-10T14:03:31Z", + "html_url": + "https://github.com/fedora-infra/anitya/issues/283#issuecomment-225190438", + "id": 225190438, + "updated_at": "2016-06-10T14:03:31Z", + "url": + "https://api.github.com/repos/fedora-infra/anitya/issues/comments/225190438", + "user": { + "gravatar_id": "", + "html_url": "https://github.com/pypingou", + "id": 1240038, + "login": "pypingou", + "site_admin": false, + "type": "User", + "url": "https://api.github.com/users/pypingou" + } + }, + "fas_usernames": { + "fedora-infra": "github_org_fedora-infra", + "pypingou": "pingou" + }, + "issue": { + "assignee": null, + "body": + "@juhp it seems that the stackage backend is broken", + "closed_at": "2016-04-29T14:53:10Z", + "comments": 8, + "created_at": "2016-04-15T16:15:57Z", + "html_url": + "https://github.com/fedora-infra/anitya/issues/283", + "id": 148703615, + "labels": [], + "locked": false, + "milestone": null, + "number": 283, + "state": "closed", + "title": "stackage backend broken", + "updated_at": "2016-06-10T14:03:31Z", + "url": + "https://api.github.com/repos/fedora-infra/anitya/issues/283", + "user": { + "gravatar_id": "", + "html_url": "https://github.com/pypingou", + "id": 1240038, + "login": "pypingou", + "site_admin": false, + "type": "User", + "url": "https://api.github.com/users/pypingou" + } + }, + "organization": { + "description": "Fedora Infrastructure Team", + "id": 3316637, + "login": "fedora-infra", + "url": "https://api.github.com/orgs/fedora-infra" + }, + "repository": { + "created_at": "2013-11-29T10:17:26Z", + "default_branch": "master", + "description": + "A cross-distribution upstream release monitoring project", + "fork": false, + "forks": 33, + "forks_count": 33, + "full_name": "fedora-infra/anitya", + "has_downloads": true, + "has_issues": true, + "has_pages": false, + "has_wiki": false, + "homepage": "https://release-monitoring.org", + "html_url": "https://github.com/fedora-infra/anitya", + "id": 14798348, + "language": "Python", + "name": "anitya", + "open_issues": 25, + "open_issues_count": 25, + "owner": { + "gravatar_id": "", + "html_url": "https://github.com/fedora-infra", + "id": 3316637, + "login": "fedora-infra", + "site_admin": false, + "type": "Organization", + "url": "https://api.github.com/users/fedora-infra" + }, + "private": false, + "pushed_at": "2016-06-05T18:16:15Z", + "size": 4364, + "stargazers_count": 56, + "updated_at": "2016-06-10T09:43:58Z", + "url": "https://api.github.com/repos/fedora-infra/anitya", + "watchers": 56, + "watchers_count": 56 + }, + "sender": { + "gravatar_id": "", + "html_url": "https://github.com/pypingou", + "id": 1240038, + "login": "pypingou", + "site_admin": false, + "type": "User", + "url": "https://api.github.com/users/pypingou" + } + }, + "msg_id": "2016-0490127f-473f-4d01-8e3a-a864a56dc302", + "signature": + "MNpAVdrPW78dcSe94FOS+/6QFBYo/LkrV5ee9tQedkhurHY1BGpaFHlU5l8cNVEpB7rr", + "source_name": "datanommer", + "source_version": "0.6.5", + "timestamp": 1465567413.0, + "topic": "org.fedoraproject.prod.github.issue.comment" +} diff --git a/hubs/tests/test_api/test_fedmsg.py b/hubs/tests/test_api/test_fedmsg.py index ef3b6db..d6e67ef 100644 --- a/hubs/tests/test_api/test_fedmsg.py +++ b/hubs/tests/test_api/test_fedmsg.py @@ -1,271 +1,23 @@ import json +import os import hubs.tests import hubs.models from hubs.app import app +from hubs.tests import json_path class TestFeed(hubs.tests.APPTest): + + with open(json_path + 'message_involved.json', 'r') as fp: + message_involved = json.loads(fp.read()) + + with open(json_path + 'message_not_involved.json', 'r') as fp: + message_not_involved = json.loads(fp.read()) + # TODO this test relies on a specific filter for the atelic user # It would be better to fake preferences on FAS user = hubs.tests.FakeAuthorization('atelic') - message_involved = { - 'timestamp': 1465567413.0, - 'topic': 'io.pagure.prod.pagure.issue.new', - 'msg_id': '2016-0490127f-473f-4d01-ASDF-a864a56dc302', - 'msg': { - 'action': 'created', - 'comment': { - 'body': - 'hm, there is something odd, the stackage page is being inconsistent, one time the version number for LTS is linked, one time it isn\'t.\r\n\r\nIt\'s as if there are 2 servers running 2 different versions of the application', - 'created_at': '2016-06-10T14:03:31Z', - 'html_url': - 'https://github.com/fedora-infra/anitya/issues/283#issuecomment-225190438', - 'id': 225190438, - 'updated_at': '2016-06-10T14:03:31Z', - 'url': - 'https://api.github.com/repos/fedora-infra/anitya/issues/comments/225190438', - 'user': { - 'gravatar_id': '', - 'html_url': 'https://github.com/pypingou', - 'id': 1240038, - 'login': 'pypingou', - 'site_admin': False, - 'type': 'User', - 'url': 'https://api.github.com/users/pypingou' - } - }, - 'fas_usernames': { - 'fedora-infra': 'github_org_fedora-infra', - 'pypingou': 'pingou' - }, - 'issue': { - 'assignee': None, - 'body': - '@juhp it seems that the stackage backend is broken: https://release-monitoring.org/projects/updates/failed?name=&log=stackage want to look at it?', - 'closed_at': '2016-04-29T14:53:10Z', - 'comments': 8, - 'created_at': '2016-04-15T16:15:57Z', - 'html_url': - 'https://github.com/fedora-infra/anitya/issues/283', - 'id': 148703615, - 'labels': [], - 'locked': False, - 'milestone': None, - 'number': 283, - 'state': 'closed', - 'title': 'stackage backend broken', - 'updated_at': '2016-06-10T14:03:31Z', - 'url': - 'https://api.github.com/repos/fedora-infra/anitya/issues/283', - 'user': { - 'gravatar_id': '', - 'html_url': 'https://github.com/pypingou', - 'id': 1240038, - 'login': 'pypingou', - 'site_admin': False, - 'type': 'User', - 'url': 'https://api.github.com/users/pypingou' - } - }, - 'organization': { - 'description': 'Fedora Infrastructure Team', - 'id': 3316637, - 'login': 'fedora-infra', - 'url': 'https://api.github.com/orgs/fedora-infra' - }, - 'repository': { - 'created_at': '2013-11-29T10:17:26Z', - 'default_branch': 'master', - 'description': 'A cross-distribution upstream release project', - 'fork': False, - 'forks': 33, - 'forks_count': 33, - 'full_name': 'fedora-infra/anitya', - 'has_downloads': True, - 'has_issues': True, - 'has_pages': False, - 'has_wiki': False, - 'homepage': 'https://release-monitoring.org', - 'html_url': 'https://github.com/fedora-infra/anitya', - 'id': 14798348, - 'language': 'Python', - 'name': 'anitya', - 'open_issues': 25, - 'open_issues_count': 25, - 'owner': { - 'gravatar_id': '', - 'html_url': 'https://github.com/fedora-infra', - 'id': 3316637, - 'login': 'fedora-infra', - 'site_admin': False, - 'type': 'Organization', - 'url': 'https://api.github.com/users/fedora-infra' - }, - 'private': False, - 'pushed_at': '2016-06-05T18:16:15Z', - 'size': 4364, - 'stargazers_count': 56, - 'updated_at': '2016-06-10T09:43:58Z', - 'url': 'https://api.github.com/repos/fedora-infra/anitya', - 'watchers': 56, - 'watchers_count': 56 - }, - 'sender': { - 'gravatar_id': '', - 'html_url': 'https://github.com/pypingou', - 'id': 1240038, - 'login': 'pypingou', - 'site_admin': False, - 'type': 'User', - 'url': 'https://api.github.com/users/pypingou' - } - }, - 'arguments': { - 'categories': [ - 'pagure' - ], - 'contains': [], - 'delta': 172800.0, - 'end': 1465839365.0, - 'grouped': False, - 'meta': [], - 'not_categories': [], - 'not_packages': [], - 'not_topics': [], - 'not_users': [], - 'order': 'desc', - 'packages': [], - 'page': 1, - 'rows_per_page': 1, - 'start': 1465666565.0, - 'topics': [], - 'users': [] - }, - 'count': 1, - 'pages': 225, - 'total': 225 - } - message_not_involved = { - 'topic': 'org.fedoraproject.prod.github.issue.comment', - 'i': 1, - 'msg': { - 'action': 'created', - 'comment': { - 'body': - 'hm, there is something odd, the stackage page is being inconsistent, one time the version number for LTS is linked, one time it isn\'t.\r\n\r\nIt\'s as if there are 2 servers running 2 different versions of the application', - 'created_at': '2016-06-10T14:03:31Z', - 'html_url': - 'https://github.com/fedora-infra/anitya/issues/283#issuecomment-225190438', - 'id': 225190438, - 'updated_at': '2016-06-10T14:03:31Z', - 'url': - 'https://api.github.com/repos/fedora-infra/anitya/issues/comments/225190438', - 'user': { - 'gravatar_id': '', - 'html_url': 'https://github.com/pypingou', - 'id': 1240038, - 'login': 'pypingou', - 'site_admin': False, - 'type': 'User', - 'url': 'https://api.github.com/users/pypingou' - } - }, - 'fas_usernames': { - 'fedora-infra': 'github_org_fedora-infra', - 'pypingou': 'pingou' - }, - 'issue': { - 'assignee': None, - 'body': - '@juhp it seems that the stackage backend is broken: https://release-monitoring.org/projects/updates/failed?name=&log=stackage want to look at it?', - 'closed_at': '2016-04-29T14:53:10Z', - 'comments': 8, - 'created_at': '2016-04-15T16:15:57Z', - 'html_url': - 'https://github.com/fedora-infra/anitya/issues/283', - 'id': 148703615, - 'labels': [], - 'locked': False, - 'milestone': None, - 'number': 283, - 'state': 'closed', - 'title': 'stackage backend broken', - 'updated_at': '2016-06-10T14:03:31Z', - 'url': - 'https://api.github.com/repos/fedora-infra/anitya/issues/283', - 'user': { - 'gravatar_id': '', - 'html_url': 'https://github.com/pypingou', - 'id': 1240038, - 'login': 'pypingou', - 'site_admin': False, - 'type': 'User', - 'url': 'https://api.github.com/users/pypingou' - } - }, - 'organization': { - 'description': 'Fedora Infrastructure Team', - 'id': 3316637, - 'login': 'fedora-infra', - 'url': 'https://api.github.com/orgs/fedora-infra' - }, - 'repository': { - 'created_at': '2013-11-29T10:17:26Z', - 'default_branch': 'master', - 'description': - 'A cross-distribution upstream release monitoring project', - 'fork': False, - 'forks': 33, - 'forks_count': 33, - 'full_name': 'fedora-infra/anitya', - 'has_downloads': True, - 'has_issues': True, - 'has_pages': False, - 'has_wiki': False, - 'homepage': 'https://release-monitoring.org', - 'html_url': 'https://github.com/fedora-infra/anitya', - 'id': 14798348, - 'language': 'Python', - 'name': 'anitya', - 'open_issues': 25, - 'open_issues_count': 25, - 'owner': { - 'gravatar_id': '', - 'html_url': 'https://github.com/fedora-infra', - 'id': 3316637, - 'login': 'fedora-infra', - 'site_admin': False, - 'type': 'Organization', - 'url': 'https://api.github.com/users/fedora-infra' - }, - 'private': False, - 'pushed_at': '2016-06-05T18:16:15Z', - 'size': 4364, - 'stargazers_count': 56, - 'updated_at': '2016-06-10T09:43:58Z', - 'url': 'https://api.github.com/repos/fedora-infra/anitya', - 'watchers': 56, - 'watchers_count': 56 - }, - 'sender': { - 'gravatar_id': '', - 'html_url': 'https://github.com/pypingou', - 'id': 1240038, - 'login': 'pypingou', - 'site_admin': False, - 'type': 'User', - 'url': 'https://api.github.com/users/pypingou' - } - }, - 'msg_id': '2016-0490127f-473f-4d01-8e3a-a864a56dc302', - 'signature': - 'MNpAVdrPW78dcSe94FOS+/6QFBYo/LkrV5ee9tQedkhurHY1BGpaFHlU5l8cNVEpB7rr/zhHgQ+V\nmE3zYPmW/aREgvUoQgz74TR5F6/nK4Q1cD97VkFgHCadxZC6kjXd4H3BahEYnD+erj1iaArcdZaI\nXyKLZUBJLYL4JiXlmec=\n', - 'source_name': 'datanommer', - 'source_version': '0.6.5', - 'timestamp': 1465567413.0, - 'topic': 'org.fedoraproject.prod.github.issue.comment' - } plugin = 'feed'