feat: add Users view; improve CRUD master for SQLAlchemy models
This commit is contained in:
parent
33589f1cd8
commit
eac3b81918
33 changed files with 1510 additions and 253 deletions
|
@ -8,46 +8,15 @@ import deform
|
|||
from pyramid import testing
|
||||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttaweb.forms import base
|
||||
from wuttaweb.forms import base, widgets
|
||||
from wuttaweb import helpers
|
||||
|
||||
|
||||
class TestFieldList(TestCase):
|
||||
|
||||
def test_insert_before(self):
|
||||
fields = base.FieldList(['f1', 'f2'])
|
||||
self.assertEqual(fields, ['f1', 'f2'])
|
||||
|
||||
# typical
|
||||
fields.insert_before('f1', 'XXX')
|
||||
self.assertEqual(fields, ['XXX', 'f1', 'f2'])
|
||||
fields.insert_before('f2', 'YYY')
|
||||
self.assertEqual(fields, ['XXX', 'f1', 'YYY', 'f2'])
|
||||
|
||||
# appends new field if reference field is invalid
|
||||
fields.insert_before('f3', 'ZZZ')
|
||||
self.assertEqual(fields, ['XXX', 'f1', 'YYY', 'f2', 'ZZZ'])
|
||||
|
||||
def test_insert_after(self):
|
||||
fields = base.FieldList(['f1', 'f2'])
|
||||
self.assertEqual(fields, ['f1', 'f2'])
|
||||
|
||||
# typical
|
||||
fields.insert_after('f1', 'XXX')
|
||||
self.assertEqual(fields, ['f1', 'XXX', 'f2'])
|
||||
fields.insert_after('XXX', 'YYY')
|
||||
self.assertEqual(fields, ['f1', 'XXX', 'YYY', 'f2'])
|
||||
|
||||
# appends new field if reference field is invalid
|
||||
fields.insert_after('f3', 'ZZZ')
|
||||
self.assertEqual(fields, ['f1', 'XXX', 'YYY', 'f2', 'ZZZ'])
|
||||
|
||||
|
||||
class TestForm(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
|
||||
'wutta.web.menus.handler_spec': 'tests.util:NullMenuHandler',
|
||||
})
|
||||
self.app = self.config.get_app()
|
||||
self.request = testing.DummyRequest(wutta_config=self.config, use_oruga=False)
|
||||
|
@ -74,7 +43,7 @@ class TestForm(TestCase):
|
|||
|
||||
def test_init_with_none(self):
|
||||
form = self.make_form()
|
||||
self.assertIsNone(form.fields)
|
||||
self.assertEqual(form.fields, [])
|
||||
|
||||
def test_init_with_fields(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
|
@ -115,6 +84,79 @@ class TestForm(TestCase):
|
|||
form.set_fields(['baz'])
|
||||
self.assertEqual(form.fields, ['baz'])
|
||||
|
||||
def test_remove(self):
|
||||
form = self.make_form(fields=['one', 'two', 'three', 'four'])
|
||||
self.assertEqual(form.fields, ['one', 'two', 'three', 'four'])
|
||||
form.remove('two', 'three')
|
||||
self.assertEqual(form.fields, ['one', 'four'])
|
||||
|
||||
def test_set_node(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.nodes, {})
|
||||
|
||||
# complete node
|
||||
node = colander.SchemaNode(colander.Bool(), name='foo')
|
||||
form.set_node('foo', node)
|
||||
self.assertIs(form.nodes['foo'], node)
|
||||
|
||||
# type only
|
||||
typ = colander.Bool()
|
||||
form.set_node('foo', typ)
|
||||
node = form.nodes['foo']
|
||||
self.assertIsInstance(node, colander.SchemaNode)
|
||||
self.assertIsInstance(node.typ, colander.Bool)
|
||||
self.assertEqual(node.name, 'foo')
|
||||
|
||||
# schema is updated if already present
|
||||
schema = form.get_schema()
|
||||
self.assertIsNotNone(schema)
|
||||
typ = colander.Date()
|
||||
form.set_node('foo', typ)
|
||||
node = form.nodes['foo']
|
||||
self.assertIsInstance(node, colander.SchemaNode)
|
||||
self.assertIsInstance(node.typ, colander.Date)
|
||||
self.assertEqual(node.name, 'foo')
|
||||
|
||||
def test_set_widget(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.widgets, {})
|
||||
|
||||
# basic
|
||||
widget = widgets.SelectWidget()
|
||||
form.set_widget('foo', widget)
|
||||
self.assertIs(form.widgets['foo'], widget)
|
||||
|
||||
# schema is updated if already present
|
||||
schema = form.get_schema()
|
||||
self.assertIsNotNone(schema)
|
||||
self.assertIs(schema['foo'].widget, widget)
|
||||
new_widget = widgets.TextInputWidget()
|
||||
form.set_widget('foo', new_widget)
|
||||
self.assertIs(form.widgets['foo'], new_widget)
|
||||
self.assertIs(schema['foo'].widget, new_widget)
|
||||
|
||||
def test_set_validator(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.validators, {})
|
||||
|
||||
def validate1(node, value):
|
||||
pass
|
||||
|
||||
# basic
|
||||
form.set_validator('foo', validate1)
|
||||
self.assertIs(form.validators['foo'], validate1)
|
||||
|
||||
def validate2(node, value):
|
||||
pass
|
||||
|
||||
# schema is updated if already present
|
||||
schema = form.get_schema()
|
||||
self.assertIsNotNone(schema)
|
||||
self.assertIs(schema['foo'].validator, validate1)
|
||||
form.set_validator('foo', validate2)
|
||||
self.assertIs(form.validators['foo'], validate2)
|
||||
self.assertIs(schema['foo'].validator, validate2)
|
||||
|
||||
def test_get_schema(self):
|
||||
model = self.app.model
|
||||
form = self.make_form()
|
||||
|
@ -144,6 +186,13 @@ class TestForm(TestCase):
|
|||
self.assertIn('name', schema)
|
||||
self.assertIn('value', schema)
|
||||
|
||||
# but node overrides are honored when auto-generating
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
value_node = colander.SchemaNode(colander.Bool(), name='value')
|
||||
form.set_node('value', value_node)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['value'], value_node)
|
||||
|
||||
# schema is auto-generated if model_instance provided
|
||||
form = self.make_form(model_instance=model.Setting(name='uhoh'))
|
||||
self.assertEqual(form.fields, ['name', 'value'])
|
||||
|
@ -166,7 +215,23 @@ class TestForm(TestCase):
|
|||
form.set_required('bar', False)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['foo'].missing, colander.required)
|
||||
self.assertIsNone(schema['bar'].missing)
|
||||
self.assertIs(schema['bar'].missing, colander.null)
|
||||
|
||||
# validator overrides are honored
|
||||
def validate(node, value): pass
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
form.set_validator('name', validate)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['name'].validator, validate)
|
||||
|
||||
# validator can be set for whole form
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
schema = form.get_schema()
|
||||
self.assertIsNone(schema.validator)
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
form.set_validator(None, validate)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema.validator, validate)
|
||||
|
||||
def test_get_deform(self):
|
||||
model = self.app.model
|
||||
|
@ -372,34 +437,6 @@ class TestForm(TestCase):
|
|||
self.assertEqual(len(errors), 1)
|
||||
self.assertEqual(errors[0], "something is wrong")
|
||||
|
||||
def test_get_vue_field_value(self):
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
|
||||
# null field value
|
||||
value = form.get_vue_field_value('foo')
|
||||
self.assertEqual(value, 'null')
|
||||
|
||||
# non-default / explicit value
|
||||
# TODO: surely need a different approach to set value
|
||||
dform = form.get_deform()
|
||||
dform['foo'].cstruct = 'blarg'
|
||||
value = form.get_vue_field_value('foo')
|
||||
self.assertEqual(value, '"blarg"')
|
||||
|
||||
def test_jsonify_value(self):
|
||||
form = self.make_form()
|
||||
|
||||
# null field value
|
||||
value = form.jsonify_value(colander.null)
|
||||
self.assertEqual(value, 'null')
|
||||
value = form.jsonify_value(None)
|
||||
self.assertEqual(value, 'null')
|
||||
|
||||
# string value
|
||||
value = form.jsonify_value('blarg')
|
||||
self.assertEqual(value, '"blarg"')
|
||||
|
||||
def test_validate(self):
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
|
|
199
tests/forms/test_schema.py
Normal file
199
tests/forms/test_schema.py
Normal file
|
@ -0,0 +1,199 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
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 tests.util import DataTestCase
|
||||
|
||||
|
||||
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 raises error
|
||||
node = mod.ObjectNode(colander.String())
|
||||
self.assertRaises(NotImplementedError, node.dictify, person)
|
||||
|
||||
# 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 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)
|
||||
|
||||
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):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
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)
|
||||
|
||||
# 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):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
value = typ.objectify(person.uuid)
|
||||
self.assertIs(value, person)
|
||||
|
||||
# error if not found
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
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):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
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):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
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):
|
||||
typ = mod.ObjectRef(self.request, session=self.session)
|
||||
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):
|
||||
typ = mod.ObjectRef(self.request, session=self.session, 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(DataTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.setup_db()
|
||||
self.request = testing.DummyRequest(wutta_config=self.config)
|
||||
|
||||
def test_sort_query(self):
|
||||
typ = mod.PersonRef(self.request, session=self.session)
|
||||
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)
|
32
tests/forms/test_widgets.py
Normal file
32
tests/forms/test_widgets.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
import colander
|
||||
import deform
|
||||
from pyramid import testing
|
||||
|
||||
from wuttaweb.forms import widgets
|
||||
from wuttaweb.forms.schema import PersonRef
|
||||
from tests.util import WebTestCase
|
||||
|
||||
class TestObjectRefWidget(WebTestCase):
|
||||
|
||||
def test_serialize(self):
|
||||
model = self.app.model
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
self.session.add(person)
|
||||
self.session.commit()
|
||||
|
||||
# standard (editable)
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session))
|
||||
widget = widgets.ObjectRefWidget(self.request)
|
||||
field = deform.Field(node)
|
||||
html = widget.serialize(field, person.uuid)
|
||||
self.assertIn('<select ', html)
|
||||
|
||||
# readonly
|
||||
node = colander.SchemaNode(PersonRef(self.request, session=self.session))
|
||||
node.model_instance = person
|
||||
widget = widgets.ObjectRefWidget(self.request)
|
||||
field = deform.Field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertEqual(html, '<span>Betty Boop</span>')
|
|
@ -14,7 +14,7 @@ class TestGrid(TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
|
||||
'wutta.web.menus.handler_spec': 'tests.util:NullMenuHandler',
|
||||
})
|
||||
self.app = self.config.get_app()
|
||||
|
||||
|
@ -35,7 +35,7 @@ class TestGrid(TestCase):
|
|||
# empty
|
||||
grid = self.make_grid()
|
||||
self.assertIsNone(grid.key)
|
||||
self.assertIsNone(grid.columns)
|
||||
self.assertEqual(grid.columns, [])
|
||||
self.assertIsNone(grid.data)
|
||||
|
||||
# now with columns
|
||||
|
@ -56,8 +56,8 @@ class TestGrid(TestCase):
|
|||
|
||||
# empty
|
||||
grid = self.make_grid()
|
||||
self.assertIsNone(grid.columns)
|
||||
self.assertIsNone(grid.get_columns())
|
||||
self.assertEqual(grid.columns, [])
|
||||
self.assertEqual(grid.get_columns(), [])
|
||||
|
||||
# explicit
|
||||
grid = self.make_grid(columns=['foo', 'bar'])
|
||||
|
@ -69,6 +69,12 @@ class TestGrid(TestCase):
|
|||
self.assertEqual(grid.columns, ['name', 'value'])
|
||||
self.assertEqual(grid.get_columns(), ['name', 'value'])
|
||||
|
||||
def test_remove(self):
|
||||
grid = self.make_grid(columns=['one', 'two', 'three', 'four'])
|
||||
self.assertEqual(grid.columns, ['one', 'two', 'three', 'four'])
|
||||
grid.remove('two', 'three')
|
||||
self.assertEqual(grid.columns, ['one', 'four'])
|
||||
|
||||
def test_linked_columns(self):
|
||||
grid = self.make_grid(columns=['foo', 'bar'])
|
||||
self.assertEqual(grid.linked_columns, [])
|
||||
|
@ -118,18 +124,17 @@ class TestGrid(TestCase):
|
|||
|
||||
def test_get_vue_data(self):
|
||||
|
||||
# null by default
|
||||
# empty if no columns defined
|
||||
grid = self.make_grid()
|
||||
data = grid.get_vue_data()
|
||||
self.assertIsNone(data)
|
||||
self.assertEqual(data, [])
|
||||
|
||||
# is usually a list
|
||||
# typical data is a list
|
||||
mydata = [
|
||||
{'foo': 'bar'},
|
||||
]
|
||||
grid = self.make_grid(data=mydata)
|
||||
grid = self.make_grid(columns=['foo'], data=mydata)
|
||||
data = grid.get_vue_data()
|
||||
self.assertIs(data, mydata)
|
||||
self.assertEqual(data, [{'foo': 'bar'}])
|
||||
|
||||
# if grid has actions, that list may be supplemented
|
||||
|
|
|
@ -215,7 +215,7 @@ class TestBeforeRender(TestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
|
||||
'wutta.web.menus.handler_spec': 'tests.util:NullMenuHandler',
|
||||
})
|
||||
|
||||
def make_request(self):
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
import json
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
import colander
|
||||
from fanstatic import Library, Resource
|
||||
from pyramid import testing
|
||||
|
||||
|
@ -10,6 +12,37 @@ from wuttjamaican.conf import WuttaConfig
|
|||
from wuttaweb import util
|
||||
|
||||
|
||||
class TestFieldList(TestCase):
|
||||
|
||||
def test_insert_before(self):
|
||||
fields = util.FieldList(['f1', 'f2'])
|
||||
self.assertEqual(fields, ['f1', 'f2'])
|
||||
|
||||
# typical
|
||||
fields.insert_before('f1', 'XXX')
|
||||
self.assertEqual(fields, ['XXX', 'f1', 'f2'])
|
||||
fields.insert_before('f2', 'YYY')
|
||||
self.assertEqual(fields, ['XXX', 'f1', 'YYY', 'f2'])
|
||||
|
||||
# appends new field if reference field is invalid
|
||||
fields.insert_before('f3', 'ZZZ')
|
||||
self.assertEqual(fields, ['XXX', 'f1', 'YYY', 'f2', 'ZZZ'])
|
||||
|
||||
def test_insert_after(self):
|
||||
fields = util.FieldList(['f1', 'f2'])
|
||||
self.assertEqual(fields, ['f1', 'f2'])
|
||||
|
||||
# typical
|
||||
fields.insert_after('f1', 'XXX')
|
||||
self.assertEqual(fields, ['f1', 'XXX', 'f2'])
|
||||
fields.insert_after('XXX', 'YYY')
|
||||
self.assertEqual(fields, ['f1', 'XXX', 'YYY', 'f2'])
|
||||
|
||||
# appends new field if reference field is invalid
|
||||
fields.insert_after('f3', 'ZZZ')
|
||||
self.assertEqual(fields, ['f1', 'XXX', 'YYY', 'f2', 'ZZZ'])
|
||||
|
||||
|
||||
class TestGetLibVer(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -455,3 +488,40 @@ class TestRenderCsrfToken(TestCase):
|
|||
self.assertIn('name="_csrf"', html)
|
||||
token = util.get_csrf_token(self.request)
|
||||
self.assertIn(f'value="{token}"', html)
|
||||
|
||||
|
||||
class TestMakeJsonSafe(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig()
|
||||
self.app = self.config.get_app()
|
||||
|
||||
def test_null(self):
|
||||
value = util.make_json_safe(colander.null)
|
||||
self.assertIsNone(value)
|
||||
|
||||
value = util.make_json_safe(None)
|
||||
self.assertIsNone(value)
|
||||
|
||||
def test_invalid(self):
|
||||
model = self.app.model
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
self.assertRaises(TypeError, json.dumps, person)
|
||||
value = util.make_json_safe(person, key='person')
|
||||
self.assertEqual(value, "Betty Boop")
|
||||
|
||||
def test_dict(self):
|
||||
model = self.app.model
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
|
||||
data = {
|
||||
'foo': 'bar',
|
||||
'person': person,
|
||||
}
|
||||
|
||||
self.assertRaises(TypeError, json.dumps, data)
|
||||
value = util.make_json_safe(data)
|
||||
self.assertEqual(value, {
|
||||
'foo': 'bar',
|
||||
'person': "Betty Boop",
|
||||
})
|
||||
|
|
|
@ -7,9 +7,36 @@ from pyramid import testing
|
|||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttaweb import subscribers
|
||||
from wuttaweb.menus import MenuHandler
|
||||
|
||||
|
||||
class WebTestCase(TestCase):
|
||||
class DataTestCase(TestCase):
|
||||
"""
|
||||
Base class for test suites requiring a full (typical) database.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.setup_db()
|
||||
|
||||
def setup_db(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.db.default.url': 'sqlite://',
|
||||
})
|
||||
self.app = self.config.get_app()
|
||||
|
||||
# init db
|
||||
model = self.app.model
|
||||
model.Base.metadata.create_all(bind=self.config.appdb_engine)
|
||||
self.session = self.app.make_session()
|
||||
|
||||
def tearDown(self):
|
||||
self.teardown_db()
|
||||
|
||||
def teardown_db(self):
|
||||
pass
|
||||
|
||||
|
||||
class WebTestCase(DataTestCase):
|
||||
"""
|
||||
Base class for test suites requiring a full (typical) web app.
|
||||
"""
|
||||
|
@ -18,24 +45,15 @@ class WebTestCase(TestCase):
|
|||
self.setup_web()
|
||||
|
||||
def setup_web(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.db.default.url': 'sqlite://',
|
||||
'wutta.web.menus.handler_spec': 'tests.utils:NullMenuHandler',
|
||||
})
|
||||
|
||||
self.setup_db()
|
||||
self.request = testing.DummyRequest()
|
||||
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
'mako.directories': ['wuttaweb:templates'],
|
||||
# TODO: have not need this yet, but will?
|
||||
# 'pyramid_deform.template_search_path': 'wuttaweb:templates/deform',
|
||||
})
|
||||
|
||||
# init db
|
||||
self.app = self.config.get_app()
|
||||
model = self.app.model
|
||||
model.Base.metadata.create_all(bind=self.config.appdb_engine)
|
||||
self.session = self.app.make_session()
|
||||
|
||||
# init web
|
||||
self.pyramid_config.include('pyramid_mako')
|
||||
self.pyramid_config.include('wuttaweb.static')
|
||||
|
@ -55,3 +73,12 @@ class WebTestCase(TestCase):
|
|||
|
||||
def teardown_web(self):
|
||||
testing.tearDown()
|
||||
self.teardown_db()
|
||||
|
||||
|
||||
class NullMenuHandler(MenuHandler):
|
||||
"""
|
||||
Dummy menu handler for testing.
|
||||
"""
|
||||
def make_menus(self, request, **kwargs):
|
||||
return []
|
|
@ -1,11 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from wuttaweb.menus import MenuHandler
|
||||
|
||||
|
||||
class NullMenuHandler(MenuHandler):
|
||||
"""
|
||||
Dummy menu handler for testing.
|
||||
"""
|
||||
def make_menus(self, request, **kwargs):
|
||||
return []
|
|
@ -11,8 +11,7 @@ from pyramid.httpexceptions import HTTPFound, HTTPNotFound
|
|||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttaweb.views import master
|
||||
from wuttaweb.subscribers import new_request_set_user
|
||||
|
||||
from tests.views.utils import WebTestCase
|
||||
from tests.util import WebTestCase
|
||||
|
||||
|
||||
class TestMasterView(WebTestCase):
|
||||
|
@ -387,6 +386,19 @@ class TestMasterView(WebTestCase):
|
|||
with patch.object(view, 'get_query', new=get_query):
|
||||
self.assertRaises(ValueError, view.get_grid_data, session=self.session)
|
||||
|
||||
def test_configure_grid(self):
|
||||
model = self.app.model
|
||||
|
||||
# uuid field is pruned
|
||||
with patch.multiple(master.MasterView, create=True,
|
||||
model_class=model.Setting):
|
||||
view = master.MasterView(self.request)
|
||||
grid = view.make_grid(model_class=model.Setting,
|
||||
columns=['uuid', 'name', 'value'])
|
||||
self.assertIn('uuid', grid.columns)
|
||||
view.configure_grid(grid)
|
||||
self.assertNotIn('uuid', grid.columns)
|
||||
|
||||
def test_get_instance(self):
|
||||
model = self.app.model
|
||||
self.app.save_setting(self.session, 'foo', 'bar')
|
||||
|
@ -454,7 +466,7 @@ class TestMasterView(WebTestCase):
|
|||
model_name='Widget',
|
||||
model_key='uuid'):
|
||||
view = master.MasterView(self.request)
|
||||
form = view.make_model_form()
|
||||
form = view.make_model_form(fields=['name', 'description'])
|
||||
form.validated = {'name': 'first'}
|
||||
obj = view.objectify(form)
|
||||
self.assertIs(obj, form.validated)
|
||||
|
@ -666,7 +678,6 @@ class TestMasterView(WebTestCase):
|
|||
self.assertIn('frazzle', response.text)
|
||||
|
||||
def delete_instance(setting):
|
||||
print(setting) # TODO
|
||||
self.app.delete_setting(self.session, setting['name'])
|
||||
|
||||
# post request to save settings
|
||||
|
|
|
@ -7,7 +7,7 @@ from sqlalchemy import orm
|
|||
from pyramid.httpexceptions import HTTPNotFound
|
||||
|
||||
from wuttaweb.views import people
|
||||
from tests.views.utils import WebTestCase
|
||||
from tests.util import WebTestCase
|
||||
|
||||
|
||||
class TestPersonView(WebTestCase):
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
from unittest.mock import patch
|
||||
|
||||
from tests.views.utils import WebTestCase
|
||||
|
||||
from pyramid.httpexceptions import HTTPNotFound
|
||||
|
||||
from wuttaweb.views import settings
|
||||
from tests.util import WebTestCase
|
||||
|
||||
|
||||
class TestAppInfoView(WebTestCase):
|
||||
|
|
58
tests/views/test_users.py
Normal file
58
tests/views/test_users.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from sqlalchemy import orm
|
||||
|
||||
import colander
|
||||
from pyramid.httpexceptions import HTTPNotFound
|
||||
|
||||
from wuttaweb.views import users
|
||||
from tests.util import WebTestCase
|
||||
|
||||
|
||||
class TestPersonView(WebTestCase):
|
||||
|
||||
def make_view(self):
|
||||
return users.UserView(self.request)
|
||||
|
||||
def test_get_query(self):
|
||||
view = self.make_view()
|
||||
query = view.get_query(session=self.session)
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
|
||||
def test_configure_grid(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
grid = view.make_grid(model_class=model.User)
|
||||
self.assertFalse(grid.is_linked('person'))
|
||||
view.configure_grid(grid)
|
||||
self.assertTrue(grid.is_linked('person'))
|
||||
|
||||
def test_configure_form(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
form = view.make_form(model_class=model.Person)
|
||||
self.assertIsNone(form.is_required('person'))
|
||||
view.configure_form(form)
|
||||
self.assertFalse(form.is_required('person'))
|
||||
|
||||
def test_unique_username(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='foo')
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(users, 'Session', return_value=self.session):
|
||||
|
||||
# invalid if same username in data
|
||||
node = colander.SchemaNode(colander.String(), name='username')
|
||||
self.assertRaises(colander.Invalid, view.unique_username, node, 'foo')
|
||||
|
||||
# but not if username belongs to current user
|
||||
view.editing = True
|
||||
self.request.matchdict = {'uuid': user.uuid}
|
||||
node = colander.SchemaNode(colander.String(), name='username')
|
||||
self.assertIsNone(view.unique_username(node, 'foo'))
|
Loading…
Add table
Add a link
Reference in a new issue