UPD: More and better tests.

This commit is contained in:
2019-03-29 16:56:44 +01:00
parent 80e9271209
commit 4c1c6b48df
6 changed files with 244 additions and 35 deletions

View File

@@ -3,6 +3,7 @@ import os
from django.apps import apps from django.apps import apps
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.core import mail as django_mail
from django.test import SimpleTestCase, TestCase, tag from django.test import SimpleTestCase, TestCase, tag
from django.urls import reverse from django.urls import reverse
from selenium import webdriver from selenium import webdriver
@@ -44,6 +45,15 @@ class EmailTestMixin(object):
email_base_url = 'http://localhost' email_base_url = 'http://localhost'
email_subject_prefix = '[Test]' email_subject_prefix = '[Test]'
def get_mail_for_user(self, user):
recipient = '"{fullname}" <{email}>'.format(fullname=user.get_full_name(), email=user.email)
mails = []
for mail in django_mail.outbox:
if recipient in mail.recipients():
mails.append(mail)
return mails
def assertSender(self, mail): def assertSender(self, mail):
self.assertEqual(mail.from_email, self.email_sender) self.assertEqual(mail.from_email, self.email_sender)

View File

@@ -35,9 +35,10 @@ class TemplatesTestCase(SimpleTestCase):
'<script type="text/javascript" src="{static_url}dav_base/bootstrap/js/bootstrap.min.js"></script>', '<script type="text/javascript" src="{static_url}dav_base/bootstrap/js/bootstrap.min.js"></script>',
) )
content = response.content.decode('utf-8')
for needle in html_needles: for needle in html_needles:
needle = needle.format(static_url=static_url) needle = needle.format(static_url=static_url)
self.assertInHTML(needle, response.content.decode('utf-8')) self.assertInHTML(needle, content)
def test_page_footer(self): def test_page_footer(self):
response = self.response_from_root_view response = self.response_from_root_view

View File

