From 7d6632e95220db8302e6910fad16ddacdd576f4a Mon Sep 17 00:00:00 2001
From: skrzepto <shims506@gmail.com>
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 <a href="/login/fedora">login</a>' 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 <a href="/login/fedora">login</a>' 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 <a href="/login/fedora">login</a>' 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 <ebarbour@redhat.com>
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"<h5>{long_form}</h5>".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 <ebarbour@redhat.com>
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 <ebarbour@redhat.com>
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 <shims506@gmail.com>
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('/<hub>/<idx>')
 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('/<hub>/<idx>/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/<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 <a href="/login/fedora">login</a>' in result.data)
+            self.assertFalse('Not logged in.  Click to <a href="'
+                             '/login/fedora">login</a>' 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 <a href="/login/fedora">login</a>' in result.data)
+            str_expected = 'Not logged in.  Click to ' \
+                           '<a href="/login/fedora">login</a>'
+            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 <a href="/login/fedora">login</a>' in result.data)
+            self.assertFalse('Not logged in.  Click to <a href="'
+                             '/login/fedora">login</a>' 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 <a href="'
+                             '/login/fedora">login</a>' in result.data)
+            self.assertTrue('<a href="#" class="dropdown-item">Full Name: '
+                            'fullname: ralph</a>' 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 <ebarbour@redhat.com>
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 <shims506@gmail.com>
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 = '<h6 class="dropdown-header">Account Information</h6>'
+            self.assertTrue(expected_str in result.data)
+            expected_str = '<a href="#" class="dropdown-item">Full Name: fullname: ralph</a>'
+            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 = '<h6 class="dropdown-header">Account Information</h6>'
+            self.assertTrue(expected_str in result.data)
+            expected_str = '<a href="#" class="dropdown-item">Full Name: fullname: ralph</a>'
+            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 = '<input id="fmn_context" class="form-control" type="text"'
+            self.assertTrue(expected_str in result.data)
+
+    @unittest.skip("Authorization layer not present yet")
+    def test_hub_edit_widget_get_logged_out(self):
+        result = self.app.get('/ralph/31/edit', follow_redirects=True)
+        self.assertEqual(result.status_code, 403)
+
+    def test_hub_edit_widget_post_empty_data_logged_in(self):
+        user = tests.FakeAuthorization('ralph')
+        with tests.auth_set(app, user):
+            data = {}
+            url = '/ralph/31/edit'
+            result = self.app.post(url, data=data, follow_redirects=False)
+            self.assertEqual(result.status_code, 302)
+            self.assertEqual(urlparse(result.location).path, '/ralph/')
 
 if __name__ == '__main__':
     unittest.main()

From 865b26f3707b8d6c3f20caee12abe60a1bbe9146 Mon Sep 17 00:00:00 2001
From: Eric Barbour <ebarbour@redhat.com>
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 <shims506@gmail.com>
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)

