wcs/tests/test_categories.py

248 lines
6.6 KiB
Python

import io
import os
import pickle
import time
import pytest
from django.utils.encoding import force_bytes
from quixote import cleanup
from wcs.categories import (
BlockCategory,
CardDefCategory,
Category,
CommentTemplateCategory,
DataSourceCategory,
MailTemplateCategory,
WorkflowCategory,
)
from .utilities import clean_temporary_pub, create_temporary_pub
category_classes = [
Category,
CardDefCategory,
BlockCategory,
WorkflowCategory,
MailTemplateCategory,
CommentTemplateCategory,
DataSourceCategory,
]
def setup_module(module):
cleanup()
global pub
pub = create_temporary_pub()
def teardown_module(module):
clean_temporary_pub()
@pytest.mark.parametrize('category_class', category_classes)
def test_store(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test2 = category_class.get(1)
assert test.id == test2.id
assert test.name == test2.name
assert test.description == test2.description
@pytest.mark.parametrize('category_class', category_classes)
def test_urlname(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test = category_class.get(1)
assert test.url_name == 'test'
@pytest.mark.parametrize('category_class', category_classes)
def test_duplicate_urlname(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.store()
test = category_class.get(1)
assert test.url_name == 'test'
test2 = category_class()
test2.name = 'Test'
test2.store()
test2 = category_class.get(2)
assert test2.url_name == 'test-2'
@pytest.mark.parametrize('category_class', category_classes)
def test_name_giving_a_forbidden_slug(category_class):
category_class.wipe()
test = category_class()
test.name = 'API'
test.store()
test = category_class.get(1)
assert test.url_name == 'cat-api'
@pytest.mark.parametrize('category_class', category_classes)
def test_sort_positions(category_class):
category_class.wipe()
categories = []
for i in range(10):
test = category_class()
test.name = 'Test %s' % i
test.position = 10 - i
categories.append(test)
# unset some positions, those categories will appear last
for i in range(8, 10):
categories[i].position = None
category_class.sort_by_position(categories)
assert categories[0].name == 'Test 7'
assert categories[-1].name in ('Test 8', 'Test 9')
@pytest.mark.parametrize('category_class', category_classes)
def test_xml_export(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test = category_class.get(test.id)
assert b'<name>Test</name>' in test.export_to_xml_string(include_id=True)
assert b' id="1"' in test.export_to_xml_string(include_id=True)
assert b' id="1"' not in test.export_to_xml_string(include_id=False)
@pytest.mark.parametrize('category_class', category_classes)
def test_xml_import(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test = category_class.get(1)
fd = io.BytesIO(test.export_to_xml_string(include_id=True))
test2 = category_class.import_from_xml(fd, include_id=True)
assert test.id == test2.id
assert test.name == test2.name
assert test.description == test2.description
def test_load_old_pickle():
Category.wipe()
test = Category()
test.id = '1'
test.name = 'Test'
test.description = 'Hello world'
os.mkdir(os.path.join(pub.app_dir, 'categories'))
with open(os.path.join(pub.app_dir, 'categories', '1'), 'wb') as fd:
pickle.dump(test, fd)
test2 = Category.get(1)
assert test.id == test2.id
assert test.name == test2.name
assert test.description == test2.description
# check it's been migrated to XML on disk
with open(os.path.join(pub.app_dir, 'categories', '1'), 'rb') as fd:
assert fd.read(1) == b'<'
def test_load_old_python2_pickle():
Category.wipe()
test = Category()
test.id = '1'
test.name = 'Test'
test.description = 'Hello world'
# turn pickle to bytes
def deep_str2bytes(obj, seen=None):
# reverse deep_bytes2str
if seen is None:
seen = {}
if obj is None or isinstance(obj, (int, float, bytes, time.struct_time, type(Ellipsis))):
return obj
if id(obj) in seen:
return obj
if isinstance(obj, str):
return force_bytes(obj)
seen[id(obj)] = True
if isinstance(obj, dict):
new_d = {}
for k, v in obj.items():
new_d[force_bytes(k)] = deep_str2bytes(v, seen)
return new_d
if isinstance(obj, list):
return [deep_str2bytes(x, seen) for x in obj]
if hasattr(obj, '__class__') and obj.__class__.__module__.startswith(('wcs.', 'qommon.', 'modules.')):
obj.__dict__ = deep_str2bytes(obj.__dict__, seen)
return obj
return obj
os.mkdir(os.path.join(pub.app_dir, 'categories'))
test.__dict__ = deep_str2bytes(test.__dict__)
with open(os.path.join(pub.app_dir, 'categories', '1'), 'wb') as fd:
pickle.dump(test, fd)
test2 = Category.get(1)
assert test2.id == '1'
assert test2.name == 'Test'
assert test2.description == 'Hello world'
@pytest.mark.parametrize('category_class', category_classes)
def test_get_by_urlname(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test = category_class.get(test.id)
test2 = category_class.get_by_urlname('test')
assert test.id == test2.id
@pytest.mark.parametrize('category_class', category_classes)
def test_has_urlname(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test = category_class.get(test.id)
assert category_class.has_urlname('test')
assert not category_class.has_urlname('foobar')
@pytest.mark.parametrize('category_class', category_classes)
def test_remove_self(category_class):
category_class.wipe()
test = category_class()
test.name = 'Test'
test.description = 'Hello world'
test.store()
test = category_class.get(test.id)
test.remove_self()
with pytest.raises(KeyError):
category_class.get(test.id)