3
0
Fork 0
wuttaweb/tests/forms/test_schema.py

516 lines
17 KiB
Python

# -*- coding: utf-8; -*-
import datetime
import decimal
from unittest import TestCase
from unittest.mock import patch
import colander
from pyramid import testing
from sqlalchemy import orm
from wuttjamaican.conf import WuttaConfig
from wuttaweb.forms import schema as mod
from wuttaweb.forms import widgets
from wuttaweb.testing import DataTestCase, WebTestCase
class TestWuttaDateTime(TestCase):
def test_deserialize(self):
typ = mod.WuttaDateTime()
node = colander.SchemaNode(typ)
result = typ.deserialize(node, colander.null)
self.assertIs(result, colander.null)
result = typ.deserialize(node, '2024-12-11T10:33 PM')
self.assertIsInstance(result, datetime.datetime)
self.assertEqual(result, datetime.datetime(2024, 12, 11, 22, 33))
self.assertIsNone(result.tzinfo)
result = typ.deserialize(node, '2024-12-11T22:33:00')
self.assertIsInstance(result, datetime.datetime)
self.assertEqual(result, datetime.datetime(2024, 12, 11, 22, 33))
self.assertIsNone(result.tzinfo)
self.assertRaises(colander.Invalid, typ.deserialize, node, 'bogus')
class TestObjectNode(DataTestCase):
def setUp(self):
self.setup_db()
self.request = testing.DummyRequest(wutta_config=self.config)
def test_dictify(self):
model = self.app.model
person = model.Person(full_name="Betty Boop")
# unsupported type is converted to string
node = mod.ObjectNode(colander.String())
value = node.dictify(person)
self.assertEqual(value, "Betty Boop")
# but supported type can dictify
node = mod.ObjectNode(mod.PersonRef(self.request))
value = node.dictify(person)
self.assertIs(value, person)
def test_objectify(self):
model = self.app.model
person = model.Person(full_name="Betty Boop")
# unsupported type raises error
node = mod.ObjectNode(colander.String())
self.assertRaises(NotImplementedError, node.objectify, person)
# but supported type can objectify
node = mod.ObjectNode(mod.PersonRef(self.request))
value = node.objectify(person)
self.assertIs(value, person)
class TestWuttaEnum(WebTestCase):
def test_widget_maker(self):
enum = self.app.enum
typ = mod.WuttaEnum(self.request, enum.UpgradeStatus)
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.SelectWidget)
MOCK_STATUS_ONE = 1
MOCK_STATUS_TWO = 2
MOCK_STATUS = {
MOCK_STATUS_ONE: 'one',
MOCK_STATUS_TWO: 'two',
}
class TestWuttaDictEnum(WebTestCase):
def test_widget_maker(self):
typ = mod.WuttaDictEnum(self.request, MOCK_STATUS)
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.SelectWidget)
self.assertEqual(widget.values, [
(1, 'one'),
(2, 'two'),
])
class TestWuttaMoney(WebTestCase):
def test_widget_maker(self):
enum = self.app.enum
# default scale
typ = mod.WuttaMoney(self.request)
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.WuttaMoneyInputWidget)
self.assertEqual(widget.scale, 2)
# custom scale
typ = mod.WuttaMoney(self.request, scale=4)
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.WuttaMoneyInputWidget)
self.assertEqual(widget.scale, 4)
class TestWuttaQuantity(WebTestCase):
def test_serialize(self):
node = colander.SchemaNode(mod.WuttaQuantity(self.request))
typ = node.typ
# null
result = typ.serialize(node, colander.null)
self.assertIs(result, colander.null)
result = typ.serialize(node, None)
self.assertIs(result, colander.null)
# quantity
result = typ.serialize(node, 42)
self.assertEqual(result, '42')
result = typ.serialize(node, 42.00)
self.assertEqual(result, '42')
result = typ.serialize(node, decimal.Decimal('42.00'))
self.assertEqual(result, '42')
result = typ.serialize(node, 42.13)
self.assertEqual(result, '42.13')
class TestObjectRef(DataTestCase):
def setUp(self):
self.setup_db()
self.request = testing.DummyRequest(wutta_config=self.config)
def test_empty_option(self):
# null by default
typ = mod.ObjectRef(self.request)
self.assertIsNone(typ.empty_option)
# passing true yields default empty option
typ = mod.ObjectRef(self.request, empty_option=True)
self.assertEqual(typ.empty_option, ('', "(none)"))
# can set explicitly
typ = mod.ObjectRef(self.request, empty_option=('foo', 'bar'))
self.assertEqual(typ.empty_option, ('foo', 'bar'))
# can set just a label
typ = mod.ObjectRef(self.request, empty_option="(empty)")
self.assertEqual(typ.empty_option, ('', "(empty)"))
def test_model_class(self):
typ = mod.ObjectRef(self.request)
self.assertRaises(NotImplementedError, getattr, typ, 'model_class')
def test_serialize(self):
model = self.app.model
node = colander.SchemaNode(colander.String())
# null
typ = mod.ObjectRef(self.request)
value = typ.serialize(node, colander.null)
self.assertIs(value, colander.null)
# model instance
person = model.Person(full_name="Betty Boop")
self.session.add(person)
self.session.commit()
self.assertIsNotNone(person.uuid)
typ = mod.ObjectRef(self.request)
value = typ.serialize(node, person)
self.assertEqual(value, person.uuid.hex)
# null w/ empty option
typ = mod.ObjectRef(self.request, empty_option=('bad', 'BAD'))
value = typ.serialize(node, colander.null)
self.assertEqual(value, 'bad')
def test_deserialize(self):
model = self.app.model
node = colander.SchemaNode(colander.String())
# null
typ = mod.ObjectRef(self.request)
value = typ.deserialize(node, colander.null)
self.assertIs(value, colander.null)
# model instance
person = model.Person(full_name="Betty Boop")
self.session.add(person)
self.session.commit()
self.assertIsNotNone(person.uuid)
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.ObjectRef(self.request)
value = typ.deserialize(node, person.uuid)
self.assertIs(value, person)
def test_dictify(self):
model = self.app.model
node = colander.SchemaNode(colander.String())
# model instance
person = model.Person(full_name="Betty Boop")
self.session.add(person)
self.session.commit()
self.assertIsNotNone(person.uuid)
typ = mod.ObjectRef(self.request)
value = typ.dictify(person)
self.assertIs(value, person)
def test_objectify(self):
model = self.app.model
node = colander.SchemaNode(colander.String())
# null
typ = mod.ObjectRef(self.request)
value = typ.objectify(None)
self.assertIsNone(value)
with patch.object(mod, 'Session', return_value=self.session):
# model instance
person = model.Person(full_name="Betty Boop")
self.session.add(person)
self.session.commit()
self.assertIsNotNone(person.uuid)
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
# can specify as uuid
typ = mod.ObjectRef(self.request)
value = typ.objectify(person.uuid)
self.assertIs(value, person)
# or can specify object proper
typ = mod.ObjectRef(self.request)
value = typ.objectify(person)
self.assertIs(value, person)
# error if not found
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
typ = mod.ObjectRef(self.request)
self.assertRaises(ValueError, typ.objectify, 'WRONG-UUID')
def test_get_query(self):
model = self.app.model
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.ObjectRef(self.request)
query = typ.get_query()
self.assertIsInstance(query, orm.Query)
def test_sort_query(self):
model = self.app.model
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.ObjectRef(self.request)
query = typ.get_query()
sorted_query = typ.sort_query(query)
self.assertIs(sorted_query, query)
def test_widget_maker(self):
model = self.app.model
person = model.Person(full_name="Betty Boop")
self.session.add(person)
self.session.commit()
# basic
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.ObjectRef(self.request)
widget = typ.widget_maker()
self.assertEqual(len(widget.values), 1)
self.assertEqual(widget.values[0][1], "Betty Boop")
# empty option
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.ObjectRef(self.request, empty_option=True)
widget = typ.widget_maker()
self.assertEqual(len(widget.values), 2)
self.assertEqual(widget.values[0][1], "(none)")
self.assertEqual(widget.values[1][1], "Betty Boop")
class TestPersonRef(WebTestCase):
def test_sort_query(self):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.PersonRef(self.request)
query = typ.get_query()
self.assertIsInstance(query, orm.Query)
sorted_query = typ.sort_query(query)
self.assertIsInstance(sorted_query, orm.Query)
self.assertIsNot(sorted_query, query)
def test_get_object_url(self):
self.pyramid_config.add_route('people.view', '/people/{uuid}')
model = self.app.model
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.PersonRef(self.request)
person = model.Person(full_name="Barney Rubble")
self.session.add(person)
self.session.commit()
url = typ.get_object_url(person)
self.assertIsNotNone(url)
self.assertIn(f'/people/{person.uuid}', url)
class TestRoleRef(WebTestCase):
def test_sort_query(self):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.RoleRef(self.request)
query = typ.get_query()
self.assertIsInstance(query, orm.Query)
sorted_query = typ.sort_query(query)
self.assertIsInstance(sorted_query, orm.Query)
self.assertIsNot(sorted_query, query)
def test_get_object_url(self):
self.pyramid_config.add_route('roles.view', '/roles/{uuid}')
model = self.app.model
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.RoleRef(self.request)
role = model.Role(name='Manager')
self.session.add(role)
self.session.commit()
url = typ.get_object_url(role)
self.assertIsNotNone(url)
self.assertIn(f'/roles/{role.uuid}', url)
class TestUserRef(WebTestCase):
def test_sort_query(self):
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.UserRef(self.request)
query = typ.get_query()
self.assertIsInstance(query, orm.Query)
sorted_query = typ.sort_query(query)
self.assertIsInstance(sorted_query, orm.Query)
self.assertIsNot(sorted_query, query)
def test_get_object_url(self):
self.pyramid_config.add_route('users.view', '/users/{uuid}')
model = self.app.model
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.UserRef(self.request)
user = model.User(username='barney')
self.session.add(user)
self.session.commit()
url = typ.get_object_url(user)
self.assertIsNotNone(url)
self.assertIn(f'/users/{user.uuid}', url)
class TestUserRefs(DataTestCase):
def setUp(self):
self.setup_db()
self.request = testing.DummyRequest(wutta_config=self.config)
def test_widget_maker(self):
model = self.app.model
with patch.object(mod, 'Session', return_value=self.session):
typ = mod.UserRefs(self.request)
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.UserRefsWidget)
class TestRoleRefs(DataTestCase):
def setUp(self):
self.setup_db()
self.request = testing.DummyRequest(wutta_config=self.config)
def test_widget_maker(self):
model = self.app.model
auth = self.app.get_auth_handler()
admin = auth.get_role_administrator(self.session)
authed = auth.get_role_authenticated(self.session)
anon = auth.get_role_anonymous(self.session)
blokes = model.Role(name="Blokes")
self.session.add(blokes)
self.session.commit()
with patch.object(mod, 'Session', return_value=self.session):
# with root access, default values include: admin, blokes
self.request.is_root = True
typ = mod.RoleRefs(self.request)
widget = typ.widget_maker()
self.assertEqual(len(widget.values), 2)
self.assertEqual(widget.values[0][1], "Administrator")
self.assertEqual(widget.values[1][1], "Blokes")
# without root, default values include: blokes
self.request.is_root = False
typ = mod.RoleRefs(self.request)
widget = typ.widget_maker()
self.assertEqual(len(widget.values), 1)
self.assertEqual(widget.values[0][1], "Blokes")
class TestPermissions(DataTestCase):
def setUp(self):
self.setup_db()
self.request = testing.DummyRequest(wutta_config=self.config)
def test_widget_maker(self):
# no supported permissions
permissions = {}
typ = mod.Permissions(self.request, permissions)
widget = typ.widget_maker()
self.assertEqual(len(widget.values), 0)
# supported permissions are morphed to values
permissions = {
'widgets': {
'label': "Widgets",
'perms': {
'widgets.polish': {
'label': "Polish the widgets",
},
},
},
}
typ = mod.Permissions(self.request, permissions)
widget = typ.widget_maker()
self.assertEqual(len(widget.values), 1)
self.assertEqual(widget.values[0], ('widgets.polish', "Polish the widgets"))
class TestFileDownload(DataTestCase):
def setUp(self):
self.setup_db()
self.request = testing.DummyRequest(wutta_config=self.config)
def test_widget_maker(self):
# sanity / coverage check
typ = mod.FileDownload(self.request, url='/foo')
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.FileDownloadWidget)
self.assertEqual(widget.url, '/foo')
class TestEmailRecipients(TestCase):
def test_serialize(self):
typ = mod.EmailRecipients()
node = colander.SchemaNode(typ)
recips = [
'alice@example.com',
'bob@example.com',
]
recips_str = ', '.join(recips)
# values
result = typ.serialize(node, recips_str)
self.assertEqual(result, '\n'.join(recips))
# null
result = typ.serialize(node, colander.null)
self.assertIs(result, colander.null)
def test_deserialize(self):
typ = mod.EmailRecipients()
node = colander.SchemaNode(typ)
recips = [
'alice@example.com',
'bob@example.com',
]
recips_str = ', '.join(recips)
# values
result = typ.deserialize(node, recips_str)
self.assertEqual(result, recips_str)
# null
result = typ.deserialize(node, colander.null)
self.assertIs(result, colander.null)
def test_widget_maker(self):
typ = mod.EmailRecipients()
widget = typ.widget_maker()
self.assertIsInstance(widget, widgets.EmailRecipientsWidget)