| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | # -*- coding: utf-8; -*- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  | import datetime | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  | import decimal | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | import functools | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | from unittest import TestCase | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | from unittest.mock import MagicMock, patch | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 14:05:10 -05:00
										 |  |  | from sqlalchemy import orm | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | from pyramid import testing | 
					
						
							|  |  |  | from pyramid.response import Response | 
					
						
							| 
									
										
										
										
											2024-08-15 02:10:08 -05:00
										 |  |  | from pyramid.httpexceptions import HTTPNotFound | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | from wuttjamaican.conf import WuttaConfig | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  | from wuttaweb.views import master as mod | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  | from wuttaweb.views import View | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  | from wuttaweb.progress import SessionProgress | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | from wuttaweb.subscribers import new_request_set_user | 
					
						
							| 
									
										
										
										
											2025-10-29 18:32:35 -05:00
										 |  |  | from wuttaweb.testing import WebTestCase, VersionWebTestCase | 
					
						
							|  |  |  | from wuttaweb.grids import Grid | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | class TestMasterView(WebTestCase): | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-13 16:29:34 -05:00
										 |  |  |     def make_view(self): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         return mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-13 16:29:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     def test_defaults(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="Widget", | 
					
						
							|  |  |  |             model_key="uuid", | 
					
						
							|  |  |  |             deletable_bulk=True, | 
					
						
							|  |  |  |             has_autocomplete=True, | 
					
						
							|  |  |  |             downloadable=True, | 
					
						
							|  |  |  |             executable=True, | 
					
						
							|  |  |  |             configurable=True, | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ############################## | 
					
						
							|  |  |  |     # class methods | 
					
						
							|  |  |  |     ############################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_model_class(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # no model class by default | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertIsNone(mod.MasterView.get_model_class()) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify | 
					
						
							|  |  |  |         MyModel = MagicMock() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertIs(mod.MasterView.get_model_class(), MyModel) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_model_name(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_model_name) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Widget"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_model_name(), "Widget") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Blaster") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_model_name(), "Blaster") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_model_name_normalized(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_model_name_normalized) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify *normalized* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name_normalized="widget" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_model_name_normalized(), "widget") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *standard* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Blaster"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_model_name_normalized(), "blaster") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Dinosaur") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_model_name_normalized(), "dinosaur") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_model_title(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_model_title) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify  model title | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_title="Wutta Widget"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title(), "Wutta Widget") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Blaster"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title(), "Blaster") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Dinosaur") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title(), "Dinosaur") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_model_title_plural(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_model_title_plural) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify *plural* model title | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_title_plural="People"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title_plural(), "People") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *singular* model title | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_title="Wutta Widget"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title_plural(), "Wutta Widgets") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Blaster"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title_plural(), "Blasters") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Dinosaur") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_model_title_plural(), "Dinosaurs") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |     def test_get_model_key(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_model_key) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify model key | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_key="uuid"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_model_key(), ("uuid",)) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     def test_get_route_prefix(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_route_prefix) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify route prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, route_prefix="widgets"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_route_prefix(), "widgets") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify *normalized* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name_normalized="blaster" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_route_prefix(), "blasters") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *standard* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Dinosaur"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_route_prefix(), "dinosaurs") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Truck") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_route_prefix(), "trucks") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  |     def test_get_permission_prefix(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_permission_prefix) | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify permission prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             mod.MasterView, "permission_prefix", new="widgets", create=True | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_permission_prefix(), "widgets") | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify route prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object(mod.MasterView, "route_prefix", new="widgets", create=True): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_permission_prefix(), "widgets") | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         Truck = MagicMock(__name__="Truck") | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=Truck, create=True): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_permission_prefix(), "trucks") | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     def test_get_url_prefix(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_url_prefix) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify url prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, url_prefix="/widgets"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_url_prefix(), "/widgets") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify route prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, route_prefix="trucks"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_url_prefix(), "/trucks") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *normalized* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name_normalized="blaster" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_url_prefix(), "/blasters") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *standard* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Dinosaur"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_url_prefix(), "/dinosaurs") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Machine") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_url_prefix(), "/machines") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |     def test_get_instance_url_prefix(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_instance_url_prefix) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # typical example with url_prefix and simple key | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, url_prefix="/widgets", model_key="uuid" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual( | 
					
						
							|  |  |  |                 mod.MasterView.get_instance_url_prefix(), "/widgets/{uuid}" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # typical example with composite key | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, url_prefix="/widgets", model_key=("foo", "bar") | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual( | 
					
						
							|  |  |  |                 mod.MasterView.get_instance_url_prefix(), "/widgets/{foo}|{bar}" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     def test_get_template_prefix(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_template_prefix) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify template prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, template_prefix="/widgets"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_template_prefix(), "/widgets") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify url prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, url_prefix="/trees"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_template_prefix(), "/trees") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify route prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, route_prefix="trucks"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_template_prefix(), "/trucks") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *normalized* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name_normalized="blaster" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_template_prefix(), "/blasters") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *standard* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Dinosaur"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_template_prefix(), "/dinosaurs") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Machine") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_template_prefix(), "/machines") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  |     def test_get_grid_key(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_grid_key) | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify grid key | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, grid_key="widgets"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_grid_key(), "widgets") | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify route prefix | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, route_prefix="trucks"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_grid_key(), "trucks") | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *normalized* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name_normalized="blaster" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_grid_key(), "blasters") | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *standard* model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Dinosaur"): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_grid_key(), "dinosaurs") | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Machine") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							|  |  |  |             self.assertEqual(mod.MasterView.get_grid_key(), "machines") | 
					
						
							| 
									
										
										
										
											2024-08-07 14:00:53 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  |     def test_get_config_title(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # error by default (since no model class) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertRaises(AttributeError, mod.MasterView.get_config_title) | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify config title | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, config_title="Widgets"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_config_title(), "Widgets") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # subclass may specify *plural* model title | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_title_plural="People"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_config_title(), "People") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify *singular* model title | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_title="Wutta Widget"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_config_title(), "Wutta Widgets") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model name | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Blaster"): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_config_title(), "Blasters") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # or it may specify model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         MyModel = MagicMock(__name__="Dinosaur") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=MyModel): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             self.assertEqual(mod.MasterView.get_config_title(), "Dinosaurs") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |     def test_get_row_model_class(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no default | 
					
						
							|  |  |  |         self.assertIsNone(mod.MasterView.get_row_model_class()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # class may specify | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             mod.MasterView, "row_model_class", create=True, new=model.User | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |             self.assertIs(mod.MasterView.get_row_model_class(), model.User) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     ############################## | 
					
						
							|  |  |  |     # support methods | 
					
						
							|  |  |  |     ############################## | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  |     def test_get_class_hierarchy(self): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         class MyView(mod.MasterView): | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         view = MyView(self.request) | 
					
						
							|  |  |  |         classes = view.get_class_hierarchy() | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         self.assertEqual(classes, [View, mod.MasterView, MyView]) | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |     def test_has_perm(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         auth = self.app.get_auth_handler() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Setting"): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # anonymous user | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertFalse(view.has_perm("list")) | 
					
						
							|  |  |  |             self.assertFalse(self.request.has_perm("list")) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # reset | 
					
						
							|  |  |  |             del self.request.user_permissions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # make user with perms | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             barney = model.User(username="barney") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             self.session.add(barney) | 
					
						
							|  |  |  |             blokes = model.Role(name="Blokes") | 
					
						
							|  |  |  |             self.session.add(blokes) | 
					
						
							|  |  |  |             barney.roles.append(blokes) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             auth.grant_permission(blokes, "settings.list") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # this user has perms | 
					
						
							|  |  |  |             self.request.user = barney | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertTrue(view.has_perm("list")) | 
					
						
							|  |  |  |             self.assertTrue(self.request.has_perm("settings.list")) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_has_any_perm(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         auth = self.app.get_auth_handler() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Setting"): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # anonymous user | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertFalse(view.has_any_perm("list", "view")) | 
					
						
							|  |  |  |             self.assertFalse( | 
					
						
							|  |  |  |                 self.request.has_any_perm("settings.list", "settings.view") | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # reset | 
					
						
							|  |  |  |             del self.request.user_permissions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # make user with perms | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             barney = model.User(username="barney") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             self.session.add(barney) | 
					
						
							|  |  |  |             blokes = model.Role(name="Blokes") | 
					
						
							|  |  |  |             self.session.add(blokes) | 
					
						
							|  |  |  |             barney.roles.append(blokes) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             auth.grant_permission(blokes, "settings.view") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # this user has perms | 
					
						
							|  |  |  |             self.request.user = barney | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertTrue(view.has_any_perm("list", "view")) | 
					
						
							|  |  |  |             self.assertTrue(self.request.has_any_perm("settings.list", "settings.view")) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |     def test_make_button(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # normal | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         html = view.make_button("click me") | 
					
						
							|  |  |  |         self.assertIn("<b-button ", html) | 
					
						
							|  |  |  |         self.assertIn("click me", html) | 
					
						
							|  |  |  |         self.assertNotIn("is-primary", html) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # primary as primary | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         html = view.make_button("click me", primary=True) | 
					
						
							|  |  |  |         self.assertIn("<b-button ", html) | 
					
						
							|  |  |  |         self.assertIn("click me", html) | 
					
						
							|  |  |  |         self.assertIn("is-primary", html) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # primary as variant | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         html = view.make_button("click me", variant="is-primary") | 
					
						
							|  |  |  |         self.assertIn("<b-button ", html) | 
					
						
							|  |  |  |         self.assertIn("click me", html) | 
					
						
							|  |  |  |         self.assertIn("is-primary", html) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # primary as type | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         html = view.make_button("click me", type="is-primary") | 
					
						
							|  |  |  |         self.assertIn("<b-button ", html) | 
					
						
							|  |  |  |         self.assertIn("click me", html) | 
					
						
							|  |  |  |         self.assertIn("is-primary", html) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-02 22:35:43 -06:00
										 |  |  |         # with url | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         html = view.make_button("click me", url="http://example.com") | 
					
						
							| 
									
										
										
										
											2025-01-02 22:35:43 -06:00
										 |  |  |         self.assertIn('<b-button tag="a"', html) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.assertIn("click me", html) | 
					
						
							| 
									
										
										
										
											2025-01-02 22:35:43 -06:00
										 |  |  |         self.assertIn('href="http://example.com"', html) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |     def test_make_progress(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # basic | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.request.session.id = "mockid" | 
					
						
							|  |  |  |         progress = view.make_progress("foo") | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |         self.assertIsInstance(progress, SessionProgress) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_render_progress(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.add_route("progress", "/progress/{key}") | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # sanity / coverage check | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         progress = MagicMock() | 
					
						
							|  |  |  |         response = view.render_progress(progress) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     def test_render_to_response(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("appinfo", "/appinfo/") | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         def widgets(request): | 
					
						
							|  |  |  |             return {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.pyramid_config.add_route("widgets", "/widgets/") | 
					
						
							|  |  |  |         self.pyramid_config.add_view(widgets, route_name="widgets") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |         # basic sanity check using /master/index.mako | 
					
						
							|  |  |  |         # (nb. it skips /widgets/index.mako since that doesn't exist) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name="Widget", creatable=False | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             response = view.render_to_response("index", {}) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |             self.assertIsInstance(response, Response) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # basic sanity check using /appinfo/index.mako | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="AppInfo", | 
					
						
							|  |  |  |             route_prefix="appinfo", | 
					
						
							|  |  |  |             url_prefix="/appinfo", | 
					
						
							|  |  |  |             creatable=False, | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             response = view.render_to_response( | 
					
						
							|  |  |  |                 "index", | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     # nb. grid is required for this template | 
					
						
							|  |  |  |                     "grid": MagicMock(), | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |             self.assertIsInstance(response, Response) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # bad template name causes error | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Widget"): | 
					
						
							|  |  |  |             self.assertRaises(IOError, view.render_to_response, "nonexistent", {}) | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |     def test_get_index_title(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_title_plural="Wutta Widgets" | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							|  |  |  |             self.assertEqual(view.get_index_title(), "Wutta Widgets") | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 19:57:26 -05:00
										 |  |  |     def test_get_index_url(self): | 
					
						
							|  |  |  |         self.pyramid_config.add_route("widgets", "/widgets") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_name="Widget"): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # normal | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             self.assertEqual(view.get_index_url(), "http://example.com/widgets") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # list/index not supported | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             view.listable = False | 
					
						
							|  |  |  |             self.assertIsNone(view.get_index_url()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  |     def test_collect_labels(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no labels by default | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         labels = view.collect_labels() | 
					
						
							|  |  |  |         self.assertEqual(labels, {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # labels come from all classes; subclass wins | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             View, "labels", new={"foo": "Foo", "bar": "Bar"}, create=True | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             with patch.object( | 
					
						
							|  |  |  |                 mod.MasterView, "labels", new={"foo": "FOO FIGHTERS"}, create=True | 
					
						
							|  |  |  |             ): | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 labels = view.collect_labels() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(labels, {"foo": "FOO FIGHTERS", "bar": "Bar"}) | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_set_labels(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             mod.MasterView, "model_class", new=model.Setting, create=True | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # no labels by default | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             view.set_labels(grid) | 
					
						
							|  |  |  |             self.assertEqual(grid.labels, {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # labels come from all classes; subclass wins | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object( | 
					
						
							|  |  |  |                 mod.MasterView, "labels", new={"name": "SETTING NAME"}, create=True | 
					
						
							|  |  |  |             ): | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 view.set_labels(grid) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(grid.labels, {"name": "SETTING NAME"}) | 
					
						
							| 
									
										
										
										
											2024-08-15 20:51:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |     def test_make_model_grid(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.add_route("settings.delete_bulk", "/settings/delete-bulk") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name="Widget", model_key="uuid" | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             grid = view.make_model_grid() | 
					
						
							|  |  |  |             self.assertIsNone(grid.model_class) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # explicit model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertIs(grid.model_class, model.Setting) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-23 14:14:41 -05:00
										 |  |  |         # no row class by default | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-23 14:14:41 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertIsNone(grid.row_class) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # can specify row class | 
					
						
							|  |  |  |         get_row_class = MagicMock() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_class=model.Setting, | 
					
						
							|  |  |  |             grid_row_class=get_row_class, | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-23 14:14:41 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertIs(grid.row_class, get_row_class) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |         # no actions by default | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertEqual(grid.actions, []) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # now let's test some more actions logic | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_class=model.Setting, | 
					
						
							|  |  |  |             viewable=True, | 
					
						
							|  |  |  |             editable=True, | 
					
						
							|  |  |  |             deletable=True, | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # should have 3 actions now, but for lack of perms | 
					
						
							|  |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertEqual(len(grid.actions), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # but root user has perms, so gets 3 actions | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(self.request, "is_root", new=True): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |                 grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertEqual(len(grid.actions), 3) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         # no tools by default | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertEqual(grid.tools, {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # delete-results tool added if master/perms allow | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_class=model.Setting, deletable_bulk=True | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             with patch.object(self.request, "is_root", new=True): | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |                 grid = view.make_model_grid(session=self.session) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertIn("delete-results", grid.tools) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  |     def test_get_grid_data(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo", "bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  |         self.session.commit() | 
					
						
							| 
									
										
										
										
											2024-08-14 16:58:08 -05:00
										 |  |  |         setting = self.session.query(model.Setting).one() | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # empty by default | 
					
						
							| 
									
										
										
										
											2025-09-01 12:10:12 -05:00
										 |  |  |         self.assertIsNone(mod.MasterView.model_class) | 
					
						
							| 
									
										
										
										
											2024-08-14 16:58:08 -05:00
										 |  |  |         data = view.get_grid_data(session=self.session) | 
					
						
							|  |  |  |         self.assertEqual(data, []) | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-18 14:05:10 -05:00
										 |  |  |         # grid with model class will produce data query | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-18 14:05:10 -05:00
										 |  |  |             query = view.get_grid_data(session=self.session) | 
					
						
							|  |  |  |             self.assertIsInstance(query, orm.Query) | 
					
						
							|  |  |  |             data = query.all() | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  |             self.assertEqual(len(data), 1) | 
					
						
							| 
									
										
										
										
											2024-08-14 16:58:08 -05:00
										 |  |  |             self.assertIs(data[0], setting) | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-12 21:17:08 -05:00
										 |  |  |     def test_configure_grid(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # uuid field is pruned | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             grid = view.make_grid( | 
					
						
							|  |  |  |                 model_class=model.Setting, columns=["uuid", "name", "value"] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             self.assertIn("uuid", grid.columns) | 
					
						
							| 
									
										
										
										
											2024-08-12 21:17:08 -05:00
										 |  |  |             view.configure_grid(grid) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertNotIn("uuid", grid.columns) | 
					
						
							| 
									
										
										
										
											2024-08-12 21:17:08 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |     def test_grid_render_bool(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         user = model.User(username="barney", active=None) | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # null | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_bool(user, "active", None) | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |         self.assertIsNone(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # true | 
					
						
							|  |  |  |         user.active = True | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_bool(user, "active", True) | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |         self.assertEqual(value, "Yes") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # false | 
					
						
							|  |  |  |         user.active = False | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_bool(user, "active", False) | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |         self.assertEqual(value, "No") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_grid_render_currency(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj = {"amount": None} | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # null | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_currency(obj, "amount", None) | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |         self.assertIsNone(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # normal amount | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj["amount"] = decimal.Decimal("100.42") | 
					
						
							|  |  |  |         value = view.grid_render_currency(obj, "amount", "100.42") | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |         self.assertEqual(value, "$100.42") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # negative amount | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj["amount"] = decimal.Decimal("-100.42") | 
					
						
							|  |  |  |         value = view.grid_render_currency(obj, "amount", "-100.42") | 
					
						
							| 
									
										
										
										
											2024-08-23 19:23:40 -05:00
										 |  |  |         self.assertEqual(value, "($100.42)") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  |     def test_grid_render_datetime(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj = {"dt": None} | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # null | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_datetime(obj, "dt", None) | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  |         self.assertIsNone(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # normal | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj["dt"] = datetime.datetime(2024, 8, 24, 11) | 
					
						
							|  |  |  |         value = view.grid_render_datetime(obj, "dt", "2024-08-24T11:00:00") | 
					
						
							|  |  |  |         self.assertEqual(value, "2024-08-24 11:00:00 AM") | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_grid_render_enum(self): | 
					
						
							|  |  |  |         enum = self.app.enum | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj = {"status": None} | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # null | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_enum(obj, "status", None, enum=enum.UpgradeStatus) | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  |         self.assertIsNone(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # normal | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         obj["status"] = enum.UpgradeStatus.SUCCESS | 
					
						
							|  |  |  |         value = view.grid_render_enum(obj, "status", "SUCCESS", enum=enum.UpgradeStatus) | 
					
						
							|  |  |  |         self.assertEqual(value, "SUCCESS") | 
					
						
							| 
									
										
										
										
											2024-08-24 11:29:52 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-13 16:29:34 -05:00
										 |  |  |     def test_grid_render_notes(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # null | 
					
						
							|  |  |  |         text = None | 
					
						
							|  |  |  |         role = model.Role(name="Foo", notes=text) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_notes(role, "notes", text) | 
					
						
							| 
									
										
										
										
											2024-08-13 16:29:34 -05:00
										 |  |  |         self.assertIsNone(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # short string | 
					
						
							|  |  |  |         text = "hello world" | 
					
						
							|  |  |  |         role = model.Role(name="Foo", notes=text) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_notes(role, "notes", text) | 
					
						
							| 
									
										
										
										
											2024-08-13 16:29:34 -05:00
										 |  |  |         self.assertEqual(value, text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # long string | 
					
						
							|  |  |  |         text = "hello world " * 20 | 
					
						
							|  |  |  |         role = model.Role(name="Foo", notes=text) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         value = view.grid_render_notes(role, "notes", text) | 
					
						
							|  |  |  |         self.assertIn("<span ", value) | 
					
						
							| 
									
										
										
										
											2024-08-13 16:29:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |     def test_get_instance(self): | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo", "bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         self.assertEqual(self.session.query(model.Setting).count(), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # default not implemented | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |         self.assertRaises(NotImplementedError, view.get_instance) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |         # fetch from DB if model class is known | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # existing setting is returned | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.matchdict = {"name": "foo"} | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             setting = view.get_instance(session=self.session) | 
					
						
							|  |  |  |             self.assertIsInstance(setting, model.Setting) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(setting.name, "foo") | 
					
						
							|  |  |  |             self.assertEqual(setting.value, "bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # missing setting not found | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.matchdict = {"name": "blarg"} | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             self.assertRaises(HTTPNotFound, view.get_instance, session=self.session) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  |     def test_get_action_route_kwargs(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             mod.MasterView, "model_class", new=model.Setting, create=True | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # dict object | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             setting = {"name": "foo", "value": "bar"} | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  |             kw = view.get_action_route_kwargs(setting) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(kw, {"name": "foo"}) | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # mapped object | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             setting = model.Setting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  |             kw = view.get_action_route_kwargs(setting) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(kw, {"name": "foo"}) | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # non-standard object | 
					
						
							|  |  |  |             class MySetting: | 
					
						
							|  |  |  |                 def __init__(self, **kw): | 
					
						
							|  |  |  |                     self.__dict__.update(kw) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             setting = MySetting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  |             kw = view.get_action_route_kwargs(setting) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(kw, {"name": "foo"}) | 
					
						
							| 
									
										
										
										
											2025-01-14 11:49:47 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  |     def test_get_action_url_for_dict(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         setting = {"name": "foo", "value": "bar"} | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             url = view.get_action_url_view(setting, 0) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(url, self.request.route_url("settings.view", name="foo")) | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_action_url_for_orm_object(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         setting = model.Setting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  |         self.session.add(setting) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             url = view.get_action_url_view(setting, 0) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(url, self.request.route_url("settings.view", name="foo")) | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_action_url_for_adhoc_object(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  |         class MockSetting: | 
					
						
							|  |  |  |             def __init__(self, **kw): | 
					
						
							|  |  |  |                 self.__dict__.update(kw) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         setting = MockSetting(name="foo", value="bar") | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             url = view.get_action_url_view(setting, 0) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(url, self.request.route_url("settings.view", name="foo")) | 
					
						
							| 
									
										
										
										
											2024-11-25 19:11:41 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |     def test_get_action_url_view(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         setting = model.Setting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |         self.session.add(setting) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             url = view.get_action_url_view(setting, 0) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(url, self.request.route_url("settings.view", name="foo")) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_action_url_edit(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         setting = model.Setting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |         self.session.add(setting) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # typical | 
					
						
							|  |  |  |             url = view.get_action_url_edit(setting, 0) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(url, self.request.route_url("settings.edit", name="foo")) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # but null if instance not editable | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "is_editable", return_value=False): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |                 url = view.get_action_url_edit(setting, 0) | 
					
						
							|  |  |  |                 self.assertIsNone(url) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_action_url_delete(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         setting = model.Setting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |         self.session.add(setting) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # typical | 
					
						
							|  |  |  |             url = view.get_action_url_delete(setting, 0) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(url, self.request.route_url("settings.delete", name="foo")) | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # but null if instance not deletable | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "is_deletable", return_value=False): | 
					
						
							| 
									
										
										
										
											2024-08-14 21:20:00 -05:00
										 |  |  |                 url = view.get_action_url_delete(setting, 0) | 
					
						
							|  |  |  |                 self.assertIsNone(url) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |     def test_make_model_form(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name="Widget", model_key="uuid" | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             form = view.make_model_form() | 
					
						
							|  |  |  |             self.assertIsNone(form.model_class) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # explicit model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             form = view.make_model_form() | 
					
						
							|  |  |  |             self.assertIs(form.model_class, model.Setting) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  |     def test_configure_form(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # uuid field is pruned | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             form = view.make_form( | 
					
						
							|  |  |  |                 model_class=model.Setting, fields=["uuid", "name", "value"] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             self.assertIn("uuid", form.fields) | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  |             view.configure_form(form) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertNotIn("uuid", form.fields) | 
					
						
							| 
									
										
										
										
											2024-08-11 18:21:02 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |     def test_objectify(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo", "bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         self.assertEqual(self.session.query(model.Setting).count(), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no model class | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_name="Widget", model_key="uuid" | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             form = view.make_model_form(fields=["name", "description"]) | 
					
						
							|  |  |  |             form.validated = {"name": "first"} | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             obj = view.objectify(form) | 
					
						
							|  |  |  |             self.assertIs(obj, form.validated) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # explicit model class (editing) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_class=model.Setting, editing=True | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             form = view.make_model_form() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             form.validated = {"name": "foo", "value": "blarg"} | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             form.model_instance = self.session.query(model.Setting).one() | 
					
						
							|  |  |  |             obj = view.objectify(form) | 
					
						
							|  |  |  |             self.assertIsInstance(obj, model.Setting) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(obj.name, "foo") | 
					
						
							|  |  |  |             self.assertEqual(obj.value, "blarg") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # explicit model class (creating) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_class=model.Setting, creating=True | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             form = view.make_model_form() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             form.validated = {"name": "another", "value": "whatever"} | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             obj = view.objectify(form) | 
					
						
							|  |  |  |             self.assertIsInstance(obj, model.Setting) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(obj.name, "another") | 
					
						
							|  |  |  |             self.assertEqual(obj.value, "whatever") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_persist(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # new instance is persisted | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             setting = model.Setting(name="foo", value="bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 0) | 
					
						
							|  |  |  |             view.persist(setting, session=self.session) | 
					
						
							|  |  |  |             self.session.commit() | 
					
						
							|  |  |  |             setting = self.session.query(model.Setting).one() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(setting.name, "foo") | 
					
						
							|  |  |  |             self.assertEqual(setting.value, "bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 19:21:58 -05:00
										 |  |  |     ############################## | 
					
						
							|  |  |  |     # view methods | 
					
						
							|  |  |  |     ############################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_index(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.create", "/settings/new") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.view", "/settings/{name}") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.edit", "/settings/{name}/edit") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.delete", "/settings/{name}/delete") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |         # sanity/coverage check using /settings/ | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="Setting", | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             get_index_url=MagicMock(return_value="/settings/"), | 
					
						
							|  |  |  |             grid_columns=["name", "value"], | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |             response = view.index() | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # then again with data, to include view action url | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             data = [{"name": "foo", "value": "bar"}] | 
					
						
							|  |  |  |             with patch.object(view, "get_grid_data", return_value=data): | 
					
						
							| 
									
										
										
										
											2024-08-14 15:10:54 -05:00
										 |  |  |                 response = view.index() | 
					
						
							| 
									
										
										
										
											2024-08-16 22:52:24 -05:00
										 |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(response.content_type, "text/html") | 
					
						
							| 
									
										
										
										
											2024-08-16 22:52:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # then once more as 'partial' - aka. data only | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.request.GET = {"partial": "1"} | 
					
						
							| 
									
										
										
										
											2024-08-16 22:52:24 -05:00
										 |  |  |                 response = view.index() | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(response.content_type, "application/json") | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 13:50:29 -05:00
										 |  |  |                 # redirects when view is reset | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.request.GET = {"reset-view": "1", "hash": "foo"} | 
					
						
							|  |  |  |                 with patch.object(self.request, "current_route_url"): | 
					
						
							| 
									
										
										
										
											2024-08-22 13:50:29 -05:00
										 |  |  |                     response = view.index() | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 302) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |     def test_create(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.view", "/settings/{name}") | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # sanity/coverage check using /settings/new | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="Setting", | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             get_index_url=MagicMock(return_value="/settings/"), | 
					
						
							|  |  |  |             form_fields=["name", "value"], | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # no setting yet | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertIsNone(self.app.get_setting(self.session, "foo.bar")) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # get the form page | 
					
						
							|  |  |  |             response = view.create() | 
					
						
							|  |  |  |             self.assertIsInstance(response, Response) | 
					
						
							|  |  |  |             self.assertEqual(response.status_code, 200) | 
					
						
							|  |  |  |             # self.assertIn('frazzle', response.text) | 
					
						
							|  |  |  |             # nb. no error | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertNotIn("Required", response.text) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             def persist(setting): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.app.save_setting(self.session, setting["name"], setting["value"]) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |                 self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # post request to save setting | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.method = "POST" | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |             self.request.POST = { | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 "name": "foo.bar", | 
					
						
							|  |  |  |                 "value": "fraggle", | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "persist", new=persist): | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |                 response = view.create() | 
					
						
							|  |  |  |             # nb. should get redirect back to view page | 
					
						
							|  |  |  |             self.assertEqual(response.status_code, 302) | 
					
						
							|  |  |  |             # setting should now be in DB | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(self.app.get_setting(self.session, "foo.bar"), "fraggle") | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # try another post with invalid data (value is required) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.method = "POST" | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |             self.request.POST = {} | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "persist", new=persist): | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |                 response = view.create() | 
					
						
							|  |  |  |             # nb. should get a form with errors | 
					
						
							|  |  |  |             self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertIn("Required", response.text) | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  |             # setting did not change in DB | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual(self.app.get_setting(self.session, "foo.bar"), "fraggle") | 
					
						
							| 
									
										
										
										
											2024-08-11 12:41:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  |     def test_view(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.create", "/settings/new") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.edit", "/settings/{name}/edit") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.delete", "/settings/{name}/delete") | 
					
						
							| 
									
										
										
										
											2024-08-07 19:47:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # sanity/coverage check using /settings/XXX | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         setting = {"name": "foo.bar", "value": "baz"} | 
					
						
							|  |  |  |         self.request.matchdict = {"name": "foo.bar"} | 
					
						
							|  |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="Setting", | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             get_index_url=MagicMock(return_value="/settings/"), | 
					
						
							|  |  |  |             grid_columns=["name", "value"], | 
					
						
							|  |  |  |             form_fields=["name", "value"], | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "get_instance", return_value=setting): | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                 response = view.view() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |     def test_view_with_rows(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("people", "/people/") | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  |         person = model.Person(full_name="Whitney Houston") | 
					
						
							|  |  |  |         self.session.add(person) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         user = model.User(username="whitney", person=person) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |         self.session.add(user) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         get_row_grid_data = MagicMock() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             Session=MagicMock(return_value=self.session), | 
					
						
							|  |  |  |             model_class=model.Person, | 
					
						
							|  |  |  |             route_prefix="people", | 
					
						
							|  |  |  |             has_rows=True, | 
					
						
							|  |  |  |             row_model_class=model.User, | 
					
						
							|  |  |  |             get_row_grid_data=get_row_grid_data, | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             with patch.object(self.request, "matchdict", new={"uuid": person.uuid}): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                 view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # just for coverage | 
					
						
							|  |  |  |                 get_row_grid_data.return_value = [] | 
					
						
							|  |  |  |                 response = view.view() | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(response.content_type, "text/html") | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # now with data... | 
					
						
							|  |  |  |                 get_row_grid_data.return_value = [user] | 
					
						
							|  |  |  |                 response = view.view() | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(response.content_type, "text/html") | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # then once more as 'partial' - aka. data only | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 with patch.dict(self.request.GET, {"partial": 1}): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                     response = view.view() | 
					
						
							|  |  |  |                     self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     self.assertEqual(response.content_type, "application/json") | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # redirects when view is reset | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 with patch.dict(self.request.GET, {"reset-view": "1", "hash": "foo"}): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                     # nb. mock current route | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     with patch.object(self.request, "current_route_url"): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                         response = view.view() | 
					
						
							|  |  |  |                         self.assertEqual(response.status_code, 302) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |     def test_edit(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.create", "/settings/new") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.view", "/settings/{name}") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.delete", "/settings/{name}/delete") | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo.bar", "frazzle") | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def get_instance(): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             setting = self.session.get(model.Setting, "foo.bar") | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |             return { | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 "name": setting.name, | 
					
						
							|  |  |  |                 "value": setting.value, | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # sanity/coverage check using /settings/XXX/edit | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.request.matchdict = {"name": "foo.bar"} | 
					
						
							|  |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="Setting", | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             get_index_url=MagicMock(return_value="/settings/"), | 
					
						
							|  |  |  |             form_fields=["name", "value"], | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "get_instance", new=get_instance): | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # get the form page | 
					
						
							|  |  |  |                 response = view.edit() | 
					
						
							|  |  |  |                 self.assertIsInstance(response, Response) | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertIn("frazzle", response.text) | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                 # nb. no error | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertNotIn("Required", response.text) | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 def persist(setting): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     self.app.save_setting(self.session, "foo.bar", setting["value"]) | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                     self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # post request to save settings | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.request.method = "POST" | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                 self.request.POST = { | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     "name": "foo.bar", | 
					
						
							|  |  |  |                     "value": "froogle", | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 with patch.object(view, "persist", new=persist): | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                     response = view.edit() | 
					
						
							|  |  |  |                 # nb. should get redirect back to view page | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |                 self.assertEqual(response.status_code, 302) | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                 # setting should be updated in DB | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual( | 
					
						
							|  |  |  |                     self.app.get_setting(self.session, "foo.bar"), "froogle" | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |                 # try another post with invalid data (value is required) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.request.method = "POST" | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |                 self.request.POST = {} | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 with patch.object(view, "persist", new=persist): | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                     response = view.edit() | 
					
						
							|  |  |  |                 # nb. should get a form with errors | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertIn("Required", response.text) | 
					
						
							| 
									
										
										
										
											2024-08-10 21:07:38 -05:00
										 |  |  |                 # setting did not change in DB | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual( | 
					
						
							|  |  |  |                     self.app.get_setting(self.session, "foo.bar"), "froogle" | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |     def test_delete(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.create", "/settings/new") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.view", "/settings/{name}") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("settings.edit", "/settings/{name}/edit") | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo.bar", "frazzle") | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         self.assertEqual(self.session.query(model.Setting).count(), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def get_instance(): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             setting = self.session.get(model.Setting, "foo.bar") | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |             return { | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 "name": setting.name, | 
					
						
							|  |  |  |                 "value": setting.value, | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # sanity/coverage check using /settings/XXX/delete | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.request.matchdict = {"name": "foo.bar"} | 
					
						
							|  |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_name="Setting", | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             get_index_url=MagicMock(return_value="/settings/"), | 
					
						
							|  |  |  |             form_fields=["name", "value"], | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "get_instance", new=get_instance): | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # get the form page | 
					
						
							|  |  |  |                 response = view.delete() | 
					
						
							|  |  |  |                 self.assertIsInstance(response, Response) | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertIn("frazzle", response.text) | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 def delete_instance(setting): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     self.app.delete_setting(self.session, setting["name"]) | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.request.method = "POST" | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |                 self.request.POST = {} | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 with patch.object(view, "delete_instance", new=delete_instance): | 
					
						
							| 
									
										
										
										
											2024-08-14 16:58:08 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     # enforces "instance not deletable" rules | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     with patch.object(view, "is_deletable", return_value=False): | 
					
						
							| 
									
										
										
										
											2024-08-14 16:58:08 -05:00
										 |  |  |                         response = view.delete() | 
					
						
							|  |  |  |                     # nb. should get redirect back to view page | 
					
						
							|  |  |  |                     self.assertEqual(response.status_code, 302) | 
					
						
							|  |  |  |                     # setting remains in DB | 
					
						
							|  |  |  |                     self.assertEqual(self.session.query(model.Setting).count(), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # post request to delete setting | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |                     response = view.delete() | 
					
						
							| 
									
										
										
										
											2024-08-14 16:58:08 -05:00
										 |  |  |                     # nb. should get redirect back to view page | 
					
						
							|  |  |  |                     self.assertEqual(response.status_code, 302) | 
					
						
							|  |  |  |                     # setting should be gone from DB | 
					
						
							|  |  |  |                     self.assertEqual(self.session.query(model.Setting).count(), 0) | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_delete_instance(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo.bar", "frazzle") | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         setting = self.session.query(model.Setting).one() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_class=model.Setting, | 
					
						
							|  |  |  |             form_fields=["name", "value"], | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2024-08-11 16:52:13 -05:00
										 |  |  |             view.delete_instance(setting) | 
					
						
							|  |  |  |             self.session.commit() | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 0) | 
					
						
							| 
									
										
										
										
											2024-08-11 09:56:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |     def test_delete_bulk(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.add_route("settings", "/settings/") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("progress", "/progress/{key}") | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  |         sample_data = [ | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             {"name": "foo1", "value": "ONE"}, | 
					
						
							|  |  |  |             {"name": "foo2", "value": "two"}, | 
					
						
							|  |  |  |             {"name": "foo3", "value": "three"}, | 
					
						
							|  |  |  |             {"name": "foo4", "value": "four"}, | 
					
						
							|  |  |  |             {"name": "foo5", "value": "five"}, | 
					
						
							|  |  |  |             {"name": "foo6", "value": "six"}, | 
					
						
							|  |  |  |             {"name": "foo7", "value": "seven"}, | 
					
						
							|  |  |  |             {"name": "foo8", "value": "eight"}, | 
					
						
							|  |  |  |             {"name": "foo9", "value": "nine"}, | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         ] | 
					
						
							|  |  |  |         for setting in sample_data: | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.app.save_setting(self.session, setting["name"], setting["value"]) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         sample_query = self.session.query(model.Setting) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # sanity check on sample data | 
					
						
							|  |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             data = grid.get_visible_data() | 
					
						
							|  |  |  |             self.assertEqual(len(data), 9) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # and then let's filter it a little | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.GET = {"value": "s", "value.verb": "contains"} | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertEqual(len(grid.filters), 2) | 
					
						
							|  |  |  |             self.assertEqual(len(grid.active_filters), 1) | 
					
						
							|  |  |  |             data = grid.get_visible_data() | 
					
						
							|  |  |  |             self.assertEqual(len(data), 2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             # okay now let's delete those via quick method | 
					
						
							|  |  |  |             # (user should be redirected back to index) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.multiple( | 
					
						
							|  |  |  |                 view, | 
					
						
							|  |  |  |                 deletable_bulk_quick=True, | 
					
						
							|  |  |  |                 make_model_grid=MagicMock(return_value=grid), | 
					
						
							|  |  |  |             ): | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |                 response = view.delete_bulk() | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             self.assertEqual(response.status_code, 302) | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 7) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             # now use another filter since those records are gone | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.GET = {"name": "foo2", "name.verb": "equal"} | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             grid = view.make_model_grid(session=self.session) | 
					
						
							|  |  |  |             self.assertEqual(len(grid.filters), 2) | 
					
						
							|  |  |  |             self.assertEqual(len(grid.active_filters), 1) | 
					
						
							|  |  |  |             data = grid.get_visible_data() | 
					
						
							|  |  |  |             self.assertEqual(len(data), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # this time we delete "slowly" with progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.session.id = "ignorethis" | 
					
						
							|  |  |  |             with patch.multiple( | 
					
						
							|  |  |  |                 view, | 
					
						
							|  |  |  |                 deletable_bulk_quick=False, | 
					
						
							|  |  |  |                 make_model_grid=MagicMock(return_value=grid), | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 with patch.object(mod, "threading") as threading: | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |                     response = view.delete_bulk() | 
					
						
							|  |  |  |                     threading.Thread.return_value.start.assert_called_once_with() | 
					
						
							|  |  |  |             # nb. user is shown progress page | 
					
						
							|  |  |  |             self.assertEqual(response.status_code, 200) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_delete_bulk_action(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.add_route("settings", "/settings/") | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  |         sample_data = [ | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             {"name": "foo1", "value": "ONE"}, | 
					
						
							|  |  |  |             {"name": "foo2", "value": "two"}, | 
					
						
							|  |  |  |             {"name": "foo3", "value": "three"}, | 
					
						
							|  |  |  |             {"name": "foo4", "value": "four"}, | 
					
						
							|  |  |  |             {"name": "foo5", "value": "five"}, | 
					
						
							|  |  |  |             {"name": "foo6", "value": "six"}, | 
					
						
							|  |  |  |             {"name": "foo7", "value": "seven"}, | 
					
						
							|  |  |  |             {"name": "foo8", "value": "eight"}, | 
					
						
							|  |  |  |             {"name": "foo9", "value": "nine"}, | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         ] | 
					
						
							|  |  |  |         for setting in sample_data: | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.app.save_setting(self.session, setting["name"], setting["value"]) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         sample_query = self.session.query(model.Setting) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # basic bulk delete | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 9) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             settings = ( | 
					
						
							|  |  |  |                 self.session.query(model.Setting) | 
					
						
							|  |  |  |                 .filter(model.Setting.value.ilike("%s%")) | 
					
						
							|  |  |  |                 .all() | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             self.assertEqual(len(settings), 2) | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             view.delete_bulk_action(settings) | 
					
						
							| 
									
										
										
										
											2024-08-24 14:26:13 -05:00
										 |  |  |             self.session.commit() | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 7) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 13:31:33 -05:00
										 |  |  |     def test_do_thread_body(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # nb. so far this is just proving coverage, in case caller | 
					
						
							|  |  |  |         # does not specify an error handler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def func(): | 
					
						
							|  |  |  |             raise RuntimeError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # with error handler | 
					
						
							|  |  |  |         onerror = MagicMock() | 
					
						
							|  |  |  |         view.do_thread_body(func, (), {}, onerror) | 
					
						
							|  |  |  |         onerror.assert_called_once_with() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # without error handler | 
					
						
							|  |  |  |         onerror.reset_mock() | 
					
						
							|  |  |  |         view.do_thread_body(func, (), {}) | 
					
						
							|  |  |  |         onerror.assert_not_called() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |     def test_delete_bulk_thread(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.add_route("settings", "/settings/") | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  |         sample_data = [ | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             {"name": "foo1", "value": "ONE"}, | 
					
						
							|  |  |  |             {"name": "foo2", "value": "two"}, | 
					
						
							|  |  |  |             {"name": "foo3", "value": "three"}, | 
					
						
							|  |  |  |             {"name": "foo4", "value": "four"}, | 
					
						
							|  |  |  |             {"name": "foo5", "value": "five"}, | 
					
						
							|  |  |  |             {"name": "foo6", "value": "six"}, | 
					
						
							|  |  |  |             {"name": "foo7", "value": "seven"}, | 
					
						
							|  |  |  |             {"name": "foo8", "value": "eight"}, | 
					
						
							|  |  |  |             {"name": "foo9", "value": "nine"}, | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |         ] | 
					
						
							|  |  |  |         for setting in sample_data: | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.app.save_setting(self.session, setting["name"], setting["value"]) | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  |         sample_query = self.session.query(model.Setting) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Setting): | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # basic delete, no progress | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 9) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             settings = self.session.query(model.Setting).filter( | 
					
						
							|  |  |  |                 model.Setting.value.ilike("%s%") | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             self.assertEqual(settings.count(), 2) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(self.app, "make_session", return_value=self.session): | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |                 view.delete_bulk_thread(settings) | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # basic delete, with progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             settings = self.session.query(model.Setting).filter( | 
					
						
							|  |  |  |                 model.Setting.name == "foo1" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             self.assertEqual(settings.count(), 1) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(self.app, "make_session", return_value=self.session): | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |                 view.delete_bulk_thread(settings, progress=MagicMock()) | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # error, no progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             settings = self.session.query(model.Setting).filter( | 
					
						
							|  |  |  |                 model.Setting.name == "foo2" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |             self.assertEqual(settings.count(), 1) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(self.app, "make_session", return_value=self.session): | 
					
						
							|  |  |  |                 with patch.object(view, "delete_bulk_action", side_effect=RuntimeError): | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |                     view.delete_bulk_thread(settings) | 
					
						
							|  |  |  |             # nb. nothing was deleted | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # error, with progress | 
					
						
							|  |  |  |             self.assertEqual(settings.count(), 1) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(self.app, "make_session", return_value=self.session): | 
					
						
							|  |  |  |                 with patch.object(view, "delete_bulk_action", side_effect=RuntimeError): | 
					
						
							| 
									
										
										
										
											2024-08-24 19:28:13 -05:00
										 |  |  |                     view.delete_bulk_thread(settings, progress=MagicMock()) | 
					
						
							|  |  |  |             # nb. nothing was deleted | 
					
						
							|  |  |  |             self.assertEqual(self.session.query(model.Setting).count(), 6) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |     def test_autocomplete(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         person1 = model.Person(full_name="George Jones") | 
					
						
							|  |  |  |         self.session.add(person1) | 
					
						
							|  |  |  |         person2 = model.Person(full_name="George Strait") | 
					
						
							|  |  |  |         self.session.add(person2) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no results for empty term | 
					
						
							|  |  |  |         self.request.GET = {} | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         results = view.autocomplete() | 
					
						
							|  |  |  |         self.assertEqual(len(results), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # search yields no results | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.request.GET = {"term": "sally"} | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object(view, "autocomplete_data", return_value=[]): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             results = view.autocomplete() | 
					
						
							|  |  |  |             self.assertEqual(len(results), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # search yields 2 results | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.request.GET = {"term": "george"} | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object(view, "autocomplete_data", return_value=[person1, person2]): | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |             results = view.autocomplete() | 
					
						
							|  |  |  |             self.assertEqual(len(results), 2) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual( | 
					
						
							|  |  |  |                 [res["value"] for res in results], [p.uuid for p in [person1, person2]] | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_autocomplete_normalize(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         person = model.Person(full_name="Betty Boop", uuid="bogus") | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         normal = view.autocomplete_normalize(person) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.assertEqual(normal, {"value": "bogus", "label": "Betty Boop"}) | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |     def test_download(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo", "bar") | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_class=model.Setting, | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             Session=MagicMock(return_value=self.session), | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.matchdict = {"name": "foo"} | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # 404 if no filename | 
					
						
							|  |  |  |             response = view.download() | 
					
						
							|  |  |  |             self.assertEqual(response.status_code, 404) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # 404 if bad filename | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.GET = {"filename": "doesnotexist"} | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |             response = view.download() | 
					
						
							|  |  |  |             self.assertEqual(response.status_code, 404) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # 200 if good filename | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             foofile = self.write_file("foo.txt", "foo") | 
					
						
							|  |  |  |             with patch.object(view, "download_path", return_value=foofile): | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |                 response = view.download() | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual( | 
					
						
							|  |  |  |                     response.content_disposition, 'attachment; filename="foo.txt"' | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_execute(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.add_route("settings.view", "/settings/{name}") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("progress", "/progress/{key}") | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.app.save_setting(self.session, "foo", "bar") | 
					
						
							|  |  |  |         user = model.User(username="barney") | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |         self.session.add(user) | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_class=model.Setting, | 
					
						
							|  |  |  |             model_key="name", | 
					
						
							|  |  |  |             Session=MagicMock(return_value=self.session), | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.matchdict = {"name": "foo"} | 
					
						
							|  |  |  |             self.request.session.id = "mockid" | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |             self.request.user = user | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |             # basic usage; user is shown progress page | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(mod, "threading") as threading: | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  |                 response = view.execute() | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 threading.Thread.return_value.start.assert_called_once_with() | 
					
						
							|  |  |  |                 self.assertEqual(response.status_code, 200) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_execute_thread(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         enum = self.app.enum | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         user = model.User(username="barney") | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |         self.session.add(user) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         upgrade = model.Upgrade( | 
					
						
							|  |  |  |             description="test", created_by=user, status=enum.UpgradeStatus.PENDING | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |         self.session.add(upgrade) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Upgrade): | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # basic execute, no progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "execute_instance") as execute_instance: | 
					
						
							|  |  |  |                 view.execute_thread({"uuid": upgrade.uuid}, user.uuid) | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 execute_instance.assert_called_once() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # basic execute, with progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "execute_instance") as execute_instance: | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 progress = MagicMock() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 view.execute_thread( | 
					
						
							|  |  |  |                     {"uuid": upgrade.uuid}, user.uuid, progress=progress | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 execute_instance.assert_called_once() | 
					
						
							|  |  |  |                 progress.handle_success.assert_called_once_with() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # error, no progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "execute_instance") as execute_instance: | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 execute_instance.side_effect = RuntimeError | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 view.execute_thread({"uuid": upgrade.uuid}, user.uuid) | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 execute_instance.assert_called_once() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # error, with progress | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "execute_instance") as execute_instance: | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 progress = MagicMock() | 
					
						
							|  |  |  |                 execute_instance.side_effect = RuntimeError | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 view.execute_thread( | 
					
						
							|  |  |  |                     {"uuid": upgrade.uuid}, user.uuid, progress=progress | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-08-25 15:52:29 -05:00
										 |  |  |                 execute_instance.assert_called_once() | 
					
						
							|  |  |  |                 progress.handle_error.assert_called_once() | 
					
						
							| 
									
										
										
										
											2024-08-25 12:20:28 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  |     def test_configure(self): | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.pyramid_config.include("wuttaweb.views.common") | 
					
						
							|  |  |  |         self.pyramid_config.include("wuttaweb.views.auth") | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # mock settings | 
					
						
							|  |  |  |         settings = [ | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             {"name": "wutta.app_title"}, | 
					
						
							|  |  |  |             {"name": "wutta.foo", "value": "bar"}, | 
					
						
							|  |  |  |             {"name": "wutta.flag", "type": bool}, | 
					
						
							|  |  |  |             {"name": "wutta.number", "type": int, "default": 42}, | 
					
						
							|  |  |  |             {"name": "wutta.value1", "save_if_empty": True}, | 
					
						
							|  |  |  |             {"name": "wutta.value2", "save_if_empty": False}, | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-21 11:46:38 -05:00
										 |  |  |         view = mod.MasterView(self.request) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             self.request, "current_route_url", return_value="/appinfo/configure" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             with patch.object(mod, "Session", return_value=self.session): | 
					
						
							|  |  |  |                 with patch.multiple( | 
					
						
							|  |  |  |                     mod.MasterView, | 
					
						
							|  |  |  |                     create=True, | 
					
						
							|  |  |  |                     model_name="AppInfo", | 
					
						
							|  |  |  |                     route_prefix="appinfo", | 
					
						
							|  |  |  |                     template_prefix="/appinfo", | 
					
						
							|  |  |  |                     creatable=False, | 
					
						
							|  |  |  |                     get_index_url=MagicMock(return_value="/appinfo/"), | 
					
						
							|  |  |  |                     configure_get_simple_settings=MagicMock(return_value=settings), | 
					
						
							|  |  |  |                 ): | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                     # nb. appinfo/configure template requires menu_handlers | 
					
						
							|  |  |  |                     original_context = view.configure_get_context | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                     def get_context(**kw): | 
					
						
							|  |  |  |                         kw = original_context(**kw) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                         kw["menu_handlers"] = [] | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                         return kw | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     with patch.object(view, "configure_get_context", new=get_context): | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         # get the form page | 
					
						
							|  |  |  |                         response = view.configure(session=self.session) | 
					
						
							|  |  |  |                         self.assertIsInstance(response, Response) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         # post request to save settings | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                         self.request.method = "POST" | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                         self.request.POST = { | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                             "wutta.app_title": "Wutta", | 
					
						
							|  |  |  |                             "wutta.foo": "bar", | 
					
						
							|  |  |  |                             "wutta.flag": "true", | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                         } | 
					
						
							|  |  |  |                         response = view.configure(session=self.session) | 
					
						
							|  |  |  |                         # nb. should get redirect back to configure page | 
					
						
							|  |  |  |                         self.assertEqual(response.status_code, 302) | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                         # should now have 5 settings | 
					
						
							|  |  |  |                         count = self.session.query(model.Setting).count() | 
					
						
							|  |  |  |                         self.assertEqual(count, 5) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                         get_setting = functools.partial( | 
					
						
							|  |  |  |                             self.app.get_setting, self.session | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                         self.assertEqual(get_setting("wutta.app_title"), "Wutta") | 
					
						
							|  |  |  |                         self.assertEqual(get_setting("wutta.foo"), "bar") | 
					
						
							|  |  |  |                         self.assertEqual(get_setting("wutta.flag"), "true") | 
					
						
							|  |  |  |                         self.assertEqual(get_setting("wutta.number"), "42") | 
					
						
							|  |  |  |                         self.assertEqual(get_setting("wutta.value1"), "") | 
					
						
							|  |  |  |                         self.assertEqual(get_setting("wutta.value2"), None) | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         # post request to remove settings | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                         self.request.method = "POST" | 
					
						
							|  |  |  |                         self.request.POST = {"remove_settings": "1"} | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                         response = view.configure(session=self.session) | 
					
						
							|  |  |  |                         # nb. should get redirect back to configure page | 
					
						
							|  |  |  |                         self.assertEqual(response.status_code, 302) | 
					
						
							| 
									
										
										
										
											2024-08-06 18:52:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-13 13:28:34 -06:00
										 |  |  |                         # should now have 0 settings | 
					
						
							|  |  |  |                         count = self.session.query(model.Setting).count() | 
					
						
							|  |  |  |                         self.assertEqual(count, 0) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 10:13:07 -05:00
										 |  |  |     def test_configure_get_simple_settings(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         settings = view.configure_get_simple_settings() | 
					
						
							|  |  |  |         self.assertEqual(settings, []) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-06 19:29:58 -06:00
										 |  |  |     def test_configure_gather_settings(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         simple_settings = [ | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             {"name": "wutta.app_title"}, | 
					
						
							|  |  |  |             {"name": "wutta.foo"}, | 
					
						
							|  |  |  |             {"name": "wutta.flag", "type": bool, "default": True}, | 
					
						
							|  |  |  |             {"name": "wutta.number", "type": int, "default": 42}, | 
					
						
							|  |  |  |             {"name": "wutta.value1", "save_if_empty": True}, | 
					
						
							|  |  |  |             {"name": "wutta.value2", "save_if_empty": False}, | 
					
						
							|  |  |  |             {"name": "wutta.value3", "save_if_empty": False, "default": "baz"}, | 
					
						
							| 
									
										
										
										
											2025-01-06 19:29:58 -06:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         data = { | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             "wutta.app_title": "Poser", | 
					
						
							|  |  |  |             "wutta.foo": "bar", | 
					
						
							|  |  |  |             "wutta.number": 44, | 
					
						
							|  |  |  |             "wutta.value1": None, | 
					
						
							| 
									
										
										
										
											2025-01-06 19:29:58 -06:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             view, "configure_get_simple_settings", return_value=simple_settings | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2025-01-06 19:29:58 -06:00
										 |  |  |             settings = view.configure_gather_settings(data) | 
					
						
							|  |  |  |             self.assertEqual(len(settings), 6) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.assertEqual( | 
					
						
							|  |  |  |                 settings, | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                     {"name": "wutta.app_title", "value": "Poser"}, | 
					
						
							|  |  |  |                     {"name": "wutta.foo", "value": "bar"}, | 
					
						
							|  |  |  |                     {"name": "wutta.flag", "value": "false"}, | 
					
						
							|  |  |  |                     {"name": "wutta.number", "value": "44"}, | 
					
						
							|  |  |  |                     {"name": "wutta.value1", "value": ""}, | 
					
						
							|  |  |  |                     {"name": "wutta.value3", "value": "baz"}, | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2025-01-06 19:29:58 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |     ############################## | 
					
						
							|  |  |  |     # row methods | 
					
						
							|  |  |  |     ############################## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_collect_row_labels(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # default labels | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         labels = view.collect_row_labels() | 
					
						
							|  |  |  |         self.assertEqual(labels, {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # labels come from all classes; subclass wins | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object( | 
					
						
							|  |  |  |             View, "row_labels", create=True, new={"foo": "Foo", "bar": "Bar"} | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             with patch.object( | 
					
						
							|  |  |  |                 mod.MasterView, "row_labels", create=True, new={"foo": "FOO FIGHTERS"} | 
					
						
							|  |  |  |             ): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 labels = view.collect_row_labels() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                 self.assertEqual(labels, {"foo": "FOO FIGHTERS", "bar": "Bar"}) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_set_row_labels(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         person = model.Person(full_name="Fred Flintstone") | 
					
						
							|  |  |  |         self.session.add(person) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, | 
					
						
							|  |  |  |             create=True, | 
					
						
							|  |  |  |             model_class=model.Person, | 
					
						
							|  |  |  |             has_rows=True, | 
					
						
							|  |  |  |             row_model_class=model.User, | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # no labels by default | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             grid = view.make_row_model_grid(person, key="person.users", data=[]) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |             view.set_row_labels(grid) | 
					
						
							|  |  |  |             self.assertEqual(grid.labels, {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # labels come from all classes; subclass wins | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object( | 
					
						
							|  |  |  |                 View, "row_labels", create=True, new={"username": "USERNAME"} | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 with patch.object( | 
					
						
							|  |  |  |                     mod.MasterView, | 
					
						
							|  |  |  |                     "row_labels", | 
					
						
							|  |  |  |                     create=True, | 
					
						
							|  |  |  |                     new={"username": "UserName"}, | 
					
						
							|  |  |  |                 ): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                     view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     grid = view.make_row_model_grid(person, key="person.users", data=[]) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                     view.set_row_labels(grid) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     self.assertEqual(grid.labels, {"username": "UserName"}) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_row_grid_data(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         person = model.Person(full_name="Fred Flintstone") | 
					
						
							|  |  |  |         self.session.add(person) | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         self.assertRaises(NotImplementedError, view.get_row_grid_data, person) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_row_grid_columns(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no default | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         self.assertIsNone(view.get_row_grid_columns()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # class may specify | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object(view, "row_grid_columns", create=True, new=["foo", "bar"]): | 
					
						
							|  |  |  |             self.assertEqual(view.get_row_grid_columns(), ["foo", "bar"]) | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_row_grid_key(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.multiple( | 
					
						
							|  |  |  |             mod.MasterView, create=True, model_key="id", grid_key="widgets" | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             self.request.matchdict = {"id": 42} | 
					
						
							|  |  |  |             self.assertEqual(view.get_row_grid_key(), "widgets.42") | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_make_row_model_grid(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         person = model.Person(full_name="Barney Rubble") | 
					
						
							|  |  |  |         self.session.add(person) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         self.request.matchdict = {"uuid": person.uuid} | 
					
						
							|  |  |  |         with patch.multiple(mod.MasterView, create=True, model_class=model.Person): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # specify data | 
					
						
							|  |  |  |             grid = view.make_row_model_grid(person, data=[]) | 
					
						
							|  |  |  |             self.assertIsNone(grid.model_class) | 
					
						
							|  |  |  |             self.assertEqual(grid.data, []) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # fetch data | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "get_row_grid_data", return_value=[]): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |                 grid = view.make_row_model_grid(person) | 
					
						
							|  |  |  |                 self.assertIsNone(grid.model_class) | 
					
						
							|  |  |  |                 self.assertEqual(grid.data, []) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-02 22:52:32 -06:00
										 |  |  |             # view action | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |             with patch.object(view, "rows_viewable", new=True): | 
					
						
							|  |  |  |                 with patch.object(view, "get_row_action_url_view", return_value="#"): | 
					
						
							| 
									
										
										
										
											2025-01-02 22:52:32 -06:00
										 |  |  |                     grid = view.make_row_model_grid(person, data=[]) | 
					
						
							|  |  |  |                     self.assertEqual(len(grid.actions), 1) | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |                     self.assertEqual(grid.actions[0].key, "view") | 
					
						
							| 
									
										
										
										
											2025-01-02 22:52:32 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_get_row_action_url_view(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  |         row = MagicMock() | 
					
						
							|  |  |  |         self.assertRaises(NotImplementedError, view.get_row_action_url_view, row, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |     def test_get_rows_title(self): | 
					
						
							|  |  |  |         view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # no default | 
					
						
							|  |  |  |         self.assertIsNone(view.get_rows_title()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # class may specify | 
					
						
							| 
									
										
										
										
											2025-08-31 12:26:43 -05:00
										 |  |  |         with patch.object(view, "rows_title", create=True, new="Mock Rows"): | 
					
						
							| 
									
										
										
										
											2024-12-14 10:38:49 -06:00
										 |  |  |             self.assertEqual(view.get_rows_title(), "Mock Rows") | 
					
						
							| 
									
										
										
										
											2025-10-29 18:32:35 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestVersionedMasterView(VersionWebTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def make_view(self): | 
					
						
							|  |  |  |         return mod.MasterView(self.request) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-29 19:16:03 -05:00
										 |  |  |     def test_is_versioned(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # User is versioned by default | 
					
						
							|  |  |  |             self.assertTrue(mod.MasterView.is_versioned()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # but view can override w/ attr | 
					
						
							|  |  |  |             with patch.object( | 
					
						
							|  |  |  |                 mod.MasterView, "model_is_versioned", new=False, create=True | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 self.assertFalse(mod.MasterView.is_versioned()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-29 18:32:35 -05:00
										 |  |  |     def test_defaults(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-29 19:16:03 -05:00
										 |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							| 
									
										
										
										
											2025-10-29 18:32:35 -05:00
										 |  |  |             mod.MasterView.defaults(self.pyramid_config) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_model_version_class(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             vercls = view.get_model_version_class() | 
					
						
							|  |  |  |             self.assertEqual(vercls.__name__, "UserVersion") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_should_expose_versions(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							| 
									
										
										
										
											2025-10-29 19:16:03 -05:00
										 |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							| 
									
										
										
										
											2025-10-29 18:32:35 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # fully enabled for root user | 
					
						
							|  |  |  |             with patch.object(self.request, "is_root", new=True): | 
					
						
							|  |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 self.assertTrue(view.should_expose_versions()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # but not if user has no access | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             self.assertFalse(view.should_expose_versions()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # again, works for root user | 
					
						
							|  |  |  |             with patch.object(self.request, "is_root", new=True): | 
					
						
							|  |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 self.assertTrue(view.should_expose_versions()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # but not if config disables versioning | 
					
						
							|  |  |  |                 with patch.object(view.app, "continuum_is_enabled", return_value=False): | 
					
						
							|  |  |  |                     self.assertFalse(view.should_expose_versions()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_version_grid_key(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # default | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             self.assertEqual(view.get_version_grid_key(), "users.history") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # custom | 
					
						
							|  |  |  |             with patch.object( | 
					
						
							|  |  |  |                 mod.MasterView, | 
					
						
							|  |  |  |                 "version_grid_key", | 
					
						
							|  |  |  |                 new="users_custom_history", | 
					
						
							|  |  |  |                 create=True, | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 self.assertEqual(view.get_version_grid_key(), "users_custom_history") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_version_grid_columns(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # default | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             self.assertEqual( | 
					
						
							|  |  |  |                 view.get_version_grid_columns(), | 
					
						
							|  |  |  |                 ["id", "issued_at", "user", "remote_addr"], | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # custom | 
					
						
							|  |  |  |             with patch.object( | 
					
						
							|  |  |  |                 mod.MasterView, | 
					
						
							|  |  |  |                 "version_grid_columns", | 
					
						
							|  |  |  |                 new=["issued_at", "user"], | 
					
						
							|  |  |  |                 create=True, | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 self.assertEqual(view.get_version_grid_columns(), ["issued_at", "user"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_version_grid_data(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         user = model.User(username="fred") | 
					
						
							|  |  |  |         self.session.add(user) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  |         user.username = "freddie" | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  |             query = view.get_version_grid_data(user) | 
					
						
							|  |  |  |             self.assertIsInstance(query, orm.Query) | 
					
						
							|  |  |  |             transactions = query.all() | 
					
						
							|  |  |  |             self.assertEqual(len(transactions), 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_configure_version_grid(self): | 
					
						
							|  |  |  |         import sqlalchemy_continuum as continuum | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         txncls = continuum.transaction_class(model.User) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # this is mostly just for coverage, but we at least can | 
					
						
							|  |  |  |             # confirm something does change | 
					
						
							|  |  |  |             grid = view.make_grid(model_class=txncls) | 
					
						
							|  |  |  |             self.assertNotIn("issued_at", grid.linked_columns) | 
					
						
							|  |  |  |             view.configure_version_grid(grid) | 
					
						
							|  |  |  |             self.assertIn("issued_at", grid.linked_columns) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_make_version_grid(self): | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         user = model.User(username="fred") | 
					
						
							|  |  |  |         self.session.add(user) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  |         user.username = "freddie" | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             with patch.object(mod.MasterView, "Session", return_value=self.session): | 
					
						
							|  |  |  |                 with patch.dict(self.request.matchdict, uuid=user.uuid): | 
					
						
							|  |  |  |                     view = self.make_view() | 
					
						
							|  |  |  |                     grid = view.make_version_grid() | 
					
						
							|  |  |  |                     self.assertIsInstance(grid, Grid) | 
					
						
							|  |  |  |                     self.assertIsInstance(grid.data, orm.Query) | 
					
						
							|  |  |  |                     self.assertEqual(len(grid.data.all()), 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_view_versions(self): | 
					
						
							|  |  |  |         self.pyramid_config.add_route("home", "/") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("login", "/auth/login") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users", "/users/") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users.view", "/users/{uuid}") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users.version", "/users/{uuid}/versions/{txnid}") | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         user = model.User(username="fred") | 
					
						
							|  |  |  |         self.session.add(user) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  |         user.username = "freddie" | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             with patch.object(mod.MasterView, "Session", return_value=self.session): | 
					
						
							|  |  |  |                 with patch.dict(self.request.matchdict, uuid=user.uuid): | 
					
						
							|  |  |  |                     view = self.make_view() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # normal, full page | 
					
						
							|  |  |  |                     response = view.view_versions() | 
					
						
							|  |  |  |                     self.assertEqual(response.content_type, "text/html") | 
					
						
							|  |  |  |                     self.assertIn("<b-table", response.text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # partial page | 
					
						
							|  |  |  |                     with patch.dict(self.request.params, partial="1"): | 
					
						
							|  |  |  |                         response = view.view_versions() | 
					
						
							|  |  |  |                         self.assertEqual(response.content_type, "application/json") | 
					
						
							|  |  |  |                         self.assertIn("data", response.json) | 
					
						
							|  |  |  |                         self.assertEqual(len(response.json["data"]), 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_get_relevant_versions(self): | 
					
						
							|  |  |  |         import sqlalchemy_continuum as continuum | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         txncls = continuum.transaction_class(model.User) | 
					
						
							|  |  |  |         vercls = continuum.version_class(model.User) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         user = model.User(username="fred") | 
					
						
							|  |  |  |         self.session.add(user) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         txn = ( | 
					
						
							|  |  |  |             self.session.query(txncls) | 
					
						
							|  |  |  |             .join(vercls, vercls.transaction_id == txncls.id) | 
					
						
							|  |  |  |             .order_by(txncls.id) | 
					
						
							|  |  |  |             .first() | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             with patch.object(mod.MasterView, "Session", return_value=self.session): | 
					
						
							|  |  |  |                 view = self.make_view() | 
					
						
							|  |  |  |                 versions = view.get_relevant_versions(txn, user) | 
					
						
							|  |  |  |                 self.assertEqual(len(versions), 1) | 
					
						
							|  |  |  |                 version = versions[0] | 
					
						
							|  |  |  |                 self.assertIsInstance(version, vercls) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_view_version(self): | 
					
						
							|  |  |  |         import sqlalchemy_continuum as continuum | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.pyramid_config.add_route("home", "/") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("login", "/auth/login") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users", "/users/") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users.view", "/users/{uuid}") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users.versions", "/users/{uuid}/versions/") | 
					
						
							|  |  |  |         self.pyramid_config.add_route("users.version", "/users/{uuid}/versions/{txnid}") | 
					
						
							|  |  |  |         model = self.app.model | 
					
						
							|  |  |  |         txncls = continuum.transaction_class(model.User) | 
					
						
							|  |  |  |         vercls = continuum.version_class(model.User) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         user = model.User(username="fred") | 
					
						
							|  |  |  |         self.session.add(user) | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  |         user.username = "freddie" | 
					
						
							|  |  |  |         self.session.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         transactions = ( | 
					
						
							|  |  |  |             self.session.query(txncls) | 
					
						
							|  |  |  |             .join(vercls, vercls.transaction_id == txncls.id) | 
					
						
							|  |  |  |             .order_by(txncls.id) | 
					
						
							|  |  |  |             .all() | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual(len(transactions), 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with patch.object(mod.MasterView, "model_class", new=model.User): | 
					
						
							|  |  |  |             with patch.object(mod.MasterView, "Session", return_value=self.session): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # invalid txnid | 
					
						
							|  |  |  |                 with patch.dict(self.request.matchdict, uuid=user.uuid, txnid=999999): | 
					
						
							|  |  |  |                     view = self.make_view() | 
					
						
							|  |  |  |                     self.assertRaises(HTTPNotFound, view.view_version) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # first txn | 
					
						
							|  |  |  |                 first = transactions[0] | 
					
						
							|  |  |  |                 with patch.dict(self.request.matchdict, uuid=user.uuid, txnid=first.id): | 
					
						
							|  |  |  |                     view = self.make_view() | 
					
						
							|  |  |  |                     response = view.view_version() | 
					
						
							|  |  |  |                     self.assertIn( | 
					
						
							|  |  |  |                         '<table class="table is-fullwidth is-bordered is-narrow">', | 
					
						
							|  |  |  |                         response.text, | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # second txn | 
					
						
							|  |  |  |                 second = transactions[1] | 
					
						
							|  |  |  |                 with patch.dict( | 
					
						
							|  |  |  |                     self.request.matchdict, uuid=user.uuid, txnid=second.id | 
					
						
							|  |  |  |                 ): | 
					
						
							|  |  |  |                     view = self.make_view() | 
					
						
							|  |  |  |                     response = view.view_version() | 
					
						
							|  |  |  |                     self.assertIn( | 
					
						
							|  |  |  |                         '<table class="table is-fullwidth is-bordered is-narrow">', | 
					
						
							|  |  |  |                         response.text, | 
					
						
							|  |  |  |                     ) |