wcs/tests/test_misc.py

741 lines
27 KiB
Python

# -*- coding: utf-8 -*-
import base64
import datetime
import json
import os
import pickle
import pwd
import re
import socket
import time
import mock
import pytest
from django.core.cache import cache
from django.utils import translation
from quixote import cleanup
from utilities import clean_temporary_pub, create_temporary_pub, get_app
import wcs.api # workaround against circular dependencies :/
import wcs.qommon.storage
from wcs.admin.settings import FileTypesDirectory
from wcs.fields import StringField
from wcs.qommon import evalutils, force_str
from wcs.qommon.backoffice.listing import pagination_links
from wcs.qommon.emails import docutils
from wcs.qommon.emails import email as send_email
from wcs.qommon.form import FileSizeWidget
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.humantime import humanduration2seconds, seconds2humanduration
from wcs.qommon.misc import (
date_format,
ellipsize,
format_time,
get_as_datetime,
json_loads,
normalize_geolocation,
parse_isotime,
simplify,
)
from wcs.qommon.upload_storage import PicklableUpload
from wcs.scripts import Script
from wcs.wf.jump import JumpWorkflowStatusItem
from wcs.workflows import Workflow
def setup_module(module):
cleanup()
def teardown_module(module):
clean_temporary_pub()
def test_parse_file_size():
assert FileSizeWidget.parse_file_size('17') == 17
assert FileSizeWidget.parse_file_size('17o') == 17
assert FileSizeWidget.parse_file_size('17 K') == 17 * 10 ** 3
assert FileSizeWidget.parse_file_size('17 M') == 17 * 10 ** 6
assert FileSizeWidget.parse_file_size('17 Mo') == 17 * 10 ** 6
assert FileSizeWidget.parse_file_size('17 MB') == 17 * 10 ** 6
assert FileSizeWidget.parse_file_size('17 Kio') == 17 * 2 ** 10
assert FileSizeWidget.parse_file_size('17 Mio') == 17 * 2 ** 20
assert FileSizeWidget.parse_file_size('17K') == 17 * 10 ** 3
assert FileSizeWidget.parse_file_size('17 K') == 17 * 10 ** 3
assert FileSizeWidget.parse_file_size(' 17 K ') == 17 * 10 ** 3
def test_parse_invalid_file_size():
for test_value in ('17i', 'hello', '0.4K', '2G'):
with pytest.raises(ValueError):
FileSizeWidget.parse_file_size(test_value)
@pytest.mark.parametrize(
'seconds, expected',
[
(1, '1 second'),
(3, '3 seconds'),
(100000, '1 day, 3 hours, 46 minutes and 40 seconds'),
(13, '13 seconds'),
(60, '1 minute'),
(3600, '1 hour'),
],
)
def test_humantime(seconds, expected):
pub = create_temporary_pub()
pub.ngettext = translation.ngettext
assert seconds2humanduration(seconds) == expected
assert humanduration2seconds(seconds2humanduration(seconds)) == seconds
def test_parse_mimetypes():
assert FileTypesDirectory.parse_mimetypes('application/pdf') == ['application/pdf']
assert FileTypesDirectory.parse_mimetypes('.pdf') == ['application/pdf']
assert set(FileTypesDirectory.parse_mimetypes('.pdf, .odt')) == set(
['application/pdf', 'application/vnd.oasis.opendocument.text']
)
def test_format_mimetypes():
assert FileTypesDirectory.format_mimetypes(['application/pdf']) == 'application/pdf (.pdf)'
assert (
FileTypesDirectory.format_mimetypes(['application/pdf', 'text/rtf'])
== 'application/pdf (.pdf), text/rtf'
)
assert FileTypesDirectory.format_mimetypes(['application/pdf', 'application/msword']) in (
'application/pdf (.pdf), application/msword (.doc)',
'application/pdf (.pdf), application/msword (.dot)',
'application/pdf (.pdf), application/msword (.wiz)',
)
assert (
FileTypesDirectory.format_mimetypes(
[
'application/pdf',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/msword',
]
)
== 'application/pdf (.pdf), '
'application/vnd.openxmlformats-officedocument.wordprocessingml.document (.docx)'
'...'
)
def test_simplify_unchanged():
assert simplify('test') == 'test'
assert simplify('another-test') == 'another-test'
assert simplify('another_test', '_') == 'another_test'
def test_simplify_space():
assert simplify('test again') == 'test-again'
assert simplify(' test again ') == 'test-again'
assert simplify('test again', '_') == 'test_again'
assert simplify(' test again ', '_') == 'test_again'
def test_simplify_apostrophes():
assert simplify('test\'again') == 'test-again'
assert simplify('test\'\'\'again') == 'test-again'
def test_simplify_accented():
assert simplify(u'cliché') == 'cliche'
def test_simplify_remove():
assert simplify('this is: (a) "test"') == 'this-is-a-test'
assert simplify('a test; again?') == 'a-test-again'
def test_simplify_mix():
assert simplify(u' this is: (a) "cliché" ') == 'this-is-a-cliche'
assert simplify(u' À "cliché"; again? ') == 'a-cliche-again'
def test_json_str_decoder():
json_str = json.dumps({'lst': [{'a': 'b'}, 1, 2], 'bla': u'éléphant'})
assert type(list(json_loads(json_str).keys())[0]) is str
assert type(json_loads(json_str)['lst'][0]['a']) is str
assert type(json_loads(json_str)['bla']) is str
assert json_loads(json_str)['bla'] == force_str(u'éléphant')
def test_format_time():
assert format_time(None, '%(month_name)s') == '?'
assert format_time(1500000000, '%(month_name)s') == 'July'
assert format_time(1500000000, '%(month_name)s', gmtime=True) == 'July'
assert format_time(1500000000, '%(hour)s') == '4'
assert format_time(1500000000, '%(hour)s', gmtime=True) == '2'
assert format_time((2016, 8), '%(month)s') == '8'
assert format_time((2016, 8, 2), '%(month)s') == '8'
assert (
format_time(
time.localtime(
1500000000,
),
'%(month)s',
)
== '7'
)
assert (
format_time(
time.localtime(
1500000000,
),
'%(weekday_name)s',
)
== 'Friday'
)
def test_parse_isotime():
assert 1420107019 == parse_isotime('2015-01-01T10:10:19Z')
assert 1420107019 == parse_isotime('2015-01-01T10:10:19+00:00Z')
with pytest.raises(ValueError):
parse_isotime('2015-01-01T10:10:19')
with pytest.raises(ValueError):
parse_isotime('2015-01-0110:10:19Z')
def test_script_substitution_variable():
pub = create_temporary_pub()
pub.substitutions.feed(pub)
variables = pub.substitutions.get_context_variables()
with pytest.raises(AttributeError):
assert variables['script'].hello_world()
os.mkdir(os.path.join(pub.app_dir, 'scripts'))
fd = open(os.path.join(pub.app_dir, 'scripts', 'hello_world.py'), 'w')
fd.write('"""docstring"""\nresult = "hello world"')
fd.close()
assert variables['script'].hello_world() == 'hello world'
assert Script('hello_world').__doc__ == 'docstring'
os.mkdir(os.path.join(pub.APP_DIR, 'scripts'))
fd = open(os.path.join(pub.APP_DIR, 'scripts', 'hello_world.py'), 'w')
fd.write('result = "hello global world"')
fd.close()
assert variables['script'].hello_world() == 'hello world'
os.unlink(os.path.join(pub.app_dir, 'scripts', 'hello_world.py'))
assert variables['script'].hello_world() == 'hello global world'
fd = open(os.path.join(pub.app_dir, 'scripts', 'hello_world.py'), 'w')
fd.write('result = site_url')
fd.close()
assert variables['script'].hello_world() == 'http://example.net'
def test_default_charset():
pub = create_temporary_pub()
resp = get_app(pub).get('/')
assert 'utf-8' in resp.headers['Content-Type']
def test_age_in_years():
create_temporary_pub()
assert evalutils.age_in_years('2000-01-01', '2016-05-26') == 16
assert evalutils.age_in_years(datetime.date(2000, 1, 1), '2016-05-26') == 16
assert evalutils.age_in_years(time.struct_time((2000, 1, 1, 0, 0, 0, 0, 0, 0)), '2016-05-26') == 16
assert evalutils.age_in_years('2000-06-01', '2016-05-26') == 15
assert evalutils.age_in_years('2000-02-29', '2016-02-29') == 16
assert evalutils.age_in_years('2000-02-28', '2016-02-29') == 16
assert evalutils.age_in_years('2000-03-01', '2016-02-29') == 15
assert evalutils.age_in_years('2000-01-01') >= 16
def test_age_in_years_and_months():
create_temporary_pub()
assert evalutils.age_in_years_and_months('2000-01-01', '2016-05-26') == (16, 4)
assert evalutils.age_in_years_and_months('2000-01-01', datetime.date(2016, 5, 26)) == (16, 4)
assert evalutils.age_in_years_and_months(datetime.date(2000, 1, 1), '2016-05-26') == (16, 4)
assert evalutils.age_in_years_and_months(
time.struct_time((2000, 1, 1, 0, 0, 0, 0, 0, 0)), '2016-05-26'
) == (16, 4)
assert evalutils.age_in_years_and_months('2000-06-01', '2016-05-26') == (15, 11)
assert evalutils.age_in_years_and_months('2000-02-29', '2016-02-29') == (16, 0)
assert evalutils.age_in_years_and_months('2000-02-28', '2016-02-29') == (16, 0)
assert evalutils.age_in_years_and_months('2000-03-01', '2016-02-29') == (15, 11)
assert evalutils.age_in_years_and_months('2000-01-01') >= (16, 0)
def test_age_in_days():
assert evalutils.age_in_days('2000-01-01', '2001-01-01') == 366
assert evalutils.age_in_days(datetime.date(2000, 1, 1), '2001-01-01') == 366
assert evalutils.age_in_days(time.struct_time((2000, 1, 1, 0, 0, 0, 0, 0, 0)), '2001-01-01') == 366
assert evalutils.age_in_days('2001-01-01', '2002-01-01') == 365
def test_age_in_seconds():
assert evalutils.age_in_seconds('2000-01-01 00:00', '2000-01-01 01:00') == 3600
assert evalutils.age_in_seconds('2000-01-01', '2000-01-01 01:00') == 3600
assert evalutils.age_in_seconds(datetime.date(2000, 1, 1), '2000-01-01 01:00') == 3600
assert (
evalutils.age_in_seconds(time.struct_time((2000, 1, 1, 0, 0, 0, 0, 0, 0)), '2000-01-01 01:00') == 3600
)
def test_date_format():
pub = create_temporary_pub()
pub.cfg['language'] = {}
pub.write_cfg()
orig_environ = os.environ.copy()
try:
if 'LC_TIME' in os.environ:
del os.environ['LC_TIME']
if 'LC_ALL' in os.environ:
del os.environ['LC_ALL']
assert date_format() == '%Y-%m-%d'
os.environ['LC_ALL'] = 'nl_BE.UTF-8'
assert date_format() == '%Y-%m-%d'
os.environ['LC_ALL'] = 'fr_BE.UTF-8'
assert date_format() == '%d/%m/%Y'
os.environ['LC_TIME'] = 'nl_BE.UTF-8'
assert date_format() == '%Y-%m-%d'
pub.cfg['language'] = {'language': 'fr'}
assert date_format() == '%d/%m/%Y'
finally:
os.environ = orig_environ
def test_get_as_datetime():
pub = create_temporary_pub()
datetime_value = datetime.datetime(2017, 4, 25, 12, 0)
assert get_as_datetime('2017-04-25 12:00') == datetime_value
assert get_as_datetime('2017-04-25 12:00:00') == datetime_value
assert get_as_datetime('2017-04-25T12:00:00Z') == datetime_value
assert get_as_datetime('2017-04-25T12:00:00') == datetime_value
assert get_as_datetime('25/04/2017 12:00') == datetime_value
def test_pagination():
pub = create_temporary_pub()
req = HTTPRequest(None, {'SERVER_NAME': 'example.net', 'SCRIPT_NAME': ''})
req.response.filter = {}
pub.form = {'ajax': 'true'}
pub._set_request(req)
def get_texts(s):
return [x for x in re.findall(r'>(.*?)<', str(s)) if x.strip()]
assert get_texts(pagination_links(0, 10, 0)) == ['1', '(0-0/0)', 'Per page: ', '10']
assert get_texts(pagination_links(0, 10, 10)) == ['1', '(1-10/10)', 'Per page: ', '10']
assert get_texts(pagination_links(0, 10, 20)) == ['1', '2', '(1-10/20)', 'Per page: ', '10', '20']
assert get_texts(pagination_links(10, 10, 20)) == ['1', '2', '(11-20/20)', 'Per page: ', '10', '20']
assert get_texts(pagination_links(10, 10, 50)) == [
'1',
'2',
'3',
'4',
'5',
'(11-20/50)',
'Per page: ',
'10',
'20',
'50',
]
assert get_texts(pagination_links(10, 10, 500)) == [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'&#8230;',
'50',
'(11-20/500)',
'Per page: ',
'10',
'20',
'50',
'100',
]
assert get_texts(pagination_links(100, 10, 500)) == [
'1',
'&#8230;',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'&#8230;',
'50',
'(101-110/500)',
'Per page: ',
'10',
'20',
'50',
'100',
]
assert get_texts(pagination_links(100, 20, 500)) == [
'1',
'&#8230;',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'&#8230;',
'25',
'(101-120/500)',
'Per page: ',
'10',
'20',
'50',
'100',
]
# check limit
assert '(1-10/1000)' in get_texts(pagination_links(0, 10, 1000))
assert '(1-100/1000)' in get_texts(pagination_links(0, 100, 1000))
assert '(1-100/1000)' in get_texts(pagination_links(0, 101, 1000)) # 100 is the max
# new default pagination, more than 100
if not pub.site_options.has_section('options'):
pub.site_options.add_section('options')
pub.site_options.set('options', 'default-page-size', '500')
fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
pub.site_options.write(fd)
fd.close()
assert '(1-101/1000)' in get_texts(pagination_links(0, 101, 1000))
assert '(1-500/1000)' in get_texts(pagination_links(0, 500, 1000))
assert '(1-500/1000)' in get_texts(pagination_links(0, 501, 1000)) # 500 is the max
def test_email_signature_plain(emails):
pub = create_temporary_pub()
pub.cfg['emails'] = {'footer': 'Footer\nText'}
send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
assert emails.count() == 1
assert not emails.emails['test']['msg'].is_multipart()
assert b'Footer\nText' in emails.emails['test']['msg'].get_payload(decode=True)
def test_email_from(emails):
pub = create_temporary_pub()
send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
assert emails.count() == 1
assert emails.emails['test']['from'] == '%s@%s' % (pwd.getpwuid(os.getuid())[0], socket.getfqdn())
pub.cfg['emails'] = {'from': 'foo@localhost'}
send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
assert emails.count() == 1
assert emails.emails['test']['from'] == 'foo@localhost'
assert emails.emails['test']['msg']['From'] == 'foo@localhost'
if not pub.site_options.has_section('variables'):
pub.site_options.add_section('variables')
pub.site_options.set('variables', 'global_title', 'HELLO')
send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
assert emails.count() == 1
assert emails.emails['test']['from'] == 'foo@localhost'
assert emails.emails['test']['msg']['From'] in (
'=?utf-8?q?HELLO?= <foo@localhost>',
'HELLO <foo@localhost>',
)
@pytest.mark.skipif('docutils is None')
def test_email_signature_rst(emails):
pub = create_temporary_pub()
pub.cfg['emails'] = {'footer': 'Footer\nText'}
send_email('test', mail_body='Hello', email_rcpt='test@localhost')
assert emails.count() == 1
assert emails.emails['test']['msg'].is_multipart()
assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
assert b'Footer\nText' in emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
assert b'>Footer<' in emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
@pytest.mark.skipif('docutils is None')
def test_email_signature_rst_pipes(emails):
pub = create_temporary_pub()
pub.cfg['emails'] = {'footer': '| Footer\n| Text'}
send_email('test', mail_body='Hello', email_rcpt='test@localhost')
assert emails.count() == 1
assert emails.emails['test']['msg'].is_multipart()
assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
assert b'Footer\nText' in emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
assert b'>Footer<' in emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
def test_email_plain_with_attachments(emails):
pub = create_temporary_pub()
jpg = PicklableUpload('test.jpeg', 'image/jpeg')
jpg_content = open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb').read()
jpg.receive([jpg_content])
txt = PicklableUpload('test.txt', 'text/plain')
txt.receive([b'foo-text-bar'])
odt = PicklableUpload('test.odt', 'application/vnd.oasis.opendocument.text')
odt_content = open(os.path.join(os.path.dirname(__file__), 'template.odt'), 'rb').read()
odt.receive([odt_content])
send_email('jpg', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[jpg])
assert emails.count() == 1
assert emails.emails['jpg']['msg'].is_multipart()
assert emails.emails['jpg']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['jpg']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['jpg']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
assert base64.b64decode(emails.emails['jpg']['msg'].get_payload()[1].get_payload()) == jpg_content
send_email('txt', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[txt])
assert emails.emails['txt']['msg'].is_multipart()
assert emails.emails['txt']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['txt']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['txt']['msg'].get_payload()[1].get_content_type() == 'text/plain'
assert emails.emails['txt']['msg'].get_payload()[1].get_payload(decode=True) == b'foo-text-bar'
send_email(
'jpgodt', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[jpg, odt]
)
assert emails.emails['jpgodt']['msg'].is_multipart()
assert emails.emails['jpgodt']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['jpgodt']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['jpgodt']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
assert (
emails.emails['jpgodt']['msg'].get_payload()[2].get_content_type()
== 'application/vnd.oasis.opendocument.text'
)
assert base64.b64decode(emails.emails['jpgodt']['msg'].get_payload()[1].get_payload()) == jpg_content
assert base64.b64decode(emails.emails['jpgodt']['msg'].get_payload()[2].get_payload()) == odt_content
unknown = PicklableUpload('test.eo', 'x-foo/x-bar')
unknown.receive([b'barfoo'])
send_email(
'unknown', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[unknown]
)
assert emails.emails['unknown']['msg'].is_multipart()
assert emails.emails['unknown']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['unknown']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['unknown']['msg'].get_payload()[1].get_content_type() == 'x-foo/x-bar'
assert emails.emails['unknown']['msg'].get_payload()[1].get_payload(decode=False).strip() == 'YmFyZm9v'
send_email(
'test-bad-attachment',
mail_body='Hello',
email_rcpt='test@localhost',
want_html=False,
attachments=['foobad'],
)
assert not emails.emails['test-bad-attachment']['msg'].is_multipart()
assert emails.count() == 5
@pytest.mark.skipif('docutils is None')
def test_email_plain_and_html_with_attachments(emails):
pub = create_temporary_pub()
pub.cfg['emails'] = {'footer': 'Footer\nText'}
jpg = PicklableUpload('test.jpeg', 'image/jpeg')
jpg_content = open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb').read()
jpg.receive([jpg_content])
send_email('test', mail_body='Hello', email_rcpt='test@localhost', attachments=[jpg])
assert emails.count() == 1
assert emails.emails['test']['msg'].is_multipart()
assert emails.emails['test']['msg'].get_content_subtype() == 'mixed'
assert emails.emails['test']['msg'].get_payload()[0].is_multipart()
assert emails.emails['test']['msg'].get_payload()[0].get_content_subtype() == 'alternative'
assert emails.emails['test']['msg'].get_payload()[0].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['test']['msg'].get_payload()[0].get_payload()[1].get_content_type() == 'text/html'
assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
def test_cache():
cache.set('hello', 'world')
assert cache.get('hello') == 'world'
def test_normalize_geolocation():
assert normalize_geolocation({'lat': 10.0, 'lon': 0.0}) == {'lat': 10.0, 'lon': 0.0}
assert normalize_geolocation({'lat': -10.0, 'lon': 0.0}) == {'lat': -10.0, 'lon': 0.0}
assert normalize_geolocation({'lat': 100.0, 'lon': 0.0}) == {'lat': -80.0, 'lon': 0.0}
assert normalize_geolocation({'lat': -100.0, 'lon': 0.0}) == {'lat': 80.0, 'lon': 0.0}
assert normalize_geolocation({'lat': 180.0, 'lon': 0.0}) == {'lat': 0.0, 'lon': 0.0}
assert normalize_geolocation({'lat': -180.0, 'lon': 0.0}) == {'lat': 0.0, 'lon': 0.0}
assert normalize_geolocation({'lat': 200.0, 'lon': 0.0}) == {'lat': 20.0, 'lon': 0.0}
assert normalize_geolocation({'lat': -200.0, 'lon': 0.0}) == {'lat': -20.0, 'lon': 0.0}
assert normalize_geolocation({'lat': 0.0, 'lon': 10.0}) == {'lat': 0.0, 'lon': 10.0}
assert normalize_geolocation({'lat': 0.0, 'lon': -10.0}) == {'lat': 0.0, 'lon': -10.0}
assert normalize_geolocation({'lat': 0.0, 'lon': 200.0}) == {'lat': 0.0, 'lon': -160.0}
assert normalize_geolocation({'lat': 0.0, 'lon': -200.0}) == {'lat': 0.0, 'lon': 160.0}
assert normalize_geolocation({'lat': 0.0, 'lon': 360.0}) == {'lat': 0.0, 'lon': 0.0}
assert normalize_geolocation({'lat': 0.0, 'lon': -360.0}) == {'lat': 0.0, 'lon': 0.0}
assert normalize_geolocation({'lat': 0.0, 'lon': 400.0}) == {'lat': 0.0, 'lon': 40.0}
assert normalize_geolocation({'lat': 0.0, 'lon': -400.0}) == {'lat': 0.0, 'lon': -40.0}
@pytest.mark.skipif('docutils is None')
def test_email_with_enumeration(emails):
pub = create_temporary_pub()
pub.cfg['emails'] = {'footer': 'Footer\nText'}
mail_body = '''
A. FooAlpha1
B. FooAlpha2
1. Num1
2. Num2
M. Francis Kuntz
'''
send_email('test', mail_body=mail_body, email_rcpt='test@localhost')
assert emails.count() == 1
assert emails.emails['test']['msg'].is_multipart()
assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
text = emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
html = emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
assert html.count(b'<ol') == 1
assert not b'<ul' in html
assert b'arabic simple' in html
assert b'M. Francis Kuntz' in html
@pytest.mark.skipif('docutils is None')
def test_email_with_unexpected_transition(emails):
pub = create_temporary_pub()
mail_body = '''
Value:
A
Other value:
?????????
Plop:
C
bye,
'''
send_email('test', mail_body=mail_body, email_rcpt='test@localhost')
assert emails.count() == 1
assert emails.emails['test']['msg'].is_multipart()
assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
text = emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
html = emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
assert text.count(b'\n ?????????\n') == 1
assert html.count(b'<dd>?????????</dd>') == 1
def test_dict_from_prefix():
d = evalutils.dict_from_prefix('var1', {})
assert d == {}
d = evalutils.dict_from_prefix('', {'k1': 'v1'})
assert d == {'k1': 'v1'}
d = evalutils.dict_from_prefix('k', {'k1': 'v1', 'k2': 'v2'})
assert d == {'1': 'v1', '2': 'v2'}
d = evalutils.dict_from_prefix('v', {'k1': 'v1', 'k2': 'v2'})
assert d == {}
def test_objects_repr():
workflow = Workflow(name='wf')
st1 = workflow.add_status('Status1', 'st1')
jump = JumpWorkflowStatusItem()
jump.id = '_jump'
st1.items.append(jump)
assert 'st1' in repr(st1)
assert '_jump' in repr(jump)
field = StringField()
assert repr(field) == '<StringField None None>'
field.id = '1'
field.label = 'test'
assert repr(field) == "<StringField 1 'test'>"
@pytest.mark.parametrize(
'value, length, expected',
[
('', 30, ''),
(None, 30, 'None'),
('foo bar', 30, 'foo bar'),
('01234567890123456789012345678', 30, '01234567890123456789012345678'),
('012345678901234567890123456789', 30, '012345678901234567890123456789'),
('0123456789012345678901234567890', 30, '012345678901234567890123456(…)'),
('foo bar', 4, 'f(…)'),
('foo bar', 3, 'foo'),
('foo bar', 2, 'fo'),
],
)
def test_ellipsize(value, length, expected):
create_temporary_pub()
assert ellipsize(value, length=length) == expected
def test_criteria_repr():
criteria = wcs.qommon.storage.GreaterOrEqual('foo', 'bar')
assert 'GreaterOrEqual' in repr(criteria)
assert 'foo' in repr(criteria)
assert 'bar' in repr(criteria)
def test_related_field_repr():
from wcs.backoffice.management import RelatedField
related_field = RelatedField(None, field=StringField(label='foo'), parent_field=StringField(label='bar'))
assert 'foo' in repr(related_field)
assert 'bar' in repr(related_field)
def test_find_vc_version():
import wcs.qommon.admin.menu
with mock.patch('os.path.exists') as os_path_exists, mock.patch('subprocess.Popen') as popen:
def mocked_os_path_exists(path):
return bool(not path.endswith('setup.py'))
os_path_exists.side_effect = mocked_os_path_exists
def mocked_popen(*args, **kwargs):
class Process:
returncode = 0
def communicate(self):
return (
b'''Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-===============-============-=================================================
ii wcs 5.71-1~eob100+1 all web application to design and set up online forms
''',
'',
)
return Process()
popen.side_effect = mocked_popen
version = wcs.qommon.admin.menu._find_vc_version()
assert version == 'wcs 5.71-1~eob100+1 (Debian)'
def test_uwsgi_spooler_import():
with pytest.raises(ImportError):
import wcs.qommon.spooler