3
0
Fork 0

fix: format all code with black

and from now on should not deviate from that...
This commit is contained in:
Lance Edgar 2025-08-31 12:26:43 -05:00
parent 8a09fb1a3c
commit 4d0693862d
68 changed files with 6693 additions and 5659 deletions

View file

@ -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")

View file

@ -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"])

View file

@ -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)

View file

@ -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)

View file

@ -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])

View file

@ -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")

View file

@ -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

View file

@ -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)

View file

@ -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!")

View file

@ -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"))

View file

@ -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)

View file

@ -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"))

View file

@ -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

View file

@ -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"})