home · contact · privacy
51f7cc2d3e5b7a657e5baa96ab290b28cf4fe372
[plomtask] / tests / conditions.py
1 """Test Conditions module."""
2 from unittest import TestCase
3 from tests.utils import TestCaseWithDB, TestCaseWithServer
4 from plomtask.conditions import Condition
5 from plomtask.processes import Process
6 from plomtask.todos import Todo
7 from plomtask.exceptions import NotFoundException, HandledException
8
9
10 class TestsSansDB(TestCase):
11     """Tests requiring no DB setup."""
12
13     def test_Condition_id_setting(self) -> None:
14         """Test .id_ being set and its legal range being enforced."""
15         with self.assertRaises(HandledException):
16             Condition(0)
17         condition = Condition(5)
18         self.assertEqual(condition.id_, 5)
19
20
21 class TestsWithDB(TestCaseWithDB):
22     """Tests requiring DB, but not server setup."""
23
24     def check_storage(self, content: list[Condition]) -> None:
25         """Test cache and DB equal content."""
26         expected_cache = {}
27         for item in content:
28             expected_cache[item.id_] = item
29         self.assertEqual(Condition.get_cache(), expected_cache)
30         db_found: list[Condition] = []
31         for item in content:
32             assert isinstance(item.id_, int)
33             for row in self.db_conn.row_where(Condition.table_name, 'id',
34                                               item.id_):
35                 db_found += [Condition.from_table_row(self.db_conn, row)]
36         self.assertEqual(sorted(content), sorted(db_found))
37
38     def test_Condition_saving_and_caching(self) -> None:
39         """Test .save/.save_core."""
40         c = Condition(None, False)
41         c.title.set('title1')
42         c.title.set('title2')
43         c.description.set('desc1')
44         c.description.set('desc2')
45         # check object init itself doesn't store anything yet
46         self.check_storage([])
47         # check saving stores in cache and DB
48         c.save(self.db_conn)
49         self.check_storage([c])
50         # check attributes set properly (and not unset by saving)
51         self.assertEqual(c.id_, 1)
52         self.assertEqual(c.is_active, False)
53         self.assertEqual(sorted(c.title.history.values()),
54                          ['title1', 'title2'])
55         self.assertEqual(sorted(c.description.history.values()),
56                          ['desc1', 'desc2'])
57
58     def test_Condition_from_table_row(self) -> None:
59         """Test .from_table_row() properly reads in class from DB"""
60         c = Condition(1, True)
61         c.title.set('title1')
62         c.title.set('title2')
63         c.description.set('desc1')
64         c.description.set('desc2')
65         c.save(self.db_conn)
66         assert isinstance(c.id_, int)
67         for row in self.db_conn.row_where(Condition.table_name, 'id', c.id_):
68             retrieved = Condition.from_table_row(self.db_conn, row)
69             assert isinstance(retrieved, Condition)
70             self.assertEqual(c, retrieved)
71             self.assertEqual({c.id_: c}, Condition.get_cache())
72             # pylint: disable=no-member
73             self.assertEqual(sorted(retrieved.title.history.values()),
74                              ['title1', 'title2'])
75             # pylint: disable=no-member
76             self.assertEqual(sorted(retrieved.description.history.values()),
77                              ['desc1', 'desc2'])
78
79     def test_Condition_by_id(self) -> None:
80         """Test .by_id(), including creation."""
81         # check failure if not yet saved
82         c = Condition(3, False)
83         with self.assertRaises(NotFoundException):
84             Condition.by_id(self.db_conn, 3)
85         # check identity of saved and retrieved
86         c.save(self.db_conn)
87         self.assertEqual(c, Condition.by_id(self.db_conn, 3))
88         # check create=True acts like normal instantiation (sans saving)
89         by_id_created = Condition.by_id(self.db_conn, 4, create=True)
90         self.assertEqual(Condition(4), by_id_created)
91         self.check_storage([c])
92
93     def test_Condition_all(self) -> None:
94         """Test .all()."""
95         c_1 = Condition(None, False)
96         # check pre-save .all() returns empty list
97         self.assertEqual(Condition.all(self.db_conn), [])
98         # check .save() fills .all() result
99         c_1.save(self.db_conn)
100         self.assertEqual(Condition.all(self.db_conn), [c_1])
101         c_2 = Condition(None, True)
102         c_2.save(self.db_conn)
103         self.assertEqual(sorted(Condition.all(self.db_conn)),
104                          sorted([c_1, c_2]))
105
106     def test_Condition_singularity(self) -> None:
107         """Test pointers made for single object keep pointing to it."""
108         c = Condition(None, False)
109         c.save(self.db_conn)
110         c.is_active = True
111         retrieved = Condition.by_id(self.db_conn, 1)
112         self.assertEqual(True, retrieved.is_active)
113
114     def test_Condition_remove(self) -> None:
115         """Test .remove() effects on DB and cache."""
116         # check only saved item can be removed
117         c = Condition(None, False)
118         with self.assertRaises(HandledException):
119             c.remove(self.db_conn)
120         c.save(self.db_conn)
121         c.remove(self.db_conn)
122         self.check_storage([])
123         # check guard against deleting dependencies of other classes
124         proc = Process(None)
125         todo = Todo(None, proc, False, '2024-01-01')
126         for depender in (proc, todo):
127             assert hasattr(depender, 'save')
128             assert hasattr(depender, 'set_conditions')
129             c.save(self.db_conn)
130             depender.save(self.db_conn)
131             depender.set_conditions(self.db_conn, [c.id_], 'conditions')
132             depender.save(self.db_conn)
133             with self.assertRaises(HandledException):
134                 c.remove(self.db_conn)
135             depender.set_conditions(self.db_conn, [], 'conditions')
136             depender.save(self.db_conn)
137             c.remove(self.db_conn)
138
139
140 class TestsWithServer(TestCaseWithServer):
141     """Module tests against our HTTP server/handler (and database)."""
142
143     def test_do_POST_condition(self) -> None:
144         """Test POST /condition and its effect on the database."""
145         form_data = {'title': 'foo', 'description': 'foo'}
146         self.check_post(form_data, '/condition', 302, '/condition?id=1')
147         self.assertEqual(1, len(Condition.all(self.db_conn)))
148         form_data['delete'] = ''
149         self.check_post(form_data, '/condition?id=', 404)
150         self.check_post(form_data, '/condition?id=2', 404)
151         self.check_post(form_data, '/condition?id=1', 302, '/conditions')
152         self.assertEqual(0, len(Condition.all(self.db_conn)))
153
154     def test_do_GET(self) -> None:
155         """Test /condition and /conditions response codes."""
156         form_data = {'title': 'foo', 'description': 'foo'}
157         self.check_post(form_data, '/condition', 302, '/condition?id=1')
158         self.check_get_defaults('/condition')
159         self.check_get('/conditions', 200)