From 7d6632e95220db8302e6910fad16ddacdd576f4a Mon Sep 17 00:00:00 2001 From: skrzepto Date: Jun 14 2016 16:04:47 +0000 Subject: [PATCH 1/9] pushing my work on unittesting up --- diff --git a/hubs/tests/__init__.py b/hubs/tests/__init__.py index e69de29..8dbca6c 100644 --- a/hubs/tests/__init__.py +++ b/hubs/tests/__init__.py @@ -0,0 +1,141 @@ +from contextlib import contextmanager +import json +from datetime import datetime, timedelta + +import munch +from os.path import dirname +import unittest + +import requests +import vcr + +import hubs.models + +cassette_dir = dirname(dirname(__file__)) + '/vcr-request-data/' + + +class APPTest(unittest.TestCase): + def setUp(self): + filename = cassette_dir + self.id() + self.vcr = vcr.use_cassette(filename, record_mode='new_episodes') + self.vcr.__enter__() + + import hubs.app + hubs.app.fedmsg_config = { + 'hubs.sqlalchemy.uri': 'sqlite://', # in memory + } + hubs.app.session = hubs.models.init( + hubs.app.fedmsg_config['hubs.sqlalchemy.uri'], + create=True, + ) + self.app = hubs.app.app.test_client() + self.app.testing = True + self.session = hubs.app.session + self.populate() + + def tearDown(self): + self.vcr.__exit__() + self.session.remove() + + def populate(self): + for user in ['devyani7', 'dhrish', 'shalini', 'ralph', 'decause']: + openid = '%s.id.fedoraproject.org' % user + fullname = user.title() + hubs.models.User.get_or_create( + hubs.app.session, openid=openid, fullname=fullname) + + hubs.app.session.flush() + + hub = hubs.models.Hub.by_name(hubs.app.session, 'ralph') + widget = hubs.models.Widget( + plugin='about', + index=500, + _config=json.dumps({"text": "Testing."}), + ) + hub.widgets.append(widget) + + for team in ['i18n', 'infra', 'old']: + hub = hubs.models.Hub(name=team, summary="the %s team" % team) + if hub.name == 'old': + hub.last_refreshed = datetime.utcnow() - timedelta(days=100) + hub.last_updated = datetime.utcnow() - timedelta(days=200) + + hubs.app.session.add(hub) + widget = hubs.models.Widget(plugin='meetings', index=11, + _config=json.dumps({'calendar': team})) + hub.widgets.append(widget) + hubs.app.session.commit() + + # TODO - test that it is in the registry + # TODO - test that it has all the things it needs + + def widget_instance(self, hubname, plugin): + hub = hubs.models.Hub.by_name(self.session, hubname) + if not hub: + raise ValueError("No such hub %r" % hubname) + for widget in hub.widgets: + if widget.plugin == plugin: + return widget + raise KeyError("No such widget found for %s/%s" % (hubname, plugin)) + + @staticmethod + def get_fedmsg(idx): + url = 'https://apps.fedoraproject.org/datagrepper/id' + response = requests.get(url, params=dict(id=idx)) + if not bool(response): + raise IOError("Failed to talk to %r %r" % (response.url, response)) + return response.json() + + +@contextmanager +def auth_set(APP, auth): + """ 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 + APP.before_request_funcs[None] = [] + + def handler(sender, **kwargs): + g.auth = auth + if not auth: + munch.Munch(logged_in=False) + + with appcontext_pushed.connected_to(handler, APP): + yield + +class FakeUser(object): + """ Fake user used to test the fedocallib library. """ + + def __init__(self, username='username'): + """ Constructor. + :arg groups: list of the groups in which this fake user is + supposed to be. + """ + self.username = username + self.openid = username + 'id.fedoraproject.org' + self.booksmarks = [] + + def __getitem__(self, key): + return self.dic[key] + + +class FakeAuthorization(object): + """ Fake user used to test the fedocallib library. """ + + def __init__(self, username='username'): + """ Constructor. + :arg groups: list of the groups in which this fake user is + supposed to be. + """ + self.logged_in = True + self.fullname = 'fullname: ' + username + self.email = 'email: ' + username + self.openid = username + 'id.fedoraproject.org' + self.user = FakeUser(username) + self.avatar = 'avatar_src_url' + self.nickname = username + + def __getitem__(self, key): + return self.dic[key] diff --git a/hubs/tests/test_fedora_hubs_flask_api.py b/hubs/tests/test_fedora_hubs_flask_api.py new file mode 100644 index 0000000..bf79d06 --- /dev/null +++ b/hubs/tests/test_fedora_hubs_flask_api.py @@ -0,0 +1,144 @@ +import unittest +from urlparse import urlparse + +from flask import json +from os.path import dirname +import vcr + +import hubs +from hubs import tests +from hubs.app import app + +import hubs.models + +import fedmsg.config + +cassette_dir = dirname(dirname(__file__)) + '/vcr-request-data/' + + +class HubsAPITest(hubs.tests.APPTest): + @unittest.skip("Can't seem to get redirected to the login in these tests") + def test_index_logged_out(self): + result = self.app.get('/', follow_redirects=True) + # its trying to redirect to login id.fedoraproject.org/openid + # assert the status code of the response + self.assertEqual(result.status_code, 200) + + def test_index_logged_in(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.get('/', follow_redirects=True) + # its trying to redirect to login id.fedoraproject.org/openid + # assert the status code of the response + self.assertEqual(result.status_code, 200) + self.assertFalse('Not logged in. Click to login' in result.data) + + def test_hub_logged_out(self): + with tests.auth_set(app, None): + # for some reason def check_auth() is not running and i need to set it to none so it won't crash + result = self.app.get('/ralph', follow_redirects=True) + # assert the status code of the response + self.assertEqual(result.status_code, 200) + self.assertTrue('Not logged in. Click to login' in result.data) + + @unittest.skip("Can't seem to get redirected to the login in these tests") + def test_groups_logged_out(self): + with tests.auth_set(app, None): + # for some reason def check_auth() is not running and i need to set it to none so it won't crash + result = self.app.get('/groups', follow_redirects=True) + # assert the status code of the response + self.assertEqual(result.status_code, 200) + # this will redirect to fedora.login which unittests can't handle atm + pass + + def test_groups_logged_in(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.get('/groups', follow_redirects=True) + # assert the status code of the response + self.assertEqual(result.status_code, 200) + self.assertTrue("ZOMG - is the Hub Of The Month!" in result.data) + + def test_hub_logged_in(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.get('/ralph', follow_redirects=True) + self.assertEqual(result.status_code, 200) + self.assertFalse('Not logged in. Click to login' in result.data) + + def test_hub_json(self): + with tests.auth_set(app, None): + # for some reason def check_auth() is not running and i need to set it to none so it won't crash + result = self.app.get('/ralph/json', follow_redirects=True) + # assert the status code of the response + self.assertEqual(result.status_code, 200) + data = { + "avatar": "https://seccdn.libravatar.org/avatar/9c9f7784935381befc302fe3c814f9136e7a33953d0318761669b8643f4df55c?s=312&d=retro", + "left_width": 8, + "members": ["ralph"], + "name": "ralph", + "owners": ["ralph"], + "subscribers": [], + "summary": "Ralph", + "widgets": [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 51] + } + self.assertDictEqual(data, json.loads(result.data)) + + @unittest.skip("Authorization layer not present yet") + def test_hub_edit_get_logged_out(self): + # FAILING: Authorization layer not present yet + with tests.auth_set(app, None): + result = self.app.get('/ralph/edit', follow_redirects=True) + self.assertEqual(result.status_code, 403) # failing right + # We do not have the authorization layer in place yet + + @unittest.skip("Authorization layer not present yet") + def test_hub_edit_get_logged_in_not_owner(self): + # FAILING: Authorization layer not present yet + user = tests.FakeAuthorization('not_ralph') + with tests.auth_set(app, user): + result = self.app.get('/ralph/edit', follow_redirects=True) + self.assertEqual(result.status_code, 403) # failing right + # We do not have the authorization layer in place yet + + def test_hub_edit_get_logged_in_owner(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.get('/ralph/edit', follow_redirects=True) + self.assertEqual(result.status_code, 200) + # We do not have the authorization layer in place yet so everyone can edit + + @unittest.skip("Authorization layer not present yet") + def test_hub_edit_post_logged_out(self): + # FAILING: Authorization layer not present yet + with tests.auth_set(app, None): + result = self.app.post('/ralph/edit', follow_redirects=True) + self.assertEqual(result.status_code, 403) # failing right + # We do not have the authorization layer in place yet + + @unittest.skip("Authorization layer not present yet") + def test_hub_edit_post_logged_in_not_owner(self): + # FAILING: Authorization layer not present yet + user = tests.FakeAuthorization('not_ralph') + with tests.auth_set(app, user): + result = self.app.post('/ralph/edit', follow_redirects=True) + self.assertEqual(result.status_code, 403) # failing right + # We do not have the authorization layer in place yet + + # WIP: commenting out so I can push this updates to branch so others can contribute + ''' + def test_hub_edit_post_logged_in_owner_no_data(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.post('/ralph/edit', follow_redirects=True) + self.assertEqual(result.status_code, 200) + assert 'Invalid widget identifiers submitted' in result.data + assert 'Invalid indexes submitted' in result.data + assert 'The number of indexes and the number of widgets ' \ + 'are not of the same length' in result.data + assert 'Invalid widget identifiers submitted' in result.data + assert 'Invalid indexes submitted' in result.data + ''' + +if __name__ == '__main__': + unittest.main() diff --git a/hubs/tests/test_widgets/test_about.py b/hubs/tests/test_widgets/test_about.py index 6890f7b..38bddee 100644 --- a/hubs/tests/test_widgets/test_about.py +++ b/hubs/tests/test_widgets/test_about.py @@ -1,5 +1,7 @@ import json +from nose.tools import assert_dict_equal + import hubs.tests.test_widgets @@ -17,3 +19,32 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): u'source_url': u'/source/about', u'text': u'Testing.', }) + + def test_should_invalidate_wrong_topic(self): + widget = self.widget_instance('ralph', self.plugin) + msg = {'topic': 'hubs.widget.update.WRONG.TOPIC', 'msg': {'widget': {'id': widget.idx}}} + module = hubs.widgets.registry[widget.plugin] + result = module.should_invalidate(msg, self.session, widget) + assert not result + + def test_should_invalidate_wrong_widget_id(self): + widget = self.widget_instance('ralph', self.plugin) + msg = {'topic': 'hubs.widget.update', 'msg': {'widget': {'id': widget.idx+1}}} + module = hubs.widgets.registry[widget.plugin] + result = module.should_invalidate(msg, self.session, widget) + assert not result + + def test_should_invalidate_good_match(self): + widget = self.widget_instance('ralph', self.plugin) + msg = {'topic': 'hubs.widget.update', 'msg': {'widget': {'id': widget.idx}}} + module = hubs.widgets.registry[widget.plugin] + result = module.should_invalidate(msg, self.session, widget) + assert result + + ''' + def test_data(self): + widget = self.widget_instance('ralph', self.plugin) + module = hubs.widgets.registry[widget.plugin] + result = module.data(self.session, widget, 'I love oss.') + assert_dict_equal({'text': 'I love oss.'}, result) + ''' \ No newline at end of file diff --git a/hubs/tests/test_widgets/test_badges.py b/hubs/tests/test_widgets/test_badges.py index 4f668b1..7edd96e 100644 --- a/hubs/tests/test_widgets/test_badges.py +++ b/hubs/tests/test_widgets/test_badges.py @@ -1,5 +1,6 @@ import json +from mock import patch, MagicMock import hubs.tests.test_widgets @@ -16,21 +17,68 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): def test_should_invalidate_wrong_topic(self): widget = self.widget_instance('ralph', self.plugin) - msg = self.get_fedmsg('2016-ebb84660-59e9-4e68-af8f-4e6f49348b88') + # msg = self.get_fedmsg('2016-ebb84660-59e9-4e68-af8f-4e6f49348b88') + msg = {'topic': 'hubs.widget.update.WRONG.TOPIC'} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) assert not result def test_should_invalidate_wrong_user(self): widget = self.widget_instance('ralph', self.plugin) - msg = self.get_fedmsg('2016-e371c7f6-bc8e-4632-8e33-b9102dc30b5f') + # msg = self.get_fedmsg('2016-e371c7f6-bc8e-4632-8e33-b9102dc30b5f') + msg = {'topic': 'fedbadges.badge.award', 'msg': {'user': {'username': 'not_ralph'}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) assert not result - def test_should_invalidate_good_match(self): + def test_should_invalidate_good_match_fedbadges(self): widget = self.widget_instance('ralph', self.plugin) - msg = self.get_fedmsg('2016-1fbb1135-681b-4d3b-9a40-d0f6ebd313f4') + # msg = self.get_fedmsg('2016-1fbb1135-681b-4d3b-9a40-d0f6ebd313f4') + msg = {'topic': 'fedbadges.badge.award', 'msg': {'user': {'username': 'ralph'}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) assert result + + def test_should_invalidate_good_match_hubswidget(self): + widget = self.widget_instance('ralph', self.plugin) + # msg = self.get_fedmsg('2016-1fbb1135-681b-4d3b-9a40-d0f6ebd313f4') + msg = {'topic': 'hubs.widget.update', 'msg': {'widget': {'id': widget.idx + 1}}} + module = hubs.widgets.registry[widget.plugin] + result = module.should_invalidate(msg, self.session, widget) + assert result + ''' + @patch('requests.get') + @patch('hubs.widgets.base.cache.get_or_create') + def test_data_good(self, cache_mock, requests_mock): + requests_mock.return_value = self.mock_response() + cache_mock.return_value = None + widget = self.widget_instance('ralph', self.plugin) + module = hubs.widgets.registry[widget.plugin] + result = module.data(self.session, widget, 'ralph') + assert result + ''' + @staticmethod + def mock_response(): + test_data_simple = '''{ + "percent_earned": 47.05882352941176, + "assertions": [{ + "description": "You attended Flock 2014, the Fedora Contributor Conference", + "tags": "flock,event,", + "issued": 1375373082.0, + "image": "https://badges.fedoraproject.org/pngs/flock-2013-attendee.png", + "first_awarded": 1375373082.0, + "first_awarded_person": "ralph", + "last_awarded_person": "gnokii", + "last_awarded": 1386188828.0, + "percent_earned": 0.404551201011378, + "id": "flock-2013-attendee", + "times_awarded": 80, + "name": "Flock 2013 Attendee" + }], + "user": "ralph", + "avatar": "" + }''' + + mock = MagicMock() + mock.json.return_value = json.loads(test_data_simple) + return mock diff --git a/hubs/tests/test_widgets/test_meetings.py b/hubs/tests/test_widgets/test_meetings.py index 90656fd..bafb6a3 100644 --- a/hubs/tests/test_widgets/test_meetings.py +++ b/hubs/tests/test_widgets/test_meetings.py @@ -20,4 +20,4 @@ class TestMeetings(hubs.tests.test_widgets.WidgetTest): widget = self.widget_instance(team, self.plugin) response = self.app.get('/%s/%i/' % (team, widget.idx)) assert response.status_code == 200, response.status_code - assert 'The i18n meeting is in' in response.data, response.data + assert 'The i18n meeting is ' in response.data, response.data diff --git a/hubs/widgets/about.py b/hubs/widgets/about.py index c1ff1f6..7023139 100755 --- a/hubs/widgets/about.py +++ b/hubs/widgets/about.py @@ -21,6 +21,6 @@ def data(session, widget, text): def should_invalidate(message, session, widget): if not message['topic'].endswith('hubs.widget.update'): return False - if message['msg']['widget']['id'] != widget.id: + if message['msg']['widget']['id'] != widget.idx: return False return True diff --git a/hubs/widgets/badges.py b/hubs/widgets/badges.py index c5a18d0..abf4b15 100755 --- a/hubs/widgets/badges.py +++ b/hubs/widgets/badges.py @@ -30,7 +30,7 @@ def data(session, widget, username): @hint(topics=[_('hubs.widget.update'), _('fedbadges.badge.award')]) def should_invalidate(message, session, widget): if message['topic'].endswith('hubs.widget.update'): - if message['msg']['widget']['id'] != widget.id: + if message['msg']['widget']['id'] != widget.idx: return True if message['topic'].endswith('fedbadges.badge.award'): From 25e67a6787237e97fef12e6428089cf75ae852c3 Mon Sep 17 00:00:00 2001 From: Eric Barbour Date: Jun 14 2016 16:16:43 +0000 Subject: [PATCH 2/9] 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 3/9] 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 4/9] 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' From 0ffdc70ceaed8dbf395eaf66bf86fe48e946bdc4 Mon Sep 17 00:00:00 2001 From: skrzepto Date: Jun 17 2016 15:00:02 +0000 Subject: [PATCH 5/9] increasing unittests, kindof figured out how to test redirection and pep8 the files adding owner of hub editing hub with no data hub edit succesful adding another test for hubs/edit for invalid data pep8 the file pep8 files and added a new function to see if flask.g.auth is set made authenticated function check if flask.g.auth is set and check what the logged_in bool is and return it undoing a pep8 to one line, changed the authenticate function to be shorter pep8 the authenticated function --- diff --git a/hubs/app.py b/hubs/app.py index c283490..4b72cee 100755 --- a/hubs/app.py +++ b/hubs/app.py @@ -31,17 +31,17 @@ app = flask.Flask(__name__) # Register some useful global filters. def days_since(then): return (datetime.datetime.utcnow() - then).days + + app.template_filter('days_since')(days_since) app.template_filter('avatar')(username2avatar) logging.basicConfig() - # TODO - put this in config so we can migrate to pagure # TODO - instead of 'develop', use the version from pkg_resources to figure out # the right tag to link people to. AGPL ftw. -SOURCE_URL = 'https://pagure.io/fedora-hubs/blob/develop/f'#/hubs/widgets/badges.py' - +SOURCE_URL = 'https://pagure.io/fedora-hubs/blob/develop/f' # /hubs/widgets/badges.py' app.config.from_object('hubs.default_config') if 'HUBS_CONFIG' in os.environ: @@ -49,6 +49,7 @@ if 'HUBS_CONFIG' in os.environ: 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') @@ -67,9 +68,17 @@ class CustomJSONEncoder(flask.json.JSONEncoder): return list(iterable) return flask.json.JSONEncoder.default(self, o) + app.json_encoder = CustomJSONEncoder +def authenticated(): + """ Utility function checking if the current auth is set or not.""" + return hasattr(flask.g, 'auth') \ + and flask.g.auth is not None \ + and flask.g.auth.logged_in + + @app.template_filter('commas') def commas(numeric): return "{:,.2f}".format(numeric) @@ -83,7 +92,7 @@ def shutdown_session(exception=None): @app.route('/') def index(): - if not flask.g.auth.logged_in: + if not authenticated(): return flask.redirect(flask.url_for('login_fedora')) return flask.redirect(flask.url_for('hub', name=flask.g.auth.nickname)) @@ -91,7 +100,7 @@ def index(): @app.route('/groups') def groups(): - if not flask.g.auth.logged_in: + if not authenticated(): return flask.redirect(flask.url_for('login_fedora')) # Get the list of promoted and non-promoted group hubs from the DB @@ -156,7 +165,7 @@ def hub_edit_post(name): w.strip().replace('widget-', '') for w in flask.request.form.getlist('right_widgets[]') if w.strip() - ] + ] try: r_widget_ids = [int(w) for w in r_widget_ids] except: @@ -166,7 +175,7 @@ def hub_edit_post(name): r_indexes = [ i.strip() for i in flask.request.form.getlist('right_indexes[]') if i.strip() - ] + ] try: r_indexes = [int(i) for i in r_indexes] @@ -187,7 +196,7 @@ def hub_edit_post(name): w.strip().replace('widget-', '') for w in flask.request.form.getlist('left_widgets[]') if w.strip() - ] + ] try: l_widget_ids = [int(w) for w in l_widget_ids] except: @@ -197,7 +206,7 @@ def hub_edit_post(name): l_indexes = [ i.strip() for i in flask.request.form.getlist('left_indexes[]') if i.strip() - ] + ] try: l_indexes = [int(i) for i in l_indexes] @@ -290,7 +299,7 @@ def hub_add_widget_get(name): widget for widget in hubs.widgets.registry if hubs.widgets.registry[widget].position in ['both', side] - ] + ] return flask.render_template( 'add_widget.html', hub=hub, @@ -311,7 +320,7 @@ def hub_add_widget_post(name): hub = get_hub(session, name) widget = widget = hubs.models.Widget( - plugin=widget_name, index=-1, left=position=='left') + plugin=widget_name, index=-1, left=position == 'left') error = False config = {} for arg in widget.module.data.widget_arguments: @@ -350,8 +359,8 @@ def hub_add_widget_post(name): @app.route('//') def widget_render(hub, idx): widget = get_widget(session, hub, idx) - return widget.render(session)#, edit=False) - #was blocking all widgets from working, sorry! + return widget.render(session) # , edit=False) + # was blocking all widgets from working, sorry! @app.route('///json') @@ -454,7 +463,7 @@ oid = OpenID(app, def login(): default = flask.url_for('index') next_url = flask.request.args.get('next', default) - if flask.g.auth.logged_in: + if authenticated(): return flask.redirect(next_url) openid_server = flask.request.form.get('openid', None) @@ -471,8 +480,8 @@ def login(): @app.route('/login/fedora') @oid.loginhandler def login_fedora(): - #default = flask.url_for('profile_redirect') - #next_url = flask.request.args.get('next', default) + # default = flask.url_for('profile_redirect') + # next_url = flask.request.args.get('next', default) return oid.try_login( 'https://id.fedoraproject.org', ask_for=['email', 'fullname', 'nickname'], @@ -509,15 +518,17 @@ def after_openid_login(resp): def login_required(function): """ Flask decorator to restrict access to logged-in users. """ + @functools.wraps(function) def decorated_function(*args, **kwargs): """ Decorated function, actually does the work. """ - if not flask.g.auth.logged_in: + if not authenticated(): flask.flash('Login required', 'errors') return flask.redirect(flask.url_for( 'login_fedora', next=flask.request.url)) return function(*args, **kwargs) + return decorated_function @@ -542,8 +553,8 @@ def check_auth(): def get_hub(session, name): """ Utility shorthand to get a hub and 404 if not found. """ - hub = session.query(hubs.models.Hub)\ - .filter(hubs.models.Hub.name == name)\ + hub = session.query(hubs.models.Hub) \ + .filter(hubs.models.Hub.name == name) \ .first() if not hub: @@ -568,8 +579,8 @@ def get_widget(session, hub, idx): flask.abort(404) -## Here are a bunch of API methods that should probably be broken out into -## their own file +# Here are a bunch of API methods that should probably be broken out into +# their own file @app.route('/api/hub//subscribe', methods=['POST']) @login_required def hub_subscribe(hub): @@ -660,7 +671,7 @@ def markup_fedmsg(): message = json.loads(data) try: nickname = flask.g.auth.nickname - except AttributeError: # Not logged in + except AttributeError: # Not logged in return flask.abort(403) preference = get_remote_preference(nickname, context) if preference: diff --git a/hubs/tests/__init__.py b/hubs/tests/__init__.py index 96379c2..5c10118 100644 --- a/hubs/tests/__init__.py +++ b/hubs/tests/__init__.py @@ -107,7 +107,7 @@ def auth_set(APP, auth): def handler(sender, **kwargs): g.auth = auth if not auth: - munch.Munch(logged_in=False) + g.auth = munch.Munch(logged_in=False) with appcontext_pushed.connected_to(handler, APP): yield diff --git a/hubs/tests/test_fedora_hubs_flask_api.py b/hubs/tests/test_fedora_hubs_flask_api.py index bf79d06..a0043f0 100644 --- a/hubs/tests/test_fedora_hubs_flask_api.py +++ b/hubs/tests/test_fedora_hubs_flask_api.py @@ -4,6 +4,7 @@ from urlparse import urlparse from flask import json from os.path import dirname import vcr +from werkzeug.datastructures import ImmutableMultiDict import hubs from hubs import tests @@ -17,12 +18,10 @@ cassette_dir = dirname(dirname(__file__)) + '/vcr-request-data/' class HubsAPITest(hubs.tests.APPTest): - @unittest.skip("Can't seem to get redirected to the login in these tests") def test_index_logged_out(self): - result = self.app.get('/', follow_redirects=True) - # its trying to redirect to login id.fedoraproject.org/openid - # assert the status code of the response - self.assertEqual(result.status_code, 200) + result = self.app.get('/', follow_redirects=False) + self.assertEqual(result.status_code, 302) + self.assertEqual(urlparse(result.location).path, "/login/fedora") def test_index_logged_in(self): user = tests.FakeAuthorization('ralph') @@ -31,25 +30,27 @@ class HubsAPITest(hubs.tests.APPTest): # its trying to redirect to login id.fedoraproject.org/openid # assert the status code of the response self.assertEqual(result.status_code, 200) - self.assertFalse('Not logged in. Click to login' in result.data) + self.assertFalse('Not logged in. Click to login' in result.data) def test_hub_logged_out(self): - with tests.auth_set(app, None): - # for some reason def check_auth() is not running and i need to set it to none so it won't crash + with app.test_request_context('/ralph'): + # need to manually call the @app.before_request + # since unittest don't call it + hubs.app.check_auth() result = self.app.get('/ralph', follow_redirects=True) # assert the status code of the response self.assertEqual(result.status_code, 200) - self.assertTrue('Not logged in. Click to login' in result.data) + str_expected = 'Not logged in. Click to ' \ + 'login' + self.assertTrue(str_expected in result.data) - @unittest.skip("Can't seem to get redirected to the login in these tests") def test_groups_logged_out(self): - with tests.auth_set(app, None): - # for some reason def check_auth() is not running and i need to set it to none so it won't crash - result = self.app.get('/groups', follow_redirects=True) - # assert the status code of the response - self.assertEqual(result.status_code, 200) - # this will redirect to fedora.login which unittests can't handle atm - pass + result = self.app.get('/groups', follow_redirects=False) + # assert the status code of the response + self.assertEqual(result.status_code, 302) + # this will redirect to fedora.login + self.assertEqual(urlparse(result.location).path, "/login/fedora") def test_groups_logged_in(self): user = tests.FakeAuthorization('ralph') @@ -64,25 +65,26 @@ class HubsAPITest(hubs.tests.APPTest): with tests.auth_set(app, user): result = self.app.get('/ralph', follow_redirects=True) self.assertEqual(result.status_code, 200) - self.assertFalse('Not logged in. Click to login' in result.data) + self.assertFalse('Not logged in. Click to login' in result.data) def test_hub_json(self): - with tests.auth_set(app, None): - # for some reason def check_auth() is not running and i need to set it to none so it won't crash - result = self.app.get('/ralph/json', follow_redirects=True) - # assert the status code of the response - self.assertEqual(result.status_code, 200) - data = { - "avatar": "https://seccdn.libravatar.org/avatar/9c9f7784935381befc302fe3c814f9136e7a33953d0318761669b8643f4df55c?s=312&d=retro", - "left_width": 8, - "members": ["ralph"], - "name": "ralph", - "owners": ["ralph"], - "subscribers": [], - "summary": "Ralph", - "widgets": [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 51] - } - self.assertDictEqual(data, json.loads(result.data)) + result = self.app.get('/ralph/json', follow_redirects=True) + # assert the status code of the response + self.assertEqual(result.status_code, 200) + data = { + "avatar": "https://seccdn.libravatar.org/avatar/" + "9c9f7784935381befc302fe3c814f9136e7a339" + "53d0318761669b8643f4df55c?s=312&d=retro", + "left_width": 8, + "members": ["ralph"], + "name": "ralph", + "owners": ["ralph"], + "subscribers": [], + "summary": "Ralph", + "widgets": [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 51] + } + self.assertDictEqual(data, json.loads(result.data)) @unittest.skip("Authorization layer not present yet") def test_hub_edit_get_logged_out(self): @@ -106,7 +108,7 @@ class HubsAPITest(hubs.tests.APPTest): with tests.auth_set(app, user): result = self.app.get('/ralph/edit', follow_redirects=True) self.assertEqual(result.status_code, 200) - # We do not have the authorization layer in place yet so everyone can edit + # We do not have the authorization layer so everyone can edit @unittest.skip("Authorization layer not present yet") def test_hub_edit_post_logged_out(self): @@ -125,20 +127,85 @@ class HubsAPITest(hubs.tests.APPTest): self.assertEqual(result.status_code, 403) # failing right # We do not have the authorization layer in place yet - # WIP: commenting out so I can push this updates to branch so others can contribute - ''' - def test_hub_edit_post_logged_in_owner_no_data(self): + def test_hub_edit_post_logged_in_owner_empty_data(self): user = tests.FakeAuthorization('ralph') with tests.auth_set(app, user): - result = self.app.post('/ralph/edit', follow_redirects=True) + result = self.app.post('/ralph/edit', data={}, + follow_redirects=True) self.assertEqual(result.status_code, 200) - assert 'Invalid widget identifiers submitted' in result.data - assert 'Invalid indexes submitted' in result.data - assert 'The number of indexes and the number of widgets ' \ - 'are not of the same length' in result.data - assert 'Invalid widget identifiers submitted' in result.data - assert 'Invalid indexes submitted' in result.data - ''' + self.assertFalse('Not logged in. Click to login' in result.data) + self.assertTrue('Full Name: ' + 'fullname: ralph' in result.data) + + def test_hub_edit_post_logged_in_owner_valid_data(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + data = ImmutableMultiDict( + [('right_indexes[]', u'0'), ('right_indexes[]', u'1'), + ('right_indexes[]', u'2'), ('right_indexes[]', u'3'), + ('right_indexes[]', u'4'), ('right_indexes[]', u'5'), + ('right_indexes[]', u'6'), ('right_indexes[]', u'7'), + ('right_indexes[]', u'8'), ('right_widgets[]', u'32'), + ('right_widgets[]', u'33'), ('right_widgets[]', u'34'), + ('right_widgets[]', u'35'), ('right_widgets[]', u'36'), + ('right_widgets[]', u'37'), ('right_widgets[]', u'38'), + ('right_widgets[]', u'39'), ('right_widgets[]', u'40'), + ('js', u'true'), ('left_indexes[]', u'0'), + ('left_indexes[]', u'1'), ('left_widgets[]', u'31'), + ('left_widgets[]', u'32')]) + result = self.app.post('/ralph/edit', data=data, + follow_redirects=True) + self.assertEqual(result.status_code, 200) + self.assertEqual(result.data, 'ok') + + def test_hub_edit_post_logged_in_owner_invalid_data_1(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + # some indexes and widgets are not integers + data = ImmutableMultiDict( + [('right_indexes[]', u'0a'), ('right_indexes[]', u'1'), + ('right_indexes[]', u'2'), ('right_indexes[]', u'3'), + ('right_indexes[]', u'4'), ('right_indexes[]', u'5'), + ('right_indexes[]', u'6'), ('right_indexes[]', u'7'), + ('right_indexes[]', u'8'), ('right_widgets[]', u'32'), + ('right_widgets[]', u'33a'), ('right_widgets[]', u'34'), + ('right_widgets[]', u'35'), ('right_widgets[]', u'36'), + ('right_widgets[]', u'37'), ('right_widgets[]', u'38'), + ('right_widgets[]', u'39'), ('right_widgets[]', u'40'), + ('js', u'true'), ('left_indexes[]', u'0a'), + ('left_indexes[]', u'1'), ('left_widgets[]', u'31a'), + ('left_widgets[]', u'32')]) + result = self.app.post('/ralph/edit', data=data, + follow_redirects=True) + self.assertEqual(result.status_code, 400) + + def test_hub_edit_post_logged_in_owner_invalid_data_2(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + # indexes len don't match widgets len + data = ImmutableMultiDict( + [('right_indexes[]', u'1'), ('right_indexes[]', u'2'), + ('right_indexes[]', u'3'), ('right_indexes[]', u'4'), + ('right_indexes[]', u'5'), ('right_indexes[]', u'6'), + ('right_indexes[]', u'7'), ('right_indexes[]', u'8'), + ('right_widgets[]', u'32'), ('right_widgets[]', u'34'), + ('right_widgets[]', u'35'), ('right_widgets[]', u'36'), + ('right_widgets[]', u'37'), ('right_widgets[]', u'38'), + ('right_widgets[]', u'39'), ('right_widgets[]', u'40'), + ('js', u'true'), ('left_indexes[]', u'0'), + ('left_indexes[]', u'1'), ('left_widgets[]', u'32')]) + result = self.app.post('/ralph/edit', data=data, + follow_redirects=True) + self.assertEqual(result.status_code, 400) + + def test_login_already_loggedin(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.get('/login', follow_redirects=False) + self.assertEqual(result.status_code, 302) + self.assertEqual(urlparse(result.location).path, "/") + if __name__ == '__main__': unittest.main() From f8497788b5ae571c0a18776817f511e0d2f54231 Mon Sep 17 00:00:00 2001 From: Eric Barbour Date: Jun 20 2016 14:47:52 +0000 Subject: [PATCH 6/9] Test login redirection for hub actions --- diff --git a/hubs/tests/test_api/test_hub.py b/hubs/tests/test_api/test_hub.py index ee749d9..785aef3 100644 --- a/hubs/tests/test_api/test_hub.py +++ b/hubs/tests/test_api/test_hub.py @@ -1,5 +1,6 @@ import flask import unittest +from urlparse import urlparse import hubs.tests import hubs.models @@ -12,12 +13,12 @@ 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)) + resp = self.app.post('/api/hub/{}/subscribe'.format(hub.name), + follow_redirects=False) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp.location, flask.url_for('fedora.login')) + self.assertEqual(urlparse(resp.location).path, '/login/fedora') def test_subscribe_when_logged_in(self): hub = hubs.models.Hub.by_name(self.session, 'infra') @@ -33,12 +34,12 @@ class TestHubSubscribe(hubs.tests.APPTest): 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)) + resp = self.app.post('/api/hub/{}/unsubscribe'.format(hub.name), + follow_redirects=False) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp.location, flask.url_for('fedora.login')) + self.assertEqual(urlparse(resp.location).path, '/login/fedora') def test_unsubscribe_when_logged_in(self): hub = hubs.models.Hub.by_name(self.session, 'infra') @@ -59,12 +60,12 @@ class TestHubUnsubscribe(hubs.tests.APPTest): 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)) + resp = self.app.post('/api/hub/{}/star'.format(hub.name), + follow_redirects=False) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp.location, flask.url_for('fedora.login')) + self.assertEqual(urlparse(resp.location).path, '/login/fedora') def test_star_when_logged_in(self): hub = hubs.models.Hub.by_name(self.session, 'infra') @@ -80,12 +81,12 @@ class TestHubStar(hubs.tests.APPTest): 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)) + resp = self.app.post('/api/hub/{}/unstar'.format(hub.name), + follow_redirects=False) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp.location, flask.url_for('fedora.login')) + self.assertEqual(urlparse(resp.location).path, '/login/fedora') def test_unstar_when_logged_in(self): hub = hubs.models.Hub.by_name(self.session, 'infra') @@ -107,12 +108,12 @@ class TestHubUnstar(hubs.tests.APPTest): 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)) + resp = self.app.post('/api/hub/{}/join'.format(hub.name), + follow_redirects=False) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp.location, flask.url_for('fedora.login')) + self.assertEqual(urlparse(resp.location).path, '/login/fedora') def test_join_when_logged_in(self): hub = hubs.models.Hub.by_name(self.session, 'infra') @@ -128,12 +129,12 @@ class TestHubJoin(hubs.tests.APPTest): 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)) + resp = self.app.post('/api/hub/{}/leave'.format(hub.name), + follow_redirects=False) self.assertEqual(resp.status_code, 302) - self.assertEqual(resp.location, flask.url_for('fedora.login')) + self.assertEqual(urlparse(resp.location).path, '/login/fedora') def test_star_when_logged_in(self): hub = hubs.models.Hub.by_name(self.session, 'infra') From f2a1fad40695a24bf298439fdae7960e80bdcf7f Mon Sep 17 00:00:00 2001 From: skrzepto Date: Jun 20 2016 15:36:38 +0000 Subject: [PATCH 7/9] adding post tests for hub/add/ widget added hubs edit post with valid minimum valid data working on hubs edit widget testing adjusting text to single quote from double --- diff --git a/hubs/tests/test_fedora_hubs_flask_api.py b/hubs/tests/test_fedora_hubs_flask_api.py index a0043f0..d9d2325 100644 --- a/hubs/tests/test_fedora_hubs_flask_api.py +++ b/hubs/tests/test_fedora_hubs_flask_api.py @@ -206,6 +206,80 @@ class HubsAPITest(hubs.tests.APPTest): self.assertEqual(result.status_code, 302) self.assertEqual(urlparse(result.location).path, "/") + def test_hub_add_widget_get_no_args(self): + result = self.app.get('/ralph/add', follow_redirects=False) + self.assertEqual(result.status_code, 400) + expected_str = 'Invalid position provided' + self.assertTrue(expected_str in result.data) + + def test_hub_add_widget_get_with_args(self): + result = self.app.get('/ralph/add?position=right', + follow_redirects=True) + self.assertEqual(result.status_code, 200) + expected_str = 'Adding widget to hub: ralph' + self.assertTrue(expected_str in result.data) + expected_str = "url: 'add/' + $('#widget').val() + '?position=right'," + self.assertTrue(expected_str in result.data) + + def test_hub_add_widget_post_no_widget_name(self): + data = {} + result = self.app.post('/ralph/add', data=data, follow_redirects=False) + self.assertEqual(result.status_code, 400) + expected_str = 'Invalid request sent' + self.assertTrue(expected_str in result.data) + + def test_hub_add_widget_post_invalid_widget_name(self): + data = {'widget_name': 'invalid_widget_name'} + result = self.app.post('/ralph/add', data=data, follow_redirects=False) + self.assertEqual(result.status_code, 404) + expected_str = 'Unknown widget called' + self.assertTrue(expected_str in result.data) + + def test_hub_add_widget_post_valid_widget_name_no_args(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + data = {'widget_name': 'about'} + result = self.app.post('/ralph/add', data=data, + follow_redirects=False) + self.assertEqual(result.status_code, 200) + expected_str = '' + self.assertTrue(expected_str in result.data) + expected_str = 'Full Name: fullname: ralph' + self.assertTrue(expected_str in result.data) + + def test_hub_add_widget_post_valid_widget_name_with_args(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + data = {'widget_name': 'about', 'text': 'text of widget'} + result = self.app.post('/ralph/add', data=data, + follow_redirects=False) + self.assertEqual(result.status_code, 200) + expected_str = '' + self.assertTrue(expected_str in result.data) + expected_str = 'Full Name: fullname: ralph' + self.assertTrue(expected_str in result.data) + + def test_hub_edit_widget_get_logged_in(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + result = self.app.get('/ralph/31/edit', follow_redirects=True) + self.assertEqual(result.status_code, 200) + expected_str = ' Date: Jun 20 2016 19:56:10 +0000 Subject: [PATCH 8/9] Move hubs.feed and PATHS down to temp endpoint --- diff --git a/hubs/app.py b/hubs/app.py index 4b72cee..64e6b91 100755 --- a/hubs/app.py +++ b/hubs/app.py @@ -20,10 +20,6 @@ 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__) @@ -52,7 +48,6 @@ 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']) @@ -650,6 +645,9 @@ def hub_leave(hub): return flask.redirect(flask.url_for('hub', name=hub.name)) +PATHS = fmn.lib.load_rules(root='fmn.rules') + + @app.route('/api/fedmsg/markup', methods=['GET']) def markup_fedmsg(): ''' @@ -658,6 +656,10 @@ def markup_fedmsg(): This route will be removed once its functionality is integrated into FMN ''' + from hubs.widgets.feed import ( + apply_markup, rehydrate_preference, + get_remote_preference + ) try: data = flask.request.args['message'] plugin = flask.request.args['plugin'] From 6922d8e8bc963ae1cc4582a28293c25e45d558e7 Mon Sep 17 00:00:00 2001 From: skrzepto Date: Jun 21 2016 12:51:32 +0000 Subject: [PATCH 9/9] cleaning up current tests in the widgets folder --- diff --git a/hubs/tests/test_widgets/test_about.py b/hubs/tests/test_widgets/test_about.py index 38bddee..a0ec275 100644 --- a/hubs/tests/test_widgets/test_about.py +++ b/hubs/tests/test_widgets/test_about.py @@ -25,26 +25,18 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): msg = {'topic': 'hubs.widget.update.WRONG.TOPIC', 'msg': {'widget': {'id': widget.idx}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert not result + self.assertFalse(result) def test_should_invalidate_wrong_widget_id(self): widget = self.widget_instance('ralph', self.plugin) msg = {'topic': 'hubs.widget.update', 'msg': {'widget': {'id': widget.idx+1}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert not result + self.assertFalse(result) def test_should_invalidate_good_match(self): widget = self.widget_instance('ralph', self.plugin) msg = {'topic': 'hubs.widget.update', 'msg': {'widget': {'id': widget.idx}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert result - - ''' - def test_data(self): - widget = self.widget_instance('ralph', self.plugin) - module = hubs.widgets.registry[widget.plugin] - result = module.data(self.session, widget, 'I love oss.') - assert_dict_equal({'text': 'I love oss.'}, result) - ''' \ No newline at end of file + self.assertTrue(result) diff --git a/hubs/tests/test_widgets/test_badges.py b/hubs/tests/test_widgets/test_badges.py index 7edd96e..b3b5197 100644 --- a/hubs/tests/test_widgets/test_badges.py +++ b/hubs/tests/test_widgets/test_badges.py @@ -13,7 +13,7 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): assert response.status_code == 200, response.status_code data = json.loads(response.data) self.assertEquals(data['plugin'], 'badges') - assert 'assertions' in data['data'], data['data'].keys() + self.assertIn('assertions', data['data'].keys()) def test_should_invalidate_wrong_topic(self): widget = self.widget_instance('ralph', self.plugin) @@ -21,7 +21,7 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): msg = {'topic': 'hubs.widget.update.WRONG.TOPIC'} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert not result + self.assertFalse(result) def test_should_invalidate_wrong_user(self): widget = self.widget_instance('ralph', self.plugin) @@ -29,7 +29,7 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): msg = {'topic': 'fedbadges.badge.award', 'msg': {'user': {'username': 'not_ralph'}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert not result + self.assertFalse(result) def test_should_invalidate_good_match_fedbadges(self): widget = self.widget_instance('ralph', self.plugin) @@ -37,7 +37,7 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): msg = {'topic': 'fedbadges.badge.award', 'msg': {'user': {'username': 'ralph'}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert result + self.assertTrue(result) def test_should_invalidate_good_match_hubswidget(self): widget = self.widget_instance('ralph', self.plugin) @@ -45,40 +45,4 @@ class TestBadges(hubs.tests.test_widgets.WidgetTest): msg = {'topic': 'hubs.widget.update', 'msg': {'widget': {'id': widget.idx + 1}}} module = hubs.widgets.registry[widget.plugin] result = module.should_invalidate(msg, self.session, widget) - assert result - ''' - @patch('requests.get') - @patch('hubs.widgets.base.cache.get_or_create') - def test_data_good(self, cache_mock, requests_mock): - requests_mock.return_value = self.mock_response() - cache_mock.return_value = None - widget = self.widget_instance('ralph', self.plugin) - module = hubs.widgets.registry[widget.plugin] - result = module.data(self.session, widget, 'ralph') - assert result - ''' - @staticmethod - def mock_response(): - test_data_simple = '''{ - "percent_earned": 47.05882352941176, - "assertions": [{ - "description": "You attended Flock 2014, the Fedora Contributor Conference", - "tags": "flock,event,", - "issued": 1375373082.0, - "image": "https://badges.fedoraproject.org/pngs/flock-2013-attendee.png", - "first_awarded": 1375373082.0, - "first_awarded_person": "ralph", - "last_awarded_person": "gnokii", - "last_awarded": 1386188828.0, - "percent_earned": 0.404551201011378, - "id": "flock-2013-attendee", - "times_awarded": 80, - "name": "Flock 2013 Attendee" - }], - "user": "ralph", - "avatar": "" - }''' - - mock = MagicMock() - mock.json.return_value = json.loads(test_data_simple) - return mock + self.assertTrue(result) \ No newline at end of file diff --git a/hubs/tests/test_widgets/test_meetings.py b/hubs/tests/test_widgets/test_meetings.py index bafb6a3..0a48a83 100644 --- a/hubs/tests/test_widgets/test_meetings.py +++ b/hubs/tests/test_widgets/test_meetings.py @@ -10,14 +10,14 @@ class TestMeetings(hubs.tests.test_widgets.WidgetTest): team = 'i18n' widget = self.widget_instance(team, self.plugin) response = self.app.get('/%s/%i/json/' % (team, widget.idx)) - assert response.status_code == 200, response.status_code + self.assertEqual(200, response.status_code) data = json.loads(response.data) meeting = data['data']['meetings']["%s meeting" % team] - assert team in meeting['meeting_name'] + self.assertIn(team, meeting['meeting_name']) def test_render_simple(self): team = 'i18n' widget = self.widget_instance(team, self.plugin) response = self.app.get('/%s/%i/' % (team, widget.idx)) - assert response.status_code == 200, response.status_code - assert 'The i18n meeting is ' in response.data, response.data + self.assertEqual(200, response.status_code) + self.assertIn('The i18n meeting is ', response.data)