@@ -1,7 +1,12 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import apps from django.apps import apps
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from ..models.event import Event
from ..models.eventstatus import EventStatus
class RoleMixin(object): class RoleMixin(object):
def create_user_for_role(self, role_name, password, first_name, last_name): def create_user_for_role(self, role_name, password, first_name, last_name):
@@ -20,3 +25,21 @@ class RoleMixin(object):
setattr(app_config.settings, setting_name, [role_name]) setattr(app_config.settings, setting_name, [role_name])
return user return user
class EventMixin(object):
def get_status_label(self, status_code):
return EventStatus.objects.get(code=status_code).label
def create_event(self, data):
event = Event(**data)
event.save()
return event
def submit_event(self, event):
event.workflow.update_status('submitted', event.owner)
return event
def accept_event(self, event, user):
event.workflow.update_status('accepted', user)
return event

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime import datetime
from django.apps import apps from django.apps import apps
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@@ -7,25 +8,24 @@ from django.test import TestCase
from dav_base.tests.generic import EmailTestMixin from dav_base.tests.generic import EmailTestMixin
from ..models.event import Event
from ..models.oneclickaction import OneClickAction from ..models.oneclickaction import OneClickAction
from .generic import RoleMixin from .generic import RoleMixin, EventMixin
TEST_EVENT_DATA = { TEST_EVENT_DATA = {
'title': u'Täst', 'title': 'Täst',
'description': u'Teßt', 'description': 'Teßt',
'mode': 'joint', 'mode': 'joint',
'sport': 'W', 'sport': 'W',
'level': 'beginner', 'level': 'beginner',
'first_day': datetime.date(2019, 3, 1), 'first_day': datetime.date(2019, 3, 1),
'country': 'DE', 'country': 'DE',
'trainer_firstname': u'Übungsleiter', 'trainer_firstname': 'Übungsleiter',
'trainer_familyname': u'Weißalles', 'trainer_familyname': 'Weißalles',
'trainer_email': 'trainer@localhost', 'trainer_email': 'trainer@localhost',
} }
EVENT_UPDATED_EMAIL_TEMPLATE = u"""Hallo {recipient_first_name}, EVENT_UPDATED_EMAIL_TEMPLATE = """Hallo {recipient_first_name},
{editor_full_name} hat die folgende Veranstaltung geändert: {editor_full_name} hat die folgende Veranstaltung geändert:
{event} {event}
@@ -53,7 +53,7 @@ Link zur Veranstaltung:
Veröffentlichung: sofort Veröffentlichung: sofort
""" """
EVENT_SUBMITTED_EMAIL_TEMPLATE = u"""Hallo {recipient_first_name}, EVENT_SUBMITTED_EMAIL_TEMPLATE = """Hallo {recipient_first_name},
eine Veranstaltung wurde in deinem Namen eingereicht. eine Veranstaltung wurde in deinem Namen eingereicht.
Die entsprechenden Referenten wurden informiert, um deine Veranstaltung frei zu geben. Die entsprechenden Referenten wurden informiert, um deine Veranstaltung frei zu geben.
@@ -67,7 +67,7 @@ Ausschreibung:
============== ==============
{event_text}""" {event_text}"""
EVENT_TO_ACCEPT_EMAIL_TEMPLATE = u"""Hallo {recipient_first_name}, EVENT_TO_ACCEPT_EMAIL_TEMPLATE = """Hallo {recipient_first_name},
{trainer_firstname} {trainer_familyname} hat eine Veranstaltung eingereicht. {trainer_firstname} {trainer_familyname} hat eine Veranstaltung eingereicht.
@@ -99,7 +99,7 @@ Bearbeitungshinweis:
==================== ====================
{internal_note}""" {internal_note}"""
EVENT_TO_PUBLISH_WEB_EMAIL_TEMPLATE = u"""Hallo {recipient_first_name}, EVENT_TO_PUBLISH_WEB_EMAIL_TEMPLATE = """Hallo {recipient_first_name},
{trainer_firstname} {trainer_familyname} hat eine neue Veranstaltung eingereicht. {trainer_firstname} {trainer_familyname} hat eine neue Veranstaltung eingereicht.
Die Veranstaltung wurde von {editor_full_name} zur Veröffentlichung Die Veranstaltung wurde von {editor_full_name} zur Veröffentlichung
@@ -132,7 +132,7 @@ Joomla HTML
</p> </p>
""" """
EVENT_TO_PUBLISH_FACEBOOK_EMAIL_TEMPLATE = u"""Hallo {recipient_first_name}, EVENT_TO_PUBLISH_FACEBOOK_EMAIL_TEMPLATE = """Hallo {recipient_first_name},
{trainer_firstname} {trainer_familyname} hat eine neue Veranstaltung eingereicht. {trainer_firstname} {trainer_familyname} hat eine neue Veranstaltung eingereicht.
Die Veranstaltung wurde von {editor_full_name} zur Veröffentlichung Die Veranstaltung wurde von {editor_full_name} zur Veröffentlichung
@@ -154,7 +154,7 @@ Ausschreibung:
{event_text}""" {event_text}"""
class EmailTestCase(EmailTestMixin, RoleMixin, TestCase): class EmailTestCase(EmailTestMixin, RoleMixin, EventMixin, TestCase):
def setUp(self): def setUp(self):
super(EmailTestCase, self).setUp() super(EmailTestCase, self).setUp()
@@ -164,8 +164,7 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
self.app_settings = app_config.settings self.app_settings = app_config.settings
event_data = TEST_EVENT_DATA event_data = TEST_EVENT_DATA
self.event = Event(**event_data) self.event = self.create_event(event_data)
self.event.save()
self.trainer = self.event.owner self.trainer = self.event.owner
self.manager_super = self.create_user_for_role('manager_super', 'password', 'Touren', 'Referent') self.manager_super = self.create_user_for_role('manager_super', 'password', 'Touren', 'Referent')
@@ -177,20 +176,20 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
model = get_user_model() model = get_user_model()
self.recipient = model.objects.create_user(username='recipient@example.com', self.recipient = model.objects.create_user(username='recipient@example.com',
email='recipient@example.com', email='recipient@example.com',
password=u'mellon12', password='mellon12',
first_name=u'Re Ö.', first_name='Re Ö.',
last_name=u'Cipient', last_name='Cipient',
) )
self.editor = model.objects.create_user(username='editor@example.com', self.editor = model.objects.create_user(username='editor@example.com',
email='editor@example.com', email='editor@example.com',
password=u'mellon12', password='mellon12',
first_name=u'Ed Ü.', first_name='Ed Ü.',
last_name=u'Itor', last_name='Itor',
) )
def test_disabled_mail(self): def test_disabled_mail(self):
self.event.workflow.update_status('submitted', self.trainer) self.event.workflow.update_status('submitted', self.trainer)
self.event.description += u' Gößweinstein' self.event.description += ' Gößweinstein'
self.event.save() self.event.save()
self.event.workflow.update_status('accepted', self.editor) self.event.workflow.update_status('accepted', self.editor)
self.event.first_day += datetime.timedelta(1) self.event.first_day += datetime.timedelta(1)
@@ -203,14 +202,14 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
self.app_settings.enable_email_on_update = True self.app_settings.enable_email_on_update = True
self.event.workflow.update_status('submitted', self.trainer) self.event.workflow.update_status('submitted', self.trainer)
self.event.description += u' Gößweinstein' self.event.description += ' Gößweinstein'
self.event.save() self.event.save()
self.assertEqual(len(django_mail.outbox), 2) self.assertEqual(len(django_mail.outbox), 2)
mail = django_mail.outbox[0] mail = django_mail.outbox[0]
self.assertSender(mail) self.assertSender(mail)
self.assertRecipients(mail, [expected_recipient]) self.assertRecipients(mail, [expected_recipient])
self.assertSubject(mail, u'Veranstaltung geändert') self.assertSubject(mail, 'Veranstaltung geändert')
expected_body = EVENT_UPDATED_EMAIL_TEMPLATE.format( expected_body = EVENT_UPDATED_EMAIL_TEMPLATE.format(
recipient_first_name=expected_recipient.first_name, recipient_first_name=expected_recipient.first_name,
@@ -231,7 +230,7 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
mail = django_mail.outbox[0] mail = django_mail.outbox[0]
self.assertSender(mail) self.assertSender(mail)
self.assertRecipients(mail, [expected_recipient]) self.assertRecipients(mail, [expected_recipient])
self.assertSubject(mail, u'Veranstaltung eingereicht') self.assertSubject(mail, 'Veranstaltung eingereicht')
expected_body = EVENT_SUBMITTED_EMAIL_TEMPLATE.format( expected_body = EVENT_SUBMITTED_EMAIL_TEMPLATE.format(
recipient_first_name=expected_recipient.first_name, recipient_first_name=expected_recipient.first_name,
@@ -251,7 +250,7 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
mail = django_mail.outbox[1] mail = django_mail.outbox[1]
self.assertSender(mail) self.assertSender(mail)
self.assertRecipients(mail, [expected_recipient]) self.assertRecipients(mail, [expected_recipient])
self.assertSubject(mail, u'Veranstaltung freigeben') self.assertSubject(mail, 'Veranstaltung freigeben')
action_parameters = '{},{},{}'.format(self.event.id, 'accepted', expected_recipient.id) action_parameters = '{},{},{}'.format(self.event.id, 'accepted', expected_recipient.id)
action = OneClickAction.objects.get(parameters=action_parameters) action = OneClickAction.objects.get(parameters=action_parameters)
@@ -272,9 +271,9 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
editor = self.manager_w editor = self.manager_w
self.event.workflow.update_status('submitted', self.trainer) self.event.workflow.update_status('submitted', self.trainer)
self.event.internal_note = u'Automatischer Software Test.' self.event.internal_note = 'Automatischer Software Test.'
self.event.planned_publication_date = datetime.date(2019, 3, 24) self.event.planned_publication_date = datetime.date(2019, 3, 24)
ppd_string = u'Sonntag, 24. März 2019' ppd_string = 'Sonntag, 24. März 2019'
self.event.save() self.event.save()
self.app_settings.enable_email_on_status_update = True self.app_settings.enable_email_on_status_update = True
@@ -284,7 +283,7 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
mail = django_mail.outbox[0] mail = django_mail.outbox[0]
self.assertSender(mail) self.assertSender(mail)
self.assertRecipients(mail, [expected_recipient]) self.assertRecipients(mail, [expected_recipient])
self.assertSubject(mail, u'{}: Veranstaltung freigegeben'.format(self.event.number)) self.assertSubject(mail, '{}: Veranstaltung freigegeben'.format(self.event.number))
expected_body = EVENT_ACCEPTED_EMAIL_TEMPLATE.format( expected_body = EVENT_ACCEPTED_EMAIL_TEMPLATE.format(
recipient_first_name=expected_recipient.first_name, recipient_first_name=expected_recipient.first_name,
@@ -302,9 +301,9 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
editor = self.manager_w editor = self.manager_w
self.event.workflow.update_status('submitted', self.trainer) self.event.workflow.update_status('submitted', self.trainer)
self.event.internal_note = u'Automatischer Software Test.' self.event.internal_note = 'Automatischer Software Test.'
self.event.planned_publication_date = datetime.date(2019, 3, 24) self.event.planned_publication_date = datetime.date(2019, 3, 24)
ppd_string = u'Sonntag, 24. März 2019' ppd_string = 'Sonntag, 24. März 2019'
self.event.save() self.event.save()
self.app_settings.enable_email_on_status_update = True self.app_settings.enable_email_on_status_update = True
@@ -314,7 +313,7 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
mail = django_mail.outbox[1] mail = django_mail.outbox[1]
self.assertSender(mail) self.assertSender(mail)
self.assertRecipients(mail, [expected_recipient]) self.assertRecipients(mail, [expected_recipient])
self.assertSubject(mail, u'{}: Veranstaltung veröffentlichen'.format(self.event.number)) self.assertSubject(mail, '{}: Veranstaltung veröffentlichen'.format(self.event.number))
action_parameters = '{},{},{}'.format(self.event.id, 'publishing_web', expected_recipient.id) action_parameters = '{},{},{}'.format(self.event.id, 'publishing_web', expected_recipient.id)
action = OneClickAction.objects.get(parameters=action_parameters) action = OneClickAction.objects.get(parameters=action_parameters)
@@ -352,7 +351,7 @@ class EmailTestCase(EmailTestMixin, RoleMixin, TestCase):
mail = django_mail.outbox[2] mail = django_mail.outbox[2]
self.assertSender(mail) self.assertSender(mail)
self.assertRecipients(mail, [expected_recipient]) self.assertRecipients(mail, [expected_recipient])
self.assertSubject(mail, u'{}: Veranstaltung veröffentlichen'.format(self.event.number)) self.assertSubject(mail, '{}: Veranstaltung veröffentlichen'.format(self.event.number))
action_parameters = '{},{},{}'.format(self.event.id, 'publishing_facebook', expected_recipient.id) action_parameters = '{},{},{}'.format(self.event.id, 'publishing_facebook', expected_recipient.id)
action = OneClickAction.objects.get(parameters=action_parameters) action = OneClickAction.objects.get(parameters=action_parameters)

View File

@@ -0,0 +1,176 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime
import re
from django.apps import apps
from django.test import TestCase
from django.urls import reverse
from django.utils.translation import ugettext
from dav_base.tests.generic import EmailTestMixin
from ..models.oneclickaction import OneClickAction
from .generic import RoleMixin, EventMixin
TEST_EVENT_DATA = {
'title': 'Täst',
'description': 'Teßt',
'mode': 'joint',
'sport': 'W',
'level': 'beginner',
'first_day': datetime.date(2019, 3, 1),
'country': 'DE',
'trainer_firstname': 'Übungsleiter',
'trainer_familyname': 'Weißalles',
'trainer_email': 'trainer@localhost',
}
class ActionTestCase(EmailTestMixin, RoleMixin, EventMixin, TestCase):
def _get_oneclick_url_from_mail(self, mail):
uuid_pattern = '[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12}'
pseudo_uuid = 'abcdef12-1234-abcd-1234-abcdef123456'
pseudo_url_path = reverse('dav_events:action_run', kwargs={'pk': pseudo_uuid})
url_path_pattern = pseudo_url_path.replace(pseudo_uuid, uuid_pattern)
url_pattern = r'{}({})'.format(self.email_base_url, url_path_pattern)
match = re.search(url_pattern, mail.body)
if match:
url = match.groups()[0]
else: # pragma: no cover
url = None
return url
def _get_uuid_from_url(self, url):
uuid_pattern = r'([a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})'
match = re.search(uuid_pattern, url)
if match:
uuid = match.groups()[0]
else: # pragma: no cover
uuid = None
return uuid
def _test_status_update(self, status_code, user):
event = self.create_event(TEST_EVENT_DATA)
self.submit_event(event)
if status_code in ('publishing_web', 'publishing_facebook'):
self.accept_event(event, user)
mails = self.get_mail_for_user(user)
self.assertEqual(len(mails), 1)
mail = mails[0]
action_url = self._get_oneclick_url_from_mail(mail)
self.assertNotEqual(action_url, None)
uuid = self._get_uuid_from_url(action_url)
self.assertNotEqual(uuid, None)
action = OneClickAction.objects.get(id=uuid)
action_command = 'EVENT_STATUS_UPDATE'
action_parameters = [str(event.id), status_code, str(user.id)]
self._assertAction(action, command=action_command, parameters=action_parameters, url=action_url)
response = self.client.get(action_url)
self.assertEqual(response.status_code, 200)
content = response.content.decode('utf-8')
status_label = self.get_status_label(status_code)
message = ugettext('Der Status wurde auf \'%(status)s\' gesetzt.') % {'status': status_label}
html = message.replace('\'', '&#39;')
self.assertInHTML(html, content)
self.assertRegex(content, r'alert-success')
self.assertTrue(event.workflow.has_reached_status(status_code))
action.refresh_from_db()
self.assertTrue(action.done)
def _assertAction(self, action, command=None, parameters=None, url=None):
if command:
self.assertEqual(action.command, command)
if parameters:
if isinstance(parameters, list):
parameters = ','.join(parameters)
self.assertEqual(action.parameters, parameters)
if url:
self.assertEqual(action.get_absolute_url(), url)
def _assertRepeated(self, response):
self.assertEqual(response.status_code, 200)
content = response.content.decode('utf-8')
html = ugettext('Diese Aktion hast du bereits ausgeführt.')
self.assertInHTML(html, content)
self.assertRegex(content, r'alert-warning')
def _assertAlready(self, response, status_code, user):
self.assertEqual(response.status_code, 200)
content = response.content.decode('utf-8')
status_label = self.get_status_label(status_code)
message = (ugettext('Der Status wurde bereits'
' am %(date)s'
' von %(user)s'
' auf \'%(status)s\' gesetzt.') % {
'status': status_label,
'date': datetime.datetime.now().strftime('%d.%m.%Y %H:%M:%S'),
'user': user.get_full_name(),
})
html = message.replace('\'', '&#39;')
self.assertInHTML(html, content)
self.assertRegex(content, r'alert-success')
def setUp(self):
super(ActionTestCase, self).setUp()
app_config = apps.get_containing_app_config(__package__)
app_config.settings.enable_email_on_status_update = True
self.manager_super = self.create_user_for_role('manager_super', 'password', 'Touren', 'Referent')
self.manager_w = self.create_user_for_role('manager_w', 'password', 'Bereichsleiter', 'Wandern')
self.publisher_web = self.create_user_for_role('publisher_web', 'password', 'Joomla', 'Redakteur')
self.publisher_facebook = self.create_user_for_role('publisher_facebook', 'password', 'Facebook', 'Redakteur')
def test_accept_by_manager_super(self):
self._test_status_update('accepted', self.manager_super)
def test_accept_by_manager_sub(self):
self._test_status_update('accepted', self.manager_w)
def test_accept_repeated(self):
event = self.create_event(TEST_EVENT_DATA)
self.submit_event(event)
action_parameters = '{},accepted,{}'.format(event.id, self.manager_super.id)
action = OneClickAction.objects.get(command='EVENT_STATUS_UPDATE', parameters=action_parameters)
action_url = action.get_absolute_url()
self.client.get(action_url)
response = self.client.get(action_url)
self._assertRepeated(response)
def test_accepted_already(self):
event = self.create_event(TEST_EVENT_DATA)
self.submit_event(event)
action_parameters = '{},accepted,{}'.format(event.id, self.manager_super.id)
action = OneClickAction.objects.get(command='EVENT_STATUS_UPDATE', parameters=action_parameters)
action_url = action.get_absolute_url()
self.client.get(action_url)
action_parameters = '{},accepted,{}'.format(event.id, self.manager_w.id)
action = OneClickAction.objects.get(command='EVENT_STATUS_UPDATE', parameters=action_parameters)
action_url = action.get_absolute_url()
response = self.client.get(action_url)
self._assertAlready(response, 'accepted', self.manager_super)
def test_publishing_by_publisher_web(self):
self._test_status_update('publishing_web', self.publisher_web)
def test_publishing_by_publisher_facebook(self):
self._test_status_update('publishing_facebook', self.publisher_facebook)

View File

@@ -427,7 +427,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
self.wait_until_stale(c, button) self.wait_until_stale(c, button)
except NoSuchElementException: except NoSuchElementException:
break break
else: else: # pragma: no cover
self.fail('Too many sub forms') self.fail('Too many sub forms')
if 'internal_note' in data: if 'internal_note' in data:
@@ -500,7 +500,7 @@ class TestCase(SeleniumAuthMixin, RoleMixin, ScreenshotTestCase):
button.click() button.click()
self.wait_until_stale(c, button) self.wait_until_stale(c, button)
else: else: # pragma: no cover
self.fail('Too many sub forms') self.fail('Too many sub forms')
if screenshots: if screenshots: