Add tests for the projector code

This commit is contained in:
Oskar Hahn 2013-10-29 18:28:05 +01:00
parent 29dc8cf200
commit 71666094e7
5 changed files with 266 additions and 19 deletions

View File

@ -67,6 +67,9 @@ def update_projector_overlay(overlay):
def call_on_projector(calls): def call_on_projector(calls):
""" """
Sends data to the projector. Sends data to the projector.
The argument call has to be a dictionary with the javascript function name
as key and the argument for it as value.
""" """
projector_js_cache = config['projector_js_cache'] projector_js_cache = config['projector_js_cache']
projector_js_cache.update(calls) projector_js_cache.update(calls)
@ -76,16 +79,21 @@ def call_on_projector(calls):
def get_projector_content(slide_dict=None): def get_projector_content(slide_dict=None):
""" """
Returns the HTML-Content block of the projector. Returns the HTML-Content block for the projector.
Slide_dict has to be an dictonary with the key 'callback'.
If slide_dict is None, use the active slide from the database.
""" """
if slide_dict is None: if slide_dict is None:
slide_dict = config['projector_active_slide'].copy() slide_dict = config['projector_active_slide'].copy()
callback = slide_dict.pop('callback', None) callback = slide_dict.pop('callback', None)
try: try:
return slide_callback[callback](**slide_dict) slide_content = slide_callback[callback](**slide_dict)
except KeyError: except KeyError:
return default_slide() slide_content = default_slide()
return slide_content
def default_slide(): def default_slide():
@ -120,7 +128,7 @@ def get_projector_overlays():
def get_projector_overlays_js(): def get_projector_overlays_js():
""" """
Returns JS-Code for the overlays. Returns JS-Code for the active overlays.
The retuned value is a list of json objects. The retuned value is a list of json objects.
""" """

View File

