fix: format all code with black
and from now on should not deviate from that...
This commit is contained in:
parent
8a09fb1a3c
commit
4d0693862d
68 changed files with 6693 additions and 5659 deletions
|
@ -10,8 +10,8 @@ from wuttaweb.cli import webapp as mod
|
|||
class TestWebapp(ConfigTestCase):
|
||||
|
||||
def make_context(self, **kwargs):
|
||||
params = {'auto_reload': False}
|
||||
params.update(kwargs.get('params', {}))
|
||||
params = {"auto_reload": False}
|
||||
params.update(kwargs.get("params", {}))
|
||||
ctx = MagicMock(params=params)
|
||||
ctx.parent.wutta_config = self.config
|
||||
return ctx
|
||||
|
@ -19,7 +19,7 @@ class TestWebapp(ConfigTestCase):
|
|||
def test_missing_config_file(self):
|
||||
# nb. our default config has no files, so can test w/ that
|
||||
ctx = self.make_context()
|
||||
with patch.object(mod, 'sys') as sys:
|
||||
with patch.object(mod, "sys") as sys:
|
||||
sys.exit.side_effect = RuntimeError
|
||||
self.assertRaises(RuntimeError, mod.webapp, ctx)
|
||||
sys.stderr.write.assert_called_once_with("no config files found!\n")
|
||||
|
@ -28,14 +28,17 @@ class TestWebapp(ConfigTestCase):
|
|||
def test_invalid_runner(self):
|
||||
|
||||
# make new config from file, with bad setting
|
||||
path = self.write_file('my.conf', """
|
||||
path = self.write_file(
|
||||
"my.conf",
|
||||
"""
|
||||
[wutta.web]
|
||||
app.runner = bogus
|
||||
""")
|
||||
""",
|
||||
)
|
||||
self.config = self.make_config(files=[path])
|
||||
|
||||
ctx = self.make_context()
|
||||
with patch.object(mod, 'sys') as sys:
|
||||
with patch.object(mod, "sys") as sys:
|
||||
sys.exit.side_effect = RuntimeError
|
||||
self.assertRaises(RuntimeError, mod.webapp, ctx)
|
||||
sys.stderr.write.assert_called_once_with("unknown web app runner: bogus\n")
|
||||
|
@ -43,64 +46,76 @@ app.runner = bogus
|
|||
|
||||
def test_pserve(self):
|
||||
|
||||
path = self.write_file('my.conf', """
|
||||
path = self.write_file(
|
||||
"my.conf",
|
||||
"""
|
||||
[wutta.web]
|
||||
app.runner = pserve
|
||||
""")
|
||||
""",
|
||||
)
|
||||
self.config = self.make_config(files=[path])
|
||||
|
||||
# normal
|
||||
with patch.object(mod, 'pserve') as pserve:
|
||||
with patch.object(mod, "pserve") as pserve:
|
||||
ctx = self.make_context()
|
||||
mod.webapp(ctx)
|
||||
pserve.main.assert_called_once_with(argv=['pserve', f'file+ini:{path}'])
|
||||
pserve.main.assert_called_once_with(argv=["pserve", f"file+ini:{path}"])
|
||||
|
||||
# with reload
|
||||
with patch.object(mod, 'pserve') as pserve:
|
||||
ctx = self.make_context(params={'auto_reload': True})
|
||||
with patch.object(mod, "pserve") as pserve:
|
||||
ctx = self.make_context(params={"auto_reload": True})
|
||||
mod.webapp(ctx)
|
||||
pserve.main.assert_called_once_with(argv=['pserve', f'file+ini:{path}', '--reload'])
|
||||
pserve.main.assert_called_once_with(
|
||||
argv=["pserve", f"file+ini:{path}", "--reload"]
|
||||
)
|
||||
|
||||
def test_uvicorn(self):
|
||||
|
||||
path = self.write_file('my.conf', """
|
||||
path = self.write_file(
|
||||
"my.conf",
|
||||
"""
|
||||
[wutta.web]
|
||||
app.runner = uvicorn
|
||||
app.spec = wuttaweb.app:make_wsgi_app
|
||||
""")
|
||||
""",
|
||||
)
|
||||
self.config = self.make_config(files=[path])
|
||||
|
||||
orig_import = __import__
|
||||
uvicorn = MagicMock()
|
||||
|
||||
def mock_import(name, *args, **kwargs):
|
||||
if name == 'uvicorn':
|
||||
if name == "uvicorn":
|
||||
return uvicorn
|
||||
return orig_import(name, *args, **kwargs)
|
||||
|
||||
# normal
|
||||
with patch('builtins.__import__', side_effect=mock_import):
|
||||
with patch("builtins.__import__", side_effect=mock_import):
|
||||
ctx = self.make_context()
|
||||
mod.webapp(ctx)
|
||||
uvicorn.run.assert_called_once_with('wuttaweb.app:make_wsgi_app',
|
||||
host='127.0.0.1',
|
||||
port=8000,
|
||||
reload=False,
|
||||
reload_dirs=None,
|
||||
factory=False,
|
||||
interface='auto',
|
||||
root_path='')
|
||||
uvicorn.run.assert_called_once_with(
|
||||
"wuttaweb.app:make_wsgi_app",
|
||||
host="127.0.0.1",
|
||||
port=8000,
|
||||
reload=False,
|
||||
reload_dirs=None,
|
||||
factory=False,
|
||||
interface="auto",
|
||||
root_path="",
|
||||
)
|
||||
|
||||
# with reload
|
||||
uvicorn.run.reset_mock()
|
||||
with patch('builtins.__import__', side_effect=mock_import):
|
||||
ctx = self.make_context(params={'auto_reload': True})
|
||||
with patch("builtins.__import__", side_effect=mock_import):
|
||||
ctx = self.make_context(params={"auto_reload": True})
|
||||
mod.webapp(ctx)
|
||||
uvicorn.run.assert_called_once_with('wuttaweb.app:make_wsgi_app',
|
||||
host='127.0.0.1',
|
||||
port=8000,
|
||||
reload=True,
|
||||
reload_dirs=None,
|
||||
factory=False,
|
||||
interface='auto',
|
||||
root_path='')
|
||||
uvicorn.run.assert_called_once_with(
|
||||
"wuttaweb.app:make_wsgi_app",
|
||||
host="127.0.0.1",
|
||||
port=8000,
|
||||
reload=True,
|
||||
reload_dirs=None,
|
||||
factory=False,
|
||||
interface="auto",
|
||||
root_path="",
|
||||
)
|
||||
|
|
|
@ -11,7 +11,7 @@ from wuttaweb.testing import WebTestCase
|
|||
class TestWuttaWebContinuumPlugin(WebTestCase):
|
||||
|
||||
def setUp(self):
|
||||
if not hasattr(mod, 'WuttaWebContinuumPlugin'):
|
||||
if not hasattr(mod, "WuttaWebContinuumPlugin"):
|
||||
pytest.skip("test not relevant without sqlalchemy-continuum")
|
||||
self.setup_web()
|
||||
|
||||
|
@ -21,17 +21,17 @@ class TestWuttaWebContinuumPlugin(WebTestCase):
|
|||
def test_get_remote_addr(self):
|
||||
plugin = self.make_plugin()
|
||||
|
||||
with patch.object(mod, 'get_current_request', return_value=None):
|
||||
with patch.object(mod, "get_current_request", return_value=None):
|
||||
self.assertIsNone(plugin.get_remote_addr(None, self.session))
|
||||
|
||||
self.request.client_addr = '127.0.0.1'
|
||||
self.assertEqual(plugin.get_remote_addr(None, self.session), '127.0.0.1')
|
||||
self.request.client_addr = "127.0.0.1"
|
||||
self.assertEqual(plugin.get_remote_addr(None, self.session), "127.0.0.1")
|
||||
|
||||
def test_get_user_id(self):
|
||||
plugin = self.make_plugin()
|
||||
|
||||
with patch.object(mod, 'get_current_request', return_value=None):
|
||||
with patch.object(mod, "get_current_request", return_value=None):
|
||||
self.assertIsNone(plugin.get_user_id(None, self.session))
|
||||
|
||||
self.request.user = MagicMock(uuid='some-random-uuid')
|
||||
self.assertEqual(plugin.get_user_id(None, self.session), 'some-random-uuid')
|
||||
self.request.user = MagicMock(uuid="some-random-uuid")
|
||||
self.assertEqual(plugin.get_user_id(None, self.session), "some-random-uuid")
|
||||
|
|
|
@ -18,17 +18,22 @@ from wuttaweb.grids import Grid
|
|||
class TestForm(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.web.menus.handler_spec': 'tests.util:NullMenuHandler',
|
||||
})
|
||||
self.config = WuttaConfig(
|
||||
defaults={
|
||||
"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)
|
||||
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
'mako.directories': ['wuttaweb:templates'],
|
||||
'pyramid_deform.template_search_path': 'wuttaweb:templates/deform',
|
||||
})
|
||||
self.pyramid_config = testing.setUp(
|
||||
request=self.request,
|
||||
settings={
|
||||
"wutta_config": self.config,
|
||||
"mako.directories": ["wuttaweb:templates"],
|
||||
"pyramid_deform.template_search_path": "wuttaweb:templates/deform",
|
||||
},
|
||||
)
|
||||
|
||||
event = MagicMock(request=self.request)
|
||||
subscribers.new_request(event)
|
||||
|
@ -40,12 +45,12 @@ class TestForm(TestCase):
|
|||
return base.Form(self.request, **kwargs)
|
||||
|
||||
def make_schema(self):
|
||||
schema = colander.Schema(children=[
|
||||
colander.SchemaNode(colander.String(),
|
||||
name='foo'),
|
||||
colander.SchemaNode(colander.String(),
|
||||
name='bar'),
|
||||
])
|
||||
schema = colander.Schema(
|
||||
children=[
|
||||
colander.SchemaNode(colander.String(), name="foo"),
|
||||
colander.SchemaNode(colander.String(), name="bar"),
|
||||
]
|
||||
)
|
||||
return schema
|
||||
|
||||
def test_init_with_none(self):
|
||||
|
@ -53,126 +58,126 @@ class TestForm(TestCase):
|
|||
self.assertEqual(form.fields, [])
|
||||
|
||||
def test_init_with_fields(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.fields, ['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.fields, ["foo", "bar"])
|
||||
|
||||
def test_init_with_schema(self):
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
self.assertEqual(form.fields, ['foo', 'bar'])
|
||||
self.assertEqual(form.fields, ["foo", "bar"])
|
||||
|
||||
def test_vue_tagname(self):
|
||||
form = self.make_form()
|
||||
self.assertEqual(form.vue_tagname, 'wutta-form')
|
||||
self.assertEqual(form.vue_tagname, "wutta-form")
|
||||
|
||||
def test_vue_component(self):
|
||||
form = self.make_form()
|
||||
self.assertEqual(form.vue_component, 'WuttaForm')
|
||||
self.assertEqual(form.vue_component, "WuttaForm")
|
||||
|
||||
def test_contains(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertIn('foo', form)
|
||||
self.assertNotIn('baz', form)
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertIn("foo", form)
|
||||
self.assertNotIn("baz", form)
|
||||
|
||||
def test_iter(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
|
||||
fields = list(iter(form))
|
||||
self.assertEqual(fields, ['foo', 'bar'])
|
||||
self.assertEqual(fields, ["foo", "bar"])
|
||||
|
||||
fields = []
|
||||
for field in form:
|
||||
fields.append(field)
|
||||
self.assertEqual(fields, ['foo', 'bar'])
|
||||
self.assertEqual(fields, ["foo", "bar"])
|
||||
|
||||
def test_set_fields(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.fields, ['foo', 'bar'])
|
||||
form.set_fields(['baz'])
|
||||
self.assertEqual(form.fields, ['baz'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.fields, ["foo", "bar"])
|
||||
form.set_fields(["baz"])
|
||||
self.assertEqual(form.fields, ["baz"])
|
||||
|
||||
def test_append(self):
|
||||
form = self.make_form(fields=['one', 'two'])
|
||||
self.assertEqual(form.fields, ['one', 'two'])
|
||||
form.append('one', 'two', 'three')
|
||||
self.assertEqual(form.fields, ['one', 'two', 'three'])
|
||||
form = self.make_form(fields=["one", "two"])
|
||||
self.assertEqual(form.fields, ["one", "two"])
|
||||
form.append("one", "two", "three")
|
||||
self.assertEqual(form.fields, ["one", "two", "three"])
|
||||
|
||||
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'])
|
||||
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'])
|
||||
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)
|
||||
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']
|
||||
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')
|
||||
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']
|
||||
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')
|
||||
self.assertEqual(node.name, "foo")
|
||||
|
||||
def test_set_widget(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
form.set_widget("foo", new_widget)
|
||||
self.assertIs(form.widgets["foo"], new_widget)
|
||||
self.assertIs(schema["foo"].widget, new_widget)
|
||||
|
||||
# can also just specify widget pseudo-type (invalid)
|
||||
self.assertNotIn('bar', form.widgets)
|
||||
self.assertRaises(ValueError, form.set_widget, 'bar', 'ldjfadjfadj')
|
||||
self.assertNotIn("bar", form.widgets)
|
||||
self.assertRaises(ValueError, form.set_widget, "bar", "ldjfadjfadj")
|
||||
|
||||
# can also just specify widget pseudo-type (valid)
|
||||
self.assertNotIn('bar', form.widgets)
|
||||
form.set_widget('bar', 'notes')
|
||||
self.assertIsInstance(form.widgets['bar'], widgets.NotesWidget)
|
||||
self.assertNotIn("bar", form.widgets)
|
||||
form.set_widget("bar", "notes")
|
||||
self.assertIsInstance(form.widgets["bar"], widgets.NotesWidget)
|
||||
|
||||
def test_make_widget(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
|
||||
# notes
|
||||
widget = form.make_widget('notes')
|
||||
widget = form.make_widget("notes")
|
||||
self.assertIsInstance(widget, widgets.NotesWidget)
|
||||
|
||||
# invalid
|
||||
widget = form.make_widget('fdajvdafjjf')
|
||||
widget = form.make_widget("fdajvdafjjf")
|
||||
self.assertIsNone(widget)
|
||||
|
||||
def test_set_default_widgets(self):
|
||||
model = self.app.model
|
||||
|
||||
# no defaults for "plain" schema
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.widgets, {})
|
||||
|
||||
# no defaults for "plain" mapped class
|
||||
|
@ -184,52 +189,56 @@ class TestForm(TestCase):
|
|||
|
||||
# widget set for datetime mapped field
|
||||
form = self.make_form(model_class=model.Upgrade)
|
||||
self.assertIn('created', form.widgets)
|
||||
self.assertIsNot(form.widgets['created'], MyWidget)
|
||||
self.assertNotIsInstance(form.widgets['created'], MyWidget)
|
||||
self.assertIn("created", form.widgets)
|
||||
self.assertIsNot(form.widgets["created"], MyWidget)
|
||||
self.assertNotIsInstance(form.widgets["created"], MyWidget)
|
||||
|
||||
# widget *not* set for datetime, if override present
|
||||
form = self.make_form(model_class=model.Upgrade,
|
||||
widgets={'created': MyWidget()})
|
||||
self.assertIn('created', form.widgets)
|
||||
self.assertIsInstance(form.widgets['created'], MyWidget)
|
||||
form = self.make_form(
|
||||
model_class=model.Upgrade, widgets={"created": MyWidget()}
|
||||
)
|
||||
self.assertIn("created", form.widgets)
|
||||
self.assertIsInstance(form.widgets["created"], MyWidget)
|
||||
|
||||
# mock up a table with all relevant column types
|
||||
class Whatever(model.Base):
|
||||
__tablename__ = 'whatever'
|
||||
__tablename__ = "whatever"
|
||||
id = sa.Column(sa.Integer(), primary_key=True)
|
||||
date = sa.Column(sa.Date())
|
||||
date_time = sa.Column(sa.DateTime())
|
||||
|
||||
# widget set for all known types
|
||||
form = self.make_form(model_class=Whatever)
|
||||
self.assertIsInstance(form.widgets['date'], widgets.WuttaDateWidget)
|
||||
self.assertIsInstance(form.widgets['date_time'], widgets.WuttaDateTimeWidget)
|
||||
self.assertIsInstance(form.widgets["date"], widgets.WuttaDateWidget)
|
||||
self.assertIsInstance(form.widgets["date_time"], widgets.WuttaDateTimeWidget)
|
||||
|
||||
def test_set_grid(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertNotIn('foo', form.widgets)
|
||||
self.assertNotIn('foogrid', form.grid_vue_context)
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertNotIn("foo", form.widgets)
|
||||
self.assertNotIn("foogrid", form.grid_vue_context)
|
||||
|
||||
grid = Grid(self.request, key='foogrid',
|
||||
columns=['a', 'b'],
|
||||
data=[{'a': 1, 'b': 2}, {'a': 3, 'b': 4}])
|
||||
grid = Grid(
|
||||
self.request,
|
||||
key="foogrid",
|
||||
columns=["a", "b"],
|
||||
data=[{"a": 1, "b": 2}, {"a": 3, "b": 4}],
|
||||
)
|
||||
|
||||
form.set_grid('foo', grid)
|
||||
self.assertIn('foo', form.widgets)
|
||||
self.assertIsInstance(form.widgets['foo'], widgets.GridWidget)
|
||||
self.assertIn('foogrid', form.grid_vue_context)
|
||||
form.set_grid("foo", grid)
|
||||
self.assertIn("foo", form.widgets)
|
||||
self.assertIsInstance(form.widgets["foo"], widgets.GridWidget)
|
||||
self.assertIn("foogrid", form.grid_vue_context)
|
||||
|
||||
def test_set_validator(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
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)
|
||||
form.set_validator("foo", validate1)
|
||||
self.assertIs(form.validators["foo"], validate1)
|
||||
|
||||
def validate2(node, value):
|
||||
pass
|
||||
|
@ -237,18 +246,18 @@ class TestForm(TestCase):
|
|||
# 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)
|
||||
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_set_default(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.defaults, {})
|
||||
|
||||
# basic
|
||||
form.set_default('foo', 42)
|
||||
self.assertEqual(form.defaults['foo'], 42)
|
||||
form.set_default("foo", 42)
|
||||
self.assertEqual(form.defaults["foo"], 42)
|
||||
|
||||
def test_get_schema(self):
|
||||
model = self.app.model
|
||||
|
@ -262,10 +271,10 @@ class TestForm(TestCase):
|
|||
self.assertIs(form.get_schema(), schema)
|
||||
|
||||
# schema is auto-generated if fields provided
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
schema = form.get_schema()
|
||||
self.assertEqual(len(schema.children), 2)
|
||||
self.assertEqual(schema['foo'].name, 'foo')
|
||||
self.assertEqual(schema["foo"].name, "foo")
|
||||
|
||||
# but auto-generating without fields is not supported
|
||||
form = self.make_form()
|
||||
|
@ -276,58 +285,62 @@ class TestForm(TestCase):
|
|||
form = self.make_form(model_class=model.Setting)
|
||||
schema = form.get_schema()
|
||||
self.assertEqual(len(schema.children), 2)
|
||||
self.assertIn('name', schema)
|
||||
self.assertIn('value', schema)
|
||||
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)
|
||||
value_node = colander.SchemaNode(colander.Bool(), name="value")
|
||||
form.set_node("value", value_node)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['value'], value_node)
|
||||
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'])
|
||||
form = self.make_form(model_instance=model.Setting(name="uhoh"))
|
||||
self.assertEqual(form.fields, ["name", "value"])
|
||||
self.assertIsNone(form.schema)
|
||||
# nb. force method to get new fields
|
||||
del form.fields
|
||||
schema = form.get_schema()
|
||||
self.assertEqual(len(schema.children), 2)
|
||||
self.assertIn('name', schema)
|
||||
self.assertIn('value', schema)
|
||||
self.assertIn("name", schema)
|
||||
self.assertIn("value", schema)
|
||||
|
||||
# ColanderAlchemy schema still has *all* requested fields
|
||||
form = self.make_form(model_instance=model.Setting(name='uhoh'),
|
||||
fields=['name', 'value', 'foo', 'bar'])
|
||||
self.assertEqual(form.fields, ['name', 'value', 'foo', 'bar'])
|
||||
form = self.make_form(
|
||||
model_instance=model.Setting(name="uhoh"),
|
||||
fields=["name", "value", "foo", "bar"],
|
||||
)
|
||||
self.assertEqual(form.fields, ["name", "value", "foo", "bar"])
|
||||
self.assertIsNone(form.schema)
|
||||
schema = form.get_schema()
|
||||
self.assertEqual(len(schema.children), 4)
|
||||
self.assertIn('name', schema)
|
||||
self.assertIn('value', schema)
|
||||
self.assertIn('foo', schema)
|
||||
self.assertIn('bar', schema)
|
||||
self.assertIn("name", schema)
|
||||
self.assertIn("value", schema)
|
||||
self.assertIn("foo", schema)
|
||||
self.assertIn("bar", schema)
|
||||
|
||||
# schema nodes are required by default
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['foo'].missing, colander.required)
|
||||
self.assertIs(schema['bar'].missing, colander.required)
|
||||
self.assertIs(schema["foo"].missing, colander.required)
|
||||
self.assertIs(schema["bar"].missing, colander.required)
|
||||
|
||||
# but fields can be marked *not* required
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form.set_required('bar', False)
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
form.set_required("bar", False)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['foo'].missing, colander.required)
|
||||
self.assertIs(schema['bar'].missing, colander.null)
|
||||
self.assertIs(schema["foo"].missing, colander.required)
|
||||
self.assertIs(schema["bar"].missing, colander.null)
|
||||
|
||||
# validator overrides are honored
|
||||
def validate(node, value): pass
|
||||
def validate(node, value):
|
||||
pass
|
||||
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
form.set_validator('name', validate)
|
||||
form.set_validator("name", validate)
|
||||
schema = form.get_schema()
|
||||
self.assertIs(schema['name'].validator, validate)
|
||||
self.assertIs(schema["name"].validator, validate)
|
||||
|
||||
# validator can be set for whole form
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
|
@ -340,9 +353,9 @@ class TestForm(TestCase):
|
|||
|
||||
# default value overrides are honored
|
||||
form = self.make_form(model_class=model.Setting)
|
||||
form.set_default('name', 'foo')
|
||||
form.set_default("name", "foo")
|
||||
schema = form.get_schema()
|
||||
self.assertEqual(schema['name'].default, 'foo')
|
||||
self.assertEqual(schema["name"].default, "foo")
|
||||
|
||||
def test_get_deform(self):
|
||||
model = self.app.model
|
||||
|
@ -350,139 +363,142 @@ class TestForm(TestCase):
|
|||
|
||||
# basic
|
||||
form = self.make_form(schema=schema)
|
||||
self.assertFalse(hasattr(form, 'deform_form'))
|
||||
self.assertFalse(hasattr(form, "deform_form"))
|
||||
dform = form.get_deform()
|
||||
self.assertIsInstance(dform, deform.Form)
|
||||
self.assertIs(form.deform_form, dform)
|
||||
|
||||
# with model instance as dict
|
||||
myobj = {'foo': 'one', 'bar': 'two'}
|
||||
myobj = {"foo": "one", "bar": "two"}
|
||||
form = self.make_form(schema=schema, model_instance=myobj)
|
||||
dform = form.get_deform()
|
||||
self.assertEqual(dform.cstruct, myobj)
|
||||
|
||||
# with sqlalchemy model instance
|
||||
myobj = model.Setting(name='foo', value='bar')
|
||||
myobj = model.Setting(name="foo", value="bar")
|
||||
form = self.make_form(model_instance=myobj)
|
||||
dform = form.get_deform()
|
||||
self.assertEqual(dform.cstruct, {'name': 'foo', 'value': 'bar'})
|
||||
self.assertEqual(dform.cstruct, {"name": "foo", "value": "bar"})
|
||||
|
||||
# sqlalchemy instance with null value
|
||||
myobj = model.Setting(name='foo', value=None)
|
||||
myobj = model.Setting(name="foo", value=None)
|
||||
form = self.make_form(model_instance=myobj)
|
||||
dform = form.get_deform()
|
||||
self.assertEqual(dform.cstruct, {'name': 'foo', 'value': colander.null})
|
||||
self.assertEqual(dform.cstruct, {"name": "foo", "value": colander.null})
|
||||
|
||||
def test_get_cancel_url(self):
|
||||
|
||||
# is referrer by default
|
||||
form = self.make_form()
|
||||
self.request.get_referrer = MagicMock(return_value='/cancel-default')
|
||||
self.assertEqual(form.get_cancel_url(), '/cancel-default')
|
||||
self.request.get_referrer = MagicMock(return_value="/cancel-default")
|
||||
self.assertEqual(form.get_cancel_url(), "/cancel-default")
|
||||
del self.request.get_referrer
|
||||
|
||||
# or can be static URL
|
||||
form = self.make_form(cancel_url='/cancel-static')
|
||||
self.assertEqual(form.get_cancel_url(), '/cancel-static')
|
||||
form = self.make_form(cancel_url="/cancel-static")
|
||||
self.assertEqual(form.get_cancel_url(), "/cancel-static")
|
||||
|
||||
# or can be fallback URL (nb. 'NOPE' indicates no referrer)
|
||||
form = self.make_form(cancel_url_fallback='/cancel-fallback')
|
||||
self.request.get_referrer = MagicMock(return_value='NOPE')
|
||||
self.assertEqual(form.get_cancel_url(), '/cancel-fallback')
|
||||
form = self.make_form(cancel_url_fallback="/cancel-fallback")
|
||||
self.request.get_referrer = MagicMock(return_value="NOPE")
|
||||
self.assertEqual(form.get_cancel_url(), "/cancel-fallback")
|
||||
del self.request.get_referrer
|
||||
|
||||
# or can be referrer fallback, i.e. home page
|
||||
form = self.make_form()
|
||||
|
||||
def get_referrer(default=None):
|
||||
if default == 'NOPE':
|
||||
return 'NOPE'
|
||||
return '/home-page'
|
||||
if default == "NOPE":
|
||||
return "NOPE"
|
||||
return "/home-page"
|
||||
|
||||
self.request.get_referrer = get_referrer
|
||||
self.assertEqual(form.get_cancel_url(), '/home-page')
|
||||
self.assertEqual(form.get_cancel_url(), "/home-page")
|
||||
del self.request.get_referrer
|
||||
|
||||
def test_get_label(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.get_label('foo'), "Foo")
|
||||
form.set_label('foo', "Baz")
|
||||
self.assertEqual(form.get_label('foo'), "Baz")
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.get_label("foo"), "Foo")
|
||||
form.set_label("foo", "Baz")
|
||||
self.assertEqual(form.get_label("foo"), "Baz")
|
||||
|
||||
def test_set_label(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
self.assertEqual(form.get_label('foo'), "Foo")
|
||||
form.set_label('foo', "Baz")
|
||||
self.assertEqual(form.get_label('foo'), "Baz")
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.get_label("foo"), "Foo")
|
||||
form.set_label("foo", "Baz")
|
||||
self.assertEqual(form.get_label("foo"), "Baz")
|
||||
|
||||
# schema should be updated when setting label
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
form.set_label('foo', "Woohoo")
|
||||
self.assertEqual(form.get_label('foo'), "Woohoo")
|
||||
self.assertEqual(schema['foo'].title, "Woohoo")
|
||||
form.set_label("foo", "Woohoo")
|
||||
self.assertEqual(form.get_label("foo"), "Woohoo")
|
||||
self.assertEqual(schema["foo"].title, "Woohoo")
|
||||
|
||||
def test_readonly_fields(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.readonly_fields, set())
|
||||
self.assertFalse(form.is_readonly('foo'))
|
||||
self.assertFalse(form.is_readonly("foo"))
|
||||
|
||||
form.set_readonly('foo')
|
||||
self.assertEqual(form.readonly_fields, {'foo'})
|
||||
self.assertTrue(form.is_readonly('foo'))
|
||||
self.assertFalse(form.is_readonly('bar'))
|
||||
form.set_readonly("foo")
|
||||
self.assertEqual(form.readonly_fields, {"foo"})
|
||||
self.assertTrue(form.is_readonly("foo"))
|
||||
self.assertFalse(form.is_readonly("bar"))
|
||||
|
||||
form.set_readonly('bar')
|
||||
self.assertEqual(form.readonly_fields, {'foo', 'bar'})
|
||||
self.assertTrue(form.is_readonly('foo'))
|
||||
self.assertTrue(form.is_readonly('bar'))
|
||||
form.set_readonly("bar")
|
||||
self.assertEqual(form.readonly_fields, {"foo", "bar"})
|
||||
self.assertTrue(form.is_readonly("foo"))
|
||||
self.assertTrue(form.is_readonly("bar"))
|
||||
|
||||
form.set_readonly('foo', False)
|
||||
self.assertEqual(form.readonly_fields, {'bar'})
|
||||
self.assertFalse(form.is_readonly('foo'))
|
||||
self.assertTrue(form.is_readonly('bar'))
|
||||
form.set_readonly("foo", False)
|
||||
self.assertEqual(form.readonly_fields, {"bar"})
|
||||
self.assertFalse(form.is_readonly("foo"))
|
||||
self.assertTrue(form.is_readonly("bar"))
|
||||
|
||||
def test_required_fields(self):
|
||||
form = self.make_form(fields=['foo', 'bar'])
|
||||
form = self.make_form(fields=["foo", "bar"])
|
||||
self.assertEqual(form.required_fields, {})
|
||||
self.assertIsNone(form.is_required('foo'))
|
||||
self.assertIsNone(form.is_required("foo"))
|
||||
|
||||
form.set_required('foo')
|
||||
self.assertEqual(form.required_fields, {'foo': True})
|
||||
self.assertTrue(form.is_required('foo'))
|
||||
self.assertIsNone(form.is_required('bar'))
|
||||
form.set_required("foo")
|
||||
self.assertEqual(form.required_fields, {"foo": True})
|
||||
self.assertTrue(form.is_required("foo"))
|
||||
self.assertIsNone(form.is_required("bar"))
|
||||
|
||||
form.set_required('bar')
|
||||
self.assertEqual(form.required_fields, {'foo': True, 'bar': True})
|
||||
self.assertTrue(form.is_required('foo'))
|
||||
self.assertTrue(form.is_required('bar'))
|
||||
form.set_required("bar")
|
||||
self.assertEqual(form.required_fields, {"foo": True, "bar": True})
|
||||
self.assertTrue(form.is_required("foo"))
|
||||
self.assertTrue(form.is_required("bar"))
|
||||
|
||||
form.set_required('foo', False)
|
||||
self.assertEqual(form.required_fields, {'foo': False, 'bar': True})
|
||||
self.assertFalse(form.is_required('foo'))
|
||||
self.assertTrue(form.is_required('bar'))
|
||||
form.set_required("foo", False)
|
||||
self.assertEqual(form.required_fields, {"foo": False, "bar": True})
|
||||
self.assertFalse(form.is_required("foo"))
|
||||
self.assertTrue(form.is_required("bar"))
|
||||
|
||||
def test_render_vue_tag(self):
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
html = form.render_vue_tag()
|
||||
self.assertEqual(html, '<wutta-form></wutta-form>')
|
||||
self.assertEqual(html, "<wutta-form></wutta-form>")
|
||||
|
||||
def test_render_vue_template(self):
|
||||
self.pyramid_config.include('pyramid_mako')
|
||||
self.pyramid_config.add_subscriber('wuttaweb.subscribers.before_render',
|
||||
'pyramid.events.BeforeRender')
|
||||
self.pyramid_config.include("pyramid_mako")
|
||||
self.pyramid_config.add_subscriber(
|
||||
"wuttaweb.subscribers.before_render", "pyramid.events.BeforeRender"
|
||||
)
|
||||
|
||||
# form button is disabled on @submit by default
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema, cancel_url='/')
|
||||
form = self.make_form(schema=schema, cancel_url="/")
|
||||
html = form.render_vue_template()
|
||||
self.assertIn('<script type="text/x-template" id="wutta-form-template">', html)
|
||||
self.assertIn('@submit', html)
|
||||
self.assertIn("@submit", html)
|
||||
|
||||
# but not if form is configured otherwise
|
||||
form = self.make_form(schema=schema, auto_disable_submit=False, cancel_url='/')
|
||||
form = self.make_form(schema=schema, auto_disable_submit=False, cancel_url="/")
|
||||
html = form.render_vue_template()
|
||||
self.assertIn('<script type="text/x-template" id="wutta-form-template">', html)
|
||||
self.assertNotIn('@submit', html)
|
||||
self.assertNotIn("@submit", html)
|
||||
|
||||
def test_add_grid_vue_context(self):
|
||||
form = self.make_form()
|
||||
|
@ -492,76 +508,84 @@ class TestForm(TestCase):
|
|||
self.assertRaises(ValueError, form.add_grid_vue_context, grid)
|
||||
|
||||
# otherwise it works
|
||||
grid = Grid(self.request, key='foo')
|
||||
grid = Grid(self.request, key="foo")
|
||||
self.assertEqual(len(form.grid_vue_context), 0)
|
||||
form.add_grid_vue_context(grid)
|
||||
self.assertEqual(len(form.grid_vue_context), 1)
|
||||
self.assertIn('foo', form.grid_vue_context)
|
||||
self.assertEqual(form.grid_vue_context['foo'], {
|
||||
'data': [],
|
||||
'row_classes': {},
|
||||
})
|
||||
self.assertIn("foo", form.grid_vue_context)
|
||||
self.assertEqual(
|
||||
form.grid_vue_context["foo"],
|
||||
{
|
||||
"data": [],
|
||||
"row_classes": {},
|
||||
},
|
||||
)
|
||||
|
||||
# calling again with same key will replace data
|
||||
records = [{'foo': 1}, {'foo': 2}]
|
||||
grid = Grid(self.request, key='foo', columns=['foo'], data=records)
|
||||
records = [{"foo": 1}, {"foo": 2}]
|
||||
grid = Grid(self.request, key="foo", columns=["foo"], data=records)
|
||||
form.add_grid_vue_context(grid)
|
||||
self.assertEqual(len(form.grid_vue_context), 1)
|
||||
self.assertIn('foo', form.grid_vue_context)
|
||||
self.assertEqual(form.grid_vue_context['foo'], {
|
||||
'data': records,
|
||||
'row_classes': {},
|
||||
})
|
||||
self.assertIn("foo", form.grid_vue_context)
|
||||
self.assertEqual(
|
||||
form.grid_vue_context["foo"],
|
||||
{
|
||||
"data": records,
|
||||
"row_classes": {},
|
||||
},
|
||||
)
|
||||
|
||||
def test_render_vue_finalize(self):
|
||||
form = self.make_form()
|
||||
html = form.render_vue_finalize()
|
||||
self.assertIn('<script>', html)
|
||||
self.assertIn("<script>", html)
|
||||
self.assertIn("Vue.component('wutta-form', WuttaForm)", html)
|
||||
|
||||
def test_render_vue_field(self):
|
||||
self.pyramid_config.include('pyramid_deform')
|
||||
self.pyramid_config.include("pyramid_deform")
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
dform = form.get_deform()
|
||||
|
||||
# typical
|
||||
html = form.render_vue_field('foo')
|
||||
html = form.render_vue_field("foo")
|
||||
self.assertIn('<b-field :horizontal="true" label="Foo">', html)
|
||||
self.assertIn('<b-input name="foo"', html)
|
||||
# nb. no error message
|
||||
self.assertNotIn('message', html)
|
||||
self.assertNotIn("message", html)
|
||||
|
||||
# readonly
|
||||
html = form.render_vue_field('foo', readonly=True)
|
||||
html = form.render_vue_field("foo", readonly=True)
|
||||
self.assertIn('<b-field :horizontal="true" label="Foo">', html)
|
||||
self.assertNotIn('<b-input name="foo"', html)
|
||||
# nb. no error message
|
||||
self.assertNotIn('message', html)
|
||||
self.assertNotIn("message", html)
|
||||
|
||||
# with error message
|
||||
with patch.object(form, 'get_field_errors', return_value=['something is wrong']):
|
||||
html = form.render_vue_field('foo')
|
||||
self.assertIn('something is wrong', html)
|
||||
with patch.object(
|
||||
form, "get_field_errors", return_value=["something is wrong"]
|
||||
):
|
||||
html = form.render_vue_field("foo")
|
||||
self.assertIn("something is wrong", html)
|
||||
|
||||
# add another field, but not to deform, so it should still
|
||||
# display but with no widget
|
||||
form.fields.append('zanzibar')
|
||||
html = form.render_vue_field('zanzibar')
|
||||
form.fields.append("zanzibar")
|
||||
html = form.render_vue_field("zanzibar")
|
||||
self.assertIn('<b-field :horizontal="true" label="Zanzibar">', html)
|
||||
self.assertNotIn('<b-input', html)
|
||||
self.assertNotIn("<b-input", html)
|
||||
# nb. no error message
|
||||
self.assertNotIn('message', html)
|
||||
self.assertNotIn("message", html)
|
||||
|
||||
# try that once more but with a model record instance
|
||||
with patch.object(form, 'model_instance', new={'zanzibar': 'omgwtfbbq'}):
|
||||
html = form.render_vue_field('zanzibar')
|
||||
self.assertIn('<b-field', html)
|
||||
with patch.object(form, "model_instance", new={"zanzibar": "omgwtfbbq"}):
|
||||
html = form.render_vue_field("zanzibar")
|
||||
self.assertIn("<b-field", html)
|
||||
self.assertIn('label="Zanzibar"', html)
|
||||
self.assertNotIn('<b-input', html)
|
||||
self.assertIn('>omgwtfbbq<', html)
|
||||
self.assertNotIn("<b-input", html)
|
||||
self.assertIn(">omgwtfbbq<", html)
|
||||
# nb. no error message
|
||||
self.assertNotIn('message', html)
|
||||
self.assertNotIn("message", html)
|
||||
|
||||
def test_get_vue_field_value(self):
|
||||
schema = self.make_schema()
|
||||
|
@ -569,20 +593,20 @@ class TestForm(TestCase):
|
|||
|
||||
# TODO: yikes what a hack (?)
|
||||
dform = form.get_deform()
|
||||
dform.set_appstruct({'foo': 'one', 'bar': 'two'})
|
||||
dform.set_appstruct({"foo": "one", "bar": "two"})
|
||||
|
||||
# null for missing field
|
||||
value = form.get_vue_field_value('doesnotexist')
|
||||
value = form.get_vue_field_value("doesnotexist")
|
||||
self.assertIsNone(value)
|
||||
|
||||
# normal value is returned
|
||||
value = form.get_vue_field_value('foo')
|
||||
self.assertEqual(value, 'one')
|
||||
value = form.get_vue_field_value("foo")
|
||||
self.assertEqual(value, "one")
|
||||
|
||||
# but not if we remove field from deform
|
||||
# TODO: what is the use case here again?
|
||||
dform.children.remove(dform['foo'])
|
||||
value = form.get_vue_field_value('foo')
|
||||
dform.children.remove(dform["foo"])
|
||||
value = form.get_vue_field_value("foo")
|
||||
self.assertIsNone(value)
|
||||
|
||||
def test_get_vue_model_data(self):
|
||||
|
@ -594,19 +618,22 @@ class TestForm(TestCase):
|
|||
self.assertEqual(len(data), 2)
|
||||
|
||||
# still just 2 fields even if we request more
|
||||
form.set_fields(['foo', 'bar', 'baz'])
|
||||
form.set_fields(["foo", "bar", "baz"])
|
||||
data = form.get_vue_model_data()
|
||||
self.assertEqual(len(data), 2)
|
||||
|
||||
# confirm bool values make it thru as-is
|
||||
schema.add(colander.SchemaNode(colander.Bool(), name='baz'))
|
||||
form = self.make_form(schema=schema, model_instance={
|
||||
'foo': 'one',
|
||||
'bar': 'two',
|
||||
'baz': True,
|
||||
})
|
||||
schema.add(colander.SchemaNode(colander.Bool(), name="baz"))
|
||||
form = self.make_form(
|
||||
schema=schema,
|
||||
model_instance={
|
||||
"foo": "one",
|
||||
"bar": "two",
|
||||
"baz": True,
|
||||
},
|
||||
)
|
||||
data = form.get_vue_model_data()
|
||||
self.assertEqual(list(data.values()), ['one', 'two', True])
|
||||
self.assertEqual(list(data.values()), ["one", "two", True])
|
||||
|
||||
def test_has_global_errors(self):
|
||||
|
||||
|
@ -617,8 +644,8 @@ class TestForm(TestCase):
|
|||
schema.validator = fail
|
||||
form = self.make_form(schema=schema)
|
||||
self.assertFalse(form.has_global_errors())
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'foo': 'one', 'bar': 'two'}
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {"foo": "one", "bar": "two"}
|
||||
self.assertFalse(form.validate())
|
||||
self.assertTrue(form.has_global_errors())
|
||||
|
||||
|
@ -631,8 +658,8 @@ class TestForm(TestCase):
|
|||
schema.validator = fail
|
||||
form = self.make_form(schema=schema)
|
||||
self.assertEqual(form.get_global_errors(), [])
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'foo': 'one', 'bar': 'two'}
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {"foo": "one", "bar": "two"}
|
||||
self.assertFalse(form.validate())
|
||||
self.assertTrue(form.get_global_errors(), ["things are bad!"])
|
||||
|
||||
|
@ -641,55 +668,55 @@ class TestForm(TestCase):
|
|||
|
||||
# simple 'Required' validation failure
|
||||
form = self.make_form(schema=schema)
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'foo': 'one'}
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {"foo": "one"}
|
||||
self.assertFalse(form.validate())
|
||||
errors = form.get_field_errors('bar')
|
||||
self.assertEqual(errors, ['Required'])
|
||||
errors = form.get_field_errors("bar")
|
||||
self.assertEqual(errors, ["Required"])
|
||||
|
||||
# no errors
|
||||
form = self.make_form(schema=schema)
|
||||
self.request.POST = {'foo': 'one', 'bar': 'two'}
|
||||
self.request.POST = {"foo": "one", "bar": "two"}
|
||||
self.assertTrue(form.validate())
|
||||
errors = form.get_field_errors('bar')
|
||||
errors = form.get_field_errors("bar")
|
||||
self.assertEqual(errors, [])
|
||||
|
||||
def test_validate(self):
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
self.assertFalse(hasattr(form, 'validated'))
|
||||
self.assertFalse(hasattr(form, "validated"))
|
||||
|
||||
# will not validate unless request is POST
|
||||
self.request.POST = {'foo': 'blarg', 'bar': 'baz'}
|
||||
self.request.method = 'GET'
|
||||
self.request.POST = {"foo": "blarg", "bar": "baz"}
|
||||
self.request.method = "GET"
|
||||
self.assertFalse(form.validate())
|
||||
self.request.method = 'POST'
|
||||
self.request.method = "POST"
|
||||
data = form.validate()
|
||||
self.assertEqual(data, {'foo': 'blarg', 'bar': 'baz'})
|
||||
self.assertEqual(data, {"foo": "blarg", "bar": "baz"})
|
||||
|
||||
# validating a second time updates form.validated
|
||||
self.request.POST = {'foo': 'BLARG', 'bar': 'BAZ'}
|
||||
self.request.POST = {"foo": "BLARG", "bar": "BAZ"}
|
||||
data = form.validate()
|
||||
self.assertEqual(data, {'foo': 'BLARG', 'bar': 'BAZ'})
|
||||
self.assertEqual(data, {"foo": "BLARG", "bar": "BAZ"})
|
||||
self.assertIs(form.validated, data)
|
||||
|
||||
# bad data does not validate
|
||||
self.request.POST = {'foo': 42, 'bar': None}
|
||||
self.request.POST = {"foo": 42, "bar": None}
|
||||
self.assertFalse(form.validate())
|
||||
dform = form.get_deform()
|
||||
self.assertEqual(len(dform.error.children), 2)
|
||||
self.assertEqual(dform['foo'].errormsg, "Pstruct is not a string")
|
||||
self.assertEqual(dform["foo"].errormsg, "Pstruct is not a string")
|
||||
|
||||
# when a form has readonly fields, validating it will *remove*
|
||||
# those fields from deform/schema as well as final data dict
|
||||
schema = self.make_schema()
|
||||
form = self.make_form(schema=schema)
|
||||
form.set_readonly('foo')
|
||||
self.request.POST = {'foo': 'one', 'bar': 'two'}
|
||||
form.set_readonly("foo")
|
||||
self.request.POST = {"foo": "one", "bar": "two"}
|
||||
data = form.validate()
|
||||
self.assertEqual(data, {'bar': 'two'})
|
||||
self.assertEqual(data, {"bar": "two"})
|
||||
dform = form.get_deform()
|
||||
self.assertNotIn('foo', schema)
|
||||
self.assertNotIn('foo', dform)
|
||||
self.assertIn('bar', schema)
|
||||
self.assertIn('bar', dform)
|
||||
self.assertNotIn("foo", schema)
|
||||
self.assertNotIn("foo", dform)
|
||||
self.assertIn("bar", schema)
|
||||
self.assertIn("bar", dform)
|
||||
|
|
|
@ -25,17 +25,17 @@ class TestWuttaDateTime(TestCase):
|
|||
result = typ.deserialize(node, colander.null)
|
||||
self.assertIs(result, colander.null)
|
||||
|
||||
result = typ.deserialize(node, '2024-12-11T10:33 PM')
|
||||
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')
|
||||
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')
|
||||
self.assertRaises(colander.Invalid, typ.deserialize, node, "bogus")
|
||||
|
||||
|
||||
class TestObjectNode(DataTestCase):
|
||||
|
@ -84,20 +84,24 @@ class TestWuttaEnum(WebTestCase):
|
|||
MOCK_STATUS_ONE = 1
|
||||
MOCK_STATUS_TWO = 2
|
||||
MOCK_STATUS = {
|
||||
MOCK_STATUS_ONE: 'one',
|
||||
MOCK_STATUS_TWO: 'two',
|
||||
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'),
|
||||
])
|
||||
self.assertEqual(
|
||||
widget.values,
|
||||
[
|
||||
(1, "one"),
|
||||
(2, "two"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TestWuttaMoney(WebTestCase):
|
||||
|
@ -132,13 +136,13 @@ class TestWuttaQuantity(WebTestCase):
|
|||
|
||||
# quantity
|
||||
result = typ.serialize(node, 42)
|
||||
self.assertEqual(result, '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')
|
||||
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')
|
||||
self.assertEqual(result, "42.13")
|
||||
|
||||
|
||||
class TestObjectRef(DataTestCase):
|
||||
|
@ -155,19 +159,19 @@ class TestObjectRef(DataTestCase):
|
|||
|
||||
# passing true yields default empty option
|
||||
typ = mod.ObjectRef(self.request, empty_option=True)
|
||||
self.assertEqual(typ.empty_option, ('', "(none)"))
|
||||
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'))
|
||||
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)"))
|
||||
self.assertEqual(typ.empty_option, ("", "(empty)"))
|
||||
|
||||
def test_model_class(self):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
self.assertRaises(NotImplementedError, getattr, typ, 'model_class')
|
||||
self.assertRaises(NotImplementedError, getattr, typ, "model_class")
|
||||
|
||||
def test_serialize(self):
|
||||
model = self.app.model
|
||||
|
@ -188,9 +192,9 @@ class TestObjectRef(DataTestCase):
|
|||
self.assertEqual(value, person.uuid.hex)
|
||||
|
||||
# null w/ empty option
|
||||
typ = mod.ObjectRef(self.request, empty_option=('bad', 'BAD'))
|
||||
typ = mod.ObjectRef(self.request, empty_option=("bad", "BAD"))
|
||||
value = typ.serialize(node, colander.null)
|
||||
self.assertEqual(value, 'bad')
|
||||
self.assertEqual(value, "bad")
|
||||
|
||||
def test_deserialize(self):
|
||||
model = self.app.model
|
||||
|
@ -206,8 +210,8 @@ class TestObjectRef(DataTestCase):
|
|||
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):
|
||||
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)
|
||||
|
@ -234,14 +238,14 @@ class TestObjectRef(DataTestCase):
|
|||
value = typ.objectify(None)
|
||||
self.assertIsNone(value)
|
||||
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
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):
|
||||
with patch.object(mod.ObjectRef, "model_class", new=model.Person):
|
||||
|
||||
# can specify as uuid
|
||||
typ = mod.ObjectRef(self.request)
|
||||
|
@ -254,22 +258,22 @@ class TestObjectRef(DataTestCase):
|
|||
self.assertIs(value, person)
|
||||
|
||||
# error if not found
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
with patch.object(mod.ObjectRef, "model_class", new=model.Person):
|
||||
typ = mod.ObjectRef(self.request)
|
||||
self.assertRaises(ValueError, typ.objectify, 'WRONG-UUID')
|
||||
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):
|
||||
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):
|
||||
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)
|
||||
|
@ -282,16 +286,16 @@ class TestObjectRef(DataTestCase):
|
|||
self.session.commit()
|
||||
|
||||
# basic
|
||||
with patch.object(mod.ObjectRef, 'model_class', new=model.Person):
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
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):
|
||||
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)
|
||||
|
@ -302,7 +306,7 @@ class TestObjectRef(DataTestCase):
|
|||
class TestPersonRef(WebTestCase):
|
||||
|
||||
def test_sort_query(self):
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
typ = mod.PersonRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
|
@ -311,9 +315,9 @@ class TestPersonRef(WebTestCase):
|
|||
self.assertIsNot(sorted_query, query)
|
||||
|
||||
def test_get_object_url(self):
|
||||
self.pyramid_config.add_route('people.view', '/people/{uuid}')
|
||||
self.pyramid_config.add_route("people.view", "/people/{uuid}")
|
||||
model = self.app.model
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
typ = mod.PersonRef(self.request)
|
||||
|
||||
person = model.Person(full_name="Barney Rubble")
|
||||
|
@ -322,13 +326,13 @@ class TestPersonRef(WebTestCase):
|
|||
|
||||
url = typ.get_object_url(person)
|
||||
self.assertIsNotNone(url)
|
||||
self.assertIn(f'/people/{person.uuid}', 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):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
typ = mod.RoleRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
|
@ -337,24 +341,24 @@ class TestRoleRef(WebTestCase):
|
|||
self.assertIsNot(sorted_query, query)
|
||||
|
||||
def test_get_object_url(self):
|
||||
self.pyramid_config.add_route('roles.view', '/roles/{uuid}')
|
||||
self.pyramid_config.add_route("roles.view", "/roles/{uuid}")
|
||||
model = self.app.model
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
typ = mod.RoleRef(self.request)
|
||||
|
||||
role = model.Role(name='Manager')
|
||||
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)
|
||||
self.assertIn(f"/roles/{role.uuid}", url)
|
||||
|
||||
|
||||
class TestUserRef(WebTestCase):
|
||||
|
||||
def test_sort_query(self):
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
typ = mod.UserRef(self.request)
|
||||
query = typ.get_query()
|
||||
self.assertIsInstance(query, orm.Query)
|
||||
|
@ -363,18 +367,18 @@ class TestUserRef(WebTestCase):
|
|||
self.assertIsNot(sorted_query, query)
|
||||
|
||||
def test_get_object_url(self):
|
||||
self.pyramid_config.add_route('users.view', '/users/{uuid}')
|
||||
self.pyramid_config.add_route("users.view", "/users/{uuid}")
|
||||
model = self.app.model
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
typ = mod.UserRef(self.request)
|
||||
|
||||
user = model.User(username='barney')
|
||||
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)
|
||||
self.assertIn(f"/users/{user.uuid}", url)
|
||||
|
||||
|
||||
class TestRoleRefs(DataTestCase):
|
||||
|
@ -393,7 +397,7 @@ class TestRoleRefs(DataTestCase):
|
|||
self.session.add(blokes)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
|
||||
# with root access, default values include: admin, blokes
|
||||
self.request.is_root = True
|
||||
|
@ -427,11 +431,11 @@ class TestPermissions(DataTestCase):
|
|||
|
||||
# supported permissions are morphed to values
|
||||
permissions = {
|
||||
'widgets': {
|
||||
'label': "Widgets",
|
||||
'perms': {
|
||||
'widgets.polish': {
|
||||
'label': "Polish the widgets",
|
||||
"widgets": {
|
||||
"label": "Widgets",
|
||||
"perms": {
|
||||
"widgets.polish": {
|
||||
"label": "Polish the widgets",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -439,7 +443,7 @@ class TestPermissions(DataTestCase):
|
|||
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"))
|
||||
self.assertEqual(widget.values[0], ("widgets.polish", "Polish the widgets"))
|
||||
|
||||
|
||||
class TestFileDownload(DataTestCase):
|
||||
|
@ -451,10 +455,10 @@ class TestFileDownload(DataTestCase):
|
|||
def test_widget_maker(self):
|
||||
|
||||
# sanity / coverage check
|
||||
typ = mod.FileDownload(self.request, url='/foo')
|
||||
typ = mod.FileDownload(self.request, url="/foo")
|
||||
widget = typ.widget_maker()
|
||||
self.assertIsInstance(widget, widgets.FileDownloadWidget)
|
||||
self.assertEqual(widget.url, '/foo')
|
||||
self.assertEqual(widget.url, "/foo")
|
||||
|
||||
|
||||
class TestEmailRecipients(TestCase):
|
||||
|
@ -464,14 +468,14 @@ class TestEmailRecipients(TestCase):
|
|||
node = colander.SchemaNode(typ)
|
||||
|
||||
recips = [
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
"alice@example.com",
|
||||
"bob@example.com",
|
||||
]
|
||||
recips_str = ', '.join(recips)
|
||||
recips_str = ", ".join(recips)
|
||||
|
||||
# values
|
||||
result = typ.serialize(node, recips_str)
|
||||
self.assertEqual(result, '\n'.join(recips))
|
||||
self.assertEqual(result, "\n".join(recips))
|
||||
|
||||
# null
|
||||
result = typ.serialize(node, colander.null)
|
||||
|
@ -482,10 +486,10 @@ class TestEmailRecipients(TestCase):
|
|||
node = colander.SchemaNode(typ)
|
||||
|
||||
recips = [
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
"alice@example.com",
|
||||
"bob@example.com",
|
||||
]
|
||||
recips_str = ', '.join(recips)
|
||||
recips_str = ", ".join(recips)
|
||||
|
||||
# values
|
||||
result = typ.deserialize(node, recips_str)
|
||||
|
|
|
@ -11,8 +11,14 @@ from pyramid import testing
|
|||
from wuttaweb import grids
|
||||
from wuttaweb.forms import widgets as mod
|
||||
from wuttaweb.forms import schema
|
||||
from wuttaweb.forms.schema import (FileDownload, PersonRef, RoleRefs, Permissions,
|
||||
WuttaDateTime, EmailRecipients)
|
||||
from wuttaweb.forms.schema import (
|
||||
FileDownload,
|
||||
PersonRef,
|
||||
RoleRefs,
|
||||
Permissions,
|
||||
WuttaDateTime,
|
||||
EmailRecipients,
|
||||
)
|
||||
from wuttaweb.testing import WebTestCase
|
||||
|
||||
|
||||
|
@ -21,7 +27,7 @@ class TestObjectRefWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def make_widget(self, **kwargs):
|
||||
|
@ -33,14 +39,14 @@ class TestObjectRefWidget(WebTestCase):
|
|||
self.session.add(person)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
with patch.object(schema, "Session", return_value=self.session):
|
||||
|
||||
# standard (editable)
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid)
|
||||
self.assertIn('<b-select ', html)
|
||||
self.assertIn("<b-select ", html)
|
||||
|
||||
# readonly
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
|
@ -48,17 +54,17 @@ class TestObjectRefWidget(WebTestCase):
|
|||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertIn('Betty Boop', html)
|
||||
self.assertNotIn('<a', html)
|
||||
self.assertIn("Betty Boop", html)
|
||||
self.assertNotIn("<a", html)
|
||||
|
||||
# with hyperlink
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
node.model_instance = person
|
||||
widget = self.make_widget(url=lambda p: '/foo')
|
||||
widget = self.make_widget(url=lambda p: "/foo")
|
||||
field = self.make_field(node)
|
||||
html = widget.serialize(field, person.uuid, readonly=True)
|
||||
self.assertIn('Betty Boop', html)
|
||||
self.assertIn('<a', html)
|
||||
self.assertIn("Betty Boop", html)
|
||||
self.assertIn("<a", html)
|
||||
self.assertIn('href="/foo"', html)
|
||||
|
||||
def test_get_template_values(self):
|
||||
|
@ -67,24 +73,25 @@ class TestObjectRefWidget(WebTestCase):
|
|||
self.session.add(person)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
with patch.object(schema, "Session", return_value=self.session):
|
||||
|
||||
# standard
|
||||
node = colander.SchemaNode(PersonRef(self.request))
|
||||
widget = self.make_widget()
|
||||
field = self.make_field(node)
|
||||
values = widget.get_template_values(field, person.uuid, {})
|
||||
self.assertIn('cstruct', values)
|
||||
self.assertNotIn('url', values)
|
||||
self.assertIn("cstruct", values)
|
||||
self.assertNotIn("url", values)
|
||||
|
||||
# readonly w/ empty option
|
||||
node = colander.SchemaNode(PersonRef(self.request,
|
||||
empty_option=('_empty_', '(empty)')))
|
||||
widget = self.make_widget(readonly=True, url=lambda obj: '/foo')
|
||||
node = colander.SchemaNode(
|
||||
PersonRef(self.request, empty_option=("_empty_", "(empty)"))
|
||||
)
|
||||
widget = self.make_widget(readonly=True, url=lambda obj: "/foo")
|
||||
field = self.make_field(node)
|
||||
values = widget.get_template_values(field, '_empty_', {})
|
||||
self.assertIn('cstruct', values)
|
||||
self.assertNotIn('url', values)
|
||||
values = widget.get_template_values(field, "_empty_", {})
|
||||
self.assertIn("cstruct", values)
|
||||
self.assertNotIn("url", values)
|
||||
|
||||
|
||||
class TestWuttaDateWidget(WebTestCase):
|
||||
|
@ -92,7 +99,7 @@ class TestWuttaDateWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def make_widget(self, **kwargs):
|
||||
|
@ -108,11 +115,11 @@ class TestWuttaDateWidget(WebTestCase):
|
|||
|
||||
# editable widget has normal picker html
|
||||
result = widget.serialize(field, str(dt))
|
||||
self.assertIn('<wutta-datepicker', result)
|
||||
self.assertIn("<wutta-datepicker", result)
|
||||
|
||||
# readonly is rendered per app convention
|
||||
result = widget.serialize(field, str(dt), readonly=True)
|
||||
self.assertEqual(result, '2025-01-15')
|
||||
self.assertEqual(result, "2025-01-15")
|
||||
|
||||
# now try again with datetime
|
||||
widget = self.make_widget()
|
||||
|
@ -120,11 +127,11 @@ class TestWuttaDateWidget(WebTestCase):
|
|||
|
||||
# editable widget has normal picker html
|
||||
result = widget.serialize(field, str(dt))
|
||||
self.assertIn('<wutta-datepicker', result)
|
||||
self.assertIn("<wutta-datepicker", result)
|
||||
|
||||
# readonly is rendered per app convention
|
||||
result = widget.serialize(field, str(dt), readonly=True)
|
||||
self.assertEqual(result, '2025-01-15')
|
||||
self.assertEqual(result, "2025-01-15")
|
||||
|
||||
|
||||
class TestWuttaDateTimeWidget(WebTestCase):
|
||||
|
@ -132,7 +139,7 @@ class TestWuttaDateTimeWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def make_widget(self, **kwargs):
|
||||
|
@ -146,11 +153,11 @@ class TestWuttaDateTimeWidget(WebTestCase):
|
|||
|
||||
# editable widget has normal picker html
|
||||
result = widget.serialize(field, str(dt))
|
||||
self.assertIn('<wutta-datepicker', result)
|
||||
self.assertIn("<wutta-datepicker", result)
|
||||
|
||||
# readonly is rendered per app convention
|
||||
result = widget.serialize(field, str(dt), readonly=True)
|
||||
self.assertEqual(result, '2024-12-12 13:49+0000')
|
||||
self.assertEqual(result, "2024-12-12 13:49+0000")
|
||||
|
||||
|
||||
class TestWuttaMoneyInputWidget(WebTestCase):
|
||||
|
@ -158,7 +165,7 @@ class TestWuttaMoneyInputWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def make_widget(self, **kwargs):
|
||||
|
@ -168,19 +175,19 @@ class TestWuttaMoneyInputWidget(WebTestCase):
|
|||
node = colander.SchemaNode(schema.WuttaMoney(self.request))
|
||||
field = self.make_field(node)
|
||||
widget = self.make_widget()
|
||||
amount = decimal.Decimal('12.34')
|
||||
amount = decimal.Decimal("12.34")
|
||||
|
||||
# editable widget has normal text input
|
||||
result = widget.serialize(field, str(amount))
|
||||
self.assertIn('<b-input', result)
|
||||
self.assertIn("<b-input", result)
|
||||
|
||||
# readonly is rendered per app convention
|
||||
result = widget.serialize(field, str(amount), readonly=True)
|
||||
self.assertEqual(result, '<span>$12.34</span>')
|
||||
self.assertEqual(result, "<span>$12.34</span>")
|
||||
|
||||
# readonly w/ null value
|
||||
result = widget.serialize(field, None, readonly=True)
|
||||
self.assertEqual(result, '<span></span>')
|
||||
self.assertEqual(result, "<span></span>")
|
||||
|
||||
|
||||
class TestFileDownloadWidget(WebTestCase):
|
||||
|
@ -188,7 +195,7 @@ class TestFileDownloadWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def test_serialize(self):
|
||||
|
@ -201,31 +208,31 @@ class TestFileDownloadWidget(WebTestCase):
|
|||
|
||||
# null value
|
||||
html = widget.serialize(field, None, readonly=True)
|
||||
self.assertNotIn('<a ', html)
|
||||
self.assertIn('<span>', html)
|
||||
self.assertNotIn("<a ", html)
|
||||
self.assertIn("<span>", html)
|
||||
|
||||
# path to nonexistent file
|
||||
html = widget.serialize(field, '/this/path/does/not/exist', readonly=True)
|
||||
self.assertNotIn('<a ', html)
|
||||
self.assertIn('<span>', html)
|
||||
html = widget.serialize(field, "/this/path/does/not/exist", readonly=True)
|
||||
self.assertNotIn("<a ", html)
|
||||
self.assertIn("<span>", html)
|
||||
|
||||
# path to actual file
|
||||
datfile = self.write_file('data.txt', "hello\n" * 1000)
|
||||
datfile = self.write_file("data.txt", "hello\n" * 1000)
|
||||
html = widget.serialize(field, datfile, readonly=True)
|
||||
self.assertNotIn('<a ', html)
|
||||
self.assertIn('<span>', html)
|
||||
self.assertIn('data.txt', html)
|
||||
self.assertIn('kB)', html)
|
||||
self.assertNotIn("<a ", html)
|
||||
self.assertIn("<span>", html)
|
||||
self.assertIn("data.txt", html)
|
||||
self.assertIn("kB)", html)
|
||||
|
||||
# path to file, w/ url
|
||||
node = colander.SchemaNode(FileDownload(self.request, url='/download/blarg'))
|
||||
node = colander.SchemaNode(FileDownload(self.request, url="/download/blarg"))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
html = widget.serialize(field, datfile, readonly=True)
|
||||
self.assertNotIn('<span>', html)
|
||||
self.assertNotIn("<span>", html)
|
||||
self.assertIn('<a href="/download/blarg">', html)
|
||||
self.assertIn('data.txt', html)
|
||||
self.assertIn('kB)', html)
|
||||
self.assertIn("data.txt", html)
|
||||
self.assertIn("kB)", html)
|
||||
|
||||
# nb. same readonly output even if we ask for editable
|
||||
html2 = widget.serialize(field, datfile, readonly=False)
|
||||
|
@ -237,13 +244,15 @@ class TestGridWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def test_serialize(self):
|
||||
grid = grids.Grid(self.request,
|
||||
columns=['foo', 'bar'],
|
||||
data=[{'foo': 1, 'bar': 2}, {'foo': 3, 'bar': 4}])
|
||||
grid = grids.Grid(
|
||||
self.request,
|
||||
columns=["foo", "bar"],
|
||||
data=[{"foo": 1, "bar": 2}, {"foo": 3, "bar": 4}],
|
||||
)
|
||||
|
||||
node = colander.SchemaNode(colander.String())
|
||||
widget = mod.GridWidget(self.request, grid)
|
||||
|
@ -251,7 +260,7 @@ class TestGridWidget(WebTestCase):
|
|||
|
||||
# readonly works okay
|
||||
html = widget.serialize(field, None, readonly=True)
|
||||
self.assertIn('<b-table ', html)
|
||||
self.assertIn("<b-table ", html)
|
||||
|
||||
# but otherwise, error
|
||||
self.assertRaises(NotImplementedError, widget.serialize, field, None)
|
||||
|
@ -262,11 +271,11 @@ class TestRoleRefsWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def test_serialize(self):
|
||||
self.pyramid_config.add_route('roles.view', '/roles/{uuid}')
|
||||
self.pyramid_config.add_route("roles.view", "/roles/{uuid}")
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
|
@ -275,7 +284,7 @@ class TestRoleRefsWidget(WebTestCase):
|
|||
self.session.commit()
|
||||
|
||||
# nb. we let the field construct the widget via our type
|
||||
with patch.object(schema, 'Session', return_value=self.session):
|
||||
with patch.object(schema, "Session", return_value=self.session):
|
||||
node = colander.SchemaNode(RoleRefs(self.request))
|
||||
field = self.make_field(node)
|
||||
widget = field.widget
|
||||
|
@ -305,16 +314,16 @@ class TestPermissionsWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def test_serialize(self):
|
||||
permissions = {
|
||||
'widgets': {
|
||||
'label': "Widgets",
|
||||
'perms': {
|
||||
'widgets.polish': {
|
||||
'label': "Polish the widgets",
|
||||
"widgets": {
|
||||
"label": "Widgets",
|
||||
"perms": {
|
||||
"widgets.polish": {
|
||||
"label": "Polish the widgets",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -330,7 +339,7 @@ class TestPermissionsWidget(WebTestCase):
|
|||
self.assertNotIn("Polish the widgets", html)
|
||||
|
||||
# readonly output includes the perm if set
|
||||
html = widget.serialize(field, {'widgets.polish'}, readonly=True)
|
||||
html = widget.serialize(field, {"widgets.polish"}, readonly=True)
|
||||
self.assertIn("Polish the widgets", html)
|
||||
|
||||
# editable output always includes the perm
|
||||
|
@ -343,7 +352,7 @@ class TestEmailRecipientsWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def test_serialize(self):
|
||||
|
@ -352,19 +361,19 @@ class TestEmailRecipientsWidget(WebTestCase):
|
|||
widget = mod.EmailRecipientsWidget()
|
||||
|
||||
recips = [
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
"alice@example.com",
|
||||
"bob@example.com",
|
||||
]
|
||||
recips_str = ', '.join(recips)
|
||||
recips_str = ", ".join(recips)
|
||||
|
||||
# readonly
|
||||
result = widget.serialize(field, recips_str, readonly=True)
|
||||
self.assertIn('<ul>', result)
|
||||
self.assertIn('<li>alice@example.com</li>', result)
|
||||
self.assertIn("<ul>", result)
|
||||
self.assertIn("<li>alice@example.com</li>", result)
|
||||
|
||||
# editable
|
||||
result = widget.serialize(field, recips_str)
|
||||
self.assertIn('<b-input', result)
|
||||
self.assertIn("<b-input", result)
|
||||
self.assertIn('type="textarea"', result)
|
||||
|
||||
def test_deserialize(self):
|
||||
|
@ -373,10 +382,10 @@ class TestEmailRecipientsWidget(WebTestCase):
|
|||
widget = mod.EmailRecipientsWidget()
|
||||
|
||||
recips = [
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
"alice@example.com",
|
||||
"bob@example.com",
|
||||
]
|
||||
recips_str = ', '.join(recips)
|
||||
recips_str = ", ".join(recips)
|
||||
|
||||
# values
|
||||
result = widget.deserialize(field, recips_str)
|
||||
|
@ -392,7 +401,7 @@ class TestBatchIdWidget(WebTestCase):
|
|||
def make_field(self, node, **kwargs):
|
||||
# TODO: not sure why default renderer is in use even though
|
||||
# pyramid_deform was included in setup? but this works..
|
||||
kwargs.setdefault('renderer', deform.Form.default_renderer)
|
||||
kwargs.setdefault("renderer", deform.Form.default_renderer)
|
||||
return deform.Field(node, **kwargs)
|
||||
|
||||
def test_serialize(self):
|
||||
|
@ -404,4 +413,4 @@ class TestBatchIdWidget(WebTestCase):
|
|||
self.assertIs(result, colander.null)
|
||||
|
||||
result = widget.serialize(field, 42)
|
||||
self.assertEqual(result, '00000042')
|
||||
self.assertEqual(result, "00000042")
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,24 +21,24 @@ class TestGridFilter(WebTestCase):
|
|||
|
||||
model = self.app.model
|
||||
self.sample_data = [
|
||||
{'name': 'foo1', 'value': 'ONE'},
|
||||
{'name': 'foo2', 'value': 'two'},
|
||||
{'name': 'foo3', 'value': 'ggg'},
|
||||
{'name': 'foo4', 'value': 'ggg'},
|
||||
{'name': 'foo5', 'value': 'ggg'},
|
||||
{'name': 'foo6', 'value': 'six'},
|
||||
{'name': 'foo7', 'value': 'seven'},
|
||||
{'name': 'foo8', 'value': 'eight'},
|
||||
{'name': 'foo9', 'value': 'nine'},
|
||||
{"name": "foo1", "value": "ONE"},
|
||||
{"name": "foo2", "value": "two"},
|
||||
{"name": "foo3", "value": "ggg"},
|
||||
{"name": "foo4", "value": "ggg"},
|
||||
{"name": "foo5", "value": "ggg"},
|
||||
{"name": "foo6", "value": "six"},
|
||||
{"name": "foo7", "value": "seven"},
|
||||
{"name": "foo8", "value": "eight"},
|
||||
{"name": "foo9", "value": "nine"},
|
||||
]
|
||||
for setting in self.sample_data:
|
||||
self.app.save_setting(self.session, setting['name'], setting['value'])
|
||||
self.app.save_setting(self.session, setting["name"], setting["value"])
|
||||
self.session.commit()
|
||||
self.sample_query = self.session.query(model.Setting)
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop('factory', mod.GridFilter)
|
||||
kwargs['model_property'] = model_property
|
||||
factory = kwargs.pop("factory", mod.GridFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_constructor(self):
|
||||
|
@ -46,158 +46,193 @@ class TestGridFilter(WebTestCase):
|
|||
|
||||
# verbs is not set by default, but can be set
|
||||
filtr = self.make_filter(model.Setting.name)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
filtr = self.make_filter(model.Setting.name, verbs=['foo', 'bar'])
|
||||
self.assertEqual(filtr.verbs, ['foo', 'bar'])
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
filtr = self.make_filter(model.Setting.name, verbs=["foo", "bar"])
|
||||
self.assertEqual(filtr.verbs, ["foo", "bar"])
|
||||
|
||||
# verb is not set by default, but can be set
|
||||
filtr = self.make_filter(model.Setting.name)
|
||||
self.assertFalse(hasattr(filtr, 'verb'))
|
||||
filtr = self.make_filter(model.Setting.name, verb='foo')
|
||||
self.assertEqual(filtr.verb, 'foo')
|
||||
self.assertFalse(hasattr(filtr, "verb"))
|
||||
filtr = self.make_filter(model.Setting.name, verb="foo")
|
||||
self.assertEqual(filtr.verb, "foo")
|
||||
|
||||
# default verb is not set by default, but can be set
|
||||
filtr = self.make_filter(model.Setting.name)
|
||||
self.assertFalse(hasattr(filtr, 'default_verb'))
|
||||
filtr = self.make_filter(model.Setting.name, default_verb='foo')
|
||||
self.assertEqual(filtr.default_verb, 'foo')
|
||||
self.assertFalse(hasattr(filtr, "default_verb"))
|
||||
filtr = self.make_filter(model.Setting.name, default_verb="foo")
|
||||
self.assertEqual(filtr.default_verb, "foo")
|
||||
|
||||
def test_repr(self):
|
||||
model = self.app.model
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.GridFilter)
|
||||
self.assertEqual(repr(filtr), "GridFilter(key='name', active=False, verb=None, value=None)")
|
||||
self.assertEqual(
|
||||
repr(filtr), "GridFilter(key='name', active=False, verb=None, value=None)"
|
||||
)
|
||||
|
||||
def test_get_verbs(self):
|
||||
model = self.app.model
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
self.assertEqual(filtr.default_verbs, ['equal', 'not_equal'])
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
self.assertEqual(filtr.default_verbs, ["equal", "not_equal"])
|
||||
|
||||
# by default, returns default verbs (plus 'is_any')
|
||||
self.assertEqual(filtr.get_verbs(), ['equal', 'not_equal', 'is_any'])
|
||||
self.assertEqual(filtr.get_verbs(), ["equal", "not_equal", "is_any"])
|
||||
|
||||
# default verbs can be a callable
|
||||
filtr.default_verbs = lambda: ['foo', 'bar']
|
||||
self.assertEqual(filtr.get_verbs(), ['foo', 'bar', 'is_any'])
|
||||
filtr.default_verbs = lambda: ["foo", "bar"]
|
||||
self.assertEqual(filtr.get_verbs(), ["foo", "bar", "is_any"])
|
||||
|
||||
# uses filtr.verbs if set
|
||||
filtr.verbs = ['is_true', 'is_false']
|
||||
self.assertEqual(filtr.get_verbs(), ['is_true', 'is_false', 'is_any'])
|
||||
filtr.verbs = ["is_true", "is_false"]
|
||||
self.assertEqual(filtr.get_verbs(), ["is_true", "is_false", "is_any"])
|
||||
|
||||
# may add is/null verbs
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter,
|
||||
nullable=True)
|
||||
self.assertEqual(filtr.get_verbs(), ['equal', 'not_equal',
|
||||
'is_null', 'is_not_null',
|
||||
'is_any'])
|
||||
filtr = self.make_filter(
|
||||
model.Setting.name, factory=mod.AlchemyFilter, nullable=True
|
||||
)
|
||||
self.assertEqual(
|
||||
filtr.get_verbs(),
|
||||
["equal", "not_equal", "is_null", "is_not_null", "is_any"],
|
||||
)
|
||||
|
||||
# filtr.verbs can be a callable
|
||||
filtr.nullable = False
|
||||
filtr.verbs = lambda: ['baz', 'blarg']
|
||||
self.assertEqual(filtr.get_verbs(), ['baz', 'blarg', 'is_any'])
|
||||
filtr.verbs = lambda: ["baz", "blarg"]
|
||||
self.assertEqual(filtr.get_verbs(), ["baz", "blarg", "is_any"])
|
||||
|
||||
def test_get_default_verb(self):
|
||||
model = self.app.model
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
self.assertEqual(filtr.default_verbs, ['equal', 'not_equal'])
|
||||
self.assertEqual(filtr.get_verbs(), ['equal', 'not_equal', 'is_any'])
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
self.assertEqual(filtr.default_verbs, ["equal", "not_equal"])
|
||||
self.assertEqual(filtr.get_verbs(), ["equal", "not_equal", "is_any"])
|
||||
|
||||
# returns first verb by default
|
||||
self.assertEqual(filtr.get_default_verb(), 'equal')
|
||||
self.assertEqual(filtr.get_default_verb(), "equal")
|
||||
|
||||
# returns filtr.verb if set
|
||||
filtr.verb = 'foo'
|
||||
self.assertEqual(filtr.get_default_verb(), 'foo')
|
||||
filtr.verb = "foo"
|
||||
self.assertEqual(filtr.get_default_verb(), "foo")
|
||||
|
||||
# returns filtr.default_verb if set
|
||||
# (nb. this overrides filtr.verb since the point of this
|
||||
# method is to return the *default* verb)
|
||||
filtr.default_verb = 'bar'
|
||||
self.assertEqual(filtr.get_default_verb(), 'bar')
|
||||
filtr.default_verb = "bar"
|
||||
self.assertEqual(filtr.get_default_verb(), "bar")
|
||||
|
||||
def test_get_verb_labels(self):
|
||||
model = self.app.model
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
self.assertEqual(filtr.get_verbs(), ['equal', 'not_equal', 'is_any'])
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
self.assertEqual(filtr.get_verbs(), ["equal", "not_equal", "is_any"])
|
||||
|
||||
labels = filtr.get_verb_labels()
|
||||
self.assertIsInstance(labels, dict)
|
||||
self.assertEqual(labels['equal'], "equal to")
|
||||
self.assertEqual(labels['not_equal'], "not equal to")
|
||||
self.assertEqual(labels['is_any'], "is any")
|
||||
self.assertEqual(labels["equal"], "equal to")
|
||||
self.assertEqual(labels["not_equal"], "not equal to")
|
||||
self.assertEqual(labels["is_any"], "is any")
|
||||
|
||||
def test_get_valueless_verbs(self):
|
||||
model = self.app.model
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
self.assertEqual(filtr.get_verbs(), ['equal', 'not_equal', 'is_any'])
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
self.assertEqual(filtr.get_verbs(), ["equal", "not_equal", "is_any"])
|
||||
|
||||
verbs = filtr.get_valueless_verbs()
|
||||
self.assertIsInstance(verbs, list)
|
||||
self.assertIn('is_any', verbs)
|
||||
self.assertIn("is_any", verbs)
|
||||
|
||||
def test_set_choices(self):
|
||||
model = self.app.model
|
||||
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter)
|
||||
self.assertEqual(filtr.choices, {})
|
||||
self.assertEqual(filtr.data_type, 'string')
|
||||
self.assertEqual(filtr.data_type, "string")
|
||||
|
||||
class MockEnum(Enum):
|
||||
FOO = 'foo'
|
||||
BAR = 'bar'
|
||||
FOO = "foo"
|
||||
BAR = "bar"
|
||||
|
||||
filtr.set_choices(MockEnum)
|
||||
self.assertEqual(filtr.choices, OrderedDict([
|
||||
('FOO', 'foo'),
|
||||
('BAR', 'bar'),
|
||||
]))
|
||||
self.assertEqual(filtr.data_type, 'choice')
|
||||
self.assertEqual(
|
||||
filtr.choices,
|
||||
OrderedDict(
|
||||
[
|
||||
("FOO", "foo"),
|
||||
("BAR", "bar"),
|
||||
]
|
||||
),
|
||||
)
|
||||
self.assertEqual(filtr.data_type, "choice")
|
||||
|
||||
filtr.set_choices(None)
|
||||
self.assertEqual(filtr.choices, {})
|
||||
self.assertEqual(filtr.data_type, 'string')
|
||||
self.assertEqual(filtr.data_type, "string")
|
||||
|
||||
def test_normalize_choices(self):
|
||||
model = self.app.model
|
||||
filtr = self.make_filter(model.Setting.name, factory=mod.AlchemyFilter)
|
||||
|
||||
class MockEnum(Enum):
|
||||
FOO = 'foo'
|
||||
BAR = 'bar'
|
||||
FOO = "foo"
|
||||
BAR = "bar"
|
||||
|
||||
choices = filtr.normalize_choices(MockEnum)
|
||||
self.assertEqual(choices, OrderedDict([
|
||||
('FOO', 'foo'),
|
||||
('BAR', 'bar'),
|
||||
]))
|
||||
self.assertEqual(
|
||||
choices,
|
||||
OrderedDict(
|
||||
[
|
||||
("FOO", "foo"),
|
||||
("BAR", "bar"),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
choices = filtr.normalize_choices(OrderedDict([
|
||||
('first', '1'),
|
||||
('second', '2'),
|
||||
]))
|
||||
self.assertEqual(choices, OrderedDict([
|
||||
('first', '1'),
|
||||
('second', '2'),
|
||||
]))
|
||||
choices = filtr.normalize_choices(
|
||||
OrderedDict(
|
||||
[
|
||||
("first", "1"),
|
||||
("second", "2"),
|
||||
]
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
choices,
|
||||
OrderedDict(
|
||||
[
|
||||
("first", "1"),
|
||||
("second", "2"),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
choices = filtr.normalize_choices({
|
||||
'bbb': 'b',
|
||||
'aaa': 'a',
|
||||
})
|
||||
self.assertEqual(choices, OrderedDict([
|
||||
('aaa', 'a'),
|
||||
('bbb', 'b'),
|
||||
]))
|
||||
choices = filtr.normalize_choices(
|
||||
{
|
||||
"bbb": "b",
|
||||
"aaa": "a",
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
choices,
|
||||
OrderedDict(
|
||||
[
|
||||
("aaa", "a"),
|
||||
("bbb", "b"),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
choices = filtr.normalize_choices(['one', 'two', 'three'])
|
||||
self.assertEqual(choices, OrderedDict([
|
||||
('one', 'one'),
|
||||
('two', 'two'),
|
||||
('three', 'three'),
|
||||
]))
|
||||
choices = filtr.normalize_choices(["one", "two", "three"])
|
||||
self.assertEqual(
|
||||
choices,
|
||||
OrderedDict(
|
||||
[
|
||||
("one", "one"),
|
||||
("two", "two"),
|
||||
("three", "three"),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
def test_apply_filter(self):
|
||||
model = self.app.model
|
||||
|
@ -205,32 +240,46 @@ class TestGridFilter(WebTestCase):
|
|||
|
||||
# default verb used as fallback
|
||||
# self.assertEqual(filtr.default_verb, 'contains')
|
||||
filtr.default_verb = 'contains'
|
||||
filtr.default_verb = "contains"
|
||||
filtr.verb = None
|
||||
with patch.object(filtr, 'filter_contains', side_effect=lambda q, v: q) as filter_contains:
|
||||
filtered_query = filtr.apply_filter(self.sample_query, value='foo')
|
||||
filter_contains.assert_called_once_with(self.sample_query, 'foo')
|
||||
with patch.object(
|
||||
filtr, "filter_contains", side_effect=lambda q, v: q
|
||||
) as filter_contains:
|
||||
filtered_query = filtr.apply_filter(self.sample_query, value="foo")
|
||||
filter_contains.assert_called_once_with(self.sample_query, "foo")
|
||||
self.assertIsNone(filtr.verb)
|
||||
|
||||
# filter verb used as fallback
|
||||
filtr.verb = 'equal'
|
||||
with patch.object(filtr, 'filter_equal', create=True, side_effect=lambda q, v: q) as filter_equal:
|
||||
filtered_query = filtr.apply_filter(self.sample_query, value='foo')
|
||||
filter_equal.assert_called_once_with(self.sample_query, 'foo')
|
||||
filtr.verb = "equal"
|
||||
with patch.object(
|
||||
filtr, "filter_equal", create=True, side_effect=lambda q, v: q
|
||||
) as filter_equal:
|
||||
filtered_query = filtr.apply_filter(self.sample_query, value="foo")
|
||||
filter_equal.assert_called_once_with(self.sample_query, "foo")
|
||||
|
||||
# filter value used as fallback
|
||||
filtr.verb = 'contains'
|
||||
filtr.value = 'blarg'
|
||||
with patch.object(filtr, 'filter_contains', side_effect=lambda q, v: q) as filter_contains:
|
||||
filtr.verb = "contains"
|
||||
filtr.value = "blarg"
|
||||
with patch.object(
|
||||
filtr, "filter_contains", side_effect=lambda q, v: q
|
||||
) as filter_contains:
|
||||
filtered_query = filtr.apply_filter(self.sample_query)
|
||||
filter_contains.assert_called_once_with(self.sample_query, 'blarg')
|
||||
filter_contains.assert_called_once_with(self.sample_query, "blarg")
|
||||
|
||||
# error if invalid verb
|
||||
self.assertRaises(mod.VerbNotSupported, filtr.apply_filter,
|
||||
self.sample_query, verb='doesnotexist')
|
||||
filtr.verbs = ['doesnotexist']
|
||||
self.assertRaises(mod.VerbNotSupported, filtr.apply_filter,
|
||||
self.sample_query, verb='doesnotexist')
|
||||
self.assertRaises(
|
||||
mod.VerbNotSupported,
|
||||
filtr.apply_filter,
|
||||
self.sample_query,
|
||||
verb="doesnotexist",
|
||||
)
|
||||
filtr.verbs = ["doesnotexist"]
|
||||
self.assertRaises(
|
||||
mod.VerbNotSupported,
|
||||
filtr.apply_filter,
|
||||
self.sample_query,
|
||||
verb="doesnotexist",
|
||||
)
|
||||
|
||||
def test_filter_is_any(self):
|
||||
model = self.app.model
|
||||
|
@ -250,24 +299,24 @@ class TestAlchemyFilter(WebTestCase):
|
|||
|
||||
model = self.app.model
|
||||
self.sample_data = [
|
||||
{'name': 'foo1', 'value': 'ONE'},
|
||||
{'name': 'foo2', 'value': 'two'},
|
||||
{'name': 'foo3', 'value': 'ggg'},
|
||||
{'name': 'foo4', 'value': 'ggg'},
|
||||
{'name': 'foo5', 'value': 'ggg'},
|
||||
{'name': 'foo6', 'value': 'six'},
|
||||
{'name': 'foo7', 'value': 'seven'},
|
||||
{'name': 'foo8', 'value': 'eight'},
|
||||
{'name': 'foo9', 'value': None},
|
||||
{"name": "foo1", "value": "ONE"},
|
||||
{"name": "foo2", "value": "two"},
|
||||
{"name": "foo3", "value": "ggg"},
|
||||
{"name": "foo4", "value": "ggg"},
|
||||
{"name": "foo5", "value": "ggg"},
|
||||
{"name": "foo6", "value": "six"},
|
||||
{"name": "foo7", "value": "seven"},
|
||||
{"name": "foo8", "value": "eight"},
|
||||
{"name": "foo9", "value": None},
|
||||
]
|
||||
for setting in self.sample_data:
|
||||
self.app.save_setting(self.session, setting['name'], setting['value'])
|
||||
self.app.save_setting(self.session, setting["name"], setting["value"])
|
||||
self.session.commit()
|
||||
self.sample_query = self.session.query(model.Setting)
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop('factory', mod.AlchemyFilter)
|
||||
kwargs['model_property'] = model_property
|
||||
factory = kwargs.pop("factory", mod.AlchemyFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_filter_equal(self):
|
||||
|
@ -280,12 +329,12 @@ class TestAlchemyFilter(WebTestCase):
|
|||
self.assertIs(filtered_query, self.sample_query)
|
||||
|
||||
# nb. by default, *is filtered* by empty string
|
||||
filtered_query = filtr.filter_equal(self.sample_query, '')
|
||||
filtered_query = filtr.filter_equal(self.sample_query, "")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 0)
|
||||
|
||||
# filtered by value
|
||||
filtered_query = filtr.filter_equal(self.sample_query, 'ggg')
|
||||
filtered_query = filtr.filter_equal(self.sample_query, "ggg")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 3)
|
||||
|
||||
|
@ -299,12 +348,12 @@ class TestAlchemyFilter(WebTestCase):
|
|||
self.assertIs(filtered_query, self.sample_query)
|
||||
|
||||
# nb. by default, *is filtered* by empty string
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, '')
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, "")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 9)
|
||||
|
||||
# filtered by value
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, 'ggg')
|
||||
filtered_query = filtr.filter_not_equal(self.sample_query, "ggg")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
|
@ -336,24 +385,24 @@ class TestStringAlchemyFilter(WebTestCase):
|
|||
|
||||
model = self.app.model
|
||||
self.sample_data = [
|
||||
{'name': 'foo1', 'value': 'ONE'},
|
||||
{'name': 'foo2', 'value': 'two'},
|
||||
{'name': 'foo3', 'value': 'ggg'},
|
||||
{'name': 'foo4', 'value': 'ggg'},
|
||||
{'name': 'foo5', 'value': 'ggg'},
|
||||
{'name': 'foo6', 'value': 'six'},
|
||||
{'name': 'foo7', 'value': 'seven'},
|
||||
{'name': 'foo8', 'value': 'eight'},
|
||||
{'name': 'foo9', 'value': 'nine'},
|
||||
{"name": "foo1", "value": "ONE"},
|
||||
{"name": "foo2", "value": "two"},
|
||||
{"name": "foo3", "value": "ggg"},
|
||||
{"name": "foo4", "value": "ggg"},
|
||||
{"name": "foo5", "value": "ggg"},
|
||||
{"name": "foo6", "value": "six"},
|
||||
{"name": "foo7", "value": "seven"},
|
||||
{"name": "foo8", "value": "eight"},
|
||||
{"name": "foo9", "value": "nine"},
|
||||
]
|
||||
for setting in self.sample_data:
|
||||
self.app.save_setting(self.session, setting['name'], setting['value'])
|
||||
self.app.save_setting(self.session, setting["name"], setting["value"])
|
||||
self.session.commit()
|
||||
self.sample_query = self.session.query(model.Setting)
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop('factory', mod.StringAlchemyFilter)
|
||||
kwargs['model_property'] = model_property
|
||||
factory = kwargs.pop("factory", mod.StringAlchemyFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_filter_contains(self):
|
||||
|
@ -364,11 +413,11 @@ class TestStringAlchemyFilter(WebTestCase):
|
|||
# not filtered for empty value
|
||||
filtered_query = filtr.filter_contains(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
filtered_query = filtr.filter_contains(self.sample_query, '')
|
||||
filtered_query = filtr.filter_contains(self.sample_query, "")
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
|
||||
# filtered by value
|
||||
filtered_query = filtr.filter_contains(self.sample_query, 'ggg')
|
||||
filtered_query = filtr.filter_contains(self.sample_query, "ggg")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 3)
|
||||
|
||||
|
@ -380,11 +429,11 @@ class TestStringAlchemyFilter(WebTestCase):
|
|||
# not filtered for empty value
|
||||
filtered_query = filtr.filter_does_not_contain(self.sample_query, None)
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
filtered_query = filtr.filter_does_not_contain(self.sample_query, '')
|
||||
filtered_query = filtr.filter_does_not_contain(self.sample_query, "")
|
||||
self.assertIs(filtered_query, self.sample_query)
|
||||
|
||||
# filtered by value
|
||||
filtered_query = filtr.filter_does_not_contain(self.sample_query, 'ggg')
|
||||
filtered_query = filtr.filter_does_not_contain(self.sample_query, "ggg")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
|
@ -392,8 +441,8 @@ class TestStringAlchemyFilter(WebTestCase):
|
|||
class TestIntegerAlchemyFilter(WebTestCase):
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop('factory', mod.IntegerAlchemyFilter)
|
||||
kwargs['model_property'] = model_property
|
||||
factory = kwargs.pop("factory", mod.IntegerAlchemyFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_coerce_value(self):
|
||||
|
@ -402,15 +451,15 @@ class TestIntegerAlchemyFilter(WebTestCase):
|
|||
|
||||
# null
|
||||
self.assertIsNone(filtr.coerce_value(None))
|
||||
self.assertIsNone(filtr.coerce_value(''))
|
||||
self.assertIsNone(filtr.coerce_value(""))
|
||||
|
||||
# typical
|
||||
self.assertEqual(filtr.coerce_value('42'), 42)
|
||||
self.assertEqual(filtr.coerce_value('-42'), -42)
|
||||
self.assertEqual(filtr.coerce_value("42"), 42)
|
||||
self.assertEqual(filtr.coerce_value("-42"), -42)
|
||||
|
||||
# invalid
|
||||
self.assertIsNone(filtr.coerce_value('42.12'))
|
||||
self.assertIsNone(filtr.coerce_value('bogus'))
|
||||
self.assertIsNone(filtr.coerce_value("42.12"))
|
||||
self.assertIsNone(filtr.coerce_value("bogus"))
|
||||
|
||||
|
||||
class TestBooleanAlchemyFilter(WebTestCase):
|
||||
|
@ -420,15 +469,9 @@ class TestBooleanAlchemyFilter(WebTestCase):
|
|||
|
||||
model = self.app.model
|
||||
self.sample_data = [
|
||||
{'username': 'alice',
|
||||
'prevent_edit': False,
|
||||
'active': True},
|
||||
{'username': 'bob',
|
||||
'prevent_edit': True,
|
||||
'active': True},
|
||||
{'username': 'charlie',
|
||||
'active': False,
|
||||
'prevent_edit': None},
|
||||
{"username": "alice", "prevent_edit": False, "active": True},
|
||||
{"username": "bob", "prevent_edit": True, "active": True},
|
||||
{"username": "charlie", "active": False, "prevent_edit": None},
|
||||
]
|
||||
for user in self.sample_data:
|
||||
user = model.User(**user)
|
||||
|
@ -437,37 +480,46 @@ class TestBooleanAlchemyFilter(WebTestCase):
|
|||
self.sample_query = self.session.query(model.User)
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop('factory', mod.BooleanAlchemyFilter)
|
||||
kwargs['model_property'] = model_property
|
||||
factory = kwargs.pop("factory", mod.BooleanAlchemyFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_get_verbs(self):
|
||||
model = self.app.model
|
||||
|
||||
# bool field, not nullable
|
||||
filtr = self.make_filter(model.User.active,
|
||||
factory=mod.BooleanAlchemyFilter,
|
||||
nullable=False)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
self.assertEqual(filtr.default_verbs, ['is_true', 'is_false'])
|
||||
filtr = self.make_filter(
|
||||
model.User.active, factory=mod.BooleanAlchemyFilter, nullable=False
|
||||
)
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
self.assertEqual(filtr.default_verbs, ["is_true", "is_false"])
|
||||
|
||||
# by default, returns default verbs (plus 'is_any')
|
||||
self.assertEqual(filtr.get_verbs(), ['is_true', 'is_false', 'is_any'])
|
||||
self.assertEqual(filtr.get_verbs(), ["is_true", "is_false", "is_any"])
|
||||
|
||||
# default verbs can be a callable
|
||||
filtr.default_verbs = lambda: ['foo', 'bar']
|
||||
self.assertEqual(filtr.get_verbs(), ['foo', 'bar', 'is_any'])
|
||||
filtr.default_verbs = lambda: ["foo", "bar"]
|
||||
self.assertEqual(filtr.get_verbs(), ["foo", "bar", "is_any"])
|
||||
|
||||
# bool field, *nullable*
|
||||
filtr = self.make_filter(model.User.active,
|
||||
factory=mod.BooleanAlchemyFilter,
|
||||
nullable=True)
|
||||
self.assertFalse(hasattr(filtr, 'verbs'))
|
||||
self.assertEqual(filtr.default_verbs, ['is_true', 'is_false'])
|
||||
filtr = self.make_filter(
|
||||
model.User.active, factory=mod.BooleanAlchemyFilter, nullable=True
|
||||
)
|
||||
self.assertFalse(hasattr(filtr, "verbs"))
|
||||
self.assertEqual(filtr.default_verbs, ["is_true", "is_false"])
|
||||
|
||||
# effective verbs also include is_false_null
|
||||
self.assertEqual(filtr.get_verbs(), ['is_true', 'is_false', 'is_false_null',
|
||||
'is_null', 'is_not_null', 'is_any'])
|
||||
self.assertEqual(
|
||||
filtr.get_verbs(),
|
||||
[
|
||||
"is_true",
|
||||
"is_false",
|
||||
"is_false_null",
|
||||
"is_null",
|
||||
"is_not_null",
|
||||
"is_any",
|
||||
],
|
||||
)
|
||||
|
||||
def test_coerce_value(self):
|
||||
model = self.app.model
|
||||
|
@ -477,11 +529,11 @@ class TestBooleanAlchemyFilter(WebTestCase):
|
|||
|
||||
self.assertTrue(filtr.coerce_value(True))
|
||||
self.assertTrue(filtr.coerce_value(1))
|
||||
self.assertTrue(filtr.coerce_value('1'))
|
||||
self.assertTrue(filtr.coerce_value("1"))
|
||||
|
||||
self.assertFalse(filtr.coerce_value(False))
|
||||
self.assertFalse(filtr.coerce_value(0))
|
||||
self.assertFalse(filtr.coerce_value(''))
|
||||
self.assertFalse(filtr.coerce_value(""))
|
||||
|
||||
def test_filter_is_true(self):
|
||||
model = self.app.model
|
||||
|
@ -515,7 +567,7 @@ class TestBooleanAlchemyFilter(WebTestCase):
|
|||
|
||||
|
||||
class TheLocalThing(Base):
|
||||
__tablename__ = 'the_local_thing'
|
||||
__tablename__ = "the_local_thing"
|
||||
id = sa.Column(sa.Integer(), primary_key=True, autoincrement=False)
|
||||
date = sa.Column(sa.DateTime(timezone=True), nullable=True)
|
||||
|
||||
|
@ -530,12 +582,12 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
model.Base.metadata.create_all(bind=self.session.bind)
|
||||
|
||||
self.sample_data = [
|
||||
{'id': 1, 'date': datetime.date(2024, 1, 1)},
|
||||
{'id': 2, 'date': datetime.date(2024, 1, 1)},
|
||||
{'id': 3, 'date': datetime.date(2024, 3, 1)},
|
||||
{'id': 4, 'date': datetime.date(2024, 3, 1)},
|
||||
{'id': 5, 'date': None},
|
||||
{'id': 6, 'date': None},
|
||||
{"id": 1, "date": datetime.date(2024, 1, 1)},
|
||||
{"id": 2, "date": datetime.date(2024, 1, 1)},
|
||||
{"id": 3, "date": datetime.date(2024, 3, 1)},
|
||||
{"id": 4, "date": datetime.date(2024, 3, 1)},
|
||||
{"id": 5, "date": None},
|
||||
{"id": 6, "date": None},
|
||||
]
|
||||
|
||||
for thing in self.sample_data:
|
||||
|
@ -546,8 +598,8 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.sample_query = self.session.query(TheLocalThing)
|
||||
|
||||
def make_filter(self, model_property, **kwargs):
|
||||
factory = kwargs.pop('factory', mod.DateAlchemyFilter)
|
||||
kwargs['model_property'] = model_property
|
||||
factory = kwargs.pop("factory", mod.DateAlchemyFilter)
|
||||
kwargs["model_property"] = model_property
|
||||
return factory(self.request, model_property.key, **kwargs)
|
||||
|
||||
def test_coerce_value(self):
|
||||
|
@ -562,12 +614,12 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.assertIs(value, result)
|
||||
|
||||
# value as string
|
||||
result = filtr.coerce_value('2024-04-01')
|
||||
result = filtr.coerce_value("2024-04-01")
|
||||
self.assertIsInstance(result, datetime.date)
|
||||
self.assertEqual(result, datetime.date(2024, 4, 1))
|
||||
|
||||
# invalid
|
||||
result = filtr.coerce_value('thisinputisbad')
|
||||
result = filtr.coerce_value("thisinputisbad")
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_greater_than(self):
|
||||
|
@ -582,12 +634,14 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date
|
||||
filtered_query = filtr.filter_greater_than(self.sample_query, datetime.date(2024, 2, 1))
|
||||
filtered_query = filtr.filter_greater_than(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_greater_than(self.sample_query, '2024-02-01')
|
||||
filtered_query = filtr.filter_greater_than(self.sample_query, "2024-02-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
|
@ -603,17 +657,21 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date (clear of boundary)
|
||||
filtered_query = filtr.filter_greater_equal(self.sample_query, datetime.date(2024, 2, 1))
|
||||
filtered_query = filtr.filter_greater_equal(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as date (at boundary)
|
||||
filtered_query = filtr.filter_greater_equal(self.sample_query, datetime.date(2024, 3, 1))
|
||||
filtered_query = filtr.filter_greater_equal(
|
||||
self.sample_query, datetime.date(2024, 3, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_greater_equal(self.sample_query, '2024-01-01')
|
||||
filtered_query = filtr.filter_greater_equal(self.sample_query, "2024-01-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
|
@ -629,12 +687,14 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date
|
||||
filtered_query = filtr.filter_less_than(self.sample_query, datetime.date(2024, 2, 1))
|
||||
filtered_query = filtr.filter_less_than(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_less_than(self.sample_query, '2024-04-01')
|
||||
filtered_query = filtr.filter_less_than(self.sample_query, "2024-04-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
|
@ -650,17 +710,21 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
self.assertEqual(filtered_query.count(), 6)
|
||||
|
||||
# value as date (clear of boundary)
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, datetime.date(2024, 2, 1))
|
||||
filtered_query = filtr.filter_less_equal(
|
||||
self.sample_query, datetime.date(2024, 2, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as date (at boundary)
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, datetime.date(2024, 3, 1))
|
||||
filtered_query = filtr.filter_less_equal(
|
||||
self.sample_query, datetime.date(2024, 3, 1)
|
||||
)
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 2)
|
||||
|
||||
# value as string
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, '2024-04-01')
|
||||
filtered_query = filtr.filter_less_equal(self.sample_query, "2024-04-01")
|
||||
self.assertIsNot(filtered_query, self.sample_query)
|
||||
self.assertEqual(filtered_query.count(), 4)
|
||||
|
||||
|
@ -668,5 +732,5 @@ class TestDateAlchemyFilter(WebTestCase):
|
|||
class TestVerbNotSupported(TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
error = mod.VerbNotSupported('equal')
|
||||
error = mod.VerbNotSupported("equal")
|
||||
self.assertEqual(str(error), "unknown filter verb not supported: equal")
|
||||
|
|
|
@ -36,34 +36,34 @@ class TestMakeWuttaConfig(FileTestCase):
|
|||
def test_basic(self):
|
||||
|
||||
# mock path to config file
|
||||
myconf = self.write_file('my.conf', '')
|
||||
settings = {'wutta.config': myconf}
|
||||
myconf = self.write_file("my.conf", "")
|
||||
settings = {"wutta.config": myconf}
|
||||
|
||||
# can make a config okay
|
||||
config = mod.make_wutta_config(settings)
|
||||
|
||||
# and that config is also stored in settings
|
||||
self.assertIn('wutta_config', settings)
|
||||
self.assertIs(settings['wutta_config'], config)
|
||||
self.assertIn("wutta_config", settings)
|
||||
self.assertIs(settings["wutta_config"], config)
|
||||
|
||||
|
||||
class TestMakePyramidConfig(DataTestCase):
|
||||
|
||||
def test_basic(self):
|
||||
with patch.object(AppHandler, 'make_session', return_value=self.session):
|
||||
settings = {'wutta_config': self.config}
|
||||
with patch.object(AppHandler, "make_session", return_value=self.session):
|
||||
settings = {"wutta_config": self.config}
|
||||
config = mod.make_pyramid_config(settings)
|
||||
self.assertIsInstance(config, Configurator)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
|
||||
|
||||
class TestMain(DataTestCase):
|
||||
|
||||
def test_basic(self):
|
||||
with patch.object(AppHandler, 'make_session', return_value=self.session):
|
||||
with patch.object(AppHandler, "make_session", return_value=self.session):
|
||||
global_config = None
|
||||
myconf = self.write_file('my.conf', '')
|
||||
settings = {'wutta.config': myconf}
|
||||
myconf = self.write_file("my.conf", "")
|
||||
settings = {"wutta.config": myconf}
|
||||
app = mod.main(global_config, **settings)
|
||||
self.assertIsInstance(app, Router)
|
||||
|
||||
|
@ -73,9 +73,9 @@ def mock_main(global_config, **settings):
|
|||
wutta_config = mod.make_wutta_config(settings)
|
||||
pyramid_config = mod.make_pyramid_config(settings)
|
||||
|
||||
pyramid_config.include('wuttaweb.static')
|
||||
pyramid_config.include('wuttaweb.subscribers')
|
||||
pyramid_config.include('wuttaweb.views')
|
||||
pyramid_config.include("wuttaweb.static")
|
||||
pyramid_config.include("wuttaweb.subscribers")
|
||||
pyramid_config.include("wuttaweb.views")
|
||||
|
||||
return pyramid_config.make_wsgi_app()
|
||||
|
||||
|
@ -83,26 +83,26 @@ def mock_main(global_config, **settings):
|
|||
class TestMakeWsgiApp(DataTestCase):
|
||||
|
||||
def test_with_callable(self):
|
||||
with patch.object(self.app, 'make_session', return_value=self.session):
|
||||
with patch.object(self.app, "make_session", return_value=self.session):
|
||||
|
||||
# specify config
|
||||
wsgi = mod.make_wsgi_app(mock_main, config=self.config)
|
||||
self.assertIsInstance(wsgi, Router)
|
||||
|
||||
# auto config
|
||||
with patch.object(mod, 'make_config', return_value=self.config):
|
||||
with patch.object(mod, "make_config", return_value=self.config):
|
||||
wsgi = mod.make_wsgi_app(mock_main)
|
||||
self.assertIsInstance(wsgi, Router)
|
||||
|
||||
def test_with_spec(self):
|
||||
|
||||
# specify config
|
||||
wsgi = mod.make_wsgi_app('tests.test_app:mock_main', config=self.config)
|
||||
wsgi = mod.make_wsgi_app("tests.test_app:mock_main", config=self.config)
|
||||
self.assertIsInstance(wsgi, Router)
|
||||
|
||||
# auto config
|
||||
with patch.object(mod, 'make_config', return_value=self.config):
|
||||
wsgi = mod.make_wsgi_app('tests.test_app:mock_main')
|
||||
with patch.object(mod, "make_config", return_value=self.config):
|
||||
wsgi = mod.make_wsgi_app("tests.test_app:mock_main")
|
||||
self.assertIsInstance(wsgi, Router)
|
||||
|
||||
def test_invalid(self):
|
||||
|
@ -112,27 +112,27 @@ class TestMakeWsgiApp(DataTestCase):
|
|||
class TestMakeAsgiApp(DataTestCase):
|
||||
|
||||
def test_with_callable(self):
|
||||
with patch.object(self.app, 'make_session', return_value=self.session):
|
||||
with patch.object(self.app, "make_session", return_value=self.session):
|
||||
|
||||
# specify config
|
||||
asgi = mod.make_asgi_app(mock_main, config=self.config)
|
||||
self.assertIsInstance(asgi, WsgiToAsgi)
|
||||
|
||||
# auto config
|
||||
with patch.object(mod, 'make_config', return_value=self.config):
|
||||
with patch.object(mod, "make_config", return_value=self.config):
|
||||
asgi = mod.make_asgi_app(mock_main)
|
||||
self.assertIsInstance(asgi, WsgiToAsgi)
|
||||
|
||||
def test_with_spec(self):
|
||||
with patch.object(self.app, 'make_session', return_value=self.session):
|
||||
with patch.object(self.app, "make_session", return_value=self.session):
|
||||
|
||||
# specify config
|
||||
asgi = mod.make_asgi_app('tests.test_app:mock_main', config=self.config)
|
||||
asgi = mod.make_asgi_app("tests.test_app:mock_main", config=self.config)
|
||||
self.assertIsInstance(asgi, WsgiToAsgi)
|
||||
|
||||
# auto config
|
||||
with patch.object(mod, 'make_config', return_value=self.config):
|
||||
asgi = mod.make_asgi_app('tests.test_app:mock_main')
|
||||
with patch.object(mod, "make_config", return_value=self.config):
|
||||
asgi = mod.make_asgi_app("tests.test_app:mock_main")
|
||||
self.assertIsInstance(asgi, WsgiToAsgi)
|
||||
|
||||
def test_invalid(self):
|
||||
|
@ -143,53 +143,65 @@ class TestEstablishTheme(DataTestCase):
|
|||
|
||||
def test_default(self):
|
||||
settings = {
|
||||
'wutta_config': self.config,
|
||||
'mako.directories': ['wuttaweb:templates'],
|
||||
"wutta_config": self.config,
|
||||
"mako.directories": ["wuttaweb:templates"],
|
||||
}
|
||||
mod.establish_theme(settings)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
self.assertEqual(settings['mako.directories'], [
|
||||
resource_path('wuttaweb:templates/themes/default'),
|
||||
'wuttaweb:templates',
|
||||
])
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
self.assertEqual(
|
||||
settings["mako.directories"],
|
||||
[
|
||||
resource_path("wuttaweb:templates/themes/default"),
|
||||
"wuttaweb:templates",
|
||||
],
|
||||
)
|
||||
|
||||
def test_mako_dirs_as_string(self):
|
||||
settings = {
|
||||
'wutta_config': self.config,
|
||||
'mako.directories': 'wuttaweb:templates',
|
||||
"wutta_config": self.config,
|
||||
"mako.directories": "wuttaweb:templates",
|
||||
}
|
||||
mod.establish_theme(settings)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
self.assertEqual(settings['mako.directories'], [
|
||||
resource_path('wuttaweb:templates/themes/default'),
|
||||
'wuttaweb:templates',
|
||||
])
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
self.assertEqual(
|
||||
settings["mako.directories"],
|
||||
[
|
||||
resource_path("wuttaweb:templates/themes/default"),
|
||||
"wuttaweb:templates",
|
||||
],
|
||||
)
|
||||
|
||||
def test_butterfly(self):
|
||||
settings = {
|
||||
'wutta_config': self.config,
|
||||
'mako.directories': 'wuttaweb:templates',
|
||||
"wutta_config": self.config,
|
||||
"mako.directories": "wuttaweb:templates",
|
||||
}
|
||||
self.app.save_setting(self.session, 'wuttaweb.theme', 'butterfly')
|
||||
self.app.save_setting(self.session, "wuttaweb.theme", "butterfly")
|
||||
self.session.commit()
|
||||
mod.establish_theme(settings)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'butterfly')
|
||||
self.assertEqual(settings['mako.directories'], [
|
||||
resource_path('wuttaweb:templates/themes/butterfly'),
|
||||
'wuttaweb:templates',
|
||||
])
|
||||
self.assertEqual(settings["wuttaweb.theme"], "butterfly")
|
||||
self.assertEqual(
|
||||
settings["mako.directories"],
|
||||
[
|
||||
resource_path("wuttaweb:templates/themes/butterfly"),
|
||||
"wuttaweb:templates",
|
||||
],
|
||||
)
|
||||
|
||||
def test_custom(self):
|
||||
settings = {
|
||||
'wutta_config': self.config,
|
||||
'mako.directories': 'wuttaweb:templates',
|
||||
"wutta_config": self.config,
|
||||
"mako.directories": "wuttaweb:templates",
|
||||
}
|
||||
self.config.setdefault('wuttaweb.themes.keys', 'anotherone')
|
||||
self.app.save_setting(self.session, 'wuttaweb.theme', 'anotherone')
|
||||
self.config.setdefault("wuttaweb.themes.keys", "anotherone")
|
||||
self.app.save_setting(self.session, "wuttaweb.theme", "anotherone")
|
||||
self.session.commit()
|
||||
mod.establish_theme(settings)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'anotherone')
|
||||
self.assertEqual(settings['mako.directories'], [
|
||||
resource_path('wuttaweb:templates/themes/anotherone'),
|
||||
'wuttaweb:templates',
|
||||
])
|
||||
self.assertEqual(settings["wuttaweb.theme"], "anotherone")
|
||||
self.assertEqual(
|
||||
settings["mako.directories"],
|
||||
[
|
||||
resource_path("wuttaweb:templates/themes/anotherone"),
|
||||
"wuttaweb:templates",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -18,10 +18,11 @@ class TestLoginUser(TestCase):
|
|||
app = config.get_app()
|
||||
model = app.model
|
||||
request = testing.DummyRequest(wutta_config=config)
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
headers = mod.login_user(request, user)
|
||||
self.assertEqual(headers, [])
|
||||
|
||||
|
||||
class TestLogoutUser(TestCase):
|
||||
|
||||
def test_basic(self):
|
||||
|
@ -36,20 +37,25 @@ class TestLogoutUser(TestCase):
|
|||
class TestWuttaSecurityPolicy(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.db.default.url': 'sqlite://',
|
||||
})
|
||||
self.config = WuttaConfig(
|
||||
defaults={
|
||||
"wutta.db.default.url": "sqlite://",
|
||||
}
|
||||
)
|
||||
|
||||
self.request = testing.DummyRequest()
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
})
|
||||
self.pyramid_config = testing.setUp(
|
||||
request=self.request,
|
||||
settings={
|
||||
"wutta_config": self.config,
|
||||
},
|
||||
)
|
||||
|
||||
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()
|
||||
self.user = model.User(username='barney')
|
||||
self.user = model.User(username="barney")
|
||||
self.session.add(self.user)
|
||||
self.session.commit()
|
||||
|
||||
|
@ -66,12 +72,16 @@ class TestWuttaSecurityPolicy(TestCase):
|
|||
self.assertIsNotNone(uuid)
|
||||
self.assertIsNone(self.policy.session_helper.authenticated_userid(self.request))
|
||||
self.policy.remember(self.request, uuid)
|
||||
self.assertEqual(self.policy.session_helper.authenticated_userid(self.request), uuid)
|
||||
self.assertEqual(
|
||||
self.policy.session_helper.authenticated_userid(self.request), uuid
|
||||
)
|
||||
|
||||
def test_forget(self):
|
||||
uuid = self.user.uuid
|
||||
self.policy.remember(self.request, uuid)
|
||||
self.assertEqual(self.policy.session_helper.authenticated_userid(self.request), uuid)
|
||||
self.assertEqual(
|
||||
self.policy.session_helper.authenticated_userid(self.request), uuid
|
||||
)
|
||||
self.policy.forget(self.request)
|
||||
self.assertIsNone(self.policy.session_helper.authenticated_userid(self.request))
|
||||
|
||||
|
@ -91,7 +101,7 @@ class TestWuttaSecurityPolicy(TestCase):
|
|||
|
||||
# invalid identity yields no user
|
||||
self.policy = self.make_policy()
|
||||
self.policy.remember(self.request, _uuid.uuid4()) # random uuid
|
||||
self.policy.remember(self.request, _uuid.uuid4()) # random uuid
|
||||
user = self.policy.identity(self.request)
|
||||
self.assertIsNone(user)
|
||||
|
||||
|
@ -112,59 +122,59 @@ class TestWuttaSecurityPolicy(TestCase):
|
|||
model = self.app.model
|
||||
|
||||
# anon has no perms
|
||||
self.assertFalse(self.policy.permits(self.request, None, 'foo.bar'))
|
||||
self.assertFalse(self.policy.permits(self.request, None, "foo.bar"))
|
||||
|
||||
# but we can grant it
|
||||
anons = auth.get_role_anonymous(self.session)
|
||||
self.user.roles.append(anons)
|
||||
auth.grant_permission(anons, 'foo.bar')
|
||||
auth.grant_permission(anons, "foo.bar")
|
||||
self.session.commit()
|
||||
|
||||
# and then perm check is satisfied
|
||||
self.assertTrue(self.policy.permits(self.request, None, 'foo.bar'))
|
||||
self.assertTrue(self.policy.permits(self.request, None, "foo.bar"))
|
||||
|
||||
# now, create a separate role and grant another perm
|
||||
# (but user does not yet belong to this role)
|
||||
role = model.Role(name='whatever')
|
||||
role = model.Role(name="whatever")
|
||||
self.session.add(role)
|
||||
auth.grant_permission(role, 'baz.edit')
|
||||
auth.grant_permission(role, "baz.edit")
|
||||
self.session.commit()
|
||||
|
||||
# so far then, user does not have the permission
|
||||
self.policy = self.make_policy()
|
||||
self.policy.remember(self.request, self.user.uuid)
|
||||
self.assertFalse(self.policy.permits(self.request, None, 'baz.edit'))
|
||||
self.assertFalse(self.policy.permits(self.request, None, "baz.edit"))
|
||||
|
||||
# but if we assign user to role, perm check should pass
|
||||
self.user.roles.append(role)
|
||||
self.session.commit()
|
||||
self.assertTrue(self.policy.permits(self.request, None, 'baz.edit'))
|
||||
self.assertTrue(self.policy.permits(self.request, None, "baz.edit"))
|
||||
|
||||
# now let's try another perm - we won't grant it, but will
|
||||
# confirm user is denied access unless they become root
|
||||
self.assertFalse(self.policy.permits(self.request, None, 'some-root-perm'))
|
||||
self.assertFalse(self.policy.permits(self.request, None, "some-root-perm"))
|
||||
self.request.is_root = True
|
||||
self.assertTrue(self.policy.permits(self.request, None, 'some-root-perm'))
|
||||
self.assertTrue(self.policy.permits(self.request, None, "some-root-perm"))
|
||||
|
||||
|
||||
class TestAddPermissionGroup(WebTestCase):
|
||||
|
||||
def test_basic(self):
|
||||
permissions = self.pyramid_config.get_settings().get('wutta_permissions', {})
|
||||
self.assertNotIn('widgets', permissions)
|
||||
self.pyramid_config.add_wutta_permission_group('widgets')
|
||||
permissions = self.pyramid_config.get_settings().get('wutta_permissions', {})
|
||||
self.assertIn('widgets', permissions)
|
||||
self.assertEqual(permissions['widgets']['label'], "Widgets")
|
||||
permissions = self.pyramid_config.get_settings().get("wutta_permissions", {})
|
||||
self.assertNotIn("widgets", permissions)
|
||||
self.pyramid_config.add_wutta_permission_group("widgets")
|
||||
permissions = self.pyramid_config.get_settings().get("wutta_permissions", {})
|
||||
self.assertIn("widgets", permissions)
|
||||
self.assertEqual(permissions["widgets"]["label"], "Widgets")
|
||||
|
||||
|
||||
class TestAddPermission(WebTestCase):
|
||||
|
||||
def test_basic(self):
|
||||
permissions = self.pyramid_config.get_settings().get('wutta_permissions', {})
|
||||
self.assertNotIn('widgets', permissions)
|
||||
self.pyramid_config.add_wutta_permission('widgets', 'widgets.polish')
|
||||
permissions = self.pyramid_config.get_settings().get('wutta_permissions', {})
|
||||
self.assertIn('widgets', permissions)
|
||||
self.assertEqual(permissions['widgets']['label'], "Widgets")
|
||||
self.assertIn('widgets.polish', permissions['widgets']['perms'])
|
||||
permissions = self.pyramid_config.get_settings().get("wutta_permissions", {})
|
||||
self.assertNotIn("widgets", permissions)
|
||||
self.pyramid_config.add_wutta_permission("widgets", "widgets.polish")
|
||||
permissions = self.pyramid_config.get_settings().get("wutta_permissions", {})
|
||||
self.assertIn("widgets", permissions)
|
||||
self.assertEqual(permissions["widgets"]["label"], "Widgets")
|
||||
self.assertIn("widgets.polish", permissions["widgets"]["perms"])
|
||||
|
|
|
@ -17,7 +17,9 @@ class TestAllSettings(DataTestCase):
|
|||
def test_all(self):
|
||||
for name in dir(mod):
|
||||
obj = getattr(mod, name)
|
||||
if (isinstance(obj, type)
|
||||
if (
|
||||
isinstance(obj, type)
|
||||
and obj is not EmailSetting
|
||||
and issubclass(obj, EmailSetting)):
|
||||
and issubclass(obj, EmailSetting)
|
||||
):
|
||||
self.check_setting(obj)
|
||||
|
|
|
@ -12,9 +12,11 @@ from wuttaweb.testing import WebTestCase
|
|||
class MockMenuHandler(MenuHandler):
|
||||
pass
|
||||
|
||||
|
||||
class LegacyMenuHandler(MenuHandler):
|
||||
pass
|
||||
|
||||
|
||||
class AnotherMenuHandler(MenuHandler):
|
||||
pass
|
||||
|
||||
|
@ -29,48 +31,48 @@ class TestWebHandler(WebTestCase):
|
|||
|
||||
# default with / root path
|
||||
url = handler.get_fanstatic_url(self.request, static.logo)
|
||||
self.assertEqual(url, '/fanstatic/wuttaweb_img/logo.png')
|
||||
self.assertEqual(url, "/fanstatic/wuttaweb_img/logo.png")
|
||||
|
||||
# what about a subpath
|
||||
self.request.script_name = '/testing'
|
||||
self.request.script_name = "/testing"
|
||||
url = handler.get_fanstatic_url(self.request, static.logo)
|
||||
self.assertEqual(url, '/testing/fanstatic/wuttaweb_img/logo.png')
|
||||
self.assertEqual(url, "/testing/fanstatic/wuttaweb_img/logo.png")
|
||||
|
||||
def test_get_favicon_url(self):
|
||||
handler = self.make_handler()
|
||||
|
||||
# default
|
||||
url = handler.get_favicon_url(self.request)
|
||||
self.assertEqual(url, '/fanstatic/wuttaweb_img/favicon.ico')
|
||||
self.assertEqual(url, "/fanstatic/wuttaweb_img/favicon.ico")
|
||||
|
||||
# config override
|
||||
self.config.setdefault('wuttaweb.favicon_url', '/testing/other.ico')
|
||||
self.config.setdefault("wuttaweb.favicon_url", "/testing/other.ico")
|
||||
url = handler.get_favicon_url(self.request)
|
||||
self.assertEqual(url, '/testing/other.ico')
|
||||
self.assertEqual(url, "/testing/other.ico")
|
||||
|
||||
def test_get_header_logo_url(self):
|
||||
handler = self.make_handler()
|
||||
|
||||
# default
|
||||
url = handler.get_header_logo_url(self.request)
|
||||
self.assertEqual(url, '/fanstatic/wuttaweb_img/favicon.ico')
|
||||
self.assertEqual(url, "/fanstatic/wuttaweb_img/favicon.ico")
|
||||
|
||||
# config override
|
||||
self.config.setdefault('wuttaweb.header_logo_url', '/testing/header.png')
|
||||
self.config.setdefault("wuttaweb.header_logo_url", "/testing/header.png")
|
||||
url = handler.get_header_logo_url(self.request)
|
||||
self.assertEqual(url, '/testing/header.png')
|
||||
self.assertEqual(url, "/testing/header.png")
|
||||
|
||||
def test_get_main_logo_url(self):
|
||||
handler = self.make_handler()
|
||||
|
||||
# default
|
||||
url = handler.get_main_logo_url(self.request)
|
||||
self.assertEqual(url, '/fanstatic/wuttaweb_img/logo.png')
|
||||
self.assertEqual(url, "/fanstatic/wuttaweb_img/logo.png")
|
||||
|
||||
# config override
|
||||
self.config.setdefault('wuttaweb.logo_url', '/testing/other.png')
|
||||
self.config.setdefault("wuttaweb.logo_url", "/testing/other.png")
|
||||
url = handler.get_main_logo_url(self.request)
|
||||
self.assertEqual(url, '/testing/other.png')
|
||||
self.assertEqual(url, "/testing/other.png")
|
||||
|
||||
def test_get_menu_handler(self):
|
||||
handler = self.make_handler()
|
||||
|
@ -81,20 +83,23 @@ class TestWebHandler(WebTestCase):
|
|||
self.assertIs(type(menus), MenuHandler)
|
||||
|
||||
# configured default
|
||||
self.config.setdefault('wutta.web.menus.handler.default_spec',
|
||||
'tests.test_handler:MockMenuHandler')
|
||||
self.config.setdefault(
|
||||
"wutta.web.menus.handler.default_spec", "tests.test_handler:MockMenuHandler"
|
||||
)
|
||||
menus = handler.get_menu_handler()
|
||||
self.assertIsInstance(menus, MockMenuHandler)
|
||||
|
||||
# configured handler (legacy)
|
||||
self.config.setdefault('wutta.web.menus.handler_spec',
|
||||
'tests.test_handler:LegacyMenuHandler')
|
||||
self.config.setdefault(
|
||||
"wutta.web.menus.handler_spec", "tests.test_handler:LegacyMenuHandler"
|
||||
)
|
||||
menus = handler.get_menu_handler()
|
||||
self.assertIsInstance(menus, LegacyMenuHandler)
|
||||
|
||||
# configued handler (proper)
|
||||
self.config.setdefault('wutta.web.menus.handler.spec',
|
||||
'tests.test_handler:AnotherMenuHandler')
|
||||
self.config.setdefault(
|
||||
"wutta.web.menus.handler.spec", "tests.test_handler:AnotherMenuHandler"
|
||||
)
|
||||
menus = handler.get_menu_handler()
|
||||
self.assertIsInstance(menus, AnotherMenuHandler)
|
||||
|
||||
|
@ -103,40 +108,51 @@ class TestWebHandler(WebTestCase):
|
|||
|
||||
# at least one spec by default
|
||||
specs = handler.get_menu_handler_specs()
|
||||
self.assertIn('wuttaweb.menus:MenuHandler', specs)
|
||||
self.assertIn("wuttaweb.menus:MenuHandler", specs)
|
||||
|
||||
# caller can specify default as string
|
||||
specs = handler.get_menu_handler_specs(default='tests.test_handler:MockMenuHandler')
|
||||
self.assertIn('wuttaweb.menus:MenuHandler', specs)
|
||||
self.assertIn('tests.test_handler:MockMenuHandler', specs)
|
||||
self.assertNotIn('tests.test_handler:AnotherMenuHandler', specs)
|
||||
specs = handler.get_menu_handler_specs(
|
||||
default="tests.test_handler:MockMenuHandler"
|
||||
)
|
||||
self.assertIn("wuttaweb.menus:MenuHandler", specs)
|
||||
self.assertIn("tests.test_handler:MockMenuHandler", specs)
|
||||
self.assertNotIn("tests.test_handler:AnotherMenuHandler", specs)
|
||||
|
||||
# caller can specify default as list
|
||||
specs = handler.get_menu_handler_specs(default=[
|
||||
'tests.test_handler:MockMenuHandler',
|
||||
'tests.test_handler:AnotherMenuHandler'])
|
||||
self.assertIn('wuttaweb.menus:MenuHandler', specs)
|
||||
self.assertIn('tests.test_handler:MockMenuHandler', specs)
|
||||
self.assertIn('tests.test_handler:AnotherMenuHandler', specs)
|
||||
specs = handler.get_menu_handler_specs(
|
||||
default=[
|
||||
"tests.test_handler:MockMenuHandler",
|
||||
"tests.test_handler:AnotherMenuHandler",
|
||||
]
|
||||
)
|
||||
self.assertIn("wuttaweb.menus:MenuHandler", specs)
|
||||
self.assertIn("tests.test_handler:MockMenuHandler", specs)
|
||||
self.assertIn("tests.test_handler:AnotherMenuHandler", specs)
|
||||
|
||||
# default can be configured
|
||||
self.config.setdefault('wutta.web.menus.handler.default_spec',
|
||||
'tests.test_handler:AnotherMenuHandler')
|
||||
self.config.setdefault(
|
||||
"wutta.web.menus.handler.default_spec",
|
||||
"tests.test_handler:AnotherMenuHandler",
|
||||
)
|
||||
specs = handler.get_menu_handler_specs()
|
||||
self.assertIn('wuttaweb.menus:MenuHandler', specs)
|
||||
self.assertNotIn('tests.test_handler:MockMenuHandler', specs)
|
||||
self.assertIn('tests.test_handler:AnotherMenuHandler', specs)
|
||||
self.assertIn("wuttaweb.menus:MenuHandler", specs)
|
||||
self.assertNotIn("tests.test_handler:MockMenuHandler", specs)
|
||||
self.assertIn("tests.test_handler:AnotherMenuHandler", specs)
|
||||
|
||||
# the rest come from entry points
|
||||
with patch.object(mod, 'load_entry_points', return_value={
|
||||
'legacy': LegacyMenuHandler,
|
||||
}):
|
||||
with patch.object(
|
||||
mod,
|
||||
"load_entry_points",
|
||||
return_value={
|
||||
"legacy": LegacyMenuHandler,
|
||||
},
|
||||
):
|
||||
specs = handler.get_menu_handler_specs()
|
||||
self.assertNotIn('wuttaweb.menus:MenuHandler', specs)
|
||||
self.assertNotIn('tests.test_handler:MockMenuHandler', specs)
|
||||
self.assertIn('tests.test_handler:LegacyMenuHandler', specs)
|
||||
self.assertNotIn("wuttaweb.menus:MenuHandler", specs)
|
||||
self.assertNotIn("tests.test_handler:MockMenuHandler", specs)
|
||||
self.assertIn("tests.test_handler:LegacyMenuHandler", specs)
|
||||
# nb. this remains from previous config default
|
||||
self.assertIn('tests.test_handler:AnotherMenuHandler', specs)
|
||||
self.assertIn("tests.test_handler:AnotherMenuHandler", specs)
|
||||
|
||||
def test_make_form(self):
|
||||
handler = self.make_handler()
|
||||
|
|
|
@ -18,13 +18,13 @@ class TestMenuHandler(WebTestCase):
|
|||
# no people entry by default
|
||||
menu = self.handler.make_admin_menu(self.request)
|
||||
self.assertIsInstance(menu, dict)
|
||||
routes = [item.get('route') for item in menu['items']]
|
||||
self.assertNotIn('people', routes)
|
||||
routes = [item.get("route") for item in menu["items"]]
|
||||
self.assertNotIn("people", routes)
|
||||
|
||||
# but we can request it
|
||||
menu = self.handler.make_admin_menu(self.request, include_people=True)
|
||||
routes = [item.get('route') for item in menu['items']]
|
||||
self.assertIn('people', routes)
|
||||
routes = [item.get("route") for item in menu["items"]]
|
||||
self.assertIn("people", routes)
|
||||
|
||||
def test_make_menus(self):
|
||||
menus = self.handler.make_menus(self.request)
|
||||
|
@ -35,20 +35,20 @@ class TestMenuHandler(WebTestCase):
|
|||
auth = self.app.get_auth_handler()
|
||||
|
||||
# user with perms
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
self.session.add(barney)
|
||||
blokes = model.Role(name="Blokes")
|
||||
self.session.add(blokes)
|
||||
barney.roles.append(blokes)
|
||||
auth.grant_permission(blokes, 'appinfo.list')
|
||||
auth.grant_permission(blokes, "appinfo.list")
|
||||
self.request.user = barney
|
||||
|
||||
# perm not granted to user
|
||||
item = {'perm': 'appinfo.configure'}
|
||||
item = {"perm": "appinfo.configure"}
|
||||
self.assertFalse(self.handler._is_allowed(self.request, item))
|
||||
|
||||
# perm *is* granted to user
|
||||
item = {'perm': 'appinfo.list'}
|
||||
item = {"perm": "appinfo.list"}
|
||||
self.assertTrue(self.handler._is_allowed(self.request, item))
|
||||
|
||||
# perm not required
|
||||
|
@ -60,49 +60,49 @@ class TestMenuHandler(WebTestCase):
|
|||
def make_menus():
|
||||
return [
|
||||
{
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
{'title': "Bar", 'url': '#'},
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
{"title": "Bar", "url": "#"},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
mock_is_allowed = MagicMock()
|
||||
with patch.object(self.handler, '_is_allowed', new=mock_is_allowed):
|
||||
with patch.object(self.handler, "_is_allowed", new=mock_is_allowed):
|
||||
|
||||
# all should be allowed
|
||||
mock_is_allowed.return_value = True
|
||||
menus = make_menus()
|
||||
self.handler._mark_allowed(self.request, menus)
|
||||
menu = menus[0]
|
||||
self.assertTrue(menu['allowed'])
|
||||
foo, bar = menu['items']
|
||||
self.assertTrue(foo['allowed'])
|
||||
self.assertTrue(bar['allowed'])
|
||||
self.assertTrue(menu["allowed"])
|
||||
foo, bar = menu["items"]
|
||||
self.assertTrue(foo["allowed"])
|
||||
self.assertTrue(bar["allowed"])
|
||||
|
||||
# none should be allowed
|
||||
mock_is_allowed.return_value = False
|
||||
menus = make_menus()
|
||||
self.handler._mark_allowed(self.request, menus)
|
||||
menu = menus[0]
|
||||
self.assertFalse(menu['allowed'])
|
||||
foo, bar = menu['items']
|
||||
self.assertFalse(foo['allowed'])
|
||||
self.assertFalse(bar['allowed'])
|
||||
self.assertFalse(menu["allowed"])
|
||||
foo, bar = menu["items"]
|
||||
self.assertFalse(foo["allowed"])
|
||||
self.assertFalse(bar["allowed"])
|
||||
|
||||
def test_mark_allowed_submenu(self):
|
||||
|
||||
def make_menus():
|
||||
return [
|
||||
{
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
{
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Bar", 'url': '#'},
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Bar", "url": "#"},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -110,215 +110,215 @@ class TestMenuHandler(WebTestCase):
|
|||
]
|
||||
|
||||
mock_is_allowed = MagicMock()
|
||||
with patch.object(self.handler, '_is_allowed', new=mock_is_allowed):
|
||||
with patch.object(self.handler, "_is_allowed", new=mock_is_allowed):
|
||||
|
||||
# all should be allowed
|
||||
mock_is_allowed.return_value = True
|
||||
menus = make_menus()
|
||||
self.handler._mark_allowed(self.request, menus)
|
||||
menu = menus[0]
|
||||
self.assertTrue(menu['allowed'])
|
||||
foo, submenu = menu['items']
|
||||
self.assertTrue(foo['allowed'])
|
||||
self.assertTrue(submenu['allowed'])
|
||||
subitem = submenu['items'][0]
|
||||
self.assertTrue(subitem['allowed'])
|
||||
self.assertTrue(menu["allowed"])
|
||||
foo, submenu = menu["items"]
|
||||
self.assertTrue(foo["allowed"])
|
||||
self.assertTrue(submenu["allowed"])
|
||||
subitem = submenu["items"][0]
|
||||
self.assertTrue(subitem["allowed"])
|
||||
|
||||
# none should be allowed
|
||||
mock_is_allowed.return_value = False
|
||||
menus = make_menus()
|
||||
self.handler._mark_allowed(self.request, menus)
|
||||
menu = menus[0]
|
||||
self.assertFalse(menu['allowed'])
|
||||
foo, submenu = menu['items']
|
||||
self.assertFalse(foo['allowed'])
|
||||
self.assertFalse(submenu['allowed'])
|
||||
subitem = submenu['items'][0]
|
||||
self.assertFalse(subitem['allowed'])
|
||||
self.assertFalse(menu["allowed"])
|
||||
foo, submenu = menu["items"]
|
||||
self.assertFalse(foo["allowed"])
|
||||
self.assertFalse(submenu["allowed"])
|
||||
subitem = submenu["items"][0]
|
||||
self.assertFalse(subitem["allowed"])
|
||||
|
||||
def test_make_menu_key(self):
|
||||
self.assertEqual(self.handler._make_menu_key('foo'), 'foo')
|
||||
self.assertEqual(self.handler._make_menu_key('FooBar'), 'foobar')
|
||||
self.assertEqual(self.handler._make_menu_key('Foo - $#Bar'), 'foobar')
|
||||
self.assertEqual(self.handler._make_menu_key('Foo__Bar'), 'foo__bar')
|
||||
self.assertEqual(self.handler._make_menu_key("foo"), "foo")
|
||||
self.assertEqual(self.handler._make_menu_key("FooBar"), "foobar")
|
||||
self.assertEqual(self.handler._make_menu_key("Foo - $#Bar"), "foobar")
|
||||
self.assertEqual(self.handler._make_menu_key("Foo__Bar"), "foo__bar")
|
||||
|
||||
def test_make_menu_entry_item(self):
|
||||
item = {'title': "Foo", 'url': '#'}
|
||||
item = {"title": "Foo", "url": "#"}
|
||||
entry = self.handler._make_menu_entry(self.request, item)
|
||||
self.assertEqual(entry['type'], 'item')
|
||||
self.assertEqual(entry['title'], "Foo")
|
||||
self.assertEqual(entry['url'], '#')
|
||||
self.assertTrue(entry['is_link'])
|
||||
self.assertEqual(entry["type"], "item")
|
||||
self.assertEqual(entry["title"], "Foo")
|
||||
self.assertEqual(entry["url"], "#")
|
||||
self.assertTrue(entry["is_link"])
|
||||
|
||||
def test_make_menu_entry_item_with_no_url(self):
|
||||
item = {'title': "Foo"}
|
||||
item = {"title": "Foo"}
|
||||
entry = self.handler._make_menu_entry(self.request, item)
|
||||
self.assertEqual(entry['type'], 'item')
|
||||
self.assertEqual(entry['title'], "Foo")
|
||||
self.assertNotIn('url', entry)
|
||||
self.assertEqual(entry["type"], "item")
|
||||
self.assertEqual(entry["title"], "Foo")
|
||||
self.assertNotIn("url", entry)
|
||||
# nb. still sets is_link = True; basically it's <a> with no href
|
||||
self.assertTrue(entry['is_link'])
|
||||
self.assertTrue(entry["is_link"])
|
||||
|
||||
def test_make_menu_entry_item_with_known_route(self):
|
||||
item = {'title': "Foo", 'route': 'home'}
|
||||
with patch.object(self.request, 'route_url', return_value='/something'):
|
||||
item = {"title": "Foo", "route": "home"}
|
||||
with patch.object(self.request, "route_url", return_value="/something"):
|
||||
entry = self.handler._make_menu_entry(self.request, item)
|
||||
self.assertEqual(entry['type'], 'item')
|
||||
self.assertEqual(entry['url'], '/something')
|
||||
self.assertTrue(entry['is_link'])
|
||||
self.assertEqual(entry["type"], "item")
|
||||
self.assertEqual(entry["url"], "/something")
|
||||
self.assertTrue(entry["is_link"])
|
||||
|
||||
def test_make_menu_entry_item_with_unknown_route(self):
|
||||
item = {'title': "Foo", 'route': 'home'}
|
||||
with patch.object(self.request, 'route_url', side_effect=KeyError):
|
||||
item = {"title": "Foo", "route": "home"}
|
||||
with patch.object(self.request, "route_url", side_effect=KeyError):
|
||||
entry = self.handler._make_menu_entry(self.request, item)
|
||||
self.assertEqual(entry['type'], 'item')
|
||||
self.assertEqual(entry["type"], "item")
|
||||
# nb. fake url is used, based on (bad) route name
|
||||
self.assertEqual(entry['url'], 'home')
|
||||
self.assertTrue(entry['is_link'])
|
||||
self.assertEqual(entry["url"], "home")
|
||||
self.assertTrue(entry["is_link"])
|
||||
|
||||
def test_make_menu_entry_sep(self):
|
||||
item = {'type': 'sep'}
|
||||
item = {"type": "sep"}
|
||||
entry = self.handler._make_menu_entry(self.request, item)
|
||||
self.assertEqual(entry['type'], 'sep')
|
||||
self.assertTrue(entry['is_sep'])
|
||||
self.assertFalse(entry['is_menu'])
|
||||
self.assertEqual(entry["type"], "sep")
|
||||
self.assertTrue(entry["is_sep"])
|
||||
self.assertFalse(entry["is_menu"])
|
||||
|
||||
def test_make_raw_menus(self):
|
||||
# minimal test to ensure it calls the other method
|
||||
with patch.object(self.handler, 'make_menus') as make_menus:
|
||||
self.handler._make_raw_menus(self.request, foo='bar')
|
||||
make_menus.assert_called_once_with(self.request, foo='bar')
|
||||
with patch.object(self.handler, "make_menus") as make_menus:
|
||||
self.handler._make_raw_menus(self.request, foo="bar")
|
||||
make_menus.assert_called_once_with(self.request, foo="bar")
|
||||
|
||||
def test_do_make_menus_prune_unallowed_item(self):
|
||||
test_menus = [
|
||||
{
|
||||
'title': "First Menu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
{'title': "Bar", 'url': '#'},
|
||||
"title": "First Menu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
{"title": "Bar", "url": "#"},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
def is_allowed(request, item):
|
||||
if item.get('title') == 'Bar':
|
||||
if item.get("title") == "Bar":
|
||||
return False
|
||||
return True
|
||||
|
||||
with patch.object(self.handler, 'make_menus', return_value=test_menus):
|
||||
with patch.object(self.handler, '_is_allowed', side_effect=is_allowed):
|
||||
with patch.object(self.handler, "make_menus", return_value=test_menus):
|
||||
with patch.object(self.handler, "_is_allowed", side_effect=is_allowed):
|
||||
menus = self.handler.do_make_menus(self.request)
|
||||
|
||||
# Foo remains but Bar is pruned
|
||||
menu = menus[0]
|
||||
self.assertEqual(len(menu['items']), 1)
|
||||
item = menu['items'][0]
|
||||
self.assertEqual(item['title'], 'Foo')
|
||||
self.assertEqual(len(menu["items"]), 1)
|
||||
item = menu["items"][0]
|
||||
self.assertEqual(item["title"], "Foo")
|
||||
|
||||
def test_do_make_menus_prune_unallowed_menu(self):
|
||||
test_menus = [
|
||||
{
|
||||
'title': "First Menu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
{'title': "Bar", 'url': '#'},
|
||||
"title": "First Menu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
{"title": "Bar", "url": "#"},
|
||||
],
|
||||
},
|
||||
{
|
||||
'title': "Second Menu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Baz", 'url': '#'},
|
||||
"title": "Second Menu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Baz", "url": "#"},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
def is_allowed(request, item):
|
||||
if item.get('title') == 'Baz':
|
||||
if item.get("title") == "Baz":
|
||||
return True
|
||||
return False
|
||||
|
||||
with patch.object(self.handler, 'make_menus', return_value=test_menus):
|
||||
with patch.object(self.handler, '_is_allowed', side_effect=is_allowed):
|
||||
with patch.object(self.handler, "make_menus", return_value=test_menus):
|
||||
with patch.object(self.handler, "_is_allowed", side_effect=is_allowed):
|
||||
menus = self.handler.do_make_menus(self.request)
|
||||
|
||||
# Second/Baz remains but First/Foo/Bar are pruned
|
||||
self.assertEqual(len(menus), 1)
|
||||
menu = menus[0]
|
||||
self.assertEqual(menu['title'], 'Second Menu')
|
||||
self.assertEqual(len(menu['items']), 1)
|
||||
item = menu['items'][0]
|
||||
self.assertEqual(item['title'], 'Baz')
|
||||
self.assertEqual(menu["title"], "Second Menu")
|
||||
self.assertEqual(len(menu["items"]), 1)
|
||||
item = menu["items"][0]
|
||||
self.assertEqual(item["title"], "Baz")
|
||||
|
||||
def test_do_make_menus_with_top_link(self):
|
||||
test_menus = [
|
||||
{
|
||||
'title': "First Menu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
{'title': "Bar", 'url': '#'},
|
||||
"title": "First Menu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
{"title": "Bar", "url": "#"},
|
||||
],
|
||||
},
|
||||
{
|
||||
'title': "Second Link",
|
||||
'type': 'link',
|
||||
"title": "Second Link",
|
||||
"type": "link",
|
||||
},
|
||||
]
|
||||
|
||||
with patch.object(self.handler, 'make_menus', return_value=test_menus):
|
||||
with patch.object(self.handler, '_is_allowed', return_value=True):
|
||||
with patch.object(self.handler, "make_menus", return_value=test_menus):
|
||||
with patch.object(self.handler, "_is_allowed", return_value=True):
|
||||
menus = self.handler.do_make_menus(self.request)
|
||||
|
||||
# ensure top link remains
|
||||
self.assertEqual(len(menus), 2)
|
||||
menu = menus[1]
|
||||
self.assertEqual(menu['title'], "Second Link")
|
||||
self.assertEqual(menu["title"], "Second Link")
|
||||
|
||||
def test_do_make_menus_with_trailing_sep(self):
|
||||
test_menus = [
|
||||
{
|
||||
'title': "First Menu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
{'title': "Bar", 'url': '#'},
|
||||
{'type': 'sep'},
|
||||
"title": "First Menu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
{"title": "Bar", "url": "#"},
|
||||
{"type": "sep"},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
with patch.object(self.handler, 'make_menus', return_value=test_menus):
|
||||
with patch.object(self.handler, '_is_allowed', return_value=True):
|
||||
with patch.object(self.handler, "make_menus", return_value=test_menus):
|
||||
with patch.object(self.handler, "_is_allowed", return_value=True):
|
||||
menus = self.handler.do_make_menus(self.request)
|
||||
|
||||
# ensure trailing sep was pruned
|
||||
menu = menus[0]
|
||||
self.assertEqual(len(menu['items']), 2)
|
||||
foo, bar = menu['items']
|
||||
self.assertEqual(foo['title'], 'Foo')
|
||||
self.assertEqual(bar['title'], 'Bar')
|
||||
self.assertEqual(len(menu["items"]), 2)
|
||||
foo, bar = menu["items"]
|
||||
self.assertEqual(foo["title"], "Foo")
|
||||
self.assertEqual(bar["title"], "Bar")
|
||||
|
||||
def test_do_make_menus_with_submenu(self):
|
||||
test_menus = [
|
||||
{
|
||||
'title': "First Menu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
"title": "First Menu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{
|
||||
'title': "First Submenu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Foo", 'url': '#'},
|
||||
"title": "First Submenu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Foo", "url": "#"},
|
||||
],
|
||||
},
|
||||
{
|
||||
'title': "Second Submenu",
|
||||
'type': 'menu',
|
||||
'items': [
|
||||
{'title': "Bar", 'url': '#'},
|
||||
"title": "Second Submenu",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{"title": "Bar", "url": "#"},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -326,20 +326,20 @@ class TestMenuHandler(WebTestCase):
|
|||
]
|
||||
|
||||
def is_allowed(request, item):
|
||||
if item.get('title') == 'Bar':
|
||||
if item.get("title") == "Bar":
|
||||
return False
|
||||
return True
|
||||
|
||||
with patch.object(self.handler, 'make_menus', return_value=test_menus):
|
||||
with patch.object(self.handler, '_is_allowed', side_effect=is_allowed):
|
||||
with patch.object(self.handler, "make_menus", return_value=test_menus):
|
||||
with patch.object(self.handler, "_is_allowed", side_effect=is_allowed):
|
||||
menus = self.handler.do_make_menus(self.request)
|
||||
|
||||
# first submenu remains, second is pruned
|
||||
menu = menus[0]
|
||||
self.assertEqual(len(menu['items']), 1)
|
||||
submenu = menu['items'][0]
|
||||
self.assertEqual(submenu['type'], 'submenu')
|
||||
self.assertEqual(submenu['title'], 'First Submenu')
|
||||
self.assertEqual(len(submenu['items']), 1)
|
||||
item = submenu['items'][0]
|
||||
self.assertEqual(item['title'], 'Foo')
|
||||
self.assertEqual(len(menu["items"]), 1)
|
||||
submenu = menu["items"][0]
|
||||
self.assertEqual(submenu["type"], "submenu")
|
||||
self.assertEqual(submenu["title"], "First Submenu")
|
||||
self.assertEqual(len(submenu["items"]), 1)
|
||||
item = submenu["items"][0]
|
||||
self.assertEqual(item["title"], "Foo")
|
||||
|
|
|
@ -27,10 +27,10 @@ class TestGetProgressSession(TestCase):
|
|||
self.request = testing.DummyRequest()
|
||||
|
||||
def test_basic(self):
|
||||
self.request.session.id = 'mockid'
|
||||
session = mod.get_progress_session(self.request, 'foo')
|
||||
self.request.session.id = "mockid"
|
||||
session = mod.get_progress_session(self.request, "foo")
|
||||
self.assertIsInstance(session, BeakerSession)
|
||||
self.assertEqual(session.id, 'mockid.progress.foo')
|
||||
self.assertEqual(session.id, "mockid.progress.foo")
|
||||
|
||||
|
||||
class TestSessionProgress(ConfigTestCase):
|
||||
|
@ -38,16 +38,16 @@ class TestSessionProgress(ConfigTestCase):
|
|||
def setUp(self):
|
||||
self.setup_config()
|
||||
self.request = testing.DummyRequest(wutta_config=self.config)
|
||||
self.request.session.id = 'mockid'
|
||||
self.request.session.id = "mockid"
|
||||
|
||||
def test_error_url(self):
|
||||
factory = mod.SessionProgress(self.request, 'foo', success_url='/blart')
|
||||
self.assertEqual(factory.error_url, '/blart')
|
||||
factory = mod.SessionProgress(self.request, "foo", success_url="/blart")
|
||||
self.assertEqual(factory.error_url, "/blart")
|
||||
|
||||
def test_basic(self):
|
||||
|
||||
# sanity / coverage check
|
||||
factory = mod.SessionProgress(self.request, 'foo')
|
||||
factory = mod.SessionProgress(self.request, "foo")
|
||||
prog = factory("doing things", 2)
|
||||
prog.update(1)
|
||||
prog.update(2)
|
||||
|
@ -56,10 +56,10 @@ class TestSessionProgress(ConfigTestCase):
|
|||
def test_error(self):
|
||||
|
||||
# sanity / coverage check
|
||||
factory = mod.SessionProgress(self.request, 'foo')
|
||||
factory = mod.SessionProgress(self.request, "foo")
|
||||
prog = factory("doing things", 2)
|
||||
prog.update(1)
|
||||
try:
|
||||
raise RuntimeError('omg')
|
||||
raise RuntimeError("omg")
|
||||
except Exception as error:
|
||||
prog.handle_error(error)
|
||||
|
|
|
@ -11,4 +11,4 @@ class TestIncludeMe(TestCase):
|
|||
with testing.testConfig() as pyramid_config:
|
||||
|
||||
# just ensure no error happens when included..
|
||||
pyramid_config.include('wuttaweb.static')
|
||||
pyramid_config.include("wuttaweb.static")
|
||||
|
|
|
@ -19,9 +19,12 @@ class TestNewRequest(TestCase):
|
|||
def setUp(self):
|
||||
self.config = WuttaConfig()
|
||||
self.request = self.make_request()
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
})
|
||||
self.pyramid_config = testing.setUp(
|
||||
request=self.request,
|
||||
settings={
|
||||
"wutta_config": self.config,
|
||||
},
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
testing.tearDown()
|
||||
|
@ -35,15 +38,15 @@ class TestNewRequest(TestCase):
|
|||
event = MagicMock(request=self.request)
|
||||
|
||||
# request gets a new attr
|
||||
self.assertFalse(hasattr(self.request, 'wutta_config'))
|
||||
self.assertFalse(hasattr(self.request, "wutta_config"))
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(hasattr(self.request, 'wutta_config'))
|
||||
self.assertTrue(hasattr(self.request, "wutta_config"))
|
||||
self.assertIs(self.request.wutta_config, self.config)
|
||||
|
||||
def test_use_oruga_default(self):
|
||||
|
||||
# request gets a new attr, false by default
|
||||
self.assertFalse(hasattr(self.request, 'use_oruga'))
|
||||
self.assertFalse(hasattr(self.request, "use_oruga"))
|
||||
event = MagicMock(request=self.request)
|
||||
subscribers.new_request(event)
|
||||
self.assertFalse(self.request.use_oruga)
|
||||
|
@ -51,17 +54,20 @@ class TestNewRequest(TestCase):
|
|||
# nb. using 'butterfly' theme should cause the 'use_oruga'
|
||||
# flag to be turned on by default
|
||||
self.request = self.make_request()
|
||||
self.request.registry.settings['wuttaweb.theme'] = 'butterfly'
|
||||
self.request.registry.settings["wuttaweb.theme"] = "butterfly"
|
||||
event = MagicMock(request=self.request)
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(self.request.use_oruga)
|
||||
|
||||
def test_use_oruga_custom(self):
|
||||
self.config.setdefault('wuttaweb.oruga_detector.spec', 'tests.test_subscribers:custom_oruga_detector')
|
||||
self.config.setdefault(
|
||||
"wuttaweb.oruga_detector.spec",
|
||||
"tests.test_subscribers:custom_oruga_detector",
|
||||
)
|
||||
event = MagicMock(request=self.request)
|
||||
|
||||
# request gets a new attr, which should be true
|
||||
self.assertFalse(hasattr(self.request, 'use_oruga'))
|
||||
self.assertFalse(hasattr(self.request, "use_oruga"))
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(self.request.use_oruga)
|
||||
|
||||
|
@ -70,20 +76,24 @@ class TestNewRequest(TestCase):
|
|||
subscribers.new_request(event)
|
||||
|
||||
# component tracking dict is missing at first
|
||||
self.assertFalse(hasattr(self.request, '_wuttaweb_registered_components'))
|
||||
self.assertFalse(hasattr(self.request, "_wuttaweb_registered_components"))
|
||||
|
||||
# registering a component
|
||||
self.request.register_component('foo-example', 'FooExample')
|
||||
self.assertTrue(hasattr(self.request, '_wuttaweb_registered_components'))
|
||||
self.request.register_component("foo-example", "FooExample")
|
||||
self.assertTrue(hasattr(self.request, "_wuttaweb_registered_components"))
|
||||
self.assertEqual(len(self.request._wuttaweb_registered_components), 1)
|
||||
self.assertIn('foo-example', self.request._wuttaweb_registered_components)
|
||||
self.assertEqual(self.request._wuttaweb_registered_components['foo-example'], 'FooExample')
|
||||
self.assertIn("foo-example", self.request._wuttaweb_registered_components)
|
||||
self.assertEqual(
|
||||
self.request._wuttaweb_registered_components["foo-example"], "FooExample"
|
||||
)
|
||||
|
||||
# re-registering same name
|
||||
self.request.register_component('foo-example', 'FooExample')
|
||||
self.request.register_component("foo-example", "FooExample")
|
||||
self.assertEqual(len(self.request._wuttaweb_registered_components), 1)
|
||||
self.assertIn('foo-example', self.request._wuttaweb_registered_components)
|
||||
self.assertEqual(self.request._wuttaweb_registered_components['foo-example'], 'FooExample')
|
||||
self.assertIn("foo-example", self.request._wuttaweb_registered_components)
|
||||
self.assertEqual(
|
||||
self.request._wuttaweb_registered_components["foo-example"], "FooExample"
|
||||
)
|
||||
|
||||
def test_get_referrer(self):
|
||||
event = MagicMock(request=self.request)
|
||||
|
@ -91,33 +101,33 @@ class TestNewRequest(TestCase):
|
|||
def home(request):
|
||||
pass
|
||||
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_view(home, route_name='home')
|
||||
self.pyramid_config.add_route("home", "/")
|
||||
self.pyramid_config.add_view(home, route_name="home")
|
||||
|
||||
self.assertFalse(hasattr(self.request, 'get_referrer'))
|
||||
self.assertFalse(hasattr(self.request, "get_referrer"))
|
||||
subscribers.new_request(event)
|
||||
self.assertTrue(hasattr(self.request, 'get_referrer'))
|
||||
self.assertTrue(hasattr(self.request, "get_referrer"))
|
||||
|
||||
# default if no referrer, is home route
|
||||
url = self.request.get_referrer()
|
||||
self.assertEqual(url, self.request.route_url('home'))
|
||||
self.assertEqual(url, self.request.route_url("home"))
|
||||
|
||||
# can specify another default
|
||||
url = self.request.get_referrer(default='https://wuttaproject.org')
|
||||
self.assertEqual(url, 'https://wuttaproject.org')
|
||||
url = self.request.get_referrer(default="https://wuttaproject.org")
|
||||
self.assertEqual(url, "https://wuttaproject.org")
|
||||
|
||||
# or referrer can come from user session
|
||||
self.request.session['referrer'] = 'https://rattailproject.org'
|
||||
self.assertIn('referrer', self.request.session)
|
||||
self.request.session["referrer"] = "https://rattailproject.org"
|
||||
self.assertIn("referrer", self.request.session)
|
||||
url = self.request.get_referrer()
|
||||
self.assertEqual(url, 'https://rattailproject.org')
|
||||
self.assertEqual(url, "https://rattailproject.org")
|
||||
# nb. referrer should also have been removed from user session
|
||||
self.assertNotIn('referrer', self.request.session)
|
||||
self.assertNotIn("referrer", self.request.session)
|
||||
|
||||
# or referrer can come from request params
|
||||
self.request.params['referrer'] = 'https://kernel.org'
|
||||
self.request.params["referrer"] = "https://kernel.org"
|
||||
url = self.request.get_referrer()
|
||||
self.assertEqual(url, 'https://kernel.org')
|
||||
self.assertEqual(url, "https://kernel.org")
|
||||
|
||||
|
||||
def custom_oruga_detector(request):
|
||||
|
@ -127,30 +137,37 @@ def custom_oruga_detector(request):
|
|||
class TestNewRequestSetUser(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.db.default.url': 'sqlite://',
|
||||
})
|
||||
self.config = WuttaConfig(
|
||||
defaults={
|
||||
"wutta.db.default.url": "sqlite://",
|
||||
}
|
||||
)
|
||||
|
||||
self.request = testing.DummyRequest(wutta_config=self.config)
|
||||
self.pyramid_config = testing.setUp(request=self.request, settings={
|
||||
'wutta_config': self.config,
|
||||
})
|
||||
self.pyramid_config = testing.setUp(
|
||||
request=self.request,
|
||||
settings={
|
||||
"wutta_config": self.config,
|
||||
},
|
||||
)
|
||||
|
||||
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()
|
||||
self.user = model.User(username='barney')
|
||||
self.user = model.User(username="barney")
|
||||
self.session.add(self.user)
|
||||
self.session.commit()
|
||||
|
||||
self.pyramid_config.set_security_policy(WuttaSecurityPolicy(db_session=self.session))
|
||||
self.pyramid_config.set_security_policy(
|
||||
WuttaSecurityPolicy(db_session=self.session)
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
testing.tearDown()
|
||||
|
||||
def test_anonymous(self):
|
||||
self.assertFalse(hasattr(self.request, 'user'))
|
||||
self.assertFalse(hasattr(self.request, "user"))
|
||||
event = MagicMock(request=self.request)
|
||||
subscribers.new_request_set_user(event)
|
||||
self.assertIsNone(self.request.user)
|
||||
|
@ -167,8 +184,8 @@ class TestNewRequestSetUser(TestCase):
|
|||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'user'))
|
||||
self.assertFalse(hasattr(self.request, 'is_admin'))
|
||||
self.assertFalse(hasattr(self.request, "user"))
|
||||
self.assertFalse(hasattr(self.request, "is_admin"))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIsNone(self.request.user)
|
||||
self.assertFalse(self.request.is_admin)
|
||||
|
@ -198,8 +215,8 @@ class TestNewRequestSetUser(TestCase):
|
|||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'user'))
|
||||
self.assertFalse(hasattr(self.request, 'is_root'))
|
||||
self.assertFalse(hasattr(self.request, "user"))
|
||||
self.assertFalse(hasattr(self.request, "is_root"))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertIsNone(self.request.user)
|
||||
self.assertFalse(self.request.is_root)
|
||||
|
@ -233,7 +250,7 @@ class TestNewRequestSetUser(TestCase):
|
|||
del self.request.is_root
|
||||
|
||||
# root status flag lives in user session
|
||||
self.request.session['is_root'] = True
|
||||
self.request.session["is_root"] = True
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertTrue(self.request.is_admin)
|
||||
self.assertTrue(self.request.is_root)
|
||||
|
@ -244,7 +261,7 @@ class TestNewRequestSetUser(TestCase):
|
|||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'user_permissions'))
|
||||
self.assertFalse(hasattr(self.request, "user_permissions"))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertEqual(self.request.user_permissions, set())
|
||||
|
||||
|
@ -254,14 +271,14 @@ class TestNewRequestSetUser(TestCase):
|
|||
# add user to role with perms
|
||||
blokes = model.Role(name="Blokes")
|
||||
self.session.add(blokes)
|
||||
auth.grant_permission(blokes, 'appinfo.list')
|
||||
auth.grant_permission(blokes, "appinfo.list")
|
||||
self.user.roles.append(blokes)
|
||||
self.session.commit()
|
||||
|
||||
# authenticated user, with perms
|
||||
self.request.user = self.user
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertEqual(self.request.user_permissions, {'appinfo.list'})
|
||||
self.assertEqual(self.request.user_permissions, {"appinfo.list"})
|
||||
|
||||
def test_has_perm(self):
|
||||
model = self.app.model
|
||||
|
@ -269,9 +286,9 @@ class TestNewRequestSetUser(TestCase):
|
|||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'has_perm'))
|
||||
self.assertFalse(hasattr(self.request, "has_perm"))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertFalse(self.request.has_perm('appinfo.list'))
|
||||
self.assertFalse(self.request.has_perm("appinfo.list"))
|
||||
|
||||
# reset
|
||||
del self.request.user_permissions
|
||||
|
@ -281,14 +298,14 @@ class TestNewRequestSetUser(TestCase):
|
|||
# add user to role with perms
|
||||
blokes = model.Role(name="Blokes")
|
||||
self.session.add(blokes)
|
||||
auth.grant_permission(blokes, 'appinfo.list')
|
||||
auth.grant_permission(blokes, "appinfo.list")
|
||||
self.user.roles.append(blokes)
|
||||
self.session.commit()
|
||||
|
||||
# authenticated user, with perms
|
||||
self.request.user = self.user
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertTrue(self.request.has_perm('appinfo.list'))
|
||||
self.assertTrue(self.request.has_perm("appinfo.list"))
|
||||
|
||||
# reset
|
||||
del self.request.user_permissions
|
||||
|
@ -299,7 +316,7 @@ class TestNewRequestSetUser(TestCase):
|
|||
self.user.roles.remove(blokes)
|
||||
self.session.commit()
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertFalse(self.request.has_perm('appinfo.list'))
|
||||
self.assertFalse(self.request.has_perm("appinfo.list"))
|
||||
|
||||
# reset
|
||||
del self.request.user_permissions
|
||||
|
@ -312,9 +329,9 @@ class TestNewRequestSetUser(TestCase):
|
|||
admin = auth.get_role_administrator(self.session)
|
||||
self.user.roles.append(admin)
|
||||
self.session.commit()
|
||||
self.request.session['is_root'] = True
|
||||
self.request.session["is_root"] = True
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertTrue(self.request.has_perm('appinfo.list'))
|
||||
self.assertTrue(self.request.has_perm("appinfo.list"))
|
||||
|
||||
def test_has_any_perm(self):
|
||||
model = self.app.model
|
||||
|
@ -322,9 +339,9 @@ class TestNewRequestSetUser(TestCase):
|
|||
event = MagicMock(request=self.request)
|
||||
|
||||
# anonymous user
|
||||
self.assertFalse(hasattr(self.request, 'has_any_perm'))
|
||||
self.assertFalse(hasattr(self.request, "has_any_perm"))
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertFalse(self.request.has_any_perm('appinfo.list'))
|
||||
self.assertFalse(self.request.has_any_perm("appinfo.list"))
|
||||
|
||||
# reset
|
||||
del self.request.user_permissions
|
||||
|
@ -334,14 +351,14 @@ class TestNewRequestSetUser(TestCase):
|
|||
# add user to role with perms
|
||||
blokes = model.Role(name="Blokes")
|
||||
self.session.add(blokes)
|
||||
auth.grant_permission(blokes, 'appinfo.list')
|
||||
auth.grant_permission(blokes, "appinfo.list")
|
||||
self.user.roles.append(blokes)
|
||||
self.session.commit()
|
||||
|
||||
# authenticated user, with perms
|
||||
self.request.user = self.user
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertTrue(self.request.has_any_perm('appinfo.list', 'appinfo.view'))
|
||||
self.assertTrue(self.request.has_any_perm("appinfo.list", "appinfo.view"))
|
||||
|
||||
# reset
|
||||
del self.request.user_permissions
|
||||
|
@ -352,7 +369,7 @@ class TestNewRequestSetUser(TestCase):
|
|||
self.user.roles.remove(blokes)
|
||||
self.session.commit()
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertFalse(self.request.has_any_perm('appinfo.list'))
|
||||
self.assertFalse(self.request.has_any_perm("appinfo.list"))
|
||||
|
||||
# reset
|
||||
del self.request.user_permissions
|
||||
|
@ -365,64 +382,66 @@ class TestNewRequestSetUser(TestCase):
|
|||
admin = auth.get_role_administrator(self.session)
|
||||
self.user.roles.append(admin)
|
||||
self.session.commit()
|
||||
self.request.session['is_root'] = True
|
||||
self.request.session["is_root"] = True
|
||||
subscribers.new_request_set_user(event, db_session=self.session)
|
||||
self.assertTrue(self.request.has_any_perm('appinfo.list'))
|
||||
self.assertTrue(self.request.has_any_perm("appinfo.list"))
|
||||
|
||||
|
||||
class TestBeforeRender(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.web.menus.handler.spec': 'tests.util:NullMenuHandler',
|
||||
})
|
||||
self.config = WuttaConfig(
|
||||
defaults={
|
||||
"wutta.web.menus.handler.spec": "tests.util:NullMenuHandler",
|
||||
}
|
||||
)
|
||||
|
||||
def make_request(self):
|
||||
request = testing.DummyRequest(use_oruga=False)
|
||||
request.registry.settings = {'wutta_config': self.config}
|
||||
request.registry.settings = {"wutta_config": self.config}
|
||||
request.wutta_config = self.config
|
||||
return request
|
||||
|
||||
def test_basic(self):
|
||||
request = self.make_request()
|
||||
event = {'request': request}
|
||||
event = {"request": request}
|
||||
|
||||
# event dict will get populated with more context
|
||||
subscribers.before_render(event)
|
||||
|
||||
self.assertIn('config', event)
|
||||
self.assertIs(event['config'], self.config)
|
||||
self.assertIn("config", event)
|
||||
self.assertIs(event["config"], self.config)
|
||||
|
||||
self.assertIn('app', event)
|
||||
self.assertIs(event['app'], self.config.get_app())
|
||||
self.assertIn("app", event)
|
||||
self.assertIs(event["app"], self.config.get_app())
|
||||
|
||||
self.assertIn('h', event)
|
||||
self.assertIs(event['h'], helpers)
|
||||
self.assertIn("h", event)
|
||||
self.assertIs(event["h"], helpers)
|
||||
|
||||
self.assertIn('url', event)
|
||||
self.assertIn("url", event)
|
||||
# TODO: not sure how to test this?
|
||||
# self.assertIs(event['url'], request.route_url)
|
||||
|
||||
self.assertIn('json', event)
|
||||
self.assertIs(event['json'], json)
|
||||
self.assertIn("json", event)
|
||||
self.assertIs(event["json"], json)
|
||||
|
||||
# current theme should be 'default' and picker not exposed
|
||||
self.assertEqual(event['theme'], 'default')
|
||||
self.assertFalse(event['expose_theme_picker'])
|
||||
self.assertNotIn('available_themes', event)
|
||||
self.assertEqual(event["theme"], "default")
|
||||
self.assertFalse(event["expose_theme_picker"])
|
||||
self.assertNotIn("available_themes", event)
|
||||
|
||||
def test_custom_theme(self):
|
||||
self.config.setdefault('wuttaweb.themes.expose_picker', 'true')
|
||||
self.config.setdefault("wuttaweb.themes.expose_picker", "true")
|
||||
request = self.make_request()
|
||||
request.registry.settings['wuttaweb.theme'] = 'butterfly'
|
||||
event = {'request': request}
|
||||
request.registry.settings["wuttaweb.theme"] = "butterfly"
|
||||
event = {"request": request}
|
||||
|
||||
# event dict will get populated with more context
|
||||
subscribers.before_render(event)
|
||||
self.assertEqual(event['theme'], 'butterfly')
|
||||
self.assertTrue(event['expose_theme_picker'])
|
||||
self.assertIn('available_themes', event)
|
||||
self.assertEqual(event['available_themes'], ['default', 'butterfly'])
|
||||
self.assertEqual(event["theme"], "butterfly")
|
||||
self.assertTrue(event["expose_theme_picker"])
|
||||
self.assertIn("available_themes", event)
|
||||
self.assertEqual(event["available_themes"], ["default", "butterfly"])
|
||||
|
||||
|
||||
class TestIncludeMe(TestCase):
|
||||
|
@ -431,4 +450,4 @@ class TestIncludeMe(TestCase):
|
|||
with testing.testConfig() as pyramid_config:
|
||||
|
||||
# just ensure no error happens when included..
|
||||
pyramid_config.include('wuttaweb.subscribers')
|
||||
pyramid_config.include("wuttaweb.subscribers")
|
||||
|
|
|
@ -22,40 +22,40 @@ from wuttaweb.testing import WebTestCase
|
|||
class TestFieldList(TestCase):
|
||||
|
||||
def test_insert_before(self):
|
||||
fields = mod.FieldList(['f1', 'f2'])
|
||||
self.assertEqual(fields, ['f1', 'f2'])
|
||||
fields = mod.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'])
|
||||
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'])
|
||||
fields.insert_before("f3", "ZZZ")
|
||||
self.assertEqual(fields, ["XXX", "f1", "YYY", "f2", "ZZZ"])
|
||||
|
||||
def test_insert_after(self):
|
||||
fields = mod.FieldList(['f1', 'f2'])
|
||||
self.assertEqual(fields, ['f1', 'f2'])
|
||||
fields = mod.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'])
|
||||
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'])
|
||||
fields.insert_after("f3", "ZZZ")
|
||||
self.assertEqual(fields, ["f1", "XXX", "YYY", "f2", "ZZZ"])
|
||||
|
||||
def test_set_sequence(self):
|
||||
fields = mod.FieldList(['f5', 'f1', 'f3', 'f4', 'f2'])
|
||||
fields = mod.FieldList(["f5", "f1", "f3", "f4", "f2"])
|
||||
|
||||
# setting sequence will only "sort" for explicit fields.
|
||||
# other fields remain in original order, but at the end.
|
||||
fields.set_sequence(['f1', 'f2', 'f3'])
|
||||
self.assertEqual(fields, ['f1', 'f2', 'f3', 'f5', 'f4'])
|
||||
fields.set_sequence(["f1", "f2", "f3"])
|
||||
self.assertEqual(fields, ["f1", "f2", "f3", "f5", "f4"])
|
||||
|
||||
|
||||
class TestGetLibVer(TestCase):
|
||||
|
@ -66,169 +66,169 @@ class TestGetLibVer(TestCase):
|
|||
self.request.wutta_config = self.config
|
||||
|
||||
def test_buefy_default(self):
|
||||
version = mod.get_libver(self.request, 'buefy')
|
||||
self.assertEqual(version, '0.9.25')
|
||||
version = mod.get_libver(self.request, "buefy")
|
||||
self.assertEqual(version, "0.9.25")
|
||||
|
||||
def test_buefy_custom_old(self):
|
||||
self.config.setdefault('wuttaweb.buefy_version', '0.9.29')
|
||||
version = mod.get_libver(self.request, 'buefy')
|
||||
self.assertEqual(version, '0.9.29')
|
||||
self.config.setdefault("wuttaweb.buefy_version", "0.9.29")
|
||||
version = mod.get_libver(self.request, "buefy")
|
||||
self.assertEqual(version, "0.9.29")
|
||||
|
||||
def test_buefy_custom_old_tailbone(self):
|
||||
self.config.setdefault('tailbone.libver.buefy', '0.9.28')
|
||||
version = mod.get_libver(self.request, 'buefy', prefix='tailbone')
|
||||
self.assertEqual(version, '0.9.28')
|
||||
self.config.setdefault("tailbone.libver.buefy", "0.9.28")
|
||||
version = mod.get_libver(self.request, "buefy", prefix="tailbone")
|
||||
self.assertEqual(version, "0.9.28")
|
||||
|
||||
def test_buefy_custom_new(self):
|
||||
self.config.setdefault('wuttaweb.libver.buefy', '0.9.29')
|
||||
version = mod.get_libver(self.request, 'buefy')
|
||||
self.assertEqual(version, '0.9.29')
|
||||
self.config.setdefault("wuttaweb.libver.buefy", "0.9.29")
|
||||
version = mod.get_libver(self.request, "buefy")
|
||||
self.assertEqual(version, "0.9.29")
|
||||
|
||||
def test_buefy_configured_only(self):
|
||||
version = mod.get_libver(self.request, 'buefy', configured_only=True)
|
||||
version = mod.get_libver(self.request, "buefy", configured_only=True)
|
||||
self.assertIsNone(version)
|
||||
|
||||
def test_buefy_default_only(self):
|
||||
self.config.setdefault('wuttaweb.libver.buefy', '0.9.29')
|
||||
version = mod.get_libver(self.request, 'buefy', default_only=True)
|
||||
self.assertEqual(version, '0.9.25')
|
||||
self.config.setdefault("wuttaweb.libver.buefy", "0.9.29")
|
||||
version = mod.get_libver(self.request, "buefy", default_only=True)
|
||||
self.assertEqual(version, "0.9.25")
|
||||
|
||||
def test_buefy_css_default(self):
|
||||
version = mod.get_libver(self.request, 'buefy.css')
|
||||
self.assertEqual(version, '0.9.25')
|
||||
version = mod.get_libver(self.request, "buefy.css")
|
||||
self.assertEqual(version, "0.9.25")
|
||||
|
||||
def test_buefy_css_custom_old(self):
|
||||
# nb. this uses same setting as buefy (js)
|
||||
self.config.setdefault('wuttaweb.buefy_version', '0.9.29')
|
||||
version = mod.get_libver(self.request, 'buefy.css')
|
||||
self.assertEqual(version, '0.9.29')
|
||||
self.config.setdefault("wuttaweb.buefy_version", "0.9.29")
|
||||
version = mod.get_libver(self.request, "buefy.css")
|
||||
self.assertEqual(version, "0.9.29")
|
||||
|
||||
def test_buefy_css_custom_new(self):
|
||||
# nb. this uses same setting as buefy (js)
|
||||
self.config.setdefault('wuttaweb.libver.buefy', '0.9.29')
|
||||
version = mod.get_libver(self.request, 'buefy.css')
|
||||
self.assertEqual(version, '0.9.29')
|
||||
self.config.setdefault("wuttaweb.libver.buefy", "0.9.29")
|
||||
version = mod.get_libver(self.request, "buefy.css")
|
||||
self.assertEqual(version, "0.9.29")
|
||||
|
||||
def test_buefy_css_configured_only(self):
|
||||
version = mod.get_libver(self.request, 'buefy.css', configured_only=True)
|
||||
version = mod.get_libver(self.request, "buefy.css", configured_only=True)
|
||||
self.assertIsNone(version)
|
||||
|
||||
def test_buefy_css_default_only(self):
|
||||
self.config.setdefault('wuttaweb.libver.buefy', '0.9.29')
|
||||
version = mod.get_libver(self.request, 'buefy.css', default_only=True)
|
||||
self.assertEqual(version, '0.9.25')
|
||||
self.config.setdefault("wuttaweb.libver.buefy", "0.9.29")
|
||||
version = mod.get_libver(self.request, "buefy.css", default_only=True)
|
||||
self.assertEqual(version, "0.9.25")
|
||||
|
||||
def test_vue_default(self):
|
||||
version = mod.get_libver(self.request, 'vue')
|
||||
self.assertEqual(version, '2.6.14')
|
||||
version = mod.get_libver(self.request, "vue")
|
||||
self.assertEqual(version, "2.6.14")
|
||||
|
||||
def test_vue_custom_old(self):
|
||||
self.config.setdefault('wuttaweb.vue_version', '3.4.31')
|
||||
version = mod.get_libver(self.request, 'vue')
|
||||
self.assertEqual(version, '3.4.31')
|
||||
self.config.setdefault("wuttaweb.vue_version", "3.4.31")
|
||||
version = mod.get_libver(self.request, "vue")
|
||||
self.assertEqual(version, "3.4.31")
|
||||
|
||||
def test_vue_custom_new(self):
|
||||
self.config.setdefault('wuttaweb.libver.vue', '3.4.31')
|
||||
version = mod.get_libver(self.request, 'vue')
|
||||
self.assertEqual(version, '3.4.31')
|
||||
self.config.setdefault("wuttaweb.libver.vue", "3.4.31")
|
||||
version = mod.get_libver(self.request, "vue")
|
||||
self.assertEqual(version, "3.4.31")
|
||||
|
||||
def test_vue_configured_only(self):
|
||||
version = mod.get_libver(self.request, 'vue', configured_only=True)
|
||||
version = mod.get_libver(self.request, "vue", configured_only=True)
|
||||
self.assertIsNone(version)
|
||||
|
||||
def test_vue_default_only(self):
|
||||
self.config.setdefault('wuttaweb.libver.vue', '3.4.31')
|
||||
version = mod.get_libver(self.request, 'vue', default_only=True)
|
||||
self.assertEqual(version, '2.6.14')
|
||||
self.config.setdefault("wuttaweb.libver.vue", "3.4.31")
|
||||
version = mod.get_libver(self.request, "vue", default_only=True)
|
||||
self.assertEqual(version, "2.6.14")
|
||||
|
||||
def test_vue_resource_default(self):
|
||||
version = mod.get_libver(self.request, 'vue_resource')
|
||||
self.assertEqual(version, '1.5.3')
|
||||
version = mod.get_libver(self.request, "vue_resource")
|
||||
self.assertEqual(version, "1.5.3")
|
||||
|
||||
def test_vue_resource_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.vue_resource', '1.5.3')
|
||||
version = mod.get_libver(self.request, 'vue_resource')
|
||||
self.assertEqual(version, '1.5.3')
|
||||
self.config.setdefault("wuttaweb.libver.vue_resource", "1.5.3")
|
||||
version = mod.get_libver(self.request, "vue_resource")
|
||||
self.assertEqual(version, "1.5.3")
|
||||
|
||||
def test_fontawesome_default(self):
|
||||
version = mod.get_libver(self.request, 'fontawesome')
|
||||
self.assertEqual(version, '5.3.1')
|
||||
version = mod.get_libver(self.request, "fontawesome")
|
||||
self.assertEqual(version, "5.3.1")
|
||||
|
||||
def test_fontawesome_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.fontawesome', '5.6.3')
|
||||
version = mod.get_libver(self.request, 'fontawesome')
|
||||
self.assertEqual(version, '5.6.3')
|
||||
self.config.setdefault("wuttaweb.libver.fontawesome", "5.6.3")
|
||||
version = mod.get_libver(self.request, "fontawesome")
|
||||
self.assertEqual(version, "5.6.3")
|
||||
|
||||
def test_bb_vue_default(self):
|
||||
version = mod.get_libver(self.request, 'bb_vue')
|
||||
self.assertEqual(version, '3.5.18')
|
||||
version = mod.get_libver(self.request, "bb_vue")
|
||||
self.assertEqual(version, "3.5.18")
|
||||
|
||||
def test_bb_vue_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.bb_vue', '3.4.30')
|
||||
version = mod.get_libver(self.request, 'bb_vue')
|
||||
self.assertEqual(version, '3.4.30')
|
||||
self.config.setdefault("wuttaweb.libver.bb_vue", "3.4.30")
|
||||
version = mod.get_libver(self.request, "bb_vue")
|
||||
self.assertEqual(version, "3.4.30")
|
||||
|
||||
def test_bb_oruga_default(self):
|
||||
version = mod.get_libver(self.request, 'bb_oruga')
|
||||
self.assertEqual(version, '0.11.4')
|
||||
version = mod.get_libver(self.request, "bb_oruga")
|
||||
self.assertEqual(version, "0.11.4")
|
||||
|
||||
def test_bb_oruga_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.bb_oruga', '0.8.11')
|
||||
version = mod.get_libver(self.request, 'bb_oruga')
|
||||
self.assertEqual(version, '0.8.11')
|
||||
self.config.setdefault("wuttaweb.libver.bb_oruga", "0.8.11")
|
||||
version = mod.get_libver(self.request, "bb_oruga")
|
||||
self.assertEqual(version, "0.8.11")
|
||||
|
||||
def test_bb_oruga_bulma_default(self):
|
||||
version = mod.get_libver(self.request, 'bb_oruga_bulma')
|
||||
self.assertEqual(version, '0.7.3')
|
||||
version = mod.get_libver(self.request, 'bb_oruga_bulma_css')
|
||||
self.assertEqual(version, '0.7.3')
|
||||
version = mod.get_libver(self.request, "bb_oruga_bulma")
|
||||
self.assertEqual(version, "0.7.3")
|
||||
version = mod.get_libver(self.request, "bb_oruga_bulma_css")
|
||||
self.assertEqual(version, "0.7.3")
|
||||
|
||||
def test_bb_oruga_bulma_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.bb_oruga_bulma', '0.2.11')
|
||||
version = mod.get_libver(self.request, 'bb_oruga_bulma')
|
||||
self.assertEqual(version, '0.2.11')
|
||||
self.config.setdefault("wuttaweb.libver.bb_oruga_bulma", "0.2.11")
|
||||
version = mod.get_libver(self.request, "bb_oruga_bulma")
|
||||
self.assertEqual(version, "0.2.11")
|
||||
|
||||
def test_bb_fontawesome_svg_core_default(self):
|
||||
version = mod.get_libver(self.request, 'bb_fontawesome_svg_core')
|
||||
self.assertEqual(version, '7.0.0')
|
||||
version = mod.get_libver(self.request, "bb_fontawesome_svg_core")
|
||||
self.assertEqual(version, "7.0.0")
|
||||
|
||||
def test_bb_fontawesome_svg_core_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.bb_fontawesome_svg_core', '6.5.1')
|
||||
version = mod.get_libver(self.request, 'bb_fontawesome_svg_core')
|
||||
self.assertEqual(version, '6.5.1')
|
||||
self.config.setdefault("wuttaweb.libver.bb_fontawesome_svg_core", "6.5.1")
|
||||
version = mod.get_libver(self.request, "bb_fontawesome_svg_core")
|
||||
self.assertEqual(version, "6.5.1")
|
||||
|
||||
def test_bb_free_solid_svg_icons_default(self):
|
||||
version = mod.get_libver(self.request, 'bb_free_solid_svg_icons')
|
||||
self.assertEqual(version, '7.0.0')
|
||||
version = mod.get_libver(self.request, "bb_free_solid_svg_icons")
|
||||
self.assertEqual(version, "7.0.0")
|
||||
|
||||
def test_bb_free_solid_svg_icons_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.bb_free_solid_svg_icons', '6.5.1')
|
||||
version = mod.get_libver(self.request, 'bb_free_solid_svg_icons')
|
||||
self.assertEqual(version, '6.5.1')
|
||||
self.config.setdefault("wuttaweb.libver.bb_free_solid_svg_icons", "6.5.1")
|
||||
version = mod.get_libver(self.request, "bb_free_solid_svg_icons")
|
||||
self.assertEqual(version, "6.5.1")
|
||||
|
||||
def test_bb_vue_fontawesome_default(self):
|
||||
version = mod.get_libver(self.request, 'bb_vue_fontawesome')
|
||||
self.assertEqual(version, '3.1.1')
|
||||
version = mod.get_libver(self.request, "bb_vue_fontawesome")
|
||||
self.assertEqual(version, "3.1.1")
|
||||
|
||||
def test_bb_vue_fontawesome_custom(self):
|
||||
self.config.setdefault('wuttaweb.libver.bb_vue_fontawesome', '3.0.8')
|
||||
version = mod.get_libver(self.request, 'bb_vue_fontawesome')
|
||||
self.assertEqual(version, '3.0.8')
|
||||
self.config.setdefault("wuttaweb.libver.bb_vue_fontawesome", "3.0.8")
|
||||
version = mod.get_libver(self.request, "bb_vue_fontawesome")
|
||||
self.assertEqual(version, "3.0.8")
|
||||
|
||||
|
||||
libcache = Library('testing', 'libcache')
|
||||
vue_js = Resource(libcache, 'vue.js')
|
||||
vue_resource_js = Resource(libcache, 'vue_resource.js')
|
||||
buefy_js = Resource(libcache, 'buefy.js')
|
||||
buefy_css = Resource(libcache, 'buefy.css')
|
||||
fontawesome_js = Resource(libcache, 'fontawesome.js')
|
||||
bb_vue_js = Resource(libcache, 'bb_vue.js')
|
||||
bb_oruga_js = Resource(libcache, 'bb_oruga.js')
|
||||
bb_oruga_bulma_js = Resource(libcache, 'bb_oruga_bulma.js')
|
||||
bb_oruga_bulma_css = Resource(libcache, 'bb_oruga_bulma.css')
|
||||
bb_fontawesome_svg_core_js = Resource(libcache, 'bb_fontawesome_svg_core.js')
|
||||
bb_free_solid_svg_icons_js = Resource(libcache, 'bb_free_solid_svg_icons.js')
|
||||
bb_vue_fontawesome_js = Resource(libcache, 'bb_vue_fontawesome.js')
|
||||
libcache = Library("testing", "libcache")
|
||||
vue_js = Resource(libcache, "vue.js")
|
||||
vue_resource_js = Resource(libcache, "vue_resource.js")
|
||||
buefy_js = Resource(libcache, "buefy.js")
|
||||
buefy_css = Resource(libcache, "buefy.css")
|
||||
fontawesome_js = Resource(libcache, "fontawesome.js")
|
||||
bb_vue_js = Resource(libcache, "bb_vue.js")
|
||||
bb_oruga_js = Resource(libcache, "bb_oruga.js")
|
||||
bb_oruga_bulma_js = Resource(libcache, "bb_oruga_bulma.js")
|
||||
bb_oruga_bulma_css = Resource(libcache, "bb_oruga_bulma.css")
|
||||
bb_fontawesome_svg_core_js = Resource(libcache, "bb_fontawesome_svg_core.js")
|
||||
bb_free_solid_svg_icons_js = Resource(libcache, "bb_free_solid_svg_icons.js")
|
||||
bb_vue_fontawesome_js = Resource(libcache, "bb_vue_fontawesome.js")
|
||||
|
||||
|
||||
class TestGetLibUrl(TestCase):
|
||||
|
@ -242,203 +242,226 @@ class TestGetLibUrl(TestCase):
|
|||
testing.tearDown()
|
||||
|
||||
def setup_fanstatic(self, register=True):
|
||||
self.pyramid_config.include('pyramid_fanstatic')
|
||||
self.pyramid_config.include("pyramid_fanstatic")
|
||||
if register:
|
||||
self.config.setdefault('wuttaweb.static_libcache.module',
|
||||
'tests.test_util')
|
||||
self.config.setdefault("wuttaweb.static_libcache.module", "tests.test_util")
|
||||
|
||||
needed = MagicMock()
|
||||
needed.library_url = MagicMock(return_value='/fanstatic')
|
||||
self.request.environ['fanstatic.needed'] = needed
|
||||
self.request.script_name = '/wutta'
|
||||
needed.library_url = MagicMock(return_value="/fanstatic")
|
||||
self.request.environ["fanstatic.needed"] = needed
|
||||
self.request.script_name = "/wutta"
|
||||
|
||||
def test_buefy_default(self):
|
||||
url = mod.get_liburl(self.request, 'buefy')
|
||||
self.assertEqual(url, 'https://unpkg.com/buefy@0.9.25/dist/buefy.min.js')
|
||||
url = mod.get_liburl(self.request, "buefy")
|
||||
self.assertEqual(url, "https://unpkg.com/buefy@0.9.25/dist/buefy.min.js")
|
||||
|
||||
def test_buefy_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.buefy', '/lib/buefy.js')
|
||||
url = mod.get_liburl(self.request, 'buefy')
|
||||
self.assertEqual(url, '/lib/buefy.js')
|
||||
self.config.setdefault("wuttaweb.liburl.buefy", "/lib/buefy.js")
|
||||
url = mod.get_liburl(self.request, "buefy")
|
||||
self.assertEqual(url, "/lib/buefy.js")
|
||||
|
||||
def test_buefy_custom_tailbone(self):
|
||||
self.config.setdefault('tailbone.liburl.buefy', '/tailbone/buefy.js')
|
||||
url = mod.get_liburl(self.request, 'buefy', prefix='tailbone')
|
||||
self.assertEqual(url, '/tailbone/buefy.js')
|
||||
self.config.setdefault("tailbone.liburl.buefy", "/tailbone/buefy.js")
|
||||
url = mod.get_liburl(self.request, "buefy", prefix="tailbone")
|
||||
self.assertEqual(url, "/tailbone/buefy.js")
|
||||
|
||||
def test_buefy_default_only(self):
|
||||
self.config.setdefault('wuttaweb.liburl.buefy', '/lib/buefy.js')
|
||||
url = mod.get_liburl(self.request, 'buefy', default_only=True)
|
||||
self.assertEqual(url, 'https://unpkg.com/buefy@0.9.25/dist/buefy.min.js')
|
||||
self.config.setdefault("wuttaweb.liburl.buefy", "/lib/buefy.js")
|
||||
url = mod.get_liburl(self.request, "buefy", default_only=True)
|
||||
self.assertEqual(url, "https://unpkg.com/buefy@0.9.25/dist/buefy.min.js")
|
||||
|
||||
def test_buefy_configured_only(self):
|
||||
url = mod.get_liburl(self.request, 'buefy', configured_only=True)
|
||||
url = mod.get_liburl(self.request, "buefy", configured_only=True)
|
||||
self.assertIsNone(url)
|
||||
|
||||
def test_buefy_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'buefy')
|
||||
self.assertEqual(url, '/wutta/fanstatic/buefy.js')
|
||||
url = mod.get_liburl(self.request, "buefy")
|
||||
self.assertEqual(url, "/wutta/fanstatic/buefy.js")
|
||||
|
||||
def test_buefy_fanstatic_tailbone(self):
|
||||
self.setup_fanstatic(register=False)
|
||||
self.config.setdefault('tailbone.static_libcache.module', 'tests.test_util')
|
||||
url = mod.get_liburl(self.request, 'buefy', prefix='tailbone')
|
||||
self.assertEqual(url, '/wutta/fanstatic/buefy.js')
|
||||
self.config.setdefault("tailbone.static_libcache.module", "tests.test_util")
|
||||
url = mod.get_liburl(self.request, "buefy", prefix="tailbone")
|
||||
self.assertEqual(url, "/wutta/fanstatic/buefy.js")
|
||||
|
||||
def test_buefy_css_default(self):
|
||||
url = mod.get_liburl(self.request, 'buefy.css')
|
||||
self.assertEqual(url, 'https://unpkg.com/buefy@0.9.25/dist/buefy.min.css')
|
||||
url = mod.get_liburl(self.request, "buefy.css")
|
||||
self.assertEqual(url, "https://unpkg.com/buefy@0.9.25/dist/buefy.min.css")
|
||||
|
||||
def test_buefy_css_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.buefy.css', '/lib/buefy.css')
|
||||
url = mod.get_liburl(self.request, 'buefy.css')
|
||||
self.assertEqual(url, '/lib/buefy.css')
|
||||
self.config.setdefault("wuttaweb.liburl.buefy.css", "/lib/buefy.css")
|
||||
url = mod.get_liburl(self.request, "buefy.css")
|
||||
self.assertEqual(url, "/lib/buefy.css")
|
||||
|
||||
def test_buefy_css_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'buefy.css')
|
||||
self.assertEqual(url, '/wutta/fanstatic/buefy.css')
|
||||
url = mod.get_liburl(self.request, "buefy.css")
|
||||
self.assertEqual(url, "/wutta/fanstatic/buefy.css")
|
||||
|
||||
def test_vue_default(self):
|
||||
url = mod.get_liburl(self.request, 'vue')
|
||||
self.assertEqual(url, 'https://unpkg.com/vue@2.6.14/dist/vue.min.js')
|
||||
url = mod.get_liburl(self.request, "vue")
|
||||
self.assertEqual(url, "https://unpkg.com/vue@2.6.14/dist/vue.min.js")
|
||||
|
||||
def test_vue_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.vue', '/lib/vue.js')
|
||||
url = mod.get_liburl(self.request, 'vue')
|
||||
self.assertEqual(url, '/lib/vue.js')
|
||||
self.config.setdefault("wuttaweb.liburl.vue", "/lib/vue.js")
|
||||
url = mod.get_liburl(self.request, "vue")
|
||||
self.assertEqual(url, "/lib/vue.js")
|
||||
|
||||
def test_vue_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'vue')
|
||||
self.assertEqual(url, '/wutta/fanstatic/vue.js')
|
||||
url = mod.get_liburl(self.request, "vue")
|
||||
self.assertEqual(url, "/wutta/fanstatic/vue.js")
|
||||
|
||||
def test_vue_resource_default(self):
|
||||
url = mod.get_liburl(self.request, 'vue_resource')
|
||||
self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/vue-resource@1.5.3')
|
||||
url = mod.get_liburl(self.request, "vue_resource")
|
||||
self.assertEqual(url, "https://cdn.jsdelivr.net/npm/vue-resource@1.5.3")
|
||||
|
||||
def test_vue_resource_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.vue_resource', '/lib/vue-resource.js')
|
||||
url = mod.get_liburl(self.request, 'vue_resource')
|
||||
self.assertEqual(url, '/lib/vue-resource.js')
|
||||
self.config.setdefault("wuttaweb.liburl.vue_resource", "/lib/vue-resource.js")
|
||||
url = mod.get_liburl(self.request, "vue_resource")
|
||||
self.assertEqual(url, "/lib/vue-resource.js")
|
||||
|
||||
def test_vue_resource_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'vue_resource')
|
||||
self.assertEqual(url, '/wutta/fanstatic/vue_resource.js')
|
||||
url = mod.get_liburl(self.request, "vue_resource")
|
||||
self.assertEqual(url, "/wutta/fanstatic/vue_resource.js")
|
||||
|
||||
def test_fontawesome_default(self):
|
||||
url = mod.get_liburl(self.request, 'fontawesome')
|
||||
self.assertEqual(url, 'https://use.fontawesome.com/releases/v5.3.1/js/all.js')
|
||||
url = mod.get_liburl(self.request, "fontawesome")
|
||||
self.assertEqual(url, "https://use.fontawesome.com/releases/v5.3.1/js/all.js")
|
||||
|
||||
def test_fontawesome_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.fontawesome', '/lib/fontawesome.js')
|
||||
url = mod.get_liburl(self.request, 'fontawesome')
|
||||
self.assertEqual(url, '/lib/fontawesome.js')
|
||||
self.config.setdefault("wuttaweb.liburl.fontawesome", "/lib/fontawesome.js")
|
||||
url = mod.get_liburl(self.request, "fontawesome")
|
||||
self.assertEqual(url, "/lib/fontawesome.js")
|
||||
|
||||
def test_fontawesome_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'fontawesome')
|
||||
self.assertEqual(url, '/wutta/fanstatic/fontawesome.js')
|
||||
url = mod.get_liburl(self.request, "fontawesome")
|
||||
self.assertEqual(url, "/wutta/fanstatic/fontawesome.js")
|
||||
|
||||
def test_bb_vue_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_vue')
|
||||
self.assertEqual(url, 'https://unpkg.com/vue@3.5.18/dist/vue.esm-browser.prod.js')
|
||||
url = mod.get_liburl(self.request, "bb_vue")
|
||||
self.assertEqual(
|
||||
url, "https://unpkg.com/vue@3.5.18/dist/vue.esm-browser.prod.js"
|
||||
)
|
||||
|
||||
def test_bb_vue_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_vue', '/lib/vue.js')
|
||||
url = mod.get_liburl(self.request, 'bb_vue')
|
||||
self.assertEqual(url, '/lib/vue.js')
|
||||
self.config.setdefault("wuttaweb.liburl.bb_vue", "/lib/vue.js")
|
||||
url = mod.get_liburl(self.request, "bb_vue")
|
||||
self.assertEqual(url, "/lib/vue.js")
|
||||
|
||||
def test_bb_vue_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_vue')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_vue.js')
|
||||
url = mod.get_liburl(self.request, "bb_vue")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_vue.js")
|
||||
|
||||
def test_bb_oruga_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_oruga')
|
||||
self.assertEqual(url, 'https://unpkg.com/@oruga-ui/oruga-next@0.11.4/dist/oruga.mjs')
|
||||
url = mod.get_liburl(self.request, "bb_oruga")
|
||||
self.assertEqual(
|
||||
url, "https://unpkg.com/@oruga-ui/oruga-next@0.11.4/dist/oruga.mjs"
|
||||
)
|
||||
|
||||
def test_bb_oruga_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_oruga', '/lib/oruga.js')
|
||||
url = mod.get_liburl(self.request, 'bb_oruga')
|
||||
self.assertEqual(url, '/lib/oruga.js')
|
||||
self.config.setdefault("wuttaweb.liburl.bb_oruga", "/lib/oruga.js")
|
||||
url = mod.get_liburl(self.request, "bb_oruga")
|
||||
self.assertEqual(url, "/lib/oruga.js")
|
||||
|
||||
def test_bb_oruga_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_oruga')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_oruga.js')
|
||||
url = mod.get_liburl(self.request, "bb_oruga")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_oruga.js")
|
||||
|
||||
def test_bb_oruga_bulma_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_oruga_bulma')
|
||||
self.assertEqual(url, 'https://unpkg.com/@oruga-ui/theme-bulma@0.7.3/dist/bulma.js')
|
||||
url = mod.get_liburl(self.request, "bb_oruga_bulma")
|
||||
self.assertEqual(
|
||||
url, "https://unpkg.com/@oruga-ui/theme-bulma@0.7.3/dist/bulma.js"
|
||||
)
|
||||
|
||||
def test_bb_oruga_bulma_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_oruga_bulma', '/lib/oruga_bulma.js')
|
||||
url = mod.get_liburl(self.request, 'bb_oruga_bulma')
|
||||
self.assertEqual(url, '/lib/oruga_bulma.js')
|
||||
self.config.setdefault("wuttaweb.liburl.bb_oruga_bulma", "/lib/oruga_bulma.js")
|
||||
url = mod.get_liburl(self.request, "bb_oruga_bulma")
|
||||
self.assertEqual(url, "/lib/oruga_bulma.js")
|
||||
|
||||
def test_bb_oruga_bulma_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_oruga_bulma')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_oruga_bulma.js')
|
||||
url = mod.get_liburl(self.request, "bb_oruga_bulma")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_oruga_bulma.js")
|
||||
|
||||
def test_bb_oruga_bulma_css_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_oruga_bulma_css')
|
||||
self.assertEqual(url, 'https://unpkg.com/@oruga-ui/theme-bulma@0.7.3/dist/bulma.css')
|
||||
url = mod.get_liburl(self.request, "bb_oruga_bulma_css")
|
||||
self.assertEqual(
|
||||
url, "https://unpkg.com/@oruga-ui/theme-bulma@0.7.3/dist/bulma.css"
|
||||
)
|
||||
|
||||
def test_bb_oruga_bulma_css_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_oruga_bulma_css', '/lib/oruga-bulma.css')
|
||||
url = mod.get_liburl(self.request, 'bb_oruga_bulma_css')
|
||||
self.assertEqual(url, '/lib/oruga-bulma.css')
|
||||
self.config.setdefault(
|
||||
"wuttaweb.liburl.bb_oruga_bulma_css", "/lib/oruga-bulma.css"
|
||||
)
|
||||
url = mod.get_liburl(self.request, "bb_oruga_bulma_css")
|
||||
self.assertEqual(url, "/lib/oruga-bulma.css")
|
||||
|
||||
def test_bb_oruga_bulma_css_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_oruga_bulma_css')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_oruga_bulma.css')
|
||||
url = mod.get_liburl(self.request, "bb_oruga_bulma_css")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_oruga_bulma.css")
|
||||
|
||||
def test_bb_fontawesome_svg_core_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_fontawesome_svg_core')
|
||||
self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core@7.0.0/+esm')
|
||||
url = mod.get_liburl(self.request, "bb_fontawesome_svg_core")
|
||||
self.assertEqual(
|
||||
url,
|
||||
"https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core@7.0.0/+esm",
|
||||
)
|
||||
|
||||
def test_bb_fontawesome_svg_core_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_fontawesome_svg_core', '/lib/fontawesome-svg-core.js')
|
||||
url = mod.get_liburl(self.request, 'bb_fontawesome_svg_core')
|
||||
self.assertEqual(url, '/lib/fontawesome-svg-core.js')
|
||||
self.config.setdefault(
|
||||
"wuttaweb.liburl.bb_fontawesome_svg_core", "/lib/fontawesome-svg-core.js"
|
||||
)
|
||||
url = mod.get_liburl(self.request, "bb_fontawesome_svg_core")
|
||||
self.assertEqual(url, "/lib/fontawesome-svg-core.js")
|
||||
|
||||
def test_bb_fontawesome_svg_core_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_fontawesome_svg_core')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_fontawesome_svg_core.js')
|
||||
url = mod.get_liburl(self.request, "bb_fontawesome_svg_core")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_fontawesome_svg_core.js")
|
||||
|
||||
def test_bb_free_solid_svg_icons_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_free_solid_svg_icons')
|
||||
self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons@7.0.0/+esm')
|
||||
url = mod.get_liburl(self.request, "bb_free_solid_svg_icons")
|
||||
self.assertEqual(
|
||||
url,
|
||||
"https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons@7.0.0/+esm",
|
||||
)
|
||||
|
||||
def test_bb_free_solid_svg_icons_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_free_solid_svg_icons', '/lib/free-solid-svg-icons.js')
|
||||
url = mod.get_liburl(self.request, 'bb_free_solid_svg_icons')
|
||||
self.assertEqual(url, '/lib/free-solid-svg-icons.js')
|
||||
self.config.setdefault(
|
||||
"wuttaweb.liburl.bb_free_solid_svg_icons", "/lib/free-solid-svg-icons.js"
|
||||
)
|
||||
url = mod.get_liburl(self.request, "bb_free_solid_svg_icons")
|
||||
self.assertEqual(url, "/lib/free-solid-svg-icons.js")
|
||||
|
||||
def test_bb_free_solid_svg_icons_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_free_solid_svg_icons')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_free_solid_svg_icons.js')
|
||||
url = mod.get_liburl(self.request, "bb_free_solid_svg_icons")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_free_solid_svg_icons.js")
|
||||
|
||||
def test_bb_vue_fontawesome_default(self):
|
||||
url = mod.get_liburl(self.request, 'bb_vue_fontawesome')
|
||||
self.assertEqual(url, 'https://cdn.jsdelivr.net/npm/@fortawesome/vue-fontawesome@3.1.1/+esm')
|
||||
url = mod.get_liburl(self.request, "bb_vue_fontawesome")
|
||||
self.assertEqual(
|
||||
url, "https://cdn.jsdelivr.net/npm/@fortawesome/vue-fontawesome@3.1.1/+esm"
|
||||
)
|
||||
|
||||
def test_bb_vue_fontawesome_custom(self):
|
||||
self.config.setdefault('wuttaweb.liburl.bb_vue_fontawesome', '/lib/vue-fontawesome.js')
|
||||
url = mod.get_liburl(self.request, 'bb_vue_fontawesome')
|
||||
self.assertEqual(url, '/lib/vue-fontawesome.js')
|
||||
self.config.setdefault(
|
||||
"wuttaweb.liburl.bb_vue_fontawesome", "/lib/vue-fontawesome.js"
|
||||
)
|
||||
url = mod.get_liburl(self.request, "bb_vue_fontawesome")
|
||||
self.assertEqual(url, "/lib/vue-fontawesome.js")
|
||||
|
||||
def test_bb_vue_fontawesome_fanstatic(self):
|
||||
self.setup_fanstatic()
|
||||
url = mod.get_liburl(self.request, 'bb_vue_fontawesome')
|
||||
self.assertEqual(url, '/wutta/fanstatic/bb_vue_fontawesome.js')
|
||||
url = mod.get_liburl(self.request, "bb_vue_fontawesome")
|
||||
self.assertEqual(url, "/wutta/fanstatic/bb_vue_fontawesome.js")
|
||||
|
||||
|
||||
class TestGetFormData(TestCase):
|
||||
|
@ -447,25 +470,25 @@ class TestGetFormData(TestCase):
|
|||
self.config = WuttaConfig()
|
||||
|
||||
def make_request(self, **kwargs):
|
||||
kwargs.setdefault('wutta_config', self.config)
|
||||
kwargs.setdefault('POST', {'foo1': 'bar'})
|
||||
kwargs.setdefault('json_body', {'foo2': 'baz'})
|
||||
kwargs.setdefault("wutta_config", self.config)
|
||||
kwargs.setdefault("POST", {"foo1": "bar"})
|
||||
kwargs.setdefault("json_body", {"foo2": "baz"})
|
||||
return testing.DummyRequest(**kwargs)
|
||||
|
||||
def test_default(self):
|
||||
request = self.make_request()
|
||||
data = mod.get_form_data(request)
|
||||
self.assertEqual(data, {'foo1': 'bar'})
|
||||
self.assertEqual(data, {"foo1": "bar"})
|
||||
|
||||
def test_is_xhr(self):
|
||||
request = self.make_request(POST=None, is_xhr=True)
|
||||
data = mod.get_form_data(request)
|
||||
self.assertEqual(data, {'foo2': 'baz'})
|
||||
self.assertEqual(data, {"foo2": "baz"})
|
||||
|
||||
def test_content_type(self):
|
||||
request = self.make_request(POST=None, content_type='application/json')
|
||||
request = self.make_request(POST=None, content_type="application/json")
|
||||
data = mod.get_form_data(request)
|
||||
self.assertEqual(data, {'foo2': 'baz'})
|
||||
self.assertEqual(data, {"foo2": "baz"})
|
||||
|
||||
|
||||
class TestGetModelFields(ConfigTestCase):
|
||||
|
@ -481,41 +504,47 @@ class TestGetModelFields(ConfigTestCase):
|
|||
def test_basic(self):
|
||||
model = self.app.model
|
||||
fields = mod.get_model_fields(self.config, model.Setting)
|
||||
self.assertEqual(fields, ['name', 'value'])
|
||||
self.assertEqual(fields, ["name", "value"])
|
||||
|
||||
def test_include_fk(self):
|
||||
model = self.app.model
|
||||
|
||||
# fk excluded by default
|
||||
fields = mod.get_model_fields(self.config, model.User)
|
||||
self.assertNotIn('person_uuid', fields)
|
||||
self.assertIn('person', fields)
|
||||
self.assertNotIn("person_uuid", fields)
|
||||
self.assertIn("person", fields)
|
||||
|
||||
# fk can be included
|
||||
fields = mod.get_model_fields(self.config, model.User, include_fk=True)
|
||||
self.assertIn('person_uuid', fields)
|
||||
self.assertIn('person', fields)
|
||||
self.assertIn("person_uuid", fields)
|
||||
self.assertIn("person", fields)
|
||||
|
||||
def test_avoid_versions(self):
|
||||
model = self.app.model
|
||||
|
||||
mapper = MagicMock(iterate_properties = [
|
||||
MagicMock(key='uuid'),
|
||||
MagicMock(key='full_name'),
|
||||
MagicMock(key='first_name'),
|
||||
MagicMock(key='middle_name'),
|
||||
MagicMock(key='last_name'),
|
||||
MagicMock(key='versions'),
|
||||
])
|
||||
mapper = MagicMock(
|
||||
iterate_properties=[
|
||||
MagicMock(key="uuid"),
|
||||
MagicMock(key="full_name"),
|
||||
MagicMock(key="first_name"),
|
||||
MagicMock(key="middle_name"),
|
||||
MagicMock(key="last_name"),
|
||||
MagicMock(key="versions"),
|
||||
]
|
||||
)
|
||||
|
||||
with patch.object(mod, 'sa') as sa:
|
||||
with patch.object(mod, "sa") as sa:
|
||||
sa.inspect.return_value = mapper
|
||||
|
||||
with patch.object(self.app, 'continuum_is_enabled', return_value=True):
|
||||
with patch.object(self.app, "continuum_is_enabled", return_value=True):
|
||||
fields = mod.get_model_fields(self.config, model.Person)
|
||||
# nb. no versions field
|
||||
self.assertEqual(set(fields), set(['uuid', 'full_name', 'first_name',
|
||||
'middle_name', 'last_name']))
|
||||
self.assertEqual(
|
||||
set(fields),
|
||||
set(
|
||||
["uuid", "full_name", "first_name", "middle_name", "last_name"]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class TestGetCsrfToken(TestCase):
|
||||
|
@ -541,7 +570,7 @@ class TestGetCsrfToken(TestCase):
|
|||
|
||||
# nb. dummy request always returns same token, so must
|
||||
# trick it into thinking it doesn't have one yet
|
||||
with patch.object(self.request.session, 'get_csrf_token', return_value=None):
|
||||
with patch.object(self.request.session, "get_csrf_token", return_value=None):
|
||||
token = mod.get_csrf_token(self.request)
|
||||
self.assertIsNotNone(token)
|
||||
|
||||
|
@ -577,7 +606,7 @@ class TestMakeJsonSafe(TestCase):
|
|||
model = self.app.model
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
self.assertRaises(TypeError, json.dumps, person)
|
||||
value = mod.make_json_safe(person, key='person')
|
||||
value = mod.make_json_safe(person, key="person")
|
||||
self.assertEqual(value, "Betty Boop")
|
||||
|
||||
def test_uuid(self):
|
||||
|
@ -586,7 +615,7 @@ class TestMakeJsonSafe(TestCase):
|
|||
self.assertEqual(value, uuid.hex)
|
||||
|
||||
def test_decimal(self):
|
||||
value = decimal.Decimal('42.42')
|
||||
value = decimal.Decimal("42.42")
|
||||
self.assertNotEqual(value, 42.42)
|
||||
result = mod.make_json_safe(value)
|
||||
self.assertEqual(result, 42.42)
|
||||
|
@ -596,34 +625,40 @@ class TestMakeJsonSafe(TestCase):
|
|||
person = model.Person(full_name="Betty Boop")
|
||||
|
||||
data = {
|
||||
'foo': 'bar',
|
||||
'person': person,
|
||||
"foo": "bar",
|
||||
"person": person,
|
||||
}
|
||||
|
||||
self.assertRaises(TypeError, json.dumps, data)
|
||||
value = mod.make_json_safe(data)
|
||||
self.assertEqual(value, {
|
||||
'foo': 'bar',
|
||||
'person': "Betty Boop",
|
||||
})
|
||||
self.assertEqual(
|
||||
value,
|
||||
{
|
||||
"foo": "bar",
|
||||
"person": "Betty Boop",
|
||||
},
|
||||
)
|
||||
|
||||
def test_list(self):
|
||||
model = self.app.model
|
||||
person = model.Person(full_name="Betty Boop")
|
||||
|
||||
data = [
|
||||
'foo',
|
||||
'bar',
|
||||
"foo",
|
||||
"bar",
|
||||
person,
|
||||
]
|
||||
|
||||
self.assertRaises(TypeError, json.dumps, data)
|
||||
value = mod.make_json_safe(data)
|
||||
self.assertEqual(value, [
|
||||
'foo',
|
||||
'bar',
|
||||
"Betty Boop",
|
||||
])
|
||||
self.assertEqual(
|
||||
value,
|
||||
[
|
||||
"foo",
|
||||
"bar",
|
||||
"Betty Boop",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TestGetAvailableThemes(TestCase):
|
||||
|
@ -634,63 +669,65 @@ class TestGetAvailableThemes(TestCase):
|
|||
|
||||
def test_defaults(self):
|
||||
themes = mod.get_available_themes(self.config)
|
||||
self.assertEqual(themes, ['default', 'butterfly'])
|
||||
self.assertEqual(themes, ["default", "butterfly"])
|
||||
|
||||
def test_sorting(self):
|
||||
self.config.setdefault('wuttaweb.themes.keys', 'default, foo2, foo4, foo1')
|
||||
self.config.setdefault("wuttaweb.themes.keys", "default, foo2, foo4, foo1")
|
||||
themes = mod.get_available_themes(self.config)
|
||||
self.assertEqual(themes, ['default', 'foo1', 'foo2', 'foo4'])
|
||||
self.assertEqual(themes, ["default", "foo1", "foo2", "foo4"])
|
||||
|
||||
def test_default_omitted(self):
|
||||
self.config.setdefault('wuttaweb.themes.keys', 'butterfly, foo')
|
||||
self.config.setdefault("wuttaweb.themes.keys", "butterfly, foo")
|
||||
themes = mod.get_available_themes(self.config)
|
||||
self.assertEqual(themes, ['default', 'butterfly', 'foo'])
|
||||
self.assertEqual(themes, ["default", "butterfly", "foo"])
|
||||
|
||||
def test_default_notfirst(self):
|
||||
self.config.setdefault('wuttaweb.themes.keys', 'butterfly, foo, default')
|
||||
self.config.setdefault("wuttaweb.themes.keys", "butterfly, foo, default")
|
||||
themes = mod.get_available_themes(self.config)
|
||||
self.assertEqual(themes, ['default', 'butterfly', 'foo'])
|
||||
self.assertEqual(themes, ["default", "butterfly", "foo"])
|
||||
|
||||
|
||||
class TestGetEffectiveTheme(DataTestCase):
|
||||
|
||||
def test_default(self):
|
||||
theme = mod.get_effective_theme(self.config)
|
||||
self.assertEqual(theme, 'default')
|
||||
self.assertEqual(theme, "default")
|
||||
|
||||
def test_override_config(self):
|
||||
self.app.save_setting(self.session, 'wuttaweb.theme', 'butterfly')
|
||||
self.app.save_setting(self.session, "wuttaweb.theme", "butterfly")
|
||||
self.session.commit()
|
||||
theme = mod.get_effective_theme(self.config)
|
||||
self.assertEqual(theme, 'butterfly')
|
||||
self.assertEqual(theme, "butterfly")
|
||||
|
||||
def test_override_param(self):
|
||||
theme = mod.get_effective_theme(self.config, theme='butterfly')
|
||||
self.assertEqual(theme, 'butterfly')
|
||||
theme = mod.get_effective_theme(self.config, theme="butterfly")
|
||||
self.assertEqual(theme, "butterfly")
|
||||
|
||||
def test_invalid(self):
|
||||
self.assertRaises(ValueError, mod.get_effective_theme, self.config, theme='invalid')
|
||||
self.assertRaises(
|
||||
ValueError, mod.get_effective_theme, self.config, theme="invalid"
|
||||
)
|
||||
|
||||
|
||||
class TestThemeTemplatePath(DataTestCase):
|
||||
|
||||
def test_default(self):
|
||||
path = mod.get_theme_template_path(self.config, theme='default')
|
||||
path = mod.get_theme_template_path(self.config, theme="default")
|
||||
# nb. even though the path does not exist, we still want to
|
||||
# pretend like it does, hence prev call should return this:
|
||||
expected = resource_path('wuttaweb:templates/themes/default')
|
||||
expected = resource_path("wuttaweb:templates/themes/default")
|
||||
self.assertEqual(path, expected)
|
||||
|
||||
def test_default(self):
|
||||
path = mod.get_theme_template_path(self.config, theme='butterfly')
|
||||
expected = resource_path('wuttaweb:templates/themes/butterfly')
|
||||
path = mod.get_theme_template_path(self.config, theme="butterfly")
|
||||
expected = resource_path("wuttaweb:templates/themes/butterfly")
|
||||
self.assertEqual(path, expected)
|
||||
|
||||
def test_custom(self):
|
||||
self.config.setdefault('wuttaweb.themes.keys', 'default, butterfly, poser')
|
||||
self.config.setdefault('wuttaweb.theme.poser', '/tmp/poser-theme')
|
||||
path = mod.get_theme_template_path(self.config, theme='poser')
|
||||
self.assertEqual(path, '/tmp/poser-theme')
|
||||
self.config.setdefault("wuttaweb.themes.keys", "default, butterfly, poser")
|
||||
self.config.setdefault("wuttaweb.theme.poser", "/tmp/poser-theme")
|
||||
path = mod.get_theme_template_path(self.config, theme="poser")
|
||||
self.assertEqual(path, "/tmp/poser-theme")
|
||||
|
||||
|
||||
class TestSetAppTheme(WebTestCase):
|
||||
|
@ -699,14 +736,14 @@ class TestSetAppTheme(WebTestCase):
|
|||
|
||||
# establish default
|
||||
settings = self.request.registry.settings
|
||||
self.assertNotIn('wuttaweb.theme', settings)
|
||||
self.assertNotIn("wuttaweb.theme", settings)
|
||||
establish_theme(settings)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
|
||||
# set to butterfly
|
||||
mod.set_app_theme(self.request, 'butterfly', session=self.session)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'butterfly')
|
||||
mod.set_app_theme(self.request, "butterfly", session=self.session)
|
||||
self.assertEqual(settings["wuttaweb.theme"], "butterfly")
|
||||
|
||||
# set back to default
|
||||
mod.set_app_theme(self.request, 'default', session=self.session)
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
mod.set_app_theme(self.request, "default", session=self.session)
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
|
|
|
@ -15,9 +15,11 @@ class DataTestCase(FileConfigTestCase):
|
|||
|
||||
def setup_db(self):
|
||||
self.setup_files()
|
||||
self.config = WuttaConfig(defaults={
|
||||
'wutta.db.default.url': 'sqlite://',
|
||||
})
|
||||
self.config = WuttaConfig(
|
||||
defaults={
|
||||
"wutta.db.default.url": "sqlite://",
|
||||
}
|
||||
)
|
||||
self.app = self.config.get_app()
|
||||
|
||||
# init db
|
||||
|
@ -36,5 +38,6 @@ class NullMenuHandler(MenuHandler):
|
|||
"""
|
||||
Dummy menu handler for testing.
|
||||
"""
|
||||
|
||||
def make_menus(self, request, **kwargs):
|
||||
return []
|
||||
|
|
|
@ -7,4 +7,4 @@ class TestIncludeMe(WebTestCase):
|
|||
|
||||
def test_basic(self):
|
||||
# just ensure no error happens when included..
|
||||
self.pyramid_config.include('wuttaweb.views')
|
||||
self.pyramid_config.include("wuttaweb.views")
|
||||
|
|
|
@ -12,13 +12,13 @@ class TestAuthView(WebTestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.setup_web()
|
||||
self.pyramid_config.include('wuttaweb.views.common')
|
||||
self.pyramid_config.include("wuttaweb.views.common")
|
||||
|
||||
def make_view(self):
|
||||
return mod.AuthView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.auth')
|
||||
self.pyramid_config.include("wuttaweb.views.auth")
|
||||
|
||||
def test_login(self):
|
||||
model = self.app.model
|
||||
|
@ -31,37 +31,37 @@ class TestAuthView(WebTestCase):
|
|||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# make a user
|
||||
barney = model.User(username='barney')
|
||||
auth.set_user_password(barney, 'testpass')
|
||||
barney = model.User(username="barney")
|
||||
auth.set_user_password(barney, "testpass")
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
|
||||
# now since user exists, form will display
|
||||
context = view.login(session=self.session)
|
||||
self.assertIn('form', context)
|
||||
self.assertIn("form", context)
|
||||
|
||||
# redirect if user already logged in
|
||||
with patch.object(self.request, 'user', new=barney):
|
||||
with patch.object(self.request, "user", new=barney):
|
||||
view = self.make_view()
|
||||
response = view.login(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# login fails w/ wrong password
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'username': 'barney', 'password': 'WRONG'}
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {"username": "barney", "password": "WRONG"}
|
||||
view = self.make_view()
|
||||
context = view.login(session=self.session)
|
||||
self.assertIn('form', context)
|
||||
self.assertIn("form", context)
|
||||
|
||||
# redirect if login succeeds
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'username': 'barney', 'password': 'testpass'}
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {"username": "barney", "password": "testpass"}
|
||||
view = self.make_view()
|
||||
response = view.login(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_logout(self):
|
||||
self.pyramid_config.add_route('login', '/login')
|
||||
self.pyramid_config.add_route("login", "/login")
|
||||
view = self.make_view()
|
||||
self.request.session.delete = MagicMock()
|
||||
response = view.logout()
|
||||
|
@ -71,7 +71,7 @@ class TestAuthView(WebTestCase):
|
|||
def test_change_password(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
|
@ -81,7 +81,7 @@ class TestAuthView(WebTestCase):
|
|||
self.assertIsInstance(redirect, HTTPFound)
|
||||
|
||||
# set initial password
|
||||
auth.set_user_password(barney, 'foo')
|
||||
auth.set_user_password(barney, "foo")
|
||||
self.session.commit()
|
||||
|
||||
# forbidden if prevent_edit is set for user
|
||||
|
@ -94,24 +94,24 @@ class TestAuthView(WebTestCase):
|
|||
|
||||
# view should now return context w/ form
|
||||
context = view.change_password()
|
||||
self.assertIn('form', context)
|
||||
self.assertIn("form", context)
|
||||
|
||||
# submit valid form, ensure password is changed
|
||||
# (nb. this also would redirect user to home page)
|
||||
self.request.method = 'POST'
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {
|
||||
'current_password': 'foo',
|
||||
"current_password": "foo",
|
||||
# nb. new_password requires colander mapping structure
|
||||
'__start__': 'new_password:mapping',
|
||||
'new_password': 'bar',
|
||||
'new_password-confirm': 'bar',
|
||||
'__end__': 'new_password:mapping',
|
||||
"__start__": "new_password:mapping",
|
||||
"new_password": "bar",
|
||||
"new_password-confirm": "bar",
|
||||
"__end__": "new_password:mapping",
|
||||
}
|
||||
redirect = view.change_password()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.session.commit()
|
||||
self.assertFalse(auth.check_user_password(barney, 'foo'))
|
||||
self.assertTrue(auth.check_user_password(barney, 'bar'))
|
||||
self.assertFalse(auth.check_user_password(barney, "foo"))
|
||||
self.assertTrue(auth.check_user_password(barney, "bar"))
|
||||
|
||||
# at this point 'foo' is the password, now let's submit some
|
||||
# invalid forms and make sure we get back a context w/ form
|
||||
|
@ -119,72 +119,77 @@ class TestAuthView(WebTestCase):
|
|||
# first try empty data
|
||||
self.request.POST = {}
|
||||
context = view.change_password()
|
||||
self.assertIn('form', context)
|
||||
dform = context['form'].get_deform()
|
||||
self.assertEqual(dform['current_password'].errormsg, "Required")
|
||||
self.assertEqual(dform['new_password'].errormsg, "Required")
|
||||
self.assertIn("form", context)
|
||||
dform = context["form"].get_deform()
|
||||
self.assertEqual(dform["current_password"].errormsg, "Required")
|
||||
self.assertEqual(dform["new_password"].errormsg, "Required")
|
||||
|
||||
# now try bad current password
|
||||
self.request.POST = {
|
||||
'current_password': 'blahblah',
|
||||
'__start__': 'new_password:mapping',
|
||||
'new_password': 'baz',
|
||||
'new_password-confirm': 'baz',
|
||||
'__end__': 'new_password:mapping',
|
||||
"current_password": "blahblah",
|
||||
"__start__": "new_password:mapping",
|
||||
"new_password": "baz",
|
||||
"new_password-confirm": "baz",
|
||||
"__end__": "new_password:mapping",
|
||||
}
|
||||
context = view.change_password()
|
||||
self.assertIn('form', context)
|
||||
dform = context['form'].get_deform()
|
||||
self.assertEqual(dform['current_password'].errormsg, "Current password is incorrect.")
|
||||
self.assertIn("form", context)
|
||||
dform = context["form"].get_deform()
|
||||
self.assertEqual(
|
||||
dform["current_password"].errormsg, "Current password is incorrect."
|
||||
)
|
||||
|
||||
# now try bad new password
|
||||
self.request.POST = {
|
||||
'current_password': 'bar',
|
||||
'__start__': 'new_password:mapping',
|
||||
'new_password': 'bar',
|
||||
'new_password-confirm': 'bar',
|
||||
'__end__': 'new_password:mapping',
|
||||
"current_password": "bar",
|
||||
"__start__": "new_password:mapping",
|
||||
"new_password": "bar",
|
||||
"new_password-confirm": "bar",
|
||||
"__end__": "new_password:mapping",
|
||||
}
|
||||
context = view.change_password()
|
||||
self.assertIn('form', context)
|
||||
dform = context['form'].get_deform()
|
||||
self.assertEqual(dform['new_password'].errormsg, "New password must be different from old password.")
|
||||
self.assertIn("form", context)
|
||||
dform = context["form"].get_deform()
|
||||
self.assertEqual(
|
||||
dform["new_password"].errormsg,
|
||||
"New password must be different from old password.",
|
||||
)
|
||||
|
||||
def test_become_root(self):
|
||||
view = mod.AuthView(self.request)
|
||||
|
||||
# GET not allowed
|
||||
self.request.method = 'GET'
|
||||
self.request.method = "GET"
|
||||
self.assertRaises(HTTPForbidden, view.become_root)
|
||||
|
||||
# non-admin users also not allowed
|
||||
self.request.method = 'POST'
|
||||
self.request.method = "POST"
|
||||
self.request.is_admin = False
|
||||
self.assertRaises(HTTPForbidden, view.become_root)
|
||||
|
||||
# but admin users can become root
|
||||
self.request.is_admin = True
|
||||
self.assertNotIn('is_root', self.request.session)
|
||||
self.assertNotIn("is_root", self.request.session)
|
||||
redirect = view.become_root()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.assertTrue(self.request.session['is_root'])
|
||||
self.assertTrue(self.request.session["is_root"])
|
||||
|
||||
def test_stop_root(self):
|
||||
view = mod.AuthView(self.request)
|
||||
|
||||
# GET not allowed
|
||||
self.request.method = 'GET'
|
||||
self.request.method = "GET"
|
||||
self.assertRaises(HTTPForbidden, view.stop_root)
|
||||
|
||||
# non-admin users also not allowed
|
||||
self.request.method = 'POST'
|
||||
self.request.method = "POST"
|
||||
self.request.is_admin = False
|
||||
self.assertRaises(HTTPForbidden, view.stop_root)
|
||||
|
||||
# but admin users can stop being root
|
||||
# (nb. there is no check whether user is currently root)
|
||||
self.request.is_admin = True
|
||||
self.assertNotIn('is_root', self.request.session)
|
||||
self.assertNotIn("is_root", self.request.session)
|
||||
redirect = view.stop_root()
|
||||
self.assertIsInstance(redirect, HTTPFound)
|
||||
self.assertFalse(self.request.session['is_root'])
|
||||
self.assertFalse(self.request.session["is_root"])
|
||||
|
|
|
@ -36,7 +36,7 @@ class TestView(WebTestCase):
|
|||
|
||||
def test_make_grid_action(self):
|
||||
view = self.make_view()
|
||||
action = view.make_grid_action('view')
|
||||
action = view.make_grid_action("view")
|
||||
self.assertIsInstance(action, GridAction)
|
||||
|
||||
def test_notfound(self):
|
||||
|
@ -46,31 +46,31 @@ class TestView(WebTestCase):
|
|||
|
||||
def test_redirect(self):
|
||||
view = self.make_view()
|
||||
error = view.redirect('/')
|
||||
error = view.redirect("/")
|
||||
self.assertIsInstance(error, HTTPFound)
|
||||
self.assertEqual(error.location, '/')
|
||||
self.assertEqual(error.location, "/")
|
||||
|
||||
def test_file_response(self):
|
||||
view = self.make_view()
|
||||
|
||||
# default uses attachment behavior
|
||||
datfile = self.write_file('dat.txt', 'hello')
|
||||
datfile = self.write_file("dat.txt", "hello")
|
||||
response = view.file_response(datfile)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content_disposition, 'attachment; filename="dat.txt"')
|
||||
|
||||
# but can disable attachment behavior
|
||||
datfile = self.write_file('dat.txt', 'hello')
|
||||
datfile = self.write_file("dat.txt", "hello")
|
||||
response = view.file_response(datfile, attachment=False)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIsNone(response.content_disposition)
|
||||
|
||||
# path not found
|
||||
crapfile = '/does/not/exist'
|
||||
crapfile = "/does/not/exist"
|
||||
response = view.file_response(crapfile)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_json_response(self):
|
||||
view = self.make_view()
|
||||
response = view.json_response({'foo': 'bar'})
|
||||
response = view.json_response({"foo": "bar"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
|
|
@ -14,14 +14,17 @@ from wuttaweb.testing import WebTestCase
|
|||
|
||||
|
||||
class MockBatch(model.BatchMixin, model.Base):
|
||||
__tablename__ = 'testing_batch_mock'
|
||||
__tablename__ = "testing_batch_mock"
|
||||
|
||||
|
||||
class MockBatchRow(model.BatchRowMixin, model.Base):
|
||||
__tablename__ = 'testing_batch_mock_row'
|
||||
__tablename__ = "testing_batch_mock_row"
|
||||
__batch_class__ = MockBatch
|
||||
|
||||
|
||||
MockBatch.__row_class__ = MockBatchRow
|
||||
|
||||
|
||||
class MockBatchHandler(BatchHandler):
|
||||
model_class = MockBatch
|
||||
|
||||
|
@ -43,43 +46,52 @@ class TestBatchMasterView(WebTestCase):
|
|||
def test_get_batch_handler(self):
|
||||
self.assertRaises(NotImplementedError, mod.BatchMasterView, self.request)
|
||||
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=42):
|
||||
with patch.object(mod.BatchMasterView, "get_batch_handler", return_value=42):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
self.assertEqual(view.batch_handler, 42)
|
||||
|
||||
def test_get_fallback_templates(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = self.make_view()
|
||||
templates = view.get_fallback_templates('view')
|
||||
self.assertEqual(templates, [
|
||||
'/batch/view.mako',
|
||||
'/master/view.mako',
|
||||
])
|
||||
templates = view.get_fallback_templates("view")
|
||||
self.assertEqual(
|
||||
templates,
|
||||
[
|
||||
"/batch/view.mako",
|
||||
"/master/view.mako",
|
||||
],
|
||||
)
|
||||
|
||||
def test_render_to_response(self):
|
||||
model = self.app.model
|
||||
handler = MockBatchHandler(self.config)
|
||||
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
batch = handler.make_batch(self.session, created_by=user)
|
||||
self.session.add(batch)
|
||||
self.session.flush()
|
||||
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(MasterView, 'render_to_response') as render_to_response:
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
with patch.object(MasterView, "render_to_response") as render_to_response:
|
||||
view = self.make_view()
|
||||
response = view.render_to_response('view', {'instance': batch})
|
||||
response = view.render_to_response("view", {"instance": batch})
|
||||
self.assertTrue(render_to_response.called)
|
||||
context = render_to_response.call_args[0][1]
|
||||
self.assertIs(context['batch'], batch)
|
||||
self.assertIs(context['batch_handler'], handler)
|
||||
self.assertIs(context["batch"], batch)
|
||||
self.assertIs(context["batch_handler"], handler)
|
||||
|
||||
def test_configure_grid(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.multiple(mod.BatchMasterView, create=True, model_class=MockBatch):
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
grid = view.make_model_grid()
|
||||
# nb. coverage only; tests nothing
|
||||
|
@ -87,19 +99,23 @@ class TestBatchMasterView(WebTestCase):
|
|||
|
||||
def test_render_batch_id(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
batch = MockBatch(id=42)
|
||||
|
||||
result = view.render_batch_id(batch, 'id', 42)
|
||||
self.assertEqual(result, '00000042')
|
||||
result = view.render_batch_id(batch, "id", 42)
|
||||
self.assertEqual(result, "00000042")
|
||||
|
||||
result = view.render_batch_id(batch, 'id', None)
|
||||
result = view.render_batch_id(batch, "id", None)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_get_instance_title(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
|
||||
batch = MockBatch(id=42)
|
||||
|
@ -113,46 +129,52 @@ class TestBatchMasterView(WebTestCase):
|
|||
def test_configure_form(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.multiple(mod.BatchMasterView, create=True, model_class=MockBatch):
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
|
||||
# creating
|
||||
with patch.object(view, 'creating', new=True):
|
||||
with patch.object(view, "creating", new=True):
|
||||
form = view.make_model_form(model_instance=None)
|
||||
view.configure_form(form)
|
||||
|
||||
batch = MockBatch(id=42)
|
||||
|
||||
# viewing
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
form = view.make_model_form(model_instance=batch)
|
||||
view.configure_form(form)
|
||||
|
||||
# editing
|
||||
with patch.object(view, 'editing', new=True):
|
||||
with patch.object(view, "editing", new=True):
|
||||
form = view.make_model_form(model_instance=batch)
|
||||
view.configure_form(form)
|
||||
|
||||
# deleting
|
||||
with patch.object(view, 'deleting', new=True):
|
||||
with patch.object(view, "deleting", new=True):
|
||||
form = view.make_model_form(model_instance=batch)
|
||||
view.configure_form(form)
|
||||
|
||||
# viewing (executed)
|
||||
batch.executed = datetime.datetime.now()
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
form = view.make_model_form(model_instance=batch)
|
||||
view.configure_form(form)
|
||||
|
||||
def test_objectify(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.multiple(mod.BatchMasterView, create=True, model_class=MockBatch):
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(mod.BatchMasterView, 'Session', return_value=self.session):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "Session", return_value=self.session
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
|
||||
# create batch
|
||||
with patch.object(view, 'creating', new=True):
|
||||
with patch.object(view, "creating", new=True):
|
||||
form = view.make_model_form(model_instance=None)
|
||||
form.validated = {}
|
||||
batch = view.objectify(form)
|
||||
|
@ -160,21 +182,28 @@ class TestBatchMasterView(WebTestCase):
|
|||
self.assertTrue(batch.id > 0)
|
||||
|
||||
# edit batch
|
||||
with patch.object(view, 'editing', new=True):
|
||||
with patch.object(view.batch_handler, 'make_batch') as make_batch:
|
||||
with patch.object(view, "editing", new=True):
|
||||
with patch.object(
|
||||
view.batch_handler, "make_batch"
|
||||
) as make_batch:
|
||||
form = view.make_model_form(model_instance=batch)
|
||||
form.validated = {'description': 'foo'}
|
||||
form.validated = {"description": "foo"}
|
||||
self.assertIsNone(batch.description)
|
||||
batch = view.objectify(form)
|
||||
self.assertEqual(batch.description, 'foo')
|
||||
self.assertEqual(batch.description, "foo")
|
||||
|
||||
def test_redirect_after_create(self):
|
||||
self.pyramid_config.add_route('mock_batches.view', '/batch/mock/{uuid}')
|
||||
self.pyramid_config.add_route("mock_batches.view", "/batch/mock/{uuid}")
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.multiple(mod.BatchMasterView, create=True,
|
||||
model_class=MockBatch,
|
||||
route_prefix='mock_batches'):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
with patch.multiple(
|
||||
mod.BatchMasterView,
|
||||
create=True,
|
||||
model_class=MockBatch,
|
||||
route_prefix="mock_batches",
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
batch = MockBatch(id=42)
|
||||
|
||||
|
@ -183,12 +212,14 @@ class TestBatchMasterView(WebTestCase):
|
|||
self.assertIsInstance(result, HTTPFound)
|
||||
|
||||
# unless populating in which case thread is launched
|
||||
self.request.session.id = 'abcdefghijk'
|
||||
with patch.object(mod, 'threading') as threading:
|
||||
self.request.session.id = "abcdefghijk"
|
||||
with patch.object(mod, "threading") as threading:
|
||||
thread = MagicMock()
|
||||
threading.Thread.return_value = thread
|
||||
with patch.object(view.batch_handler, 'should_populate', return_value=True):
|
||||
with patch.object(view, 'render_progress') as render_progress:
|
||||
with patch.object(
|
||||
view.batch_handler, "should_populate", return_value=True
|
||||
):
|
||||
with patch.object(view, "render_progress") as render_progress:
|
||||
view.redirect_after_create(batch)
|
||||
self.assertTrue(threading.Thread.called)
|
||||
thread.start.assert_called_once_with()
|
||||
|
@ -198,14 +229,16 @@ class TestBatchMasterView(WebTestCase):
|
|||
model = self.app.model
|
||||
handler = self.make_handler()
|
||||
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
|
||||
batch = handler.make_batch(self.session, created_by=user)
|
||||
self.session.add(batch)
|
||||
self.session.flush()
|
||||
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = self.make_view()
|
||||
|
||||
self.assertEqual(self.session.query(MockBatch).count(), 1)
|
||||
|
@ -215,20 +248,24 @@ class TestBatchMasterView(WebTestCase):
|
|||
def test_populate_thread(self):
|
||||
model = self.app.model
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.multiple(mod.BatchMasterView, create=True, model_class=MockBatch):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
with patch.multiple(
|
||||
mod.BatchMasterView, create=True, model_class=MockBatch
|
||||
):
|
||||
view = mod.BatchMasterView(self.request)
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
batch = MockBatch(id=42, created_by=user)
|
||||
self.session.add(batch)
|
||||
self.session.commit()
|
||||
|
||||
# nb. use our session within thread method
|
||||
with patch.object(self.app, 'make_session', return_value=self.session):
|
||||
with patch.object(self.app, "make_session", return_value=self.session):
|
||||
|
||||
# nb. prevent closing our session
|
||||
with patch.object(self.session, 'close') as close:
|
||||
with patch.object(self.session, "close") as close:
|
||||
|
||||
# without progress
|
||||
view.populate_thread(batch.uuid)
|
||||
|
@ -236,24 +273,34 @@ class TestBatchMasterView(WebTestCase):
|
|||
close.reset_mock()
|
||||
|
||||
# with progress
|
||||
self.request.session.id = 'abcdefghijk'
|
||||
view.populate_thread(batch.uuid,
|
||||
progress=SessionProgress(self.request,
|
||||
'populate_mock_batch'))
|
||||
self.request.session.id = "abcdefghijk"
|
||||
view.populate_thread(
|
||||
batch.uuid,
|
||||
progress=SessionProgress(
|
||||
self.request, "populate_mock_batch"
|
||||
),
|
||||
)
|
||||
close.assert_called_once_with()
|
||||
close.reset_mock()
|
||||
|
||||
# failure to populate, without progress
|
||||
with patch.object(view.batch_handler, 'do_populate', side_effect=RuntimeError):
|
||||
with patch.object(
|
||||
view.batch_handler, "do_populate", side_effect=RuntimeError
|
||||
):
|
||||
view.populate_thread(batch.uuid)
|
||||
close.assert_called_once_with()
|
||||
close.reset_mock()
|
||||
|
||||
# failure to populate, with progress
|
||||
with patch.object(view.batch_handler, 'do_populate', side_effect=RuntimeError):
|
||||
view.populate_thread(batch.uuid,
|
||||
progress=SessionProgress(self.request,
|
||||
'populate_mock_batch'))
|
||||
with patch.object(
|
||||
view.batch_handler, "do_populate", side_effect=RuntimeError
|
||||
):
|
||||
view.populate_thread(
|
||||
batch.uuid,
|
||||
progress=SessionProgress(
|
||||
self.request, "populate_mock_batch"
|
||||
),
|
||||
)
|
||||
close.assert_called_once_with()
|
||||
close.reset_mock()
|
||||
|
||||
|
@ -261,53 +308,64 @@ class TestBatchMasterView(WebTestCase):
|
|||
self.session.delete(batch)
|
||||
self.session.commit()
|
||||
# nb. should give up waiting after 1 second
|
||||
self.assertRaises(RuntimeError, view.populate_thread, batch.uuid)
|
||||
self.assertRaises(
|
||||
RuntimeError, view.populate_thread, batch.uuid
|
||||
)
|
||||
|
||||
def test_execute(self):
|
||||
self.pyramid_config.add_route('mock_batches.view', '/batch/mock/{uuid}')
|
||||
self.pyramid_config.add_route("mock_batches.view", "/batch/mock/{uuid}")
|
||||
model = self.app.model
|
||||
handler = MockBatchHandler(self.config)
|
||||
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
batch = handler.make_batch(self.session, created_by=user)
|
||||
self.session.add(batch)
|
||||
self.session.commit()
|
||||
|
||||
with patch.multiple(mod.BatchMasterView, create=True,
|
||||
model_class=MockBatch,
|
||||
route_prefix='mock_batches',
|
||||
get_batch_handler=MagicMock(return_value=handler),
|
||||
get_instance=MagicMock(return_value=batch)):
|
||||
with patch.multiple(
|
||||
mod.BatchMasterView,
|
||||
create=True,
|
||||
model_class=MockBatch,
|
||||
route_prefix="mock_batches",
|
||||
get_batch_handler=MagicMock(return_value=handler),
|
||||
get_instance=MagicMock(return_value=batch),
|
||||
):
|
||||
view = self.make_view()
|
||||
|
||||
# batch executes okay
|
||||
response = view.execute()
|
||||
self.assertEqual(response.status_code, 302) # redirect to "view batch"
|
||||
self.assertFalse(self.request.session.peek_flash('error'))
|
||||
self.assertEqual(response.status_code, 302) # redirect to "view batch"
|
||||
self.assertFalse(self.request.session.peek_flash("error"))
|
||||
|
||||
# but cannot be executed again
|
||||
response = view.execute()
|
||||
self.assertEqual(response.status_code, 302) # redirect to "view batch"
|
||||
self.assertEqual(response.status_code, 302) # redirect to "view batch"
|
||||
# nb. flash has error this time
|
||||
self.assertTrue(self.request.session.peek_flash('error'))
|
||||
self.assertTrue(self.request.session.peek_flash("error"))
|
||||
|
||||
def test_get_row_model_class(self):
|
||||
handler = MockBatchHandler(self.config)
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
view = self.make_view()
|
||||
|
||||
self.assertRaises(AttributeError, view.get_row_model_class)
|
||||
|
||||
# row class determined from batch class
|
||||
with patch.object(mod.BatchMasterView, 'model_class', new=MockBatch, create=True):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "model_class", new=MockBatch, create=True
|
||||
):
|
||||
cls = view.get_row_model_class()
|
||||
self.assertIs(cls, MockBatchRow)
|
||||
|
||||
self.assertRaises(AttributeError, view.get_row_model_class)
|
||||
|
||||
# view may specify row class
|
||||
with patch.object(mod.BatchMasterView, 'row_model_class', new=MockBatchRow, create=True):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "row_model_class", new=MockBatchRow, create=True
|
||||
):
|
||||
cls = view.get_row_model_class()
|
||||
self.assertIs(cls, MockBatchRow)
|
||||
|
||||
|
@ -315,7 +373,7 @@ class TestBatchMasterView(WebTestCase):
|
|||
handler = MockBatchHandler(self.config)
|
||||
model = self.app.model
|
||||
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
|
||||
batch = handler.make_batch(self.session, created_by=user)
|
||||
|
@ -324,16 +382,18 @@ class TestBatchMasterView(WebTestCase):
|
|||
handler.add_row(batch, row)
|
||||
self.session.flush()
|
||||
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
|
||||
view = self.make_view()
|
||||
self.assertRaises(AttributeError, view.get_row_grid_data, batch)
|
||||
|
||||
Session = MagicMock(return_value=self.session)
|
||||
Session.query.side_effect = lambda m: self.session.query(m)
|
||||
with patch.multiple(mod.BatchMasterView, create=True,
|
||||
Session=Session,
|
||||
model_class=MockBatch):
|
||||
with patch.multiple(
|
||||
mod.BatchMasterView, create=True, Session=Session, model_class=MockBatch
|
||||
):
|
||||
|
||||
view = self.make_view()
|
||||
data = view.get_row_grid_data(batch)
|
||||
|
@ -344,7 +404,7 @@ class TestBatchMasterView(WebTestCase):
|
|||
handler = MockBatchHandler(self.config)
|
||||
model = self.app.model
|
||||
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
|
||||
batch = handler.make_batch(self.session, created_by=user)
|
||||
|
@ -353,27 +413,31 @@ class TestBatchMasterView(WebTestCase):
|
|||
handler.add_row(batch, row)
|
||||
self.session.flush()
|
||||
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=handler):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "get_batch_handler", return_value=handler
|
||||
):
|
||||
|
||||
Session = MagicMock(return_value=self.session)
|
||||
Session.query.side_effect = lambda m: self.session.query(m)
|
||||
with patch.multiple(mod.BatchMasterView, create=True,
|
||||
Session=Session,
|
||||
model_class=MockBatch):
|
||||
with patch.multiple(
|
||||
mod.BatchMasterView, create=True, Session=Session, model_class=MockBatch
|
||||
):
|
||||
|
||||
with patch.object(self.request, 'matchdict', new={'uuid': batch.uuid}):
|
||||
with patch.object(self.request, "matchdict", new={"uuid": batch.uuid}):
|
||||
view = self.make_view()
|
||||
grid = view.make_row_model_grid(batch)
|
||||
self.assertIn('sequence', grid.labels)
|
||||
self.assertEqual(grid.labels['sequence'], "Seq.")
|
||||
self.assertIn("sequence", grid.labels)
|
||||
self.assertEqual(grid.labels["sequence"], "Seq.")
|
||||
|
||||
def test_render_row_status(self):
|
||||
with patch.object(mod.BatchMasterView, 'get_batch_handler', return_value=None):
|
||||
with patch.object(mod.BatchMasterView, "get_batch_handler", return_value=None):
|
||||
view = self.make_view()
|
||||
row = MagicMock(foo=1, STATUS={1: 'bar'})
|
||||
self.assertEqual(view.render_row_status(row, 'foo', 1), 'bar')
|
||||
row = MagicMock(foo=1, STATUS={1: "bar"})
|
||||
self.assertEqual(view.render_row_status(row, "foo", 1), "bar")
|
||||
|
||||
def test_defaults(self):
|
||||
# nb. coverage only
|
||||
with patch.object(mod.BatchMasterView, 'model_class', new=MockBatch, create=True):
|
||||
with patch.object(
|
||||
mod.BatchMasterView, "model_class", new=MockBatch, create=True
|
||||
):
|
||||
mod.BatchMasterView.defaults(self.pyramid_config)
|
||||
|
|
|
@ -15,21 +15,21 @@ class TestCommonView(WebTestCase):
|
|||
return mod.CommonView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.common')
|
||||
self.pyramid_config.include("wuttaweb.views.common")
|
||||
|
||||
def test_forbidden_view(self):
|
||||
view = self.make_view()
|
||||
context = view.forbidden_view()
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
self.assertEqual(context["index_title"], self.app.get_title())
|
||||
|
||||
def test_notfound_view(self):
|
||||
view = self.make_view()
|
||||
context = view.notfound_view()
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
self.assertEqual(context["index_title"], self.app.get_title())
|
||||
|
||||
def test_home(self):
|
||||
self.pyramid_config.add_route('setup', '/setup')
|
||||
self.pyramid_config.add_route('login', '/login')
|
||||
self.pyramid_config.add_route("setup", "/setup")
|
||||
self.pyramid_config.add_route("login", "/login")
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
|
@ -38,50 +38,50 @@ class TestCommonView(WebTestCase):
|
|||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# so add a user
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
# now we see the home page
|
||||
context = view.home(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
self.assertEqual(context["index_title"], self.app.get_title())
|
||||
|
||||
# but if configured, anons will be redirected to login
|
||||
self.config.setdefault('wuttaweb.home_redirect_to_login', 'true')
|
||||
self.config.setdefault("wuttaweb.home_redirect_to_login", "true")
|
||||
response = view.home(session=self.session)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# now only an auth'ed user can see home page
|
||||
self.request.user = user
|
||||
context = view.home(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
self.assertEqual(context["index_title"], self.app.get_title())
|
||||
|
||||
def test_feedback_make_schema(self):
|
||||
view = self.make_view()
|
||||
schema = view.feedback_make_schema()
|
||||
self.assertIsInstance(schema, colander.Schema)
|
||||
self.assertIn('message', schema)
|
||||
self.assertIn("message", schema)
|
||||
|
||||
def test_feedback(self):
|
||||
self.pyramid_config.add_route('users.view', '/users/{uuid}')
|
||||
self.pyramid_config.add_route("users.view", "/users/{uuid}")
|
||||
model = self.app.model
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
view = self.make_view()
|
||||
with patch.object(view, 'feedback_send') as feedback_send:
|
||||
with patch.object(view, "feedback_send") as feedback_send:
|
||||
|
||||
# basic send, no user
|
||||
self.request.client_addr = '127.0.0.1'
|
||||
self.request.method = 'POST'
|
||||
self.request.client_addr = "127.0.0.1"
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {
|
||||
'referrer': '/foo',
|
||||
'user_name': "Barney Rubble",
|
||||
'message': "hello world",
|
||||
"referrer": "/foo",
|
||||
"user_name": "Barney Rubble",
|
||||
"message": "hello world",
|
||||
}
|
||||
context = view.feedback()
|
||||
self.assertEqual(context, {'ok': True})
|
||||
self.assertEqual(context, {"ok": True})
|
||||
feedback_send.assert_called_once()
|
||||
|
||||
# reset
|
||||
|
@ -89,10 +89,10 @@ class TestCommonView(WebTestCase):
|
|||
|
||||
# basic send, with user
|
||||
self.request.user = user
|
||||
self.request.POST['user_uuid'] = str(user.uuid)
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
self.request.POST["user_uuid"] = str(user.uuid)
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
context = view.feedback()
|
||||
self.assertEqual(context, {'ok': True})
|
||||
self.assertEqual(context, {"ok": True})
|
||||
feedback_send.assert_called_once()
|
||||
|
||||
# reset
|
||||
|
@ -100,37 +100,35 @@ class TestCommonView(WebTestCase):
|
|||
feedback_send.reset_mock()
|
||||
|
||||
# invalid form data
|
||||
self.request.POST = {'message': 'hello world'}
|
||||
self.request.POST = {"message": "hello world"}
|
||||
context = view.feedback()
|
||||
self.assertEqual(list(context), ['error'])
|
||||
self.assertIn('Required', context['error'])
|
||||
self.assertEqual(list(context), ["error"])
|
||||
self.assertIn("Required", context["error"])
|
||||
feedback_send.assert_not_called()
|
||||
|
||||
# error on send
|
||||
self.request.POST = {
|
||||
'referrer': '/foo',
|
||||
'user_name': "Barney Rubble",
|
||||
'message': "hello world",
|
||||
"referrer": "/foo",
|
||||
"user_name": "Barney Rubble",
|
||||
"message": "hello world",
|
||||
}
|
||||
feedback_send.side_effect = RuntimeError
|
||||
context = view.feedback()
|
||||
feedback_send.assert_called_once()
|
||||
self.assertEqual(list(context), ['error'])
|
||||
self.assertIn('RuntimeError', context['error'])
|
||||
self.assertEqual(list(context), ["error"])
|
||||
self.assertIn("RuntimeError", context["error"])
|
||||
|
||||
def test_feedback_send(self):
|
||||
view = self.make_view()
|
||||
with patch.object(self.app, 'send_email') as send_email:
|
||||
view.feedback_send({'user_name': "Barney",
|
||||
'message': "hello world"})
|
||||
send_email.assert_called_once_with('feedback', {
|
||||
'user_name': "Barney",
|
||||
'message': "hello world"
|
||||
})
|
||||
with patch.object(self.app, "send_email") as send_email:
|
||||
view.feedback_send({"user_name": "Barney", "message": "hello world"})
|
||||
send_email.assert_called_once_with(
|
||||
"feedback", {"user_name": "Barney", "message": "hello world"}
|
||||
)
|
||||
|
||||
def test_setup(self):
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_route('login', '/login')
|
||||
self.pyramid_config.add_route("home", "/")
|
||||
self.pyramid_config.add_route("login", "/login")
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
@ -138,10 +136,10 @@ class TestCommonView(WebTestCase):
|
|||
# at first, can see the setup page
|
||||
self.assertEqual(self.session.query(model.User).count(), 0)
|
||||
context = view.setup(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
self.assertEqual(context["index_title"], self.app.get_title())
|
||||
|
||||
# so add a user
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
|
@ -155,25 +153,25 @@ class TestCommonView(WebTestCase):
|
|||
|
||||
# so we can see the setup page again
|
||||
context = view.setup(session=self.session)
|
||||
self.assertEqual(context['index_title'], self.app.get_title())
|
||||
self.assertEqual(context["index_title"], self.app.get_title())
|
||||
|
||||
# and finally, post data to create admin user
|
||||
self.request.method = 'POST'
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {
|
||||
'username': 'barney',
|
||||
'__start__': 'password:mapping',
|
||||
'password': 'testpass',
|
||||
'password-confirm': 'testpass',
|
||||
'__end__': 'password:mapping',
|
||||
'first_name': "Barney",
|
||||
'last_name': "Rubble",
|
||||
"username": "barney",
|
||||
"__start__": "password:mapping",
|
||||
"password": "testpass",
|
||||
"password-confirm": "testpass",
|
||||
"__end__": "password:mapping",
|
||||
"first_name": "Barney",
|
||||
"last_name": "Rubble",
|
||||
}
|
||||
response = view.setup(session=self.session)
|
||||
# nb. redirects on success
|
||||
self.assertEqual(response.status_code, 302)
|
||||
barney = self.session.query(model.User).one()
|
||||
self.assertEqual(barney.username, 'barney')
|
||||
self.assertTrue(auth.check_user_password(barney, 'testpass'))
|
||||
self.assertEqual(barney.username, "barney")
|
||||
self.assertTrue(auth.check_user_password(barney, "testpass"))
|
||||
admin = auth.get_role_administrator(self.session)
|
||||
self.assertIn(admin, barney.roles)
|
||||
self.assertIsNotNone(barney.person)
|
||||
|
@ -183,30 +181,30 @@ class TestCommonView(WebTestCase):
|
|||
self.assertEqual(person.full_name, "Barney Rubble")
|
||||
|
||||
def test_change_theme(self):
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_route("home", "/")
|
||||
settings = self.request.registry.settings
|
||||
establish_theme(settings)
|
||||
view = self.make_view()
|
||||
|
||||
# theme is not changed if not provided by caller
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
with patch.object(mod, 'set_app_theme') as set_app_theme:
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
with patch.object(mod, "set_app_theme") as set_app_theme:
|
||||
view.change_theme()
|
||||
set_app_theme.assert_not_called()
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'default')
|
||||
self.assertEqual(settings["wuttaweb.theme"], "default")
|
||||
|
||||
# but theme will change if provided
|
||||
with patch.object(self.request, 'params', new={'theme': 'butterfly'}):
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(self.request, "params", new={"theme": "butterfly"}):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
view.change_theme()
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'butterfly')
|
||||
self.assertEqual(settings["wuttaweb.theme"], "butterfly")
|
||||
|
||||
# flash error if invalid theme is provided
|
||||
self.assertFalse(self.request.session.peek_flash('error'))
|
||||
with patch.object(self.request, 'params', new={'theme': 'anotherone'}):
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
self.assertFalse(self.request.session.peek_flash("error"))
|
||||
with patch.object(self.request, "params", new={"theme": "anotherone"}):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
view.change_theme()
|
||||
self.assertEqual(settings['wuttaweb.theme'], 'butterfly')
|
||||
self.assertTrue(self.request.session.peek_flash('error'))
|
||||
messages = self.request.session.pop_flash('error')
|
||||
self.assertIn('Failed to set theme', messages[0])
|
||||
self.assertEqual(settings["wuttaweb.theme"], "butterfly")
|
||||
self.assertTrue(self.request.session.peek_flash("error"))
|
||||
messages = self.request.session.pop_flash("error")
|
||||
self.assertIn("Failed to set theme", messages[0])
|
||||
|
|
|
@ -18,194 +18,232 @@ class TestEmailSettingViews(WebTestCase):
|
|||
return mod.EmailSettingView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.email')
|
||||
self.pyramid_config.include("wuttaweb.views.email")
|
||||
|
||||
def test_get_grid_data(self):
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
view = self.make_view()
|
||||
data = view.get_grid_data()
|
||||
self.assertIsInstance(data, list)
|
||||
self.assertTrue(data) # 1+ items
|
||||
self.assertTrue(data) # 1+ items
|
||||
setting = data[0]
|
||||
self.assertIn('key', setting)
|
||||
self.assertIn('subject', setting)
|
||||
self.assertIn('sender', setting)
|
||||
self.assertIn('to', setting)
|
||||
self.assertIn('cc', setting)
|
||||
self.assertIn('notes', setting)
|
||||
self.assertIn("key", setting)
|
||||
self.assertIn("subject", setting)
|
||||
self.assertIn("sender", setting)
|
||||
self.assertIn("to", setting)
|
||||
self.assertIn("cc", setting)
|
||||
self.assertIn("notes", setting)
|
||||
|
||||
def test_configure_grid(self):
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
view = self.make_view()
|
||||
grid = view.make_model_grid()
|
||||
self.assertIn('key', grid.searchable_columns)
|
||||
self.assertIn('subject', grid.searchable_columns)
|
||||
self.assertIn("key", grid.searchable_columns)
|
||||
self.assertIn("subject", grid.searchable_columns)
|
||||
|
||||
def test_render_to_short(self):
|
||||
view = self.make_view()
|
||||
setting = EmailSetting(self.config)
|
||||
|
||||
# more than 2 recips
|
||||
result = view.render_to_short(setting, 'to', [
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
'charlie@example.com',
|
||||
'diana@example.com',
|
||||
])
|
||||
self.assertEqual(result, 'alice@example.com, bob@example.com, ...')
|
||||
result = view.render_to_short(
|
||||
setting,
|
||||
"to",
|
||||
[
|
||||
"alice@example.com",
|
||||
"bob@example.com",
|
||||
"charlie@example.com",
|
||||
"diana@example.com",
|
||||
],
|
||||
)
|
||||
self.assertEqual(result, "alice@example.com, bob@example.com, ...")
|
||||
|
||||
# just 2 recips
|
||||
result = view.render_to_short(setting, 'to', [
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
])
|
||||
self.assertEqual(result, 'alice@example.com, bob@example.com')
|
||||
result = view.render_to_short(
|
||||
setting,
|
||||
"to",
|
||||
[
|
||||
"alice@example.com",
|
||||
"bob@example.com",
|
||||
],
|
||||
)
|
||||
self.assertEqual(result, "alice@example.com, bob@example.com")
|
||||
|
||||
# just 1 recip
|
||||
result = view.render_to_short(setting, 'to', ['alice@example.com'])
|
||||
self.assertEqual(result, 'alice@example.com')
|
||||
result = view.render_to_short(setting, "to", ["alice@example.com"])
|
||||
self.assertEqual(result, "alice@example.com")
|
||||
|
||||
# no recips
|
||||
result = view.render_to_short(setting, 'to', [])
|
||||
result = view.render_to_short(setting, "to", [])
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_get_instance(self):
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
view = self.make_view()
|
||||
|
||||
# normal
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'feedback'}):
|
||||
with patch.object(self.request, "matchdict", new={"key": "feedback"}):
|
||||
setting = view.get_instance()
|
||||
self.assertIsInstance(setting, dict)
|
||||
self.assertIn('key', setting)
|
||||
self.assertIn('sender', setting)
|
||||
self.assertIn('subject', setting)
|
||||
self.assertIn('to', setting)
|
||||
self.assertIn('cc', setting)
|
||||
self.assertIn('notes', setting)
|
||||
self.assertIn('enabled', setting)
|
||||
self.assertIn("key", setting)
|
||||
self.assertIn("sender", setting)
|
||||
self.assertIn("subject", setting)
|
||||
self.assertIn("to", setting)
|
||||
self.assertIn("cc", setting)
|
||||
self.assertIn("notes", setting)
|
||||
self.assertIn("enabled", setting)
|
||||
|
||||
# not found
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'this-should_notEXIST'}):
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"key": "this-should_notEXIST"}
|
||||
):
|
||||
self.assertRaises(HTTPNotFound, view.get_instance)
|
||||
|
||||
def test_get_instance_title(self):
|
||||
view = self.make_view()
|
||||
result = view.get_instance_title({'subject': 'whatever'})
|
||||
self.assertEqual(result, 'whatever')
|
||||
result = view.get_instance_title({"subject": "whatever"})
|
||||
self.assertEqual(result, "whatever")
|
||||
|
||||
def test_configure_form(self):
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
view = self.make_view()
|
||||
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'feedback'}):
|
||||
with patch.object(self.request, "matchdict", new={"key": "feedback"}):
|
||||
setting = view.get_instance()
|
||||
form = view.make_model_form(setting)
|
||||
self.assertIn('description', form.readonly_fields)
|
||||
self.assertFalse(form.required_fields['replyto'])
|
||||
self.assertIn("description", form.readonly_fields)
|
||||
self.assertFalse(form.required_fields["replyto"])
|
||||
|
||||
def test_persist(self):
|
||||
model = self.app.model
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
view = self.make_view()
|
||||
|
||||
# start w/ no settings in db
|
||||
self.assertEqual(self.session.query(model.Setting).count(), 0)
|
||||
|
||||
# "edit" settings for feedback email
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'feedback'}):
|
||||
with patch.object(self.request, "matchdict", new={"key": "feedback"}):
|
||||
setting = view.get_instance()
|
||||
setting['subject'] = 'Testing Feedback'
|
||||
setting['sender'] = 'feedback@example.com'
|
||||
setting['replyto'] = 'feedback4@example.com'
|
||||
setting['to'] = 'feedback@example.com'
|
||||
setting['cc'] = 'feedback2@example.com'
|
||||
setting['bcc'] = 'feedback3@example.com'
|
||||
setting['notes'] = "did this work?"
|
||||
setting['enabled'] = True
|
||||
setting["subject"] = "Testing Feedback"
|
||||
setting["sender"] = "feedback@example.com"
|
||||
setting["replyto"] = "feedback4@example.com"
|
||||
setting["to"] = "feedback@example.com"
|
||||
setting["cc"] = "feedback2@example.com"
|
||||
setting["bcc"] = "feedback3@example.com"
|
||||
setting["notes"] = "did this work?"
|
||||
setting["enabled"] = True
|
||||
|
||||
# persist email settings
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
view.persist(setting)
|
||||
self.session.commit()
|
||||
|
||||
# check settings in db
|
||||
self.assertEqual(self.session.query(model.Setting).count(), 8)
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.subject'),
|
||||
"Testing Feedback")
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.sender'),
|
||||
'feedback@example.com')
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.replyto'),
|
||||
'feedback4@example.com')
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.to'),
|
||||
'feedback@example.com')
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.cc'),
|
||||
'feedback2@example.com')
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.bcc'),
|
||||
'feedback3@example.com')
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.notes'),
|
||||
"did this work?")
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.enabled'),
|
||||
'true')
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.subject"),
|
||||
"Testing Feedback",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.sender"),
|
||||
"feedback@example.com",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.replyto"),
|
||||
"feedback4@example.com",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.to"),
|
||||
"feedback@example.com",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.cc"),
|
||||
"feedback2@example.com",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.bcc"),
|
||||
"feedback3@example.com",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.notes"),
|
||||
"did this work?",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.enabled"), "true"
|
||||
)
|
||||
|
||||
# "edit" settings for feedback email
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'feedback'}):
|
||||
with patch.object(self.request, "matchdict", new={"key": "feedback"}):
|
||||
setting = view.get_instance()
|
||||
setting['subject'] = None
|
||||
setting['sender'] = None
|
||||
setting['replyto'] = None
|
||||
setting['to'] = None
|
||||
setting['cc'] = None
|
||||
setting['bcc'] = None
|
||||
setting['notes'] = None
|
||||
setting['enabled'] = False
|
||||
setting["subject"] = None
|
||||
setting["sender"] = None
|
||||
setting["replyto"] = None
|
||||
setting["to"] = None
|
||||
setting["cc"] = None
|
||||
setting["bcc"] = None
|
||||
setting["notes"] = None
|
||||
setting["enabled"] = False
|
||||
|
||||
# persist email settings
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
view.persist(setting)
|
||||
self.session.commit()
|
||||
|
||||
# check settings in db
|
||||
self.assertEqual(self.session.query(model.Setting).count(), 1)
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.subject'))
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.sender'))
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.replyto'))
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.to'))
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.cc'))
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.bcc'))
|
||||
self.assertIsNone(self.app.get_setting(self.session, 'wutta.email.feedback.notes'))
|
||||
self.assertEqual(self.app.get_setting(self.session, 'wutta.email.feedback.enabled'),
|
||||
'false')
|
||||
self.assertIsNone(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.subject")
|
||||
)
|
||||
self.assertIsNone(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.sender")
|
||||
)
|
||||
self.assertIsNone(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.replyto")
|
||||
)
|
||||
self.assertIsNone(self.app.get_setting(self.session, "wutta.email.feedback.to"))
|
||||
self.assertIsNone(self.app.get_setting(self.session, "wutta.email.feedback.cc"))
|
||||
self.assertIsNone(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.bcc")
|
||||
)
|
||||
self.assertIsNone(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.notes")
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.get_setting(self.session, "wutta.email.feedback.enabled"), "false"
|
||||
)
|
||||
|
||||
def test_render_to_response(self):
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_route('login', '/auth/login')
|
||||
self.pyramid_config.add_route('email_settings', '/email/settings')
|
||||
self.pyramid_config.add_route('email_settings.preview', '/email/settings/{key}/preview')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
self.pyramid_config.add_route("home", "/")
|
||||
self.pyramid_config.add_route("login", "/auth/login")
|
||||
self.pyramid_config.add_route("email_settings", "/email/settings")
|
||||
self.pyramid_config.add_route(
|
||||
"email_settings.preview", "/email/settings/{key}/preview"
|
||||
)
|
||||
view = self.make_view()
|
||||
|
||||
# nb. this gives coverage, but tests nothing..
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'feedback'}):
|
||||
with patch.object(self.request, "matchdict", new={"key": "feedback"}):
|
||||
setting = view.get_instance()
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
context = {'instance': setting}
|
||||
response = view.render_to_response('view', context)
|
||||
with patch.object(view, "viewing", new=True):
|
||||
context = {"instance": setting}
|
||||
response = view.render_to_response("view", context)
|
||||
self.assertIsInstance(response, Response)
|
||||
|
||||
def test_preview(self):
|
||||
self.config.setdefault('wutta.email.default.sender', 'test@example.com')
|
||||
self.config.setdefault("wutta.email.default.sender", "test@example.com")
|
||||
view = self.make_view()
|
||||
|
||||
# nb. this gives coverage, but tests nothing..
|
||||
with patch.object(self.request, 'matchdict', new={'key': 'feedback'}):
|
||||
with patch.object(self.request, "matchdict", new={"key": "feedback"}):
|
||||
|
||||
# html
|
||||
with patch.object(self.request, 'params', new={'mode': 'html'}):
|
||||
with patch.object(self.request, "params", new={"mode": "html"}):
|
||||
response = view.preview()
|
||||
self.assertEqual(response.content_type, 'text/html')
|
||||
self.assertEqual(response.content_type, "text/html")
|
||||
|
||||
# txt
|
||||
with patch.object(self.request, 'params', new={'mode': 'txt'}):
|
||||
with patch.object(self.request, "params", new={"mode": "txt"}):
|
||||
response = view.preview()
|
||||
self.assertEqual(response.content_type, 'text/plain')
|
||||
self.assertEqual(response.content_type, "text/plain")
|
||||
|
|
|
@ -7,4 +7,4 @@ from wuttaweb.testing import WebTestCase
|
|||
class TestEssentialViews(WebTestCase):
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.essential')
|
||||
self.pyramid_config.include("wuttaweb.views.essential")
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,7 +18,7 @@ class TestPersonView(WebTestCase):
|
|||
return people.PersonView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.people')
|
||||
self.pyramid_config.include("wuttaweb.views.people")
|
||||
|
||||
def test_get_query(self):
|
||||
view = self.make_view()
|
||||
|
@ -31,7 +31,7 @@ class TestPersonView(WebTestCase):
|
|||
grid = view.make_grid(model_class=model.Setting)
|
||||
self.assertEqual(grid.linked_columns, [])
|
||||
view.configure_grid(grid)
|
||||
self.assertIn('full_name', grid.linked_columns)
|
||||
self.assertIn("full_name", grid.linked_columns)
|
||||
|
||||
def test_configure_form(self):
|
||||
model = self.app.model
|
||||
|
@ -39,19 +39,19 @@ class TestPersonView(WebTestCase):
|
|||
|
||||
# full_name
|
||||
form = view.make_form(model_class=model.Person)
|
||||
self.assertIn('full_name', form)
|
||||
with patch.object(view, 'creating', new=True):
|
||||
self.assertIn("full_name", form)
|
||||
with patch.object(view, "creating", new=True):
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('full_name', form)
|
||||
self.assertNotIn("full_name", form)
|
||||
|
||||
# users
|
||||
person = model.Person()
|
||||
form = view.make_form(model_instance=person)
|
||||
self.assertNotIn('users', form.widgets)
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
self.assertNotIn("users", form.widgets)
|
||||
with patch.object(view, "viewing", new=True):
|
||||
view.configure_form(form)
|
||||
self.assertIn('users', form.widgets)
|
||||
self.assertIsInstance(form.widgets['users'], GridWidget)
|
||||
self.assertIn("users", form.widgets)
|
||||
self.assertIsInstance(form.widgets["users"], GridWidget)
|
||||
|
||||
def test_make_users_grid(self):
|
||||
model = self.app.model
|
||||
|
@ -65,13 +65,13 @@ class TestPersonView(WebTestCase):
|
|||
self.assertFalse(grid.actions)
|
||||
|
||||
# view + edit actions
|
||||
with patch.object(self.request, 'is_root', new=True):
|
||||
with patch.object(self.request, "is_root", new=True):
|
||||
grid = view.make_users_grid(person)
|
||||
self.assertIsInstance(grid, Grid)
|
||||
self.assertIn('username', grid.linked_columns)
|
||||
self.assertIn("username", grid.linked_columns)
|
||||
self.assertEqual(len(grid.actions), 2)
|
||||
self.assertEqual(grid.actions[0].key, 'view')
|
||||
self.assertEqual(grid.actions[1].key, 'edit')
|
||||
self.assertEqual(grid.actions[0].key, "view")
|
||||
self.assertEqual(grid.actions[1].key, "edit")
|
||||
|
||||
def test_objectify(self):
|
||||
model = self.app.model
|
||||
|
@ -79,15 +79,15 @@ class TestPersonView(WebTestCase):
|
|||
|
||||
# creating
|
||||
form = view.make_model_form()
|
||||
form.validated = {'first_name': 'Barney', 'last_name': 'Rubble'}
|
||||
form.validated = {"first_name": "Barney", "last_name": "Rubble"}
|
||||
person = view.objectify(form)
|
||||
self.assertEqual(person.full_name, 'Barney Rubble')
|
||||
self.assertEqual(person.full_name, "Barney Rubble")
|
||||
|
||||
# editing
|
||||
form = view.make_model_form(model_instance=person)
|
||||
form.validated = {'first_name': 'Betty', 'last_name': 'Rubble'}
|
||||
form.validated = {"first_name": "Betty", "last_name": "Rubble"}
|
||||
person2 = view.objectify(form)
|
||||
self.assertEqual(person2.full_name, 'Betty Rubble')
|
||||
self.assertEqual(person2.full_name, "Betty Rubble")
|
||||
self.assertIs(person2, person)
|
||||
|
||||
def test_autocomplete_query(self):
|
||||
|
@ -100,24 +100,24 @@ class TestPersonView(WebTestCase):
|
|||
self.session.commit()
|
||||
|
||||
view = self.make_view()
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
|
||||
# both people match
|
||||
query = view.autocomplete_query('george')
|
||||
query = view.autocomplete_query("george")
|
||||
self.assertEqual(query.count(), 2)
|
||||
|
||||
# just 1 match
|
||||
query = view.autocomplete_query('jones')
|
||||
query = view.autocomplete_query("jones")
|
||||
self.assertEqual(query.count(), 1)
|
||||
|
||||
# no matches
|
||||
query = view.autocomplete_query('sally')
|
||||
query = view.autocomplete_query("sally")
|
||||
self.assertEqual(query.count(), 0)
|
||||
|
||||
def test_view_profile(self):
|
||||
self.pyramid_config.include('wuttaweb.views.common')
|
||||
self.pyramid_config.include('wuttaweb.views.auth')
|
||||
self.pyramid_config.add_route('people', '/people/')
|
||||
self.pyramid_config.include("wuttaweb.views.common")
|
||||
self.pyramid_config.include("wuttaweb.views.auth")
|
||||
self.pyramid_config.add_route("people", "/people/")
|
||||
|
||||
model = self.app.model
|
||||
person = model.Person(full_name="Barney Rubble")
|
||||
|
@ -126,12 +126,12 @@ class TestPersonView(WebTestCase):
|
|||
|
||||
# sanity check
|
||||
view = self.make_view()
|
||||
self.request.matchdict = {'uuid': person.uuid}
|
||||
self.request.matchdict = {"uuid": person.uuid}
|
||||
response = view.view_profile(session=self.session)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_make_user(self):
|
||||
self.pyramid_config.include('wuttaweb.views.common')
|
||||
self.pyramid_config.include("wuttaweb.views.common")
|
||||
|
||||
model = self.app.model
|
||||
person = model.Person(full_name="Barney Rubble")
|
||||
|
@ -140,7 +140,7 @@ class TestPersonView(WebTestCase):
|
|||
|
||||
# sanity check
|
||||
view = self.make_view()
|
||||
self.request.matchdict = {'uuid': person.uuid}
|
||||
self.request.matchdict = {"uuid": person.uuid}
|
||||
response = view.make_user()
|
||||
# nb. this always redirects for now
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
|
|
@ -10,11 +10,11 @@ from wuttaweb.testing import WebTestCase
|
|||
class TestProgressView(WebTestCase):
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.progress')
|
||||
self.pyramid_config.include("wuttaweb.views.progress")
|
||||
|
||||
def test_basic(self):
|
||||
self.request.session.id = 'mockid'
|
||||
self.request.matchdict = {'key': 'foo'}
|
||||
self.request.session.id = "mockid"
|
||||
self.request.matchdict = {"key": "foo"}
|
||||
|
||||
# first call with no setup, will create the progress session
|
||||
# but it should be "empty" - except not really since beaker
|
||||
|
@ -23,40 +23,40 @@ class TestProgressView(WebTestCase):
|
|||
self.assertIsInstance(context, dict)
|
||||
|
||||
# now let's establish a progress session of our own
|
||||
progsess = get_progress_session(self.request, 'bar')
|
||||
progsess['maximum'] = 2
|
||||
progsess['value'] = 1
|
||||
progsess = get_progress_session(self.request, "bar")
|
||||
progsess["maximum"] = 2
|
||||
progsess["value"] = 1
|
||||
progsess.save()
|
||||
|
||||
# then call view, check results
|
||||
self.request.matchdict = {'key': 'bar'}
|
||||
self.request.matchdict = {"key": "bar"}
|
||||
context = mod.progress(self.request)
|
||||
self.assertEqual(context['maximum'], 2)
|
||||
self.assertEqual(context['value'], 1)
|
||||
self.assertNotIn('complete', context)
|
||||
self.assertEqual(context["maximum"], 2)
|
||||
self.assertEqual(context["value"], 1)
|
||||
self.assertNotIn("complete", context)
|
||||
|
||||
# now mark it as complete, check results
|
||||
progsess['complete'] = True
|
||||
progsess['success_msg'] = "yay!"
|
||||
progsess["complete"] = True
|
||||
progsess["success_msg"] = "yay!"
|
||||
progsess.save()
|
||||
context = mod.progress(self.request)
|
||||
self.assertTrue(context['complete'])
|
||||
self.assertEqual(context['success_msg'], "yay!")
|
||||
self.assertTrue(context["complete"])
|
||||
self.assertEqual(context["success_msg"], "yay!")
|
||||
|
||||
# now do that all again, with error
|
||||
progsess = get_progress_session(self.request, 'baz')
|
||||
progsess['maximum'] = 2
|
||||
progsess['value'] = 1
|
||||
progsess = get_progress_session(self.request, "baz")
|
||||
progsess["maximum"] = 2
|
||||
progsess["value"] = 1
|
||||
progsess.save()
|
||||
self.request.matchdict = {'key': 'baz'}
|
||||
self.request.matchdict = {"key": "baz"}
|
||||
context = mod.progress(self.request)
|
||||
self.assertEqual(context['maximum'], 2)
|
||||
self.assertEqual(context['value'], 1)
|
||||
self.assertNotIn('complete', context)
|
||||
self.assertNotIn('error', context)
|
||||
progsess['error'] = True
|
||||
progsess['error_msg'] = "omg!"
|
||||
self.assertEqual(context["maximum"], 2)
|
||||
self.assertEqual(context["value"], 1)
|
||||
self.assertNotIn("complete", context)
|
||||
self.assertNotIn("error", context)
|
||||
progsess["error"] = True
|
||||
progsess["error_msg"] = "omg!"
|
||||
progsess.save()
|
||||
context = mod.progress(self.request)
|
||||
self.assertTrue(context['error'])
|
||||
self.assertEqual(context['error_msg'], "omg!")
|
||||
self.assertTrue(context["error"])
|
||||
self.assertEqual(context["error_msg"], "omg!")
|
||||
|
|
|
@ -16,28 +16,29 @@ class SomeRandomReport(Report):
|
|||
"""
|
||||
This report shows something random.
|
||||
"""
|
||||
report_key = 'testing_some_random'
|
||||
|
||||
report_key = "testing_some_random"
|
||||
report_title = "Random Test Report"
|
||||
|
||||
def add_params(self, schema):
|
||||
|
||||
schema.add(colander.SchemaNode(
|
||||
colander.String(),
|
||||
name='foo',
|
||||
missing=colander.null))
|
||||
schema.add(
|
||||
colander.SchemaNode(colander.String(), name="foo", missing=colander.null)
|
||||
)
|
||||
|
||||
schema.add(colander.SchemaNode(
|
||||
colander.Date(),
|
||||
name='start_date',
|
||||
missing=colander.null))
|
||||
schema.add(
|
||||
colander.SchemaNode(
|
||||
colander.Date(), name="start_date", missing=colander.null
|
||||
)
|
||||
)
|
||||
|
||||
def get_output_columns(self):
|
||||
return ['foo']
|
||||
return ["foo"]
|
||||
|
||||
def make_data(self, params, **kwargs):
|
||||
return {
|
||||
'output_title': "Testing Output",
|
||||
'data': [{'foo': 'bar'}],
|
||||
"output_title": "Testing Output",
|
||||
"data": [{"foo": "bar"}],
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,68 +48,77 @@ class TestReportViews(WebTestCase):
|
|||
return mod.ReportView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.reports')
|
||||
self.pyramid_config.include("wuttaweb.views.reports")
|
||||
|
||||
def test_get_grid_data(self):
|
||||
view = self.make_view()
|
||||
providers = dict(self.app.providers)
|
||||
providers['wuttatest'] = MagicMock(report_modules=['tests.views.test_reports'])
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
|
||||
with patch.object(self.app, "providers", new=providers):
|
||||
|
||||
data = view.get_grid_data()
|
||||
self.assertIsInstance(data, list)
|
||||
self.assertTrue(data) # 1+ reports
|
||||
self.assertTrue(data) # 1+ reports
|
||||
|
||||
def test_normalize_report(self):
|
||||
view = self.make_view()
|
||||
report = SomeRandomReport(self.config)
|
||||
normal = view.normalize_report(report)
|
||||
help_text = normal.pop('help_text').strip()
|
||||
help_text = normal.pop("help_text").strip()
|
||||
self.assertEqual(help_text, "This report shows something random.")
|
||||
self.assertEqual(normal, {
|
||||
'report_key': 'testing_some_random',
|
||||
'report_title': "Random Test Report",
|
||||
})
|
||||
self.assertEqual(
|
||||
normal,
|
||||
{
|
||||
"report_key": "testing_some_random",
|
||||
"report_title": "Random Test Report",
|
||||
},
|
||||
)
|
||||
|
||||
def test_configure_grid(self):
|
||||
view = self.make_view()
|
||||
grid = view.make_model_grid()
|
||||
self.assertIn('report_title', grid.searchable_columns)
|
||||
self.assertIn('help_text', grid.searchable_columns)
|
||||
self.assertIn("report_title", grid.searchable_columns)
|
||||
self.assertIn("help_text", grid.searchable_columns)
|
||||
|
||||
def test_get_instance(self):
|
||||
view = self.make_view()
|
||||
providers = {
|
||||
'wuttatest': MagicMock(report_modules=['tests.views.test_reports']),
|
||||
"wuttatest": MagicMock(report_modules=["tests.views.test_reports"]),
|
||||
}
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
with patch.object(self.app, "providers", new=providers):
|
||||
|
||||
# normal
|
||||
with patch.object(self.request, 'matchdict', new={'report_key': 'testing_some_random'}):
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"report_key": "testing_some_random"}
|
||||
):
|
||||
report = view.get_instance()
|
||||
self.assertIsInstance(report, dict)
|
||||
self.assertEqual(report['report_key'], 'testing_some_random')
|
||||
self.assertEqual(report['report_title'], "Random Test Report")
|
||||
self.assertEqual(report["report_key"], "testing_some_random")
|
||||
self.assertEqual(report["report_title"], "Random Test Report")
|
||||
|
||||
# not found
|
||||
with patch.object(self.request, 'matchdict', new={'report_key': 'this-should_notEXIST'}):
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"report_key": "this-should_notEXIST"}
|
||||
):
|
||||
self.assertRaises(HTTPNotFound, view.get_instance)
|
||||
|
||||
def test_get_instance_title(self):
|
||||
view = self.make_view()
|
||||
result = view.get_instance_title({'report_title': 'whatever'})
|
||||
self.assertEqual(result, 'whatever')
|
||||
result = view.get_instance_title({"report_title": "whatever"})
|
||||
self.assertEqual(result, "whatever")
|
||||
|
||||
def test_view(self):
|
||||
self.pyramid_config.add_route('home', '/')
|
||||
self.pyramid_config.add_route('login', '/auth/login')
|
||||
self.pyramid_config.add_route('reports', '/reports/')
|
||||
self.pyramid_config.add_route('reports.view', '/reports/{report_key}')
|
||||
self.pyramid_config.add_route("home", "/")
|
||||
self.pyramid_config.add_route("login", "/auth/login")
|
||||
self.pyramid_config.add_route("reports", "/reports/")
|
||||
self.pyramid_config.add_route("reports.view", "/reports/{report_key}")
|
||||
view = self.make_view()
|
||||
providers = dict(self.app.providers)
|
||||
providers['wuttatest'] = MagicMock(report_modules=['tests.views.test_reports'])
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
with patch.object(self.request, 'matchdict', new={'report_key': 'testing_some_random'}):
|
||||
providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
|
||||
with patch.object(self.app, "providers", new=providers):
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"report_key": "testing_some_random"}
|
||||
):
|
||||
|
||||
# initial view
|
||||
response = view.view()
|
||||
|
@ -118,11 +128,15 @@ class TestReportViews(WebTestCase):
|
|||
self.assertNotIn("Testing Output", response.text)
|
||||
|
||||
# run the report
|
||||
with patch.object(self.request, 'GET', new={
|
||||
'__start__': 'start_date:mapping',
|
||||
'date': '2025-01-11',
|
||||
'__end__': 'start_date',
|
||||
}):
|
||||
with patch.object(
|
||||
self.request,
|
||||
"GET",
|
||||
new={
|
||||
"__start__": "start_date:mapping",
|
||||
"date": "2025-01-11",
|
||||
"__end__": "start_date",
|
||||
},
|
||||
):
|
||||
response = view.view()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# nb. there's a button in there somewhere, *and* an output title
|
||||
|
@ -132,105 +146,142 @@ class TestReportViews(WebTestCase):
|
|||
def test_configure_form(self):
|
||||
view = self.make_view()
|
||||
providers = dict(self.app.providers)
|
||||
providers['wuttatest'] = MagicMock(report_modules=['tests.views.test_reports'])
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
|
||||
with patch.object(self.app, "providers", new=providers):
|
||||
|
||||
with patch.object(self.request, 'matchdict', new={'report_key': 'testing_some_random'}):
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"report_key": "testing_some_random"}
|
||||
):
|
||||
report = view.get_instance()
|
||||
form = view.make_model_form(report)
|
||||
self.assertIn('help_text', form.readonly_fields)
|
||||
self.assertIn('foo', form)
|
||||
self.assertIn("help_text", form.readonly_fields)
|
||||
self.assertIn("foo", form)
|
||||
|
||||
def test_normalize_columns(self):
|
||||
view = self.make_view()
|
||||
|
||||
columns = view.normalize_columns(['foo'])
|
||||
self.assertEqual(columns, [
|
||||
{'name': 'foo', 'label': 'foo'},
|
||||
])
|
||||
columns = view.normalize_columns(["foo"])
|
||||
self.assertEqual(
|
||||
columns,
|
||||
[
|
||||
{"name": "foo", "label": "foo"},
|
||||
],
|
||||
)
|
||||
|
||||
columns = view.normalize_columns([{'name': 'foo'}])
|
||||
self.assertEqual(columns, [
|
||||
{'name': 'foo', 'label': 'foo'},
|
||||
])
|
||||
columns = view.normalize_columns([{"name": "foo"}])
|
||||
self.assertEqual(
|
||||
columns,
|
||||
[
|
||||
{"name": "foo", "label": "foo"},
|
||||
],
|
||||
)
|
||||
|
||||
columns = view.normalize_columns([{'name': 'foo', 'label': "FOO"}])
|
||||
self.assertEqual(columns, [
|
||||
{'name': 'foo', 'label': 'FOO'},
|
||||
])
|
||||
columns = view.normalize_columns([{"name": "foo", "label": "FOO"}])
|
||||
self.assertEqual(
|
||||
columns,
|
||||
[
|
||||
{"name": "foo", "label": "FOO"},
|
||||
],
|
||||
)
|
||||
|
||||
columns = view.normalize_columns([{'name': 'foo', 'label': "FOO", 'numeric': True}])
|
||||
self.assertEqual(columns, [
|
||||
{'name': 'foo', 'label': 'FOO', 'numeric': True},
|
||||
])
|
||||
columns = view.normalize_columns(
|
||||
[{"name": "foo", "label": "FOO", "numeric": True}]
|
||||
)
|
||||
self.assertEqual(
|
||||
columns,
|
||||
[
|
||||
{"name": "foo", "label": "FOO", "numeric": True},
|
||||
],
|
||||
)
|
||||
|
||||
def test_run_report(self):
|
||||
view = self.make_view()
|
||||
providers = dict(self.app.providers)
|
||||
providers['wuttatest'] = MagicMock(report_modules=['tests.views.test_reports'])
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
|
||||
with patch.object(self.app, "providers", new=providers):
|
||||
|
||||
with patch.object(self.request, 'matchdict', new={'report_key': 'testing_some_random'}):
|
||||
report = view.report_handler.get_report('testing_some_random')
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"report_key": "testing_some_random"}
|
||||
):
|
||||
report = view.report_handler.get_report("testing_some_random")
|
||||
normal = view.normalize_report(report)
|
||||
form = view.make_model_form(normal)
|
||||
|
||||
# typical
|
||||
context = view.run_report(report, {'form': form})
|
||||
self.assertEqual(sorted(context['report_params']), ['foo', 'start_date'])
|
||||
self.assertEqual(context['report_data'], {
|
||||
'output_title': "Testing Output",
|
||||
'data': [{'foo': 'bar'}],
|
||||
})
|
||||
self.assertIn('report_generated', context)
|
||||
context = view.run_report(report, {"form": form})
|
||||
self.assertEqual(
|
||||
sorted(context["report_params"]), ["foo", "start_date"]
|
||||
)
|
||||
self.assertEqual(
|
||||
context["report_data"],
|
||||
{
|
||||
"output_title": "Testing Output",
|
||||
"data": [{"foo": "bar"}],
|
||||
},
|
||||
)
|
||||
self.assertIn("report_generated", context)
|
||||
|
||||
# invalid params
|
||||
with patch.object(self.request, 'GET', new={'start_date': 'NOT_GOOD'}):
|
||||
context = view.run_report(report, {'form': form})
|
||||
self.assertNotIn('report_params', context)
|
||||
self.assertNotIn('report_data', context)
|
||||
self.assertNotIn('report_generated', context)
|
||||
with patch.object(self.request, "GET", new={"start_date": "NOT_GOOD"}):
|
||||
context = view.run_report(report, {"form": form})
|
||||
self.assertNotIn("report_params", context)
|
||||
self.assertNotIn("report_data", context)
|
||||
self.assertNotIn("report_generated", context)
|
||||
|
||||
# custom formatter
|
||||
with patch.object(report, 'get_output_columns') as get_output_columns:
|
||||
with patch.object(report, "get_output_columns") as get_output_columns:
|
||||
get_output_columns.return_value = [
|
||||
'foo',
|
||||
{'name': 'start_date',
|
||||
'formatter': lambda val: "FORMATTED VALUE"},
|
||||
"foo",
|
||||
{
|
||||
"name": "start_date",
|
||||
"formatter": lambda val: "FORMATTED VALUE",
|
||||
},
|
||||
]
|
||||
|
||||
with patch.object(report, 'make_data') as make_data:
|
||||
with patch.object(report, "make_data") as make_data:
|
||||
make_data.return_value = [
|
||||
{'foo': 'bar', 'start_date': datetime.date(2025, 1, 11)},
|
||||
{"foo": "bar", "start_date": datetime.date(2025, 1, 11)},
|
||||
]
|
||||
|
||||
context = view.run_report(report, {'form': form})
|
||||
context = view.run_report(report, {"form": form})
|
||||
get_output_columns.assert_called_once_with()
|
||||
self.assertEqual(len(context['report_columns']), 2)
|
||||
self.assertEqual(context['report_columns'][0]['name'], 'foo')
|
||||
self.assertEqual(context['report_columns'][1]['name'], 'start_date')
|
||||
self.assertEqual(context['report_data'], {
|
||||
'output_title': "Random Test Report",
|
||||
'data': [{'foo': 'bar', 'start_date': 'FORMATTED VALUE'}],
|
||||
})
|
||||
self.assertEqual(len(context["report_columns"]), 2)
|
||||
self.assertEqual(context["report_columns"][0]["name"], "foo")
|
||||
self.assertEqual(
|
||||
context["report_columns"][1]["name"], "start_date"
|
||||
)
|
||||
self.assertEqual(
|
||||
context["report_data"],
|
||||
{
|
||||
"output_title": "Random Test Report",
|
||||
"data": [
|
||||
{"foo": "bar", "start_date": "FORMATTED VALUE"}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
def test_download_data(self):
|
||||
view = self.make_view()
|
||||
providers = dict(self.app.providers)
|
||||
providers['wuttatest'] = MagicMock(report_modules=['tests.views.test_reports'])
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
with patch.object(self.request, 'matchdict', new={'report_key': 'testing_some_random'}):
|
||||
providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
|
||||
with patch.object(self.app, "providers", new=providers):
|
||||
with patch.object(
|
||||
self.request, "matchdict", new={"report_key": "testing_some_random"}
|
||||
):
|
||||
|
||||
params, columns, data = view.get_download_data()
|
||||
self.assertEqual(params, {})
|
||||
self.assertEqual(columns, [{'name': 'foo', 'label': 'foo'}])
|
||||
self.assertEqual(data, {
|
||||
'output_title': "Testing Output",
|
||||
'data': [{'foo': 'bar'}],
|
||||
})
|
||||
self.assertEqual(columns, [{"name": "foo", "label": "foo"}])
|
||||
self.assertEqual(
|
||||
data,
|
||||
{
|
||||
"output_title": "Testing Output",
|
||||
"data": [{"foo": "bar"}],
|
||||
},
|
||||
)
|
||||
|
||||
def test_download_path(self):
|
||||
view = self.make_view()
|
||||
data = {'output_title': "My Report"}
|
||||
path = view.get_download_path(data, 'csv')
|
||||
self.assertTrue(path.endswith('My Report.csv'))
|
||||
data = {"output_title": "My Report"}
|
||||
path = view.get_download_path(data, "csv")
|
||||
self.assertTrue(path.endswith("My Report.csv"))
|
||||
|
|
|
@ -18,7 +18,7 @@ class TestRoleView(WebTestCase):
|
|||
return mod.RoleView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.roles')
|
||||
self.pyramid_config.include("wuttaweb.views.roles")
|
||||
|
||||
def test_get_query(self):
|
||||
view = self.make_view()
|
||||
|
@ -29,9 +29,9 @@ class TestRoleView(WebTestCase):
|
|||
model = self.app.model
|
||||
view = self.make_view()
|
||||
grid = view.make_grid(model_class=model.Role)
|
||||
self.assertFalse(grid.is_linked('name'))
|
||||
self.assertFalse(grid.is_linked("name"))
|
||||
view.configure_grid(grid)
|
||||
self.assertTrue(grid.is_linked('name'))
|
||||
self.assertTrue(grid.is_linked("name"))
|
||||
|
||||
def test_is_editable(self):
|
||||
model = self.app.model
|
||||
|
@ -56,10 +56,10 @@ class TestRoleView(WebTestCase):
|
|||
# reset
|
||||
del self.request.user_permissions
|
||||
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
self.session.add(barney)
|
||||
barney.roles.append(blokes)
|
||||
auth.grant_permission(blokes, 'roles.edit_builtin')
|
||||
auth.grant_permission(blokes, "roles.edit_builtin")
|
||||
self.session.commit()
|
||||
|
||||
# user with perms can edit *some* built-in
|
||||
|
@ -90,9 +90,9 @@ class TestRoleView(WebTestCase):
|
|||
role = model.Role(name="Foo")
|
||||
view = self.make_view()
|
||||
form = view.make_form(model_instance=role)
|
||||
self.assertNotIn('name', form.validators)
|
||||
self.assertNotIn("name", form.validators)
|
||||
view.configure_form(form)
|
||||
self.assertIsNotNone(form.validators['name'])
|
||||
self.assertIsNotNone(form.validators["name"])
|
||||
|
||||
def test_make_users_grid(self):
|
||||
model = self.app.model
|
||||
|
@ -106,48 +106,48 @@ class TestRoleView(WebTestCase):
|
|||
self.assertFalse(grid.actions)
|
||||
|
||||
# view + edit actions
|
||||
with patch.object(self.request, 'is_root', new=True):
|
||||
with patch.object(self.request, "is_root", new=True):
|
||||
grid = view.make_users_grid(role)
|
||||
self.assertIsInstance(grid, Grid)
|
||||
self.assertIn('person', grid.linked_columns)
|
||||
self.assertIn('username', grid.linked_columns)
|
||||
self.assertIn("person", grid.linked_columns)
|
||||
self.assertIn("username", grid.linked_columns)
|
||||
self.assertEqual(len(grid.actions), 2)
|
||||
self.assertEqual(grid.actions[0].key, 'view')
|
||||
self.assertEqual(grid.actions[1].key, 'edit')
|
||||
self.assertEqual(grid.actions[0].key, "view")
|
||||
self.assertEqual(grid.actions[1].key, "edit")
|
||||
|
||||
def test_unique_name(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
role = model.Role(name='Foo')
|
||||
role = model.Role(name="Foo")
|
||||
self.session.add(role)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(mod, 'Session', return_value=self.session):
|
||||
with patch.object(mod, "Session", return_value=self.session):
|
||||
|
||||
# invalid if same name in data
|
||||
node = colander.SchemaNode(colander.String(), name='name')
|
||||
self.assertRaises(colander.Invalid, view.unique_name, node, 'Foo')
|
||||
node = colander.SchemaNode(colander.String(), name="name")
|
||||
self.assertRaises(colander.Invalid, view.unique_name, node, "Foo")
|
||||
|
||||
# but not if name belongs to current role
|
||||
view.editing = True
|
||||
self.request.matchdict = {'uuid': role.uuid}
|
||||
node = colander.SchemaNode(colander.String(), name='name')
|
||||
self.assertIsNone(view.unique_name(node, 'Foo'))
|
||||
self.request.matchdict = {"uuid": role.uuid}
|
||||
node = colander.SchemaNode(colander.String(), name="name")
|
||||
self.assertIsNone(view.unique_name(node, "Foo"))
|
||||
|
||||
def get_permissions(self):
|
||||
return {
|
||||
'widgets': {
|
||||
'label': "Widgets",
|
||||
'perms': {
|
||||
'widgets.list': {
|
||||
'label': "List widgets",
|
||||
"widgets": {
|
||||
"label": "Widgets",
|
||||
"perms": {
|
||||
"widgets.list": {
|
||||
"label": "List widgets",
|
||||
},
|
||||
'widgets.polish': {
|
||||
'label': "Polish the widgets",
|
||||
"widgets.polish": {
|
||||
"label": "Polish the widgets",
|
||||
},
|
||||
'widgets.view': {
|
||||
'label': "View widget",
|
||||
"widgets.view": {
|
||||
"label": "View widget",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -157,55 +157,59 @@ class TestRoleView(WebTestCase):
|
|||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
blokes = model.Role(name="Blokes")
|
||||
auth.grant_permission(blokes, 'widgets.list')
|
||||
auth.grant_permission(blokes, "widgets.list")
|
||||
self.session.add(blokes)
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
barney.roles.append(blokes)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
all_perms = self.get_permissions()
|
||||
self.request.registry.settings['wutta_permissions'] = all_perms
|
||||
self.request.registry.settings["wutta_permissions"] = all_perms
|
||||
|
||||
def has_perm(perm):
|
||||
if perm == 'widgets.list':
|
||||
if perm == "widgets.list":
|
||||
return True
|
||||
return False
|
||||
|
||||
with patch.object(self.request, 'has_perm', new=has_perm, create=True):
|
||||
with patch.object(self.request, "has_perm", new=has_perm, create=True):
|
||||
|
||||
# sanity check; current request has 1 perm
|
||||
self.assertTrue(self.request.has_perm('widgets.list'))
|
||||
self.assertFalse(self.request.has_perm('widgets.polish'))
|
||||
self.assertFalse(self.request.has_perm('widgets.view'))
|
||||
self.assertTrue(self.request.has_perm("widgets.list"))
|
||||
self.assertFalse(self.request.has_perm("widgets.polish"))
|
||||
self.assertFalse(self.request.has_perm("widgets.view"))
|
||||
|
||||
# when editing, user sees only the 1 perm
|
||||
with patch.object(view, 'editing', new=True):
|
||||
with patch.object(view, "editing", new=True):
|
||||
perms = view.get_available_permissions()
|
||||
self.assertEqual(list(perms), ['widgets'])
|
||||
self.assertEqual(list(perms['widgets']['perms']), ['widgets.list'])
|
||||
self.assertEqual(list(perms), ["widgets"])
|
||||
self.assertEqual(list(perms["widgets"]["perms"]), ["widgets.list"])
|
||||
|
||||
# but when viewing, same user sees all perms
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
perms = view.get_available_permissions()
|
||||
self.assertEqual(list(perms), ['widgets'])
|
||||
self.assertEqual(list(perms['widgets']['perms']),
|
||||
['widgets.list', 'widgets.polish', 'widgets.view'])
|
||||
self.assertEqual(list(perms), ["widgets"])
|
||||
self.assertEqual(
|
||||
list(perms["widgets"]["perms"]),
|
||||
["widgets.list", "widgets.polish", "widgets.view"],
|
||||
)
|
||||
|
||||
# also, when admin user is editing, sees all perms
|
||||
self.request.is_admin = True
|
||||
with patch.object(view, 'editing', new=True):
|
||||
with patch.object(view, "editing", new=True):
|
||||
perms = view.get_available_permissions()
|
||||
self.assertEqual(list(perms), ['widgets'])
|
||||
self.assertEqual(list(perms['widgets']['perms']),
|
||||
['widgets.list', 'widgets.polish', 'widgets.view'])
|
||||
self.assertEqual(list(perms), ["widgets"])
|
||||
self.assertEqual(
|
||||
list(perms["widgets"]["perms"]),
|
||||
["widgets.list", "widgets.polish", "widgets.view"],
|
||||
)
|
||||
|
||||
def test_objectify(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
blokes = model.Role(name="Blokes")
|
||||
self.session.add(blokes)
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
barney.roles.append(blokes)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
|
@ -213,56 +217,62 @@ class TestRoleView(WebTestCase):
|
|||
permissions = self.get_permissions()
|
||||
|
||||
# sanity check, role has just 1 perm
|
||||
auth.grant_permission(blokes, 'widgets.list')
|
||||
auth.grant_permission(blokes, "widgets.list")
|
||||
self.session.commit()
|
||||
self.assertEqual(blokes.permissions, ['widgets.list'])
|
||||
self.assertEqual(blokes.permissions, ["widgets.list"])
|
||||
|
||||
# form can update role perms
|
||||
view.editing = True
|
||||
self.request.matchdict = {'uuid': blokes.uuid}
|
||||
with patch.object(view, 'get_available_permissions', return_value=permissions):
|
||||
self.request.matchdict = {"uuid": blokes.uuid}
|
||||
with patch.object(view, "get_available_permissions", return_value=permissions):
|
||||
form = view.make_model_form(model_instance=blokes)
|
||||
form.validated = {'name': 'Blokes',
|
||||
'permissions': {'widgets.list', 'widgets.polish', 'widgets.view'}}
|
||||
form.validated = {
|
||||
"name": "Blokes",
|
||||
"permissions": {"widgets.list", "widgets.polish", "widgets.view"},
|
||||
}
|
||||
role = view.objectify(form)
|
||||
self.session.commit()
|
||||
self.assertIs(role, blokes)
|
||||
self.assertEqual(blokes.permissions, ['widgets.list', 'widgets.polish', 'widgets.view'])
|
||||
self.assertEqual(
|
||||
blokes.permissions, ["widgets.list", "widgets.polish", "widgets.view"]
|
||||
)
|
||||
|
||||
def test_update_permissions(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
blokes = model.Role(name="Blokes")
|
||||
auth.grant_permission(blokes, 'widgets.list')
|
||||
auth.grant_permission(blokes, "widgets.list")
|
||||
self.session.add(blokes)
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
barney.roles.append(blokes)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
permissions = self.get_permissions()
|
||||
|
||||
with patch.object(view, 'get_available_permissions', return_value=permissions):
|
||||
with patch.object(view, "get_available_permissions", return_value=permissions):
|
||||
|
||||
# no error if data is missing perms
|
||||
form = view.make_model_form(model_instance=blokes)
|
||||
form.validated = {'name': 'BloX'}
|
||||
form.validated = {"name": "BloX"}
|
||||
role = view.objectify(form)
|
||||
self.session.commit()
|
||||
self.assertIs(role, blokes)
|
||||
self.assertEqual(blokes.name, 'BloX')
|
||||
self.assertEqual(blokes.name, "BloX")
|
||||
|
||||
# sanity check, role has just 1 perm
|
||||
self.assertEqual(blokes.permissions, ['widgets.list'])
|
||||
self.assertEqual(blokes.permissions, ["widgets.list"])
|
||||
|
||||
# role perms are updated
|
||||
form = view.make_model_form(model_instance=blokes)
|
||||
form.validated = {'name': 'Blokes',
|
||||
'permissions': {'widgets.polish', 'widgets.view'}}
|
||||
form.validated = {
|
||||
"name": "Blokes",
|
||||
"permissions": {"widgets.polish", "widgets.view"},
|
||||
}
|
||||
role = view.objectify(form)
|
||||
self.session.commit()
|
||||
self.assertIs(role, blokes)
|
||||
self.assertEqual(blokes.permissions, ['widgets.polish', 'widgets.view'])
|
||||
self.assertEqual(blokes.permissions, ["widgets.polish", "widgets.view"])
|
||||
|
||||
|
||||
class TestPermissionView(WebTestCase):
|
||||
|
@ -279,17 +289,17 @@ class TestPermissionView(WebTestCase):
|
|||
model = self.app.model
|
||||
view = self.make_view()
|
||||
grid = view.make_grid(model_class=model.Permission)
|
||||
self.assertFalse(grid.is_linked('role'))
|
||||
self.assertFalse(grid.is_linked("role"))
|
||||
view.configure_grid(grid)
|
||||
self.assertTrue(grid.is_linked('role'))
|
||||
self.assertTrue(grid.is_linked("role"))
|
||||
|
||||
def test_configure_form(self):
|
||||
model = self.app.model
|
||||
role = model.Role(name="Foo")
|
||||
perm = model.Permission(role=role, permission='whatever')
|
||||
perm = model.Permission(role=role, permission="whatever")
|
||||
view = self.make_view()
|
||||
form = view.make_form(model_instance=perm)
|
||||
self.assertIsNone(form.schema)
|
||||
view.configure_form(form)
|
||||
schema = form.get_schema()
|
||||
self.assertIsInstance(schema['role'].typ, RoleRef)
|
||||
self.assertIsInstance(schema["role"].typ, RoleRef)
|
||||
|
|
|
@ -13,7 +13,7 @@ class TestAppInfoView(WebTestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.setup_web()
|
||||
self.pyramid_config.include('wuttaweb.views.essential')
|
||||
self.pyramid_config.include("wuttaweb.views.essential")
|
||||
|
||||
def make_view(self):
|
||||
return mod.AppInfoView(self.request)
|
||||
|
@ -26,7 +26,7 @@ class TestAppInfoView(WebTestCase):
|
|||
self.assertEqual(data, [])
|
||||
|
||||
# 'partial' request returns data
|
||||
self.request.GET = {'partial': '1'}
|
||||
self.request.GET = {"partial": "1"}
|
||||
data = view.get_grid_data()
|
||||
self.assertIsInstance(data, list)
|
||||
self.assertTrue(data)
|
||||
|
@ -61,7 +61,7 @@ class TestSettingView(WebTestCase):
|
|||
self.assertEqual(len(data), 0)
|
||||
|
||||
# unless we save some settings
|
||||
self.app.save_setting(self.session, 'foo', 'bar')
|
||||
self.app.save_setting(self.session, "foo", "bar")
|
||||
self.session.commit()
|
||||
query = view.get_grid_data(session=self.session)
|
||||
data = query.all()
|
||||
|
@ -71,34 +71,34 @@ class TestSettingView(WebTestCase):
|
|||
model = self.app.model
|
||||
view = self.make_view()
|
||||
grid = view.make_grid(model_class=model.Setting)
|
||||
self.assertFalse(grid.is_linked('name'))
|
||||
self.assertFalse(grid.is_linked("name"))
|
||||
view.configure_grid(grid)
|
||||
self.assertTrue(grid.is_linked('name'))
|
||||
self.assertTrue(grid.is_linked("name"))
|
||||
|
||||
def test_configure_form(self):
|
||||
view = self.make_view()
|
||||
form = view.make_form(fields=view.get_form_fields())
|
||||
self.assertNotIn('value', form.required_fields)
|
||||
self.assertNotIn("value", form.required_fields)
|
||||
view.configure_form(form)
|
||||
self.assertIn('value', form.required_fields)
|
||||
self.assertFalse(form.required_fields['value'])
|
||||
self.assertIn("value", form.required_fields)
|
||||
self.assertFalse(form.required_fields["value"])
|
||||
|
||||
def test_unique_name(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
setting = model.Setting(name='foo')
|
||||
setting = model.Setting(name="foo")
|
||||
self.session.add(setting)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
|
||||
# invalid if same name in data
|
||||
node = colander.SchemaNode(colander.String(), name='name')
|
||||
self.assertRaises(colander.Invalid, view.unique_name, node, 'foo')
|
||||
node = colander.SchemaNode(colander.String(), name="name")
|
||||
self.assertRaises(colander.Invalid, view.unique_name, node, "foo")
|
||||
|
||||
# but not if name belongs to current setting
|
||||
view.editing = True
|
||||
self.request.matchdict = {'name': 'foo'}
|
||||
node = colander.SchemaNode(colander.String(), name='name')
|
||||
self.assertIsNone(view.unique_name(node, 'foo'))
|
||||
self.request.matchdict = {"name": "foo"}
|
||||
node = colander.SchemaNode(colander.String(), name="name")
|
||||
self.assertIsNone(view.unique_name(node, "foo"))
|
||||
|
|
|
@ -17,7 +17,7 @@ class TestUpgradeView(WebTestCase):
|
|||
return mod.UpgradeView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.upgrades')
|
||||
self.pyramid_config.include("wuttaweb.views.upgrades")
|
||||
|
||||
def test_configure_grid(self):
|
||||
model = self.app.model
|
||||
|
@ -37,74 +37,79 @@ class TestUpgradeView(WebTestCase):
|
|||
self.assertIsNone(view.grid_row_class(upgrade, data, 1))
|
||||
|
||||
upgrade.status = enum.UpgradeStatus.EXECUTING
|
||||
self.assertEqual(view.grid_row_class(upgrade, data, 1), 'has-background-warning')
|
||||
self.assertEqual(
|
||||
view.grid_row_class(upgrade, data, 1), "has-background-warning"
|
||||
)
|
||||
|
||||
upgrade.status = enum.UpgradeStatus.SUCCESS
|
||||
self.assertIsNone(view.grid_row_class(upgrade, data, 1))
|
||||
|
||||
upgrade.status = enum.UpgradeStatus.FAILURE
|
||||
self.assertEqual(view.grid_row_class(upgrade, data, 1), 'has-background-warning')
|
||||
self.assertEqual(
|
||||
view.grid_row_class(upgrade, data, 1), "has-background-warning"
|
||||
)
|
||||
|
||||
def test_configure_form(self):
|
||||
self.pyramid_config.add_route('upgrades.download', '/upgrades/{uuid}/download')
|
||||
self.pyramid_config.add_route("upgrades.download", "/upgrades/{uuid}/download")
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
|
||||
# some fields exist when viewing
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
form = view.make_form(model_class=model.Upgrade, model_instance=upgrade)
|
||||
self.assertIn('created', form)
|
||||
self.assertIn("created", form)
|
||||
view.configure_form(form)
|
||||
self.assertIn('created', form)
|
||||
self.assertIn("created", form)
|
||||
|
||||
# but then are removed when creating
|
||||
with patch.object(view, 'creating', new=True):
|
||||
with patch.object(view, "creating", new=True):
|
||||
form = view.make_form(model_class=model.Upgrade)
|
||||
self.assertIn('created', form)
|
||||
self.assertIn("created", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('created', form)
|
||||
self.assertNotIn("created", form)
|
||||
|
||||
# test executed, stdout/stderr when viewing
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
|
||||
# executed is *not* shown by default
|
||||
form = view.make_form(model_class=model.Upgrade, model_instance=upgrade)
|
||||
self.assertIn('executed', form)
|
||||
self.assertIn("executed", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('executed', form)
|
||||
self.assertNotIn('stdout_file', form)
|
||||
self.assertNotIn('stderr_file', form)
|
||||
self.assertNotIn("executed", form)
|
||||
self.assertNotIn("stdout_file", form)
|
||||
self.assertNotIn("stderr_file", form)
|
||||
|
||||
# but it *is* shown if upgrade is executed
|
||||
upgrade.executed = datetime.datetime.now()
|
||||
upgrade.status = enum.UpgradeStatus.SUCCESS
|
||||
form = view.make_form(model_class=model.Upgrade, model_instance=upgrade)
|
||||
self.assertIn('executed', form)
|
||||
self.assertIn("executed", form)
|
||||
view.configure_form(form)
|
||||
self.assertIn('executed', form)
|
||||
self.assertIn('stdout_file', form)
|
||||
self.assertIn('stderr_file', form)
|
||||
self.assertIn("executed", form)
|
||||
self.assertIn("stdout_file", form)
|
||||
self.assertIn("stderr_file", form)
|
||||
|
||||
def test_objectify(self):
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
|
||||
# user and status are auto-set when creating
|
||||
self.request.user = user
|
||||
self.request.method = 'POST'
|
||||
self.request.POST = {'description': "new one"}
|
||||
with patch.object(view, 'creating', new=True):
|
||||
self.request.method = "POST"
|
||||
self.request.POST = {"description": "new one"}
|
||||
with patch.object(view, "creating", new=True):
|
||||
form = view.make_model_form()
|
||||
self.assertTrue(form.validate())
|
||||
upgrade = view.objectify(form)
|
||||
|
@ -116,13 +121,14 @@ class TestUpgradeView(WebTestCase):
|
|||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
|
||||
appdir = self.mkdir('app')
|
||||
self.config.setdefault('wutta.appdir', appdir)
|
||||
appdir = self.mkdir("app")
|
||||
self.config.setdefault("wutta.appdir", appdir)
|
||||
self.assertEqual(self.app.get_appdir(), appdir)
|
||||
|
||||
user = model.User(username='barney')
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
user = model.User(username="barney")
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
|
@ -134,21 +140,24 @@ class TestUpgradeView(WebTestCase):
|
|||
self.assertIsNone(path)
|
||||
|
||||
# with filename
|
||||
path = view.download_path(upgrade, 'foo.txt')
|
||||
self.assertEqual(path, os.path.join(appdir, 'data', 'upgrades',
|
||||
uuid[:2], uuid[2:], 'foo.txt'))
|
||||
path = view.download_path(upgrade, "foo.txt")
|
||||
self.assertEqual(
|
||||
path,
|
||||
os.path.join(appdir, "data", "upgrades", uuid[:2], uuid[2:], "foo.txt"),
|
||||
)
|
||||
|
||||
def test_get_upgrade_filepath(self):
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
|
||||
appdir = self.mkdir('app')
|
||||
self.config.setdefault('wutta.appdir', appdir)
|
||||
appdir = self.mkdir("app")
|
||||
self.config.setdefault("wutta.appdir", appdir)
|
||||
self.assertEqual(self.app.get_appdir(), appdir)
|
||||
|
||||
user = model.User(username='barney')
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
user = model.User(username="barney")
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
|
@ -157,25 +166,29 @@ class TestUpgradeView(WebTestCase):
|
|||
|
||||
# no filename
|
||||
path = view.get_upgrade_filepath(upgrade)
|
||||
self.assertEqual(path, os.path.join(appdir, 'data', 'upgrades',
|
||||
uuid[:2], uuid[2:]))
|
||||
self.assertEqual(
|
||||
path, os.path.join(appdir, "data", "upgrades", uuid[:2], uuid[2:])
|
||||
)
|
||||
|
||||
# with filename
|
||||
path = view.get_upgrade_filepath(upgrade, 'foo.txt')
|
||||
self.assertEqual(path, os.path.join(appdir, 'data', 'upgrades',
|
||||
uuid[:2], uuid[2:], 'foo.txt'))
|
||||
path = view.get_upgrade_filepath(upgrade, "foo.txt")
|
||||
self.assertEqual(
|
||||
path,
|
||||
os.path.join(appdir, "data", "upgrades", uuid[:2], uuid[2:], "foo.txt"),
|
||||
)
|
||||
|
||||
def test_delete_instance(self):
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
|
||||
appdir = self.mkdir('app')
|
||||
self.config.setdefault('wutta.appdir', appdir)
|
||||
appdir = self.mkdir("app")
|
||||
self.config.setdefault("wutta.appdir", appdir)
|
||||
self.assertEqual(self.app.get_appdir(), appdir)
|
||||
|
||||
user = model.User(username='barney')
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
user = model.User(username="barney")
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
|
@ -183,19 +196,19 @@ class TestUpgradeView(WebTestCase):
|
|||
|
||||
# mock stdout/stderr files
|
||||
upgrade_dir = view.get_upgrade_filepath(upgrade)
|
||||
stdout = view.get_upgrade_filepath(upgrade, 'stdout.log')
|
||||
with open(stdout, 'w') as f:
|
||||
f.write('stdout')
|
||||
stderr = view.get_upgrade_filepath(upgrade, 'stderr.log')
|
||||
with open(stderr, 'w') as f:
|
||||
f.write('stderr')
|
||||
stdout = view.get_upgrade_filepath(upgrade, "stdout.log")
|
||||
with open(stdout, "w") as f:
|
||||
f.write("stdout")
|
||||
stderr = view.get_upgrade_filepath(upgrade, "stderr.log")
|
||||
with open(stderr, "w") as f:
|
||||
f.write("stderr")
|
||||
|
||||
# both upgrade and files are deleted
|
||||
self.assertTrue(os.path.exists(upgrade_dir))
|
||||
self.assertTrue(os.path.exists(stdout))
|
||||
self.assertTrue(os.path.exists(stderr))
|
||||
self.assertEqual(self.session.query(model.Upgrade).count(), 1)
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
view.delete_instance(upgrade)
|
||||
self.assertFalse(os.path.exists(upgrade_dir))
|
||||
self.assertFalse(os.path.exists(stdout))
|
||||
|
@ -206,13 +219,14 @@ class TestUpgradeView(WebTestCase):
|
|||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
|
||||
appdir = self.mkdir('app')
|
||||
self.config.setdefault('wutta.appdir', appdir)
|
||||
appdir = self.mkdir("app")
|
||||
self.config.setdefault("wutta.appdir", appdir)
|
||||
self.assertEqual(self.app.get_appdir(), appdir)
|
||||
|
||||
user = model.User(username='barney')
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
user = model.User(username="barney")
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
|
@ -224,139 +238,153 @@ class TestUpgradeView(WebTestCase):
|
|||
self.assertRaises(ConfigurationError, view.execute_instance, upgrade, user)
|
||||
|
||||
# script w/ success
|
||||
goodpy = self.write_file('good.py', """
|
||||
goodpy = self.write_file(
|
||||
"good.py",
|
||||
"""
|
||||
import sys
|
||||
sys.stdout.write('hello from good.py')
|
||||
sys.exit(0)
|
||||
""")
|
||||
self.app.save_setting(self.session, 'wutta.upgrades.command', f'{python} {goodpy}')
|
||||
""",
|
||||
)
|
||||
self.app.save_setting(
|
||||
self.session, "wutta.upgrades.command", f"{python} {goodpy}"
|
||||
)
|
||||
self.assertIsNone(upgrade.executed)
|
||||
self.assertIsNone(upgrade.executed_by)
|
||||
self.assertEqual(upgrade.status, enum.UpgradeStatus.PENDING)
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(self.config, 'usedb', new=True):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
with patch.object(self.config, "usedb", new=True):
|
||||
view.execute_instance(upgrade, user)
|
||||
self.assertIsNotNone(upgrade.executed)
|
||||
self.assertIs(upgrade.executed_by, user)
|
||||
self.assertEqual(upgrade.status, enum.UpgradeStatus.SUCCESS)
|
||||
with open(view.get_upgrade_filepath(upgrade, 'stdout.log')) as f:
|
||||
self.assertEqual(f.read(), 'hello from good.py')
|
||||
with open(view.get_upgrade_filepath(upgrade, 'stderr.log')) as f:
|
||||
self.assertEqual(f.read(), '')
|
||||
with open(view.get_upgrade_filepath(upgrade, "stdout.log")) as f:
|
||||
self.assertEqual(f.read(), "hello from good.py")
|
||||
with open(view.get_upgrade_filepath(upgrade, "stderr.log")) as f:
|
||||
self.assertEqual(f.read(), "")
|
||||
|
||||
# need a new record for next test
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
# script w/ failure
|
||||
badpy = self.write_file('bad.py', """
|
||||
badpy = self.write_file(
|
||||
"bad.py",
|
||||
"""
|
||||
import sys
|
||||
sys.stderr.write('hello from bad.py')
|
||||
sys.exit(42)
|
||||
""")
|
||||
self.app.save_setting(self.session, 'wutta.upgrades.command', f'{python} {badpy}')
|
||||
""",
|
||||
)
|
||||
self.app.save_setting(
|
||||
self.session, "wutta.upgrades.command", f"{python} {badpy}"
|
||||
)
|
||||
self.assertIsNone(upgrade.executed)
|
||||
self.assertIsNone(upgrade.executed_by)
|
||||
self.assertEqual(upgrade.status, enum.UpgradeStatus.PENDING)
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(self.config, 'usedb', new=True):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
with patch.object(self.config, "usedb", new=True):
|
||||
view.execute_instance(upgrade, user)
|
||||
self.assertIsNotNone(upgrade.executed)
|
||||
self.assertIs(upgrade.executed_by, user)
|
||||
self.assertEqual(upgrade.status, enum.UpgradeStatus.FAILURE)
|
||||
with open(view.get_upgrade_filepath(upgrade, 'stdout.log')) as f:
|
||||
self.assertEqual(f.read(), '')
|
||||
with open(view.get_upgrade_filepath(upgrade, 'stderr.log')) as f:
|
||||
self.assertEqual(f.read(), 'hello from bad.py')
|
||||
with open(view.get_upgrade_filepath(upgrade, "stdout.log")) as f:
|
||||
self.assertEqual(f.read(), "")
|
||||
with open(view.get_upgrade_filepath(upgrade, "stderr.log")) as f:
|
||||
self.assertEqual(f.read(), "hello from bad.py")
|
||||
|
||||
def test_execute_progress(self):
|
||||
model = self.app.model
|
||||
enum = self.app.enum
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='barney')
|
||||
user = model.User(username="barney")
|
||||
self.session.add(user)
|
||||
upgrade = model.Upgrade(description='test', created_by=user,
|
||||
status=enum.UpgradeStatus.PENDING)
|
||||
upgrade = model.Upgrade(
|
||||
description="test", created_by=user, status=enum.UpgradeStatus.PENDING
|
||||
)
|
||||
self.session.add(upgrade)
|
||||
self.session.commit()
|
||||
|
||||
stdout = self.write_file('stdout.log', 'hello 001\n')
|
||||
stdout = self.write_file("stdout.log", "hello 001\n")
|
||||
|
||||
self.request.matchdict = {'uuid': upgrade.uuid}
|
||||
with patch.multiple(mod.UpgradeView,
|
||||
Session=MagicMock(return_value=self.session),
|
||||
get_upgrade_filepath=MagicMock(return_value=stdout)):
|
||||
self.request.matchdict = {"uuid": upgrade.uuid}
|
||||
with patch.multiple(
|
||||
mod.UpgradeView,
|
||||
Session=MagicMock(return_value=self.session),
|
||||
get_upgrade_filepath=MagicMock(return_value=stdout),
|
||||
):
|
||||
|
||||
# nb. this is used to identify progress tracker
|
||||
self.request.session.id = 'mockid#1'
|
||||
self.request.session.id = "mockid#1"
|
||||
|
||||
# first call should get the full contents
|
||||
context = view.execute_progress()
|
||||
self.assertFalse(context.get('complete'))
|
||||
self.assertFalse(context.get('error'))
|
||||
self.assertFalse(context.get("complete"))
|
||||
self.assertFalse(context.get("error"))
|
||||
# nb. newline is converted to <br>
|
||||
self.assertEqual(context['stdout'], 'hello 001<br />')
|
||||
self.assertEqual(context["stdout"], "hello 001<br />")
|
||||
|
||||
# next call should get any new contents
|
||||
with open(stdout, 'a') as f:
|
||||
f.write('hello 002\n')
|
||||
with open(stdout, "a") as f:
|
||||
f.write("hello 002\n")
|
||||
context = view.execute_progress()
|
||||
self.assertFalse(context.get('complete'))
|
||||
self.assertFalse(context.get('error'))
|
||||
self.assertEqual(context['stdout'], 'hello 002<br />')
|
||||
self.assertFalse(context.get("complete"))
|
||||
self.assertFalse(context.get("error"))
|
||||
self.assertEqual(context["stdout"], "hello 002<br />")
|
||||
|
||||
# nb. switch to a different progress tracker
|
||||
self.request.session.id = 'mockid#2'
|
||||
self.request.session.id = "mockid#2"
|
||||
|
||||
# first call should get the full contents
|
||||
context = view.execute_progress()
|
||||
self.assertFalse(context.get('complete'))
|
||||
self.assertFalse(context.get('error'))
|
||||
self.assertEqual(context['stdout'], 'hello 001<br />hello 002<br />')
|
||||
self.assertFalse(context.get("complete"))
|
||||
self.assertFalse(context.get("error"))
|
||||
self.assertEqual(context["stdout"], "hello 001<br />hello 002<br />")
|
||||
|
||||
# mark progress complete
|
||||
session = get_progress_session(self.request, 'upgrades.execute')
|
||||
session = get_progress_session(self.request, "upgrades.execute")
|
||||
session.load()
|
||||
session['complete'] = True
|
||||
session['success_msg'] = 'yay!'
|
||||
session["complete"] = True
|
||||
session["success_msg"] = "yay!"
|
||||
session.save()
|
||||
|
||||
# next call should reflect that
|
||||
self.assertEqual(self.request.session.pop_flash(), [])
|
||||
context = view.execute_progress()
|
||||
self.assertTrue(context.get('complete'))
|
||||
self.assertFalse(context.get('error'))
|
||||
self.assertTrue(context.get("complete"))
|
||||
self.assertFalse(context.get("error"))
|
||||
# nb. this is missing b/c we already got all contents
|
||||
self.assertNotIn('stdout', context)
|
||||
self.assertEqual(self.request.session.pop_flash(), ['yay!'])
|
||||
self.assertNotIn("stdout", context)
|
||||
self.assertEqual(self.request.session.pop_flash(), ["yay!"])
|
||||
|
||||
# nb. switch to a different progress tracker
|
||||
self.request.session.id = 'mockid#3'
|
||||
self.request.session.id = "mockid#3"
|
||||
|
||||
# first call should get the full contents
|
||||
context = view.execute_progress()
|
||||
self.assertFalse(context.get('complete'))
|
||||
self.assertFalse(context.get('error'))
|
||||
self.assertEqual(context['stdout'], 'hello 001<br />hello 002<br />')
|
||||
self.assertFalse(context.get("complete"))
|
||||
self.assertFalse(context.get("error"))
|
||||
self.assertEqual(context["stdout"], "hello 001<br />hello 002<br />")
|
||||
|
||||
# mark progress error
|
||||
session = get_progress_session(self.request, 'upgrades.execute')
|
||||
session = get_progress_session(self.request, "upgrades.execute")
|
||||
session.load()
|
||||
session['error'] = True
|
||||
session['error_msg'] = 'omg!'
|
||||
session["error"] = True
|
||||
session["error_msg"] = "omg!"
|
||||
session.save()
|
||||
|
||||
# next call should reflect that
|
||||
self.assertEqual(self.request.session.pop_flash('error'), [])
|
||||
self.assertEqual(self.request.session.pop_flash("error"), [])
|
||||
context = view.execute_progress()
|
||||
self.assertFalse(context.get('complete'))
|
||||
self.assertTrue(context.get('error'))
|
||||
self.assertFalse(context.get("complete"))
|
||||
self.assertTrue(context.get("error"))
|
||||
# nb. this is missing b/c we already got all contents
|
||||
self.assertNotIn('stdout', context)
|
||||
self.assertEqual(self.request.session.pop_flash('error'), ['omg!'])
|
||||
self.assertNotIn("stdout", context)
|
||||
self.assertEqual(self.request.session.pop_flash("error"), ["omg!"])
|
||||
|
||||
def test_configure_get_simple_settings(self):
|
||||
# sanity/coverage check
|
||||
|
|
|
@ -17,7 +17,7 @@ class TestUserView(WebTestCase):
|
|||
return mod.UserView(self.request)
|
||||
|
||||
def test_includeme(self):
|
||||
self.pyramid_config.include('wuttaweb.views.users')
|
||||
self.pyramid_config.include("wuttaweb.views.users")
|
||||
|
||||
def test_get_query(self):
|
||||
view = self.make_view()
|
||||
|
@ -28,35 +28,35 @@ class TestUserView(WebTestCase):
|
|||
model = self.app.model
|
||||
view = self.make_view()
|
||||
grid = view.make_grid(model_class=model.User)
|
||||
self.assertFalse(grid.is_linked('person'))
|
||||
self.assertFalse(grid.is_linked("person"))
|
||||
view.configure_grid(grid)
|
||||
self.assertTrue(grid.is_linked('person'))
|
||||
self.assertTrue(grid.is_linked("person"))
|
||||
|
||||
def test_grid_row_class(self):
|
||||
model = self.app.model
|
||||
user = model.User(username='barney', active=True)
|
||||
user = model.User(username="barney", active=True)
|
||||
data = dict(user)
|
||||
view = self.make_view()
|
||||
|
||||
self.assertIsNone(view.grid_row_class(user, data, 1))
|
||||
|
||||
user.active = False
|
||||
self.assertEqual(view.grid_row_class(user, data, 1), 'has-background-warning')
|
||||
self.assertEqual(view.grid_row_class(user, data, 1), "has-background-warning")
|
||||
|
||||
def test_is_editable(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
# active user is editable
|
||||
user = model.User(username='barney', active=True)
|
||||
user = model.User(username="barney", active=True)
|
||||
self.assertTrue(view.is_editable(user))
|
||||
|
||||
# inactive also editable
|
||||
user = model.User(username='barney', active=False)
|
||||
user = model.User(username="barney", active=False)
|
||||
self.assertTrue(view.is_editable(user))
|
||||
|
||||
# but not if prevent_edit flag is set
|
||||
user = model.User(username='barney', prevent_edit=True)
|
||||
user = model.User(username="barney", prevent_edit=True)
|
||||
self.assertFalse(view.is_editable(user))
|
||||
|
||||
# unless request user is root
|
||||
|
@ -65,95 +65,97 @@ class TestUserView(WebTestCase):
|
|||
|
||||
def test_configure_form(self):
|
||||
model = self.app.model
|
||||
person = model.Person(first_name='Barney', last_name='Rubble', full_name='Barney Rubble')
|
||||
barney = model.User(username='barney', person=person)
|
||||
person = model.Person(
|
||||
first_name="Barney", last_name="Rubble", full_name="Barney Rubble"
|
||||
)
|
||||
barney = model.User(username="barney", person=person)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
|
||||
# person replaced with first/last name when creating or editing
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('person', form)
|
||||
self.assertNotIn('first_name', form)
|
||||
self.assertNotIn('last_name', form)
|
||||
self.assertIn("person", form)
|
||||
self.assertNotIn("first_name", form)
|
||||
self.assertNotIn("last_name", form)
|
||||
view.configure_form(form)
|
||||
self.assertIn('person', form)
|
||||
self.assertNotIn('first_name', form)
|
||||
self.assertNotIn('last_name', form)
|
||||
with patch.object(view, 'creating', new=True):
|
||||
self.assertIn("person", form)
|
||||
self.assertNotIn("first_name", form)
|
||||
self.assertNotIn("last_name", form)
|
||||
with patch.object(view, "creating", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('person', form)
|
||||
self.assertNotIn('first_name', form)
|
||||
self.assertNotIn('last_name', form)
|
||||
self.assertIn("person", form)
|
||||
self.assertNotIn("first_name", form)
|
||||
self.assertNotIn("last_name", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('person', form)
|
||||
self.assertIn('first_name', form)
|
||||
self.assertIn('last_name', form)
|
||||
with patch.object(view, 'editing', new=True):
|
||||
self.assertNotIn("person", form)
|
||||
self.assertIn("first_name", form)
|
||||
self.assertIn("last_name", form)
|
||||
with patch.object(view, "editing", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('person', form)
|
||||
self.assertNotIn('first_name', form)
|
||||
self.assertNotIn('last_name', form)
|
||||
self.assertIn("person", form)
|
||||
self.assertNotIn("first_name", form)
|
||||
self.assertNotIn("last_name", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('person', form)
|
||||
self.assertIn('first_name', form)
|
||||
self.assertIn('last_name', form)
|
||||
self.assertNotIn("person", form)
|
||||
self.assertIn("first_name", form)
|
||||
self.assertIn("last_name", form)
|
||||
|
||||
# first/last name have default values when editing
|
||||
with patch.object(view, 'editing', new=True):
|
||||
with patch.object(view, "editing", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertNotIn('first_name', form.defaults)
|
||||
self.assertNotIn('last_name', form.defaults)
|
||||
self.assertNotIn("first_name", form.defaults)
|
||||
self.assertNotIn("last_name", form.defaults)
|
||||
view.configure_form(form)
|
||||
self.assertIn('first_name', form.defaults)
|
||||
self.assertEqual(form.defaults['first_name'], 'Barney')
|
||||
self.assertIn('last_name', form.defaults)
|
||||
self.assertEqual(form.defaults['last_name'], 'Rubble')
|
||||
self.assertIn("first_name", form.defaults)
|
||||
self.assertEqual(form.defaults["first_name"], "Barney")
|
||||
self.assertIn("last_name", form.defaults)
|
||||
self.assertEqual(form.defaults["last_name"], "Rubble")
|
||||
|
||||
# password removed (always, for now)
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('password', form)
|
||||
self.assertIn("password", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('password', form)
|
||||
with patch.object(view, 'editing', new=True):
|
||||
self.assertNotIn("password", form)
|
||||
with patch.object(view, "editing", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('password', form)
|
||||
self.assertIn("password", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('password', form)
|
||||
self.assertNotIn("password", form)
|
||||
|
||||
# api tokens grid shown only if current user has perm
|
||||
with patch.object(view, 'viewing', new=True):
|
||||
with patch.object(view, "viewing", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('api_tokens', form)
|
||||
self.assertIn("api_tokens", form)
|
||||
view.configure_form(form)
|
||||
self.assertNotIn('api_tokens', form)
|
||||
with patch.object(self.request, 'is_root', new=True):
|
||||
self.assertNotIn("api_tokens", form)
|
||||
with patch.object(self.request, "is_root", new=True):
|
||||
form = view.make_form(model_instance=barney)
|
||||
self.assertIn('api_tokens', form)
|
||||
self.assertIn("api_tokens", form)
|
||||
view.configure_form(form)
|
||||
self.assertIn('api_tokens', form)
|
||||
self.assertIn("api_tokens", form)
|
||||
|
||||
def test_unique_username(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(view, "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')
|
||||
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'))
|
||||
self.request.matchdict = {"uuid": user.uuid}
|
||||
node = colander.SchemaNode(colander.String(), name="username")
|
||||
self.assertIsNone(view.unique_username(node, "foo"))
|
||||
|
||||
def test_objectify(self):
|
||||
model = self.app.model
|
||||
|
@ -164,14 +166,14 @@ class TestUserView(WebTestCase):
|
|||
self.session.add(blokes)
|
||||
others = model.Role(name="Others")
|
||||
self.session.add(others)
|
||||
barney = model.User(username='barney')
|
||||
auth.set_user_password(barney, 'testpass')
|
||||
barney = model.User(username="barney")
|
||||
auth.set_user_password(barney, "testpass")
|
||||
barney.roles.append(blokes)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
|
||||
with patch.object(self.request, 'matchdict', new={'uuid': barney.uuid}):
|
||||
with patch.object(view, 'editing', new=True):
|
||||
with patch.object(self.request, "matchdict", new={"uuid": barney.uuid}):
|
||||
with patch.object(view, "editing", new=True):
|
||||
|
||||
# sanity check, user is just in 'blokes' role
|
||||
self.session.refresh(barney)
|
||||
|
@ -179,18 +181,18 @@ class TestUserView(WebTestCase):
|
|||
self.assertEqual(barney.roles[0].name, "Blokes")
|
||||
|
||||
# form can update user password
|
||||
self.assertTrue(auth.check_user_password(barney, 'testpass'))
|
||||
self.assertTrue(auth.check_user_password(barney, "testpass"))
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'set_password': 'testpass2'}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {"username": "barney", "set_password": "testpass2"}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertTrue(auth.check_user_password(barney, 'testpass2'))
|
||||
self.assertTrue(auth.check_user_password(barney, "testpass2"))
|
||||
|
||||
# form can update user roles
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'roles': {others.uuid}}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {"username": "barney", "roles": {others.uuid}}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertEqual(len(user.roles), 1)
|
||||
|
@ -199,19 +201,27 @@ class TestUserView(WebTestCase):
|
|||
# person is auto-created
|
||||
self.assertIsNone(barney.person)
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'first_name': 'Barney', 'last_name': 'Rubble'}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {
|
||||
"username": "barney",
|
||||
"first_name": "Barney",
|
||||
"last_name": "Rubble",
|
||||
}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIsNotNone(barney.person)
|
||||
self.assertEqual(barney.person.first_name, 'Barney')
|
||||
self.assertEqual(barney.person.last_name, 'Rubble')
|
||||
self.assertEqual(barney.person.full_name, 'Barney Rubble')
|
||||
self.assertEqual(barney.person.first_name, "Barney")
|
||||
self.assertEqual(barney.person.last_name, "Rubble")
|
||||
self.assertEqual(barney.person.full_name, "Barney Rubble")
|
||||
|
||||
# person is auto-removed
|
||||
self.assertIsNotNone(barney.person)
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'first_name': '', 'last_name': ''}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {
|
||||
"username": "barney",
|
||||
"first_name": "",
|
||||
"last_name": "",
|
||||
}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIsNone(barney.person)
|
||||
|
||||
|
@ -219,37 +229,45 @@ class TestUserView(WebTestCase):
|
|||
barney.person = self.session.query(model.Person).one()
|
||||
|
||||
# person name is updated
|
||||
self.assertEqual(barney.person.first_name, 'Barney')
|
||||
self.assertEqual(barney.person.last_name, 'Rubble')
|
||||
self.assertEqual(barney.person.full_name, 'Barney Rubble')
|
||||
self.assertEqual(barney.person.first_name, "Barney")
|
||||
self.assertEqual(barney.person.last_name, "Rubble")
|
||||
self.assertEqual(barney.person.full_name, "Barney Rubble")
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney', 'first_name': 'Fred', 'last_name': 'Flintstone'}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {
|
||||
"username": "barney",
|
||||
"first_name": "Fred",
|
||||
"last_name": "Flintstone",
|
||||
}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIsNotNone(barney.person)
|
||||
self.assertEqual(barney.person.first_name, 'Fred')
|
||||
self.assertEqual(barney.person.last_name, 'Flintstone')
|
||||
self.assertEqual(barney.person.full_name, 'Fred Flintstone')
|
||||
self.assertEqual(barney.person.first_name, "Fred")
|
||||
self.assertEqual(barney.person.last_name, "Flintstone")
|
||||
self.assertEqual(barney.person.full_name, "Fred Flintstone")
|
||||
|
||||
with patch.object(view, 'creating', new=True):
|
||||
with patch.object(view, "creating", new=True):
|
||||
|
||||
# person is auto-created when making new user
|
||||
form = view.make_model_form()
|
||||
form.validated = {'username': 'betty', 'first_name': 'Betty', 'last_name': 'Boop'}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {
|
||||
"username": "betty",
|
||||
"first_name": "Betty",
|
||||
"last_name": "Boop",
|
||||
}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIsNotNone(user.person)
|
||||
self.assertEqual(user.person.first_name, 'Betty')
|
||||
self.assertEqual(user.person.last_name, 'Boop')
|
||||
self.assertEqual(user.person.full_name, 'Betty Boop')
|
||||
self.assertEqual(user.person.first_name, "Betty")
|
||||
self.assertEqual(user.person.last_name, "Boop")
|
||||
self.assertEqual(user.person.full_name, "Betty Boop")
|
||||
|
||||
# nb. keep ref to last user
|
||||
last_user = user
|
||||
|
||||
# person is *not* auto-created if no name provided
|
||||
form = view.make_model_form()
|
||||
form.validated = {'username': 'betty', 'first_name': '', 'last_name': ''}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {"username": "betty", "first_name": "", "last_name": ""}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIsNone(user.person)
|
||||
self.assertIsNot(user, last_user)
|
||||
|
@ -264,20 +282,20 @@ class TestUserView(WebTestCase):
|
|||
self.session.add(blokes)
|
||||
others = model.Role(name="Others")
|
||||
self.session.add(others)
|
||||
barney = model.User(username='barney')
|
||||
barney = model.User(username="barney")
|
||||
barney.roles.append(blokes)
|
||||
self.session.add(barney)
|
||||
self.session.commit()
|
||||
view = self.make_view()
|
||||
view.editing = True
|
||||
self.request.matchdict = {'uuid': barney.uuid}
|
||||
self.request.matchdict = {"uuid": barney.uuid}
|
||||
|
||||
# no error if data is missing roles
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barneyx'}
|
||||
form.validated = {"username": "barneyx"}
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertEqual(barney.username, 'barneyx')
|
||||
self.assertEqual(barney.username, "barneyx")
|
||||
|
||||
# sanity check, user is just in 'blokes' role
|
||||
self.session.refresh(barney)
|
||||
|
@ -289,9 +307,11 @@ class TestUserView(WebTestCase):
|
|||
# - authed / anon roles are not added
|
||||
# - admin role not added if current user is not root
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney',
|
||||
'roles': {admin.uuid, authed.uuid, anon.uuid, others.uuid}}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {
|
||||
"username": "barney",
|
||||
"roles": {admin.uuid, authed.uuid, anon.uuid, others.uuid},
|
||||
}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertEqual(len(user.roles), 1)
|
||||
|
@ -302,9 +322,11 @@ class TestUserView(WebTestCase):
|
|||
# - admin role is added if current user is root
|
||||
self.request.is_root = True
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney',
|
||||
'roles': {admin.uuid, blokes.uuid, others.uuid}}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {
|
||||
"username": "barney",
|
||||
"roles": {admin.uuid, blokes.uuid, others.uuid},
|
||||
}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertEqual(len(user.roles), 3)
|
||||
|
@ -314,9 +336,8 @@ class TestUserView(WebTestCase):
|
|||
# admin role not removed if current user is not root
|
||||
self.request.is_root = False
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney',
|
||||
'roles': {blokes.uuid, others.uuid}}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {"username": "barney", "roles": {blokes.uuid, others.uuid}}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertEqual(len(user.roles), 3)
|
||||
|
@ -324,9 +345,8 @@ class TestUserView(WebTestCase):
|
|||
# admin role is removed if current user is root
|
||||
self.request.is_root = True
|
||||
form = view.make_model_form(model_instance=barney)
|
||||
form.validated = {'username': 'barney',
|
||||
'roles': {blokes.uuid, others.uuid}}
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
form.validated = {"username": "barney", "roles": {blokes.uuid, others.uuid}}
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
user = view.objectify(form)
|
||||
self.assertIs(user, barney)
|
||||
self.assertEqual(len(user.roles), 2)
|
||||
|
@ -336,27 +356,27 @@ class TestUserView(WebTestCase):
|
|||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
token = auth.add_api_token(user, 'test token')
|
||||
token = auth.add_api_token(user, "test token")
|
||||
self.session.commit()
|
||||
|
||||
normal = view.normalize_api_token(token)
|
||||
self.assertIn('uuid', normal)
|
||||
self.assertEqual(normal['uuid'], token.uuid.hex)
|
||||
self.assertIn('description', normal)
|
||||
self.assertEqual(normal['description'], 'test token')
|
||||
self.assertIn('created', normal)
|
||||
self.assertIn("uuid", normal)
|
||||
self.assertEqual(normal["uuid"], token.uuid.hex)
|
||||
self.assertIn("description", normal)
|
||||
self.assertEqual(normal["description"], "test token")
|
||||
self.assertIn("created", normal)
|
||||
|
||||
def test_make_api_tokens_grid(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
token1 = auth.add_api_token(user, 'test1')
|
||||
token2 = auth.add_api_token(user, 'test2')
|
||||
token1 = auth.add_api_token(user, "test1")
|
||||
token2 = auth.add_api_token(user, "test2")
|
||||
self.session.commit()
|
||||
|
||||
# grid should have 2 records but no tools/actions
|
||||
|
@ -367,52 +387,60 @@ class TestUserView(WebTestCase):
|
|||
self.assertEqual(len(grid.actions), 0)
|
||||
|
||||
# create + delete allowed
|
||||
with patch.object(self.request, 'is_root', new=True):
|
||||
with patch.object(self.request, "is_root", new=True):
|
||||
grid = view.make_api_tokens_grid(user)
|
||||
self.assertEqual(len(grid.tools), 1)
|
||||
self.assertIn('create', grid.tools)
|
||||
self.assertIn("create", grid.tools)
|
||||
self.assertEqual(len(grid.actions), 1)
|
||||
self.assertEqual(grid.actions[0].key, 'delete')
|
||||
self.assertEqual(grid.actions[0].key, "delete")
|
||||
|
||||
def test_add_api_token(self):
|
||||
model = self.app.model
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
self.session.commit()
|
||||
self.session.refresh(user)
|
||||
self.assertEqual(len(user.api_tokens), 0)
|
||||
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(self.request, 'matchdict', new={'uuid': user.uuid}):
|
||||
with patch.object(self.request, 'json_body', create=True,
|
||||
new={'description': 'testing'}):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
with patch.object(self.request, "matchdict", new={"uuid": user.uuid}):
|
||||
with patch.object(
|
||||
self.request,
|
||||
"json_body",
|
||||
create=True,
|
||||
new={"description": "testing"},
|
||||
):
|
||||
result = view.add_api_token()
|
||||
self.assertEqual(len(user.api_tokens), 1)
|
||||
token = user.api_tokens[0]
|
||||
self.assertEqual(result['token_string'], token.token_string)
|
||||
self.assertEqual(result['description'], 'testing')
|
||||
self.assertEqual(result["token_string"], token.token_string)
|
||||
self.assertEqual(result["description"], "testing")
|
||||
|
||||
def test_delete_api_token(self):
|
||||
model = self.app.model
|
||||
auth = self.app.get_auth_handler()
|
||||
view = self.make_view()
|
||||
|
||||
user = model.User(username='foo')
|
||||
user = model.User(username="foo")
|
||||
self.session.add(user)
|
||||
token1 = auth.add_api_token(user, 'test1')
|
||||
token2 = auth.add_api_token(user, 'test2')
|
||||
token1 = auth.add_api_token(user, "test1")
|
||||
token2 = auth.add_api_token(user, "test2")
|
||||
self.session.commit()
|
||||
self.session.refresh(user)
|
||||
self.assertEqual(len(user.api_tokens), 2)
|
||||
|
||||
with patch.object(view, 'Session', return_value=self.session):
|
||||
with patch.object(self.request, 'matchdict', new={'uuid': user.uuid}):
|
||||
with patch.object(view, "Session", return_value=self.session):
|
||||
with patch.object(self.request, "matchdict", new={"uuid": user.uuid}):
|
||||
|
||||
# normal behavior
|
||||
with patch.object(self.request, 'json_body', create=True,
|
||||
new={'uuid': token1.uuid.hex}):
|
||||
with patch.object(
|
||||
self.request,
|
||||
"json_body",
|
||||
create=True,
|
||||
new={"uuid": token1.uuid.hex},
|
||||
):
|
||||
result = view.delete_api_token()
|
||||
self.assertEqual(result, {})
|
||||
self.session.refresh(user)
|
||||
|
@ -421,17 +449,25 @@ class TestUserView(WebTestCase):
|
|||
self.assertIs(token, token2)
|
||||
|
||||
# token for wrong user
|
||||
user2 = model.User(username='bar')
|
||||
user2 = model.User(username="bar")
|
||||
self.session.add(user2)
|
||||
token3 = auth.add_api_token(user2, 'test3')
|
||||
token3 = auth.add_api_token(user2, "test3")
|
||||
self.session.commit()
|
||||
with patch.object(self.request, 'json_body', create=True,
|
||||
new={'uuid': token3.uuid.hex}):
|
||||
with patch.object(
|
||||
self.request,
|
||||
"json_body",
|
||||
create=True,
|
||||
new={"uuid": token3.uuid.hex},
|
||||
):
|
||||
result = view.delete_api_token()
|
||||
self.assertEqual(result, {'error': "API token not found"})
|
||||
self.assertEqual(result, {"error": "API token not found"})
|
||||
|
||||
# token not found
|
||||
with patch.object(self.request, 'json_body', create=True,
|
||||
new={'uuid': self.app.make_true_uuid().hex}):
|
||||
with patch.object(
|
||||
self.request,
|
||||
"json_body",
|
||||
create=True,
|
||||
new={"uuid": self.app.make_true_uuid().hex},
|
||||
):
|
||||
result = view.delete_api_token()
|
||||
self.assertEqual(result, {'error': "API token not found"})
|
||||
self.assertEqual(result, {"error": "API token not found"})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue