wcs/tests/test_mail_templates.py

498 lines
17 KiB
Python

import io
import os
import re
import xml.etree.ElementTree as ET
import pytest
from quixote import cleanup
from webtest import Upload
from wcs.categories import MailTemplateCategory
from wcs.fields import FileField
from wcs.formdef import FormDef
from wcs.mail_templates import MailTemplate
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.ident.password_accounts import PasswordAccount
from wcs.qommon.misc import indent_xml as indent
from wcs.qommon.upload_storage import PicklableUpload
from wcs.workflows import Workflow
from .utilities import clean_temporary_pub, create_temporary_pub, get_app, login
def setup_module(module):
cleanup()
def teardown_module(module):
clean_temporary_pub()
@pytest.fixture
def pub(request):
pub = create_temporary_pub()
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
pub.set_app_dir(req)
pub._set_request(req)
pub.cfg['identification'] = {'methods': ['password']}
pub.write_cfg()
return pub
@pytest.fixture
def superuser(pub):
if pub.user_class.select(lambda x: x.name == 'admin'):
user1 = pub.user_class.select(lambda x: x.name == 'admin')[0]
user1.is_admin = True
user1.store()
return user1
user1 = pub.user_class(name='admin')
user1.is_admin = True
user1.store()
account1 = PasswordAccount(id='admin')
account1.set_password('admin')
account1.user_id = user1.id
account1.store()
return user1
@pytest.fixture
def mail_template():
MailTemplate.wipe()
mail_template = MailTemplate(name='test MT')
mail_template.subject = 'test subject'
mail_template.body = 'test body'
mail_template.store()
return mail_template
def test_mail_templates_basics(pub, superuser):
MailTemplateCategory.wipe()
MailTemplate.wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/')
assert 'Mail Templates' in resp
resp = resp.click('Mail Templates')
assert 'There are no mail templates defined.' in resp
resp = resp.click('New')
resp.form['name'] = 'first mail template'
resp = resp.form.submit('cancel').follow()
assert 'There are no mail templates defined.' in resp
resp = resp.click('New')
resp.form['name'] = 'first mail template'
resp = resp.form.submit('submit').follow()
resp.form['subject'] = 'mail subject'
resp.form['body'] = 'mail body'
resp = resp.form.submit('submit').follow()
resp = resp.click('Edit')
resp.form['subject'] = 'edited mail subject'
resp.form['body'] = 'edited mail body'
resp.form['attachments$element0'] = 'plop'
resp = resp.form.submit('submit').follow()
resp = resp.click('Edit')
assert resp.form['subject'].value == 'edited mail subject'
assert resp.form['body'].value == 'edited mail body'
assert resp.form['attachments$element0'].value == 'plop'
resp = resp.form.submit('submit').follow()
resp = resp.click('Delete')
resp = resp.form.submit('cancel').follow()
assert 'first mail template' in resp
resp = resp.click('Delete')
resp = resp.form.submit('submit').follow()
assert 'first mail template' not in resp
assert 'There are no mail templates defined.' in resp
resp = resp.click('New')
resp.form['name'] = 'first mail template'
resp = resp.form.submit('submit').follow()
resp.form['subject'] = 'mail subject'
resp.form['body'] = 'mail body'
resp = resp.form.submit('submit').follow()
resp = app.get('/backoffice/workflows/')
resp = resp.click('Mail Templates')
assert 'first mail template' in resp
def test_mail_template_in_use(pub, superuser):
Workflow.wipe()
MailTemplate.wipe()
workflow = Workflow(name='test workflow')
st1 = workflow.add_status('Status1')
item = st1.add_action('sendmail')
item.to = ['_receiver']
item.subject = 'Foobar'
item.body = 'Hello'
workflow.store()
mail_template = MailTemplate(name='test mail template')
mail_template.subject = 'test subject'
mail_template.body = 'test body'
mail_template.store()
assert mail_template.is_in_use() is False
item.mail_template = mail_template.slug
workflow.store()
assert mail_template.is_in_use() is True
# check workflow usage is displayed
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/mail-templates/%s/' % mail_template.id)
assert 'Usage in workflows' in resp.text
assert 'test workflow' in resp.text
resp.click('test workflow') # make sure the link is ok
resp = resp.click('Delete')
assert 'still used' in resp.text
def test_admin_workflow_edit(pub, superuser):
MailTemplateCategory.wipe()
Workflow.wipe()
MailTemplate.wipe()
mail_template = MailTemplate(name='test mail template')
mail_template.subject = 'test subject'
mail_template.body = 'test body'
mail_template.store()
workflow = Workflow(name='test mail template')
st1 = workflow.add_status('Status1')
item = st1.add_action('sendmail')
item.to = ['_receiver']
item.subject = 'Foobar'
item.body = 'Hello'
workflow.store()
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (workflow.id, st1.id))
assert [o[0] for o in resp.form['mail_template'].options] == ['', 'test-mail-template']
cat_b = MailTemplateCategory(name='Cat B')
cat_b.store()
mail_template = MailTemplate(name='foo bar')
mail_template.category_id = cat_b.id
mail_template.store()
mail_template = MailTemplate(name='bar foo')
mail_template.category_id = cat_b.id
mail_template.store()
cat_a = MailTemplateCategory(name='Cat A')
cat_a.store()
mail_template = MailTemplate(name='foo baz')
mail_template.category_id = cat_a.id
mail_template.store()
resp = app.get('/backoffice/workflows/%s/status/%s/items/1/' % (workflow.id, st1.id))
assert [o[0] for o in resp.form['mail_template'].options] == [
'',
'foo-baz',
'bar-foo',
'foo-bar',
'test-mail-template',
]
resp.form['mail_template'] = 'test-mail-template'
resp = resp.form.submit('submit')
workflow = Workflow.get(workflow.id)
assert workflow.possible_status[0].items[0].mail_template == 'test-mail-template'
def test_mail_templates_category(pub, superuser):
MailTemplateCategory.wipe()
MailTemplate.wipe()
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/mail-templates/new')
assert 'category_id' not in resp.form.fields
mail_template = MailTemplate(name='foo')
mail_template.store()
resp = app.get('/backoffice/workflows/mail-templates/categories/')
resp = resp.click('New Category')
resp.form['name'] = 'a new category'
resp.form['description'] = 'description of the category'
resp = resp.form.submit('submit')
assert MailTemplateCategory.count() == 1
category = MailTemplateCategory.select()[0]
assert category.name == 'a new category'
resp = app.get('/backoffice/workflows/mail-templates/new')
assert 'category_id' not in resp.form.fields
resp = app.get('/backoffice/workflows/mail-templates/%s/' % mail_template.id)
resp = resp.click(href=re.compile('^edit$'))
resp.form['category_id'] = str(category.id)
resp = resp.form.submit('cancel').follow()
mail_template.refresh_from_storage()
assert mail_template.category_id is None
resp = app.get('/backoffice/workflows/mail-templates/%s/' % mail_template.id)
resp = resp.click(href=re.compile('^edit$'))
resp.form['category_id'] = str(category.id)
resp.form['subject'] = 'mail subject'
resp.form['body'] = 'mail body'
resp = resp.form.submit('submit').follow()
mail_template.refresh_from_storage()
assert str(mail_template.category_id) == str(category.id)
resp = app.get('/backoffice/workflows/mail-templates/%s/' % mail_template.id)
resp = resp.click(href=re.compile('^edit$'))
assert resp.form['category_id'].value == str(category.id)
resp = app.get('/backoffice/workflows/mail-templates/categories/')
resp = resp.click('New Category')
resp.form['name'] = 'a second category'
resp.form['description'] = 'description of the category'
resp = resp.form.submit('submit')
assert MailTemplateCategory.count() == 2
category2 = [x for x in MailTemplateCategory.select() if x.id != category.id][0]
assert category2.name == 'a second category'
app.get(
'/backoffice/workflows/mail-templates/categories/update_order?order=%s;%s;'
% (category2.id, category.id)
)
categories = MailTemplateCategory.select()
MailTemplateCategory.sort_by_position(categories)
assert [x.id for x in categories] == [str(category2.id), str(category.id)]
app.get(
'/backoffice/workflows/mail-templates/categories/update_order?order=%s;%s;'
% (category.id, category2.id)
)
categories = MailTemplateCategory.select()
MailTemplateCategory.sort_by_position(categories)
assert [x.id for x in categories] == [str(category.id), str(category2.id)]
resp = app.get('/backoffice/workflows/mail-templates/categories/')
resp = resp.click('a new category')
resp = resp.click('Delete')
resp = resp.form.submit()
mail_template.refresh_from_storage()
assert not mail_template.category_id
def test_workflow_send_mail_template_with_sql(superuser, emails):
pub = create_temporary_pub()
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
pub.set_app_dir(req)
pub._set_request(req)
Workflow.wipe()
MailTemplate.wipe()
mail_template = MailTemplate(name='test mail template')
mail_template.subject = 'test subject'
mail_template.body = 'test body'
mail_template.store()
workflow = Workflow(name='test mail template')
st1 = workflow.add_status('Status1')
item = st1.add_action('sendmail')
item.to = 'xyz@localhost'
item.subject = 'Foobar'
item.body = 'Hello'
item.mail_template = mail_template.slug
workflow.store()
formdef = FormDef()
formdef.name = 'baz'
formdef.fields = []
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.store()
item.perform(formdata)
pub.get_request().response.process_after_jobs()
assert emails.count() == 1
assert emails.get('test subject')['email_rcpt'] == ['xyz@localhost']
assert 'test body' in emails.get('test subject')['msg'].get_payload(0).get_payload()
# check nothing is sent and an error is logged if the mail template is
# missing
emails.empty()
MailTemplate.wipe()
item.perform(formdata)
pub.get_request().response.process_after_jobs()
assert emails.count() == 0
assert pub.loggederror_class.count() == 1
logged_error = pub.loggederror_class.select()[0]
assert logged_error.summary == 'reference to invalid mail template test-mail-template in status Status1'
def test_workflow_send_mail_template_attachments(pub, superuser, emails):
Workflow.wipe()
MailTemplate.wipe()
mail_template = MailTemplate(name='test mail template')
mail_template.subject = 'test subject'
mail_template.body = 'test body'
mail_template.attachments = ['form_var_file1_raw']
mail_template.store()
workflow = Workflow(name='test mail template')
st1 = workflow.add_status('Status1')
item = st1.add_action('sendmail')
item.to = 'xyz@localhost'
item.subject = 'Foobar'
item.body = 'Hello'
item.mail_template = mail_template.slug
workflow.store()
formdef = FormDef()
formdef.name = 'baz'
formdef.fields = [
FileField(id='1', label='File', type='file', varname='file1'),
]
formdef.store()
upload = PicklableUpload('test.jpeg', 'image/jpeg')
with open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb') as fd:
upload.receive([fd.read()])
formdata = formdef.data_class()()
formdata.data = {'1': upload}
formdata.just_created()
formdata.store()
pub.substitutions.feed(formdata)
item.perform(formdata)
pub.get_request().response.process_after_jobs()
assert emails.count() == 1
payloads = emails.get('test subject')['msg'].get_payload()
assert len(payloads) == 2
assert payloads[1].get_content_type() == 'image/jpeg'
# check two files are sent if mail attachments are also defined on the
# action itself.
emails.empty()
item.attachments = ['form_var_file1_raw']
item.perform(formdata)
pub.get_request().response.process_after_jobs()
payloads = emails.get('test subject')['msg'].get_payload()
assert len(payloads) == 3
assert payloads[1].get_content_type() == 'image/jpeg'
assert payloads[2].get_content_type() == 'image/jpeg'
def test_mail_templates_export(pub, superuser, mail_template):
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/mail-templates/1/')
resp = resp.click(href='export')
xml_export = resp.text
ds = io.StringIO(xml_export)
mail_template2 = MailTemplate.import_from_xml(ds)
assert mail_template2.name == 'test MT'
def test_mail_templates_import(pub, superuser, mail_template):
mail_template.slug = 'foobar'
mail_template.store()
mail_template_xml = ET.tostring(mail_template.export_to_xml(include_id=True))
MailTemplate.wipe()
assert MailTemplate.count() == 0
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/mail-templates/')
resp = resp.click(href='import')
resp.forms[0]['file'] = Upload('mail_template.wcs', mail_template_xml)
resp = resp.forms[0].submit()
assert MailTemplate.count() == 1
assert {wc.slug for wc in MailTemplate.select()} == {'foobar'}
# check slug
resp = app.get('/backoffice/workflows/mail-templates/')
resp = resp.click(href='import')
resp.forms[0]['file'] = Upload('mail_template.wcs', mail_template_xml)
resp = resp.forms[0].submit()
assert MailTemplate.count() == 2
assert {wc.slug for wc in MailTemplate.select()} == {'foobar', 'test-mt'}
resp = app.get('/backoffice/workflows/mail-templates/')
resp = resp.click(href='import')
resp.forms[0]['file'] = Upload('mail_template.wcs', mail_template_xml)
resp = resp.forms[0].submit()
assert MailTemplate.count() == 3
assert {wc.slug for wc in MailTemplate.select()} == {'foobar', 'test-mt', 'test-mt-1'}
# import an invalid file
resp = app.get('/backoffice/workflows/mail-templates/')
resp = resp.click(href='import')
resp.form['file'] = Upload('mail_template.wcs', b'garbage')
resp = resp.form.submit()
assert 'Invalid File' in resp.text
def test_mail_templates_duplicate(pub, superuser, mail_template):
app = login(get_app(pub))
resp = app.get('/backoffice/workflows/mail-templates/1/')
resp = resp.click(href='duplicate')
assert resp.form['name'].value == 'test MT (copy)'
resp = resp.form.submit('cancel').follow()
assert MailTemplate.count() == 1
resp = resp.click(href='duplicate')
assert resp.form['name'].value == 'test MT (copy)'
resp = resp.form.submit('submit').follow()
assert MailTemplate.count() == 2
resp = app.get('/backoffice/workflows/mail-templates/1/')
resp = resp.click(href='duplicate')
assert resp.form['name'].value == 'test MT (copy 2)'
resp.form['name'].value = 'other copy'
resp = resp.form.submit('submit').follow()
assert MailTemplate.count() == 3
assert {x.name for x in MailTemplate.select()} == {'test MT', 'test MT (copy)', 'other copy'}
assert {x.slug for x in MailTemplate.select()} == {'test-mt', 'test-mt-copy', 'other-copy'}
def export_to_indented_xml(mail_template, include_id=False):
mail_template_xml = mail_template.export_to_xml(include_id=include_id)
indent(mail_template_xml)
return mail_template_xml
def assert_import_export_works(mail_template, include_id=False):
mail_template2 = MailTemplate.import_from_xml_tree(
ET.fromstring(ET.tostring(mail_template.export_to_xml(include_id))), include_id
)
assert ET.tostring(export_to_indented_xml(mail_template)) == ET.tostring(
export_to_indented_xml(mail_template2)
)
return mail_template2
def test_mail_template(pub):
mail_template = MailTemplate(name='test')
assert_import_export_works(mail_template, include_id=True)
def test_mail_template_with_category(pub):
category = MailTemplateCategory(name='test category')
category.store()
mail_template = MailTemplate(name='test category')
mail_template.category_id = category.id
mail_template.store()
mail_template2 = assert_import_export_works(mail_template, include_id=True)
assert mail_template2.category_id == mail_template.category_id
# import with non existing category
MailTemplateCategory.wipe()
export = ET.tostring(mail_template.export_to_xml(include_id=True))
mail_template3 = MailTemplate.import_from_xml_tree(ET.fromstring(export), include_id=True)
assert mail_template3.category_id is None