|
21 | 21 | from django_declarative_apis.machinery import errors, filtering, tasks
|
22 | 22 | from django_declarative_apis.machinery.tasks import future_task_runner
|
23 | 23 | from django_declarative_apis.resources.utils import HttpStatusCode
|
24 |
| -from tests import testutils |
| 24 | +from tests import testutils, models |
25 | 25 |
|
26 | 26 | _TEST_RESOURCE = {"foo": "bar"}
|
27 | 27 |
|
@@ -147,70 +147,96 @@ def resource(self):
|
147 | 147 | mock_logging.error.assert_called_with("('something bad happened',)\nNone")
|
148 | 148 |
|
149 | 149 | def test_get_response_with_dirty_resource(self):
|
150 |
| - class _TestResource: |
151 |
| - def is_dirty(self, check_relationship=False): |
152 |
| - return True |
| 150 | + class _TestEndpoint1(machinery.EndpointDefinition): |
| 151 | + @machinery.endpoint_resource(type=models.DirtyFieldsModel) |
| 152 | + def resource(self): |
| 153 | + result = models.DirtyFieldsModel(field="abcde") |
| 154 | + result.fk_field = models.TestModel.objects.create(int_field=1) |
| 155 | + return result |
| 156 | + |
| 157 | + class _TestEndpoint2(machinery.EndpointDefinition): |
| 158 | + @machinery.endpoint_resource(type=models.DirtyFieldsModel) |
| 159 | + def resource(self): |
| 160 | + result = models.DirtyFieldsModel(field="abcde") |
| 161 | + result.fk_field = models.TestModel.objects.create(int_field=1) |
| 162 | + return result |
153 | 163 |
|
154 |
| - def save(self): |
| 164 | + @machinery.task |
| 165 | + def null_task(self): |
155 | 166 | pass
|
156 | 167 |
|
157 |
| - class _TestEndpoint(machinery.EndpointDefinition): |
158 |
| - @machinery.endpoint_resource(type=_TestResource) |
| 168 | + class _TestEndpoint3(machinery.EndpointDefinition): |
| 169 | + @machinery.endpoint_resource(type=models.DirtyFieldsModel) |
159 | 170 | def resource(self):
|
160 |
| - return _TestResource() |
| 171 | + result = models.DirtyFieldsModel(field="abcde") |
| 172 | + result.fk_field = models.TestModel.objects.create(int_field=1) |
| 173 | + return result |
161 | 174 |
|
162 |
| - endpoint = _TestEndpoint() |
163 |
| - manager = machinery.EndpointBinder.BoundEndpointManager( |
164 |
| - machinery._EndpointRequestLifecycleManager(endpoint), endpoint |
165 |
| - ) |
| 175 | + @machinery.task |
| 176 | + def task(self): |
| 177 | + self.resource.field = "zyxwv" |
| 178 | + |
| 179 | + for test_name, endpoint_cls, expected_call_count in ( |
| 180 | + ("No Task", _TestEndpoint1, 1), |
| 181 | + ("No-op Task", _TestEndpoint2, 1), |
| 182 | + ("With Task", _TestEndpoint3, 2), |
| 183 | + ): |
| 184 | + with self.subTest(test_name): |
| 185 | + endpoint = endpoint_cls() |
| 186 | + manager = machinery.EndpointBinder.BoundEndpointManager( |
| 187 | + machinery._EndpointRequestLifecycleManager(endpoint), endpoint |
| 188 | + ) |
166 | 189 |
|
167 |
| - class _FakeRequest: |
168 |
| - META = {} |
| 190 | + class _FakeRequest: |
| 191 | + META = {} |
169 | 192 |
|
170 |
| - manager.bound_endpoint.request = _FakeRequest() |
| 193 | + manager.bound_endpoint.request = _FakeRequest() |
171 | 194 |
|
172 |
| - with mock.patch.object(_TestResource, "save", return_value=None) as mock_save: |
173 |
| - manager.get_response() |
174 |
| - # save is called before and after tasks. since we've hardcoded _TestResource.is_dirty to return True, |
175 |
| - # both of them should fire |
176 |
| - self.assertEqual(mock_save.call_count, 2) |
| 195 | + with mock.patch.object( |
| 196 | + models.DirtyFieldsModel.objects, |
| 197 | + "update_or_create", |
| 198 | + wraps=models.DirtyFieldsModel.objects.update_or_create, |
| 199 | + ) as mock_uoc: |
| 200 | + manager.get_response() |
| 201 | + self.assertEqual(mock_uoc.call_count, expected_call_count) |
177 | 202 |
|
178 | 203 | def test_get_response_with_client_error_while_executing_tasks(self):
|
179 |
| - class _TestResource: |
180 |
| - def is_dirty(self, check_relationship=False): |
181 |
| - return True |
182 |
| - |
183 |
| - def save(self): |
184 |
| - pass |
185 |
| - |
186 | 204 | class _TestEndpoint(machinery.EndpointDefinition):
|
187 |
| - @machinery.endpoint_resource(type=_TestResource) |
| 205 | + @machinery.endpoint_resource(type=models.DirtyFieldsModel) |
188 | 206 | def resource(self):
|
189 |
| - return _TestResource() |
| 207 | + result = models.DirtyFieldsModel(id=1, field="abcde") |
| 208 | + result.fk_field = models.TestModel.objects.create(int_field=1) |
| 209 | + return result |
190 | 210 |
|
191 | 211 | @machinery.task
|
192 | 212 | def raise_an_exception(self):
|
| 213 | + self.resource.field = "zyxwv" |
193 | 214 | raise errors.ClientError(
|
194 | 215 | code=http.HTTPStatus.BAD_REQUEST,
|
195 | 216 | message="something bad happened",
|
196 | 217 | save_changes=error_should_save_changes,
|
197 | 218 | )
|
198 | 219 |
|
199 | 220 | for error_should_save_changes in (True, False):
|
200 |
| - with mock.patch.object(_TestResource, "save") as mock_save: |
201 |
| - endpoint = _TestEndpoint() |
202 |
| - manager = machinery.EndpointBinder.BoundEndpointManager( |
203 |
| - machinery._EndpointRequestLifecycleManager(endpoint), endpoint |
204 |
| - ) |
205 |
| - try: |
206 |
| - manager.get_response() |
207 |
| - self.fail("This should have failed") |
208 |
| - except errors.ClientError: |
209 |
| - # save should be called twice if the exception says the resource should be saved: once before |
210 |
| - # tasks are executed and once during exception handling. |
211 |
| - self.assertEqual( |
212 |
| - mock_save.call_count, 2 if error_should_save_changes else 1 |
| 221 | + with self.subTest(f"error_should_save_changes={error_should_save_changes}"): |
| 222 | + with mock.patch.object( |
| 223 | + models.DirtyFieldsModel.objects, |
| 224 | + "update_or_create", |
| 225 | + wraps=models.DirtyFieldsModel.objects.update_or_create, |
| 226 | + ) as mock_uoc: |
| 227 | + endpoint = _TestEndpoint() |
| 228 | + manager = machinery.EndpointBinder.BoundEndpointManager( |
| 229 | + machinery._EndpointRequestLifecycleManager(endpoint), endpoint |
213 | 230 | )
|
| 231 | + try: |
| 232 | + manager.get_response() |
| 233 | + self.fail("This should have failed") |
| 234 | + except errors.ClientError: |
| 235 | + # save should be called twice if the exception says the resource should be saved: once before |
| 236 | + # tasks are executed and once during exception handling. |
| 237 | + self.assertEqual( |
| 238 | + mock_uoc.call_count, 2 if error_should_save_changes else 1 |
| 239 | + ) |
214 | 240 |
|
215 | 241 | def test_get_response_custom_http_response(self):
|
216 | 242 | expected_data = {"foo": "bar"}
|
@@ -280,7 +306,11 @@ class _QuerySet(list):
|
280 | 306 | data = _QuerySet([_TestResource("foo", "bar"), _TestResource("bar", "baz")])
|
281 | 307 |
|
282 | 308 | filter_def = {
|
283 |
| - _TestResource: {"name": filtering.ALWAYS, "secret": filtering.NEVER} |
| 309 | + _TestResource: { |
| 310 | + "name": filtering.ALWAYS, |
| 311 | + "secret": filtering.NEVER, |
| 312 | + "foo": filtering.ALWAYS, |
| 313 | + } |
284 | 314 | }
|
285 | 315 |
|
286 | 316 | class _TestEndpoint(machinery.EndpointDefinition):
|
|
0 commit comments