@ -17,16 +17,16 @@ from . import views
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^$', url(r'^$',
views.Projector.as_view(), views.ProjectorView.as_view(),
name='projector_show'), name='projector_show'),
url(r'^preview/$', url(r'^preview/$',
views.Projector.as_view(), views.ProjectorView.as_view(),
{'callback': None}, {'callback': None},
name='projctor_preview_welcomepage'), name='projctor_preview_welcomepage'),
url(r'^preview/(?P<callback>[^/]*)/$', url(r'^preview/(?P<callback>[^/]*)/$',
views.Projector.as_view(), views.ProjectorView.as_view(),
name='projector_preview'), name='projector_preview'),
url(r'^activate/(?P<callback>[^/]*)/$', url(r'^activate/(?P<callback>[^/]*)/$',

View File

@ -48,7 +48,7 @@ class DashboardView(AjaxMixin, TemplateView):
return context return context
class Projector(TemplateView): class ProjectorView(TemplateView):
""" """
The Projector-Page. The Projector-Page.
""" """
@ -56,12 +56,9 @@ class Projector(TemplateView):
template_name = 'projector.html' template_name = 'projector.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
slide_dict = dict(self.request.GET.items())
callback = self.kwargs.get('callback', None) callback = self.kwargs.get('callback', None)
if callback:
slide_dict['callback'] = callback
if not slide_dict: if callback is None:
kwargs.update({ kwargs.update({
'content': get_projector_content(), 'content': get_projector_content(),
'overlays': get_projector_overlays(), 'overlays': get_projector_overlays(),
@ -70,11 +67,13 @@ class Projector(TemplateView):
'calls': config['projector_js_cache']}) 'calls': config['projector_js_cache']})
# For the Preview # For the Preview
else: else:
slide_dict = dict(self.request.GET.items())
slide_dict['callback'] = callback
kwargs.update({ kwargs.update({
'content': get_projector_content(slide_dict), 'content': get_projector_content(slide_dict),
'reload': False}) 'reload': False})
return super(Projector, self).get_context_data(**kwargs) return super(ProjectorView, self).get_context_data(**kwargs)
class ActivateView(RedirectView): class ActivateView(RedirectView):
@ -86,10 +85,11 @@ class ActivateView(RedirectView):
allow_ajax = True allow_ajax = True
def pre_redirect(self, request, *args, **kwargs): def pre_redirect(self, request, *args, **kwargs):
if kwargs['callback'] == 'mediafile' and \ if (kwargs['callback'] == 'mediafile' and
get_active_slide()['callback'] == 'mediafile': get_active_slide()['callback'] == 'mediafile'):
# If the current slide is a pdf and the new page is also a slide, we dont have to use # If the current slide is a pdf and the new page is also a slide,
# set_active_slide, because is causes a content reload. # we dont have to use set_active_slide, because is causes a content
# reload.
kwargs.update({'page_num': 1, 'pk': request.GET.get('pk')}) kwargs.update({'page_num': 1, 'pk': request.GET.get('pk')})
url = Mediafile.objects.get(pk=kwargs['pk'], is_presentable=True).mediafile.url url = Mediafile.objects.get(pk=kwargs['pk'], is_presentable=True).mediafile.url
config['projector_active_slide'] = kwargs config['projector_active_slide'] = kwargs

189
tests/projector/test_api.py Normal file
View File

@ -0,0 +1,189 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Tests for openslides projector api
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: 20112013 by OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from mock import MagicMock, patch
from openslides.projector import api as projector_api
from openslides.utils.test import TestCase
class ApiFunctions(TestCase):
@patch('openslides.projector.api.get_projector_content')
@patch('openslides.projector.api.ProjectorSocketHandler')
def test_update_projector(self, mock_ProjectorSocketHandler,
mock_get_projector_content):
mock_get_projector_content.return_value = 'mock_string'
projector_api.update_projector()
mock_ProjectorSocketHandler.send_updates.assert_called_with(
{'content': 'mock_string'})
@patch('openslides.projector.api.get_overlays')
@patch('openslides.projector.api.ProjectorSocketHandler')
def test_update_projector_overlay(self, mock_ProjectorSocketHandler,
mock_get_overlays):
mock_overlay = MagicMock()
mock_overlay.name = 'mock_overlay_name'
mock_overlay.get_projector_html.return_value = 'mock_html_code'
mock_overlay.get_javascript.return_value = 'mock_javascript'
mock_get_overlays.return_value = {'mock_overlay': mock_overlay}
# Test with active overlay
mock_overlay.is_active.return_value = False
projector_api.update_projector_overlay(None)
mock_ProjectorSocketHandler.send_updates.assert_called_with(
{'overlays': {'mock_overlay_name': None}})
# Test with active overlay
mock_overlay.is_active.return_value = True
projector_api.update_projector_overlay(None)
expected_data = {'overlays': {'mock_overlay_name': {
'html': 'mock_html_code',
'javascript': 'mock_javascript'}}}
mock_ProjectorSocketHandler.send_updates.assert_called_with(expected_data)
# Test with overlay name as argument
projector_api.update_projector_overlay('mock_overlay')
mock_ProjectorSocketHandler.send_updates.assert_called_with(expected_data)
# Test with overlay object as argument
projector_api.update_projector_overlay(mock_overlay)
mock_ProjectorSocketHandler.send_updates.assert_called_with(expected_data)
@patch('openslides.projector.api.config')
@patch('openslides.projector.api.ProjectorSocketHandler')
def test_call_on_projector(self, mock_ProjectorSocketHandler, mock_config):
mock_config.__getitem__.return_value = {}
data = {'some_call': 'argument'}
projector_api.call_on_projector(data)
mock_ProjectorSocketHandler.send_updates.assert_called_with(
{'calls': data})
mock_config.__getitem__.assert_called_with('projector_js_cache')
mock_config.__setitem__.assert_called_with('projector_js_cache', data)
@patch('openslides.projector.api.default_slide')
def test_get_projector_content(self, mock_default_slide):
mock_slide = MagicMock()
mock_slide.return_value = 'slide content'
with patch.dict('openslides.projector.api.slide_callback',
values={'mock_slide': mock_slide}):
value = projector_api.get_projector_content({'callback': 'mock_slide'})
self.assertEqual(value, 'slide content')
projector_api.get_projector_content({'callback': 'unknown_slide'})
self.assertTrue(mock_default_slide.called)
with patch('openslides.projector.api.config',
{'projector_active_slide': {'callback': 'mock_slide'}}):
value = projector_api.get_projector_content()
self.assertEqual(value, 'slide content')
@patch('openslides.projector.api.render_to_string')
def test_default_slide(self, mock_render_to_string):
projector_api.default_slide()
mock_render_to_string.assert_called_with('projector/default_slide.html')
@patch('openslides.projector.api.projector_overlays')
def test_get_overlays(self, mock_projector_overlays):
mock_overlay = MagicMock()
mock_overlay.name = 'mock_overlay'
mock_projector_overlays.send.return_value = ((None, mock_overlay), )
value = projector_api.get_overlays()
self.assertEqual(value, {'mock_overlay': mock_overlay})
@patch('openslides.projector.api.render_to_string')
@patch('openslides.projector.api.get_overlays')
def test_get_projector_overlays(self, mock_get_overlays, mock_render_to_string):
mock_overlay = MagicMock()
mock_overlay.get_projector_html.return_value = 'some html'
mock_get_overlays.return_value = {'overlay_name': mock_overlay}
# Test with inactive overlay
mock_overlay.is_active.return_value = False
projector_api.get_projector_overlays()
mock_render_to_string.assert_called_with(
'projector/all_overlays.html',
{'overlays': []})
# Test with active overlay
mock_overlay.is_active.return_value = True
projector_api.get_projector_overlays()
mock_render_to_string.assert_Called_with(
'projector/all_overlays.html',
{'overlays': [{'name': 'overlay_name', 'html': 'some html'}]})
@patch('openslides.projector.api.get_overlays')
def test_get_projector_overlays_js(self, mock_get_overlays):
overlay = MagicMock()
mock_get_overlays.return_value = {'overlay': overlay}
# Test with inactive overlay
overlay.is_active.return_value = False
value = projector_api.get_projector_overlays_js()
self.assertEqual(value, [])
# Test with active overlay without js
overlay.is_active.return_value = True
overlay.get_javascript.return_value = None
value = projector_api.get_projector_overlays_js()
self.assertEqual(value, [])
# Test with active overlay with js
overlay.get_javascript.return_value = 'some javascript'
value = projector_api.get_projector_overlays_js()
self.assertEqual(value, ['some javascript'])
def test_register_slide(self):
mock_slide_callback = {}
with patch('openslides.projector.api.slide_callback', mock_slide_callback):
projector_api.register_slide('some name', 'some callback')
self.assertEqual(mock_slide_callback, {'some name': 'some callback'})
@patch('openslides.projector.api.render_to_string')
@patch('openslides.projector.api.register_slide')
def test_register_slide_model(self, mock_register_slide, mock_render_to_string):
mock_SlideModel = MagicMock()
mock_SlideModel.slide_callback_name = 'mock_callback_name'
mock_SlideModel.DoesNotExist = Exception
mock_slide_object = MagicMock()
mock_slide_object.get_slide_context.return_value = 'some context'
mock_SlideModel.objects.get.return_value = mock_slide_object
projector_api.register_slide_model(mock_SlideModel, 'some template')
used_args, __ = mock_register_slide.call_args
self.assertEqual(used_args[0], 'mock_callback_name')
# Test the generated slide function
used_args[1](pk=1)
mock_render_to_string.assert_called_with('some template', 'some context')
# Test with non existing object
mock_SlideModel.objects.get.side_effect = Exception
used_args[1](pk=1)
mock_render_to_string.assert_called_with('some template', {'slide': None})
@patch('openslides.projector.api.update_projector_overlay')
@patch('openslides.projector.api.update_projector')
def test_set_active_slide(self, mock_update_projector, mock_update_projector_overlay):
mock_config = {}
with patch('openslides.projector.api.config', mock_config):
projector_api.set_active_slide('callback_name', {'some': 'kwargs'})
self.assertEqual(mock_config,
{'projector_active_slide': {'callback': 'callback_name',
'some': 'kwargs'}})
mock_update_projector.assert_called_with()
mock_update_projector_overlay.assert_called_with(None)
def test_get_active_slide(self):
mock_config = {'projector_active_slide': 'value'}
with patch('openslides.projector.api.config', mock_config):
value = projector_api.get_active_slide()
self.assertEqual(value, 'value')

View File

@ -10,12 +10,62 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.test.client import Client from django.test.client import Client, RequestFactory
from mock import call, patch
from openslides.projector.models import ProjectorSlide from openslides.projector.models import ProjectorSlide
from openslides.projector import views
from openslides.utils.test import TestCase from openslides.utils.test import TestCase
class ProjectorViewTest(TestCase):
rf = RequestFactory()
@patch('openslides.projector.views.get_projector_overlays_js')
@patch('openslides.projector.views.get_projector_overlays')
@patch('openslides.projector.views.get_projector_content')
def test_get(self, mock_get_projector_content, mock_get_projector_overlays,
mock_get_projector_overlays_js):
view = views.ProjectorView()
view.request = self.rf.get('/')
# Test preview
view.kwargs = {'callback': 'slide_callback'}
context = view.get_context_data()
mock_get_projector_content.assert_called_with(
{'callback': 'slide_callback'})
self.assertFalse(context['reload'])
# Test live view
view.kwargs = {}
mock_config = {'projector_js_cache': 'js_cache'}
with patch('openslides.projector.views.config', mock_config):
context = view.get_context_data()
mock_get_projector_content.assert_called_with()
mock_get_projector_overlays.assert_called_with()
mock_get_projector_overlays_js.assert_called_with()
self.assertTrue(context['reload'])
self.assertEqual(context['calls'], 'js_cache')
class ActivateViewTest(TestCase):
rf = RequestFactory()
@patch('openslides.projector.views.config')
@patch('openslides.projector.views.set_active_slide')
def test_get(self, mock_set_active_slide, mock_config):
view = views.ActivateView()
view.request = self.rf.get('/?some_key=some_value')
view.pre_redirect(view.request, callback='some_callback')
mock_set_active_slide.called_with('some_callback',
{'some_key': 'some_value'})
mock_config.get_default.assert_has_calls([call('projector_scroll'),
call('projector_scale')])
self.assertEqual(mock_config.__setitem__.call_count, 2)
class CustomSlidesTest(TestCase): class CustomSlidesTest(TestCase):
def setUp(self): def setUp(self):
self.admin_client = Client() self.admin_client = Client()