| |
@@ -0,0 +1,447 @@
|
| |
+ from __future__ import unicode_literals, absolute_import
|
| |
+
|
| |
+ import json
|
| |
+
|
| |
+ from hubs.models import Hub
|
| |
+ from hubs.tests import captured_templates
|
| |
+ from hubs.tests.test_widgets import WidgetTest
|
| |
+ from hubs.widgets import registry
|
| |
+
|
| |
+
|
| |
+ SAMPLE_DATA = [
|
| |
+ {
|
| |
+ 'author': {
|
| |
+ 'url': '/mattdm/', 'name': 'mattdm', 'avatar': None,
|
| |
+ },
|
| |
+ 'channel': u'#fedora-meeting',
|
| |
+ 'context_url': (
|
| |
+ 'https://meetbot.fedoraproject.org/fedora-meeting/'
|
| |
+ '2017-03-17/fesco.2017-03-17-16.00.log.html#l-466'
|
| |
+ ),
|
| |
+ 'date': 1489773443.0,
|
| |
+ 'meeting_topic': 'FESCO (2017-03-17)',
|
| |
+ 'text': ('"How to enable trim on your SSD drive" would '
|
| |
+ 'be a good Fedora Magazine article'),
|
| |
+ 'urls': [],
|
| |
+ }, {
|
| |
+ 'author': {
|
| |
+ 'url': '/jkurik/', 'name': 'jkurik', 'avatar': None,
|
| |
+ },
|
| |
+ 'channel': '#fedora-meeting-2',
|
| |
+ 'context_url': (
|
| |
+ 'https://meetbot.fedoraproject.org/fedora-meeting-2/2017-03-16/'
|
| |
+ 'f26-alpha-readiness-meeting.2017-03-16-19.00.log.html#l-103'),
|
| |
+ 'date': 1489692368.0,
|
| |
+ 'meeting_topic': 'F26 Alpha Readiness Meeting',
|
| |
+ 'text': ('The Marketing team wants to ask for help from '
|
| |
+ 'Spins, Labs SIGs and DEs SIGs to populate the '
|
| |
+ 'talking points that help us to marketing people'),
|
| |
+ 'urls': [],
|
| |
+ }, {
|
| |
+ 'author': {
|
| |
+ 'url': '/stoney/', 'name': 'stoney', 'avatar': None,
|
| |
+ },
|
| |
+ 'channel': '#foss2serve',
|
| |
+ 'context_url': (
|
| |
+ 'https://meetbot.fedoraproject.org/foss2serve/2017-03-14/'
|
| |
+ 'posse_irc_meeting_1.2.2017-03-14-17.00.log.html#l-187'),
|
| |
+ 'date': 1489512523.0,
|
| |
+ 'meeting_topic': 'POSSE IRC Meeting 1.2',
|
| |
+ 'text': '',
|
| |
+ 'urls': [],
|
| |
+ }, {
|
| |
+ 'author': {
|
| |
+ 'url': '/nitzmahone/', 'name': 'nitzmahone', 'avatar': None,
|
| |
+ },
|
| |
+ 'channel': '#ansible-meeting',
|
| |
+ 'context_url': (
|
| |
+ 'https://meetbot.fedoraproject.org/ansible-meeting/2017-03-14/'
|
| |
+ 'windows_working_group.2017-03-14-00.00.log.html#l-130'),
|
| |
+ 'date': 1489451407.0,
|
| |
+ 'meeting_topic': 'Windows Working Group',
|
| |
+ 'text': '',
|
| |
+ 'urls': [],
|
| |
+ }, {
|
| |
+ 'author': {
|
| |
+ 'url': '/jborean93/', 'name': 'jborean93', 'avatar': None
|
| |
+ },
|
| |
+ 'channel': '#ansible-meeting',
|
| |
+ 'context_url': (
|
| |
+ 'https://meetbot.fedoraproject.org/ansible-meeting/2017-03-14/'
|
| |
+ 'windows_working_group.2017-03-14-00.00.log.html#l-59'),
|
| |
+ 'date': 1489450330.0,
|
| |
+ 'meeting_topic': 'Windows Working Group',
|
| |
+ 'text': 'with installers win_msi vs win_product',
|
| |
+ 'urls': [],
|
| |
+ },
|
| |
+ ]
|
| |
+
|
| |
+
|
| |
+ class HalpViewsTestCase(WidgetTest):
|
| |
+ plugin = 'halp' # The name in hubs.widgets.registry
|
| |
+ maxDiff = None
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ super(HalpViewsTestCase, self).setUp()
|
| |
+ self.widget = self.widget_instance('ralph', self.plugin)
|
| |
+ config = self.widget.config
|
| |
+ config["hubs"] = ["fedora-devel"]
|
| |
+ config["per_page"] = 3
|
| |
+ self.widget.config = config
|
| |
+ infra_hub = Hub.query.get("infra")
|
| |
+ infra_hub.config.chat_channel = "#fedora-meeting"
|
| |
+ devyani7 = Hub.query.get("devyani7")
|
| |
+ devyani7.config.chat_channel = "#fedora-meeting-2"
|
| |
+ decause = Hub.query.get("decause")
|
| |
+ decause.config.chat_channel = "#ansible-meeting"
|
| |
+ dhrish = Hub.query.get("dhrish")
|
| |
+ dhrish.config.chat_channel = "#foss2serve"
|
| |
+ self.session.commit()
|
| |
+
|
| |
+ def _get_sample_data_with_hub_keys(self):
|
| |
+ hub_names = ["infra", "devyani7", "dhrish", "decause", "decause"]
|
| |
+ data = [req.copy() for req in SAMPLE_DATA]
|
| |
+ for index, hub_name in enumerate(hub_names):
|
| |
+ data[index].update({
|
| |
+ 'hub': hub_name,
|
| |
+ 'hubs': [hub_name],
|
| |
+ })
|
| |
+ return data
|
| |
+
|
| |
+ def test_root(self):
|
| |
+ with captured_templates(self.widget.module) as templates:
|
| |
+ response = self.app.get('/ralph/w/halp/%i/' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ self.assertEqual(len(templates), 1)
|
| |
+ _template, context = templates[0]
|
| |
+ self.assertEqual(context["hubs"], ['fedora-devel'])
|
| |
+
|
| |
+ def test_json(self):
|
| |
+ response = self.app.get('/ralph/%i/json' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertEquals(data['plugin'], 'halp')
|
| |
+ self.assertIn('hubs', data['data'].keys())
|
| |
+
|
| |
+ def test_config_add(self):
|
| |
+ with captured_templates(self.widget.module) as templates:
|
| |
+ response = self.app.get('/ralph/w/halp/add?position=right')
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ self.assertEqual(len(templates), 1)
|
| |
+ _template, context = templates[0]
|
| |
+ self.assertEqual(context["mode"], "add")
|
| |
+ self.assertEqual(context["initial"], {
|
| |
+ "hubs": ["ralph"], "per_page": 4,
|
| |
+ })
|
| |
+ self.assertEqual(context["url"], "/ralph/add/halp?position=right")
|
| |
+
|
| |
+ def test_config_edit(self):
|
| |
+ with captured_templates(self.widget.module) as templates:
|
| |
+ response = self.app.get('/ralph/w/halp/%i/config'
|
| |
+ % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ self.assertEqual(len(templates), 1)
|
| |
+ _template, context = templates[0]
|
| |
+ self.assertEqual(context["mode"], "edit")
|
| |
+ self.assertEqual(context["initial"], {
|
| |
+ 'hubs': ['fedora-devel'],
|
| |
+ 'per_page': 3,
|
| |
+ })
|
| |
+ self.assertEqual(context["url"], "/ralph/%i/edit" % self.widget.idx)
|
| |
+
|
| |
+ def test_config_hubs_suggest(self):
|
| |
+ response = self.app.get('/w/halp/hubs')
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertDictEqual(data, {
|
| |
+ 'results': ['decause', 'devyani7', 'dhrish', 'i18n', 'infra']
|
| |
+ })
|
| |
+ response = self.app.get('/w/halp/hubs?q=de')
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertDictEqual(data, {
|
| |
+ 'results': ['decause', 'devyani7']
|
| |
+ })
|
| |
+
|
| |
+ def test_data(self):
|
| |
+ expected = self._get_sample_data_with_hub_keys()
|
| |
+ # Test with no hub selected
|
| |
+ response = self.app.get('/ralph/w/halp/%i/data' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertEqual(data, {"requests": expected[:3]})
|
| |
+ # Test with the right hub selected
|
| |
+ response = self.app.get('/ralph/w/halp/%i/data?hubs=decause'
|
| |
+ % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertEqual(data, {"requests": expected[3:5]})
|
| |
+
|
| |
+ def test_data_wrong_hub(self):
|
| |
+ # Test with the wrong hub selected
|
| |
+ response = self.app.get('/ralph/w/halp/%i/data?hubs=ralph'
|
| |
+ % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertEqual(data, {"requests": []})
|
| |
+
|
| |
+ def test_search_requesters(self):
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/requesters' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertDictEqual(data, {
|
| |
+ 'results': ['jborean93', 'jkurik', 'mattdm', 'nitzmahone',
|
| |
+ 'stoney']
|
| |
+ })
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/requesters?q=j' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertDictEqual(data, {
|
| |
+ 'results': ['jborean93', 'jkurik']
|
| |
+ })
|
| |
+
|
| |
+ def test_search_all(self):
|
| |
+ expected = self._get_sample_data_with_hub_keys()
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/search' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertEqual(data, {
|
| |
+ "requests": expected[:3],
|
| |
+ 'page': {
|
| |
+ 'has_next': True,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': 5,
|
| |
+ 'total_pages': 2,
|
| |
+ },
|
| |
+ })
|
| |
+ # Page 2
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/search?page=2' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ self.assertEqual(data, {
|
| |
+ "requests": expected[3:],
|
| |
+ 'page': {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': True,
|
| |
+ 'nr': 2,
|
| |
+ 'total_entries': 5,
|
| |
+ 'total_pages': 2,
|
| |
+ },
|
| |
+ })
|
| |
+
|
| |
+ def test_search_hub(self):
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/search?hubs=infra' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ expected = self._get_sample_data_with_hub_keys()
|
| |
+ self.assertEqual(data, {
|
| |
+ "requests": expected[0:1],
|
| |
+ 'page': {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': 1,
|
| |
+ 'total_pages': 1
|
| |
+ },
|
| |
+ })
|
| |
+
|
| |
+ def test_search_people(self):
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/search?people=nitzmahone' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ expected = self._get_sample_data_with_hub_keys()
|
| |
+ self.assertEqual(data, {
|
| |
+ "requests": expected[3:4],
|
| |
+ 'page': {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': 1,
|
| |
+ 'total_pages': 1
|
| |
+ },
|
| |
+ })
|
| |
+
|
| |
+ def test_search_meetingname(self):
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/search?meetingname=Readiness' % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ expected = self._get_sample_data_with_hub_keys()
|
| |
+ self.assertEqual(data, {
|
| |
+ "requests": expected[1:2],
|
| |
+ 'page': {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': 1,
|
| |
+ 'total_pages': 1
|
| |
+ },
|
| |
+ })
|
| |
+
|
| |
+ def test_search_date(self):
|
| |
+ response = self.app.get(
|
| |
+ '/ralph/w/halp/%i/search?startdate=2017-03-16&enddate=2017-03-17'
|
| |
+ % self.widget.idx)
|
| |
+ self.assertEqual(response.status_code, 200)
|
| |
+ data = json.loads(response.get_data(as_text=True))
|
| |
+ expected = self._get_sample_data_with_hub_keys()
|
| |
+ self.assertEqual(data, {
|
| |
+ "requests": expected[1:2],
|
| |
+ 'page': {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': 1,
|
| |
+ 'total_pages': 1
|
| |
+ },
|
| |
+ })
|
| |
+
|
| |
+
|
| |
+ class HalpFunctionsTestCase(WidgetTest):
|
| |
+ plugin = 'halp' # The name in hubs.widgets.registry
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ super(HalpFunctionsTestCase, self).setUp()
|
| |
+ module = registry[self.plugin]
|
| |
+ func_class = module.get_cached_functions()['GetRequests']
|
| |
+ self.widget = self.widget_instance('ralph', self.plugin)
|
| |
+ self.func = func_class(self.widget)
|
| |
+ # The tested widget watches the infra hub.
|
| |
+ config = self.widget.config
|
| |
+ config["hubs"] = ["infra"]
|
| |
+ self.widget.config = config
|
| |
+ # The infra hub works in the fedora-infra channel.
|
| |
+ infra_hub = Hub.query.filter_by(name="infra").one()
|
| |
+ infra_hub.config.chat_channel = "#fedora-infra"
|
| |
+ self.session.commit()
|
| |
+
|
| |
+ def test_execute(self):
|
| |
+ with self.app.application.test_request_context('/'):
|
| |
+ result = self.func.execute()
|
| |
+ self.assertEqual(result, SAMPLE_DATA)
|
| |
+
|
| |
+ def test_should_invalidate_wrong_topic(self):
|
| |
+ msg = {'topic': 'hubs.WRONG.TOPIC'}
|
| |
+ result = self.func.should_invalidate(msg)
|
| |
+ self.assertFalse(result)
|
| |
+
|
| |
+ def test_should_invalidate_wrong_hub(self):
|
| |
+ # The decause hub works in the fedora-commops channel.
|
| |
+ decause_hub = Hub.query.filter_by(name="decause").one()
|
| |
+ decause_hub.config.chat_channel = "#fedora-commops"
|
| |
+ self.session.commit()
|
| |
+ msg = {'topic': 'org.fedoraproject.prod.meetbot.meeting.item.help',
|
| |
+ 'msg': {'channel': '#fedora-commops'},
|
| |
+ }
|
| |
+ # The decause hub cache would be invalidated, but not ours.
|
| |
+ result = self.func.should_invalidate(msg)
|
| |
+ self.assertFalse(result)
|
| |
+
|
| |
+ def test_should_invalidate_good_match(self):
|
| |
+ msg = {'topic': 'org.fedoraproject.prod.meetbot.meeting.item.help',
|
| |
+ 'msg': {'channel': '#fedora-infra'},
|
| |
+ }
|
| |
+ result = self.func.should_invalidate(msg)
|
| |
+ self.assertTrue(result)
|
| |
+
|
| |
+
|
| |
+ class PaginateTestCase(WidgetTest):
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ super(PaginateTestCase, self).setUp()
|
| |
+ from hubs.widgets.halp.utils import paginate # circular
|
| |
+ self.paginate = paginate
|
| |
+ self.values = ["A", "B", "C", "D"]
|
| |
+
|
| |
+ def test_base(self):
|
| |
+ with self.app.application.test_request_context('/'):
|
| |
+ result = self.paginate(self.values, 3)
|
| |
+ self.assertListEqual(result[0], self.values[:3])
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': True,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': len(self.values),
|
| |
+ 'total_pages': 2,
|
| |
+ })
|
| |
+
|
| |
+ def test_page_2(self):
|
| |
+ with self.app.application.test_request_context('/?page=2'):
|
| |
+ result = self.paginate(self.values, 3)
|
| |
+ self.assertListEqual(result[0], self.values[3:])
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': True,
|
| |
+ 'nr': 2,
|
| |
+ 'total_entries': len(self.values),
|
| |
+ 'total_pages': 2,
|
| |
+ })
|
| |
+
|
| |
+ def test_page_0(self):
|
| |
+ with self.app.application.test_request_context('/?page=0'):
|
| |
+ result = self.paginate(self.values, 3)
|
| |
+ self.assertListEqual(result[0], self.values[:3])
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': True,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': len(self.values),
|
| |
+ 'total_pages': 2,
|
| |
+ })
|
| |
+
|
| |
+ def test_invalid_page(self):
|
| |
+ with self.app.application.test_request_context('/?page=blah'):
|
| |
+ result = self.paginate(self.values, 3)
|
| |
+ self.assertListEqual(result[0], self.values[:3])
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': True,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': len(self.values),
|
| |
+ 'total_pages': 2,
|
| |
+ })
|
| |
+
|
| |
+ def test_page_too_high(self):
|
| |
+ with self.app.application.test_request_context('/?page=3'):
|
| |
+ result = self.paginate(self.values, 3)
|
| |
+ self.assertListEqual(result[0], self.values[3:])
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': True,
|
| |
+ 'nr': 2,
|
| |
+ 'total_entries': len(self.values),
|
| |
+ 'total_pages': 2,
|
| |
+ })
|
| |
+
|
| |
+ def test_single_page(self):
|
| |
+ values = self.values[:3]
|
| |
+ with self.app.application.test_request_context('/'):
|
| |
+ result = self.paginate(values, 3)
|
| |
+ self.assertListEqual(result[0], values)
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': len(values),
|
| |
+ 'total_pages': 1,
|
| |
+ })
|
| |
+
|
| |
+ def test_no_value(self):
|
| |
+ values = []
|
| |
+ with self.app.application.test_request_context('/'):
|
| |
+ result = self.paginate(values, 3)
|
| |
+ self.assertListEqual(result[0], [])
|
| |
+ self.assertDictEqual(result[1], {
|
| |
+ 'has_next': False,
|
| |
+ 'has_prev': False,
|
| |
+ 'nr': 1,
|
| |
+ 'total_entries': 0,
|
| |
+ 'total_pages': 1,
|
| |
+ })
|
| |
Maybe lowercase "help"?