0001-wcs-handle-network-error-on-requests-31438.patch
combo/apps/wcs/models.py | ||
---|---|---|
27 | 27 |
from django.utils.translation import ugettext_lazy as _ |
28 | 28 | |
29 | 29 |
from jsonfield import JSONField |
30 |
from requests.exceptions import RequestException |
|
30 | 31 | |
31 | 32 |
from combo.data.models import CellBase, Page |
32 | 33 |
from combo.data.library import register_cell_class |
... | ... | |
94 | 95 |
wcs_site = get_wcs_services().get(wcs_key) |
95 | 96 |
forms_response_json = get_wcs_json(wcs_site, 'api/formdefs/') |
96 | 97 | |
97 |
if not forms_response_json: |
|
98 |
if not forms_response_json or forms_response_json.get('err') == 1:
|
|
98 | 99 |
# can not retrieve data, don't report cell as invalid |
99 | 100 |
self.mark_as_valid() |
100 | 101 |
return |
101 | 102 | |
102 |
if isinstance(forms_response_json, dict): |
|
103 |
# forward compability with future w.c.s. API |
|
104 |
forms_response_json = forms_response_json.get('data') |
|
105 | ||
106 | 103 |
form_found = False |
107 |
for form in forms_response_json or []: |
|
104 |
for form in forms_response_json.get('data') or []:
|
|
108 | 105 |
slug = form.get('slug') |
109 | 106 |
if slug == form_slug: |
110 | 107 |
self.cached_title = form.get('title') |
... | ... | |
200 | 197 |
wcs_site = get_wcs_services().get(wcs_key) |
201 | 198 |
categories_response_json = get_wcs_json(wcs_site, 'api/categories/') |
202 | 199 | |
203 |
if not categories_response_json: |
|
200 |
if not categories_response_json or categories_response_json.get('err') == 1:
|
|
204 | 201 |
# can not retrieve data, don't report cell as invalid |
205 | 202 |
self.mark_as_valid() |
206 | 203 |
return |
207 | 204 | |
208 | 205 |
category_found = False |
209 |
for category in categories_response_json.get('data', []):
|
|
206 |
for category in categories_response_json.get('data') or []:
|
|
210 | 207 |
slug = category.get('slug') |
211 | 208 |
if slug == category_slug: |
212 | 209 |
self.cached_title = category.get('title') |
... | ... | |
305 | 302 |
wcs_site['base_url'] = url |
306 | 303 |
wcs_site['slug'] = wcs_slug |
307 | 304 | |
308 |
response = requests.get(
|
|
309 |
api_url,
|
|
310 |
remote_service=wcs_site,
|
|
311 |
user=getattr(context.get('request'), 'user', None),
|
|
312 |
cache_duration=self.cache_duration,
|
|
313 |
raise_if_not_cached=not(context.get('synchronous')),
|
|
314 |
log_errors=False)
|
|
315 |
returns.add(response.status_code)
|
|
316 |
if response.status_code == 200:
|
|
317 |
json_response = response.json()
|
|
318 |
if isinstance(json_response, list):
|
|
319 |
# backward compat with older w.c.s.
|
|
320 |
wcs_site['data'] = json_response
|
|
321 |
elif json_response.get('err', 0) == 0:
|
|
322 |
wcs_site['data'] = json_response['data']
|
|
323 |
else:
|
|
324 |
# skip errors
|
|
325 |
continue
|
|
326 |
# and mark all items with the site info
|
|
327 |
for item in wcs_site['data']:
|
|
328 |
item['site_slug'] = wcs_slug
|
|
305 |
try:
|
|
306 |
response = requests.get(
|
|
307 |
api_url,
|
|
308 |
remote_service=wcs_site,
|
|
309 |
user=getattr(context.get('request'), 'user', None),
|
|
310 |
cache_duration=self.cache_duration,
|
|
311 |
raise_if_not_cached=not(context.get('synchronous')),
|
|
312 |
log_errors=False)
|
|
313 |
returns.add(response.status_code)
|
|
314 |
response.raise_for_status()
|
|
315 |
except RequestException:
|
|
316 |
continue
|
|
317 |
json_response = response.json()
|
|
318 |
if json_response.get('err', 0) == 0: |
|
319 |
wcs_site['data'] = json_response['data'] |
|
320 |
else: |
|
321 |
# skip errors |
|
322 |
continue |
|
323 |
# and mark all items with the site info |
|
324 |
for item in wcs_site['data']: |
|
325 |
item['site_slug'] = wcs_slug |
|
329 | 326 | |
330 |
if 200 not in returns: # not a single valid answer |
|
327 |
if returns and 200 not in returns: # not a single valid answer
|
|
331 | 328 |
logging.debug('failed to get data from any %s (%r)', api_url, returns) |
332 | 329 |
if all([400 <= r < 500 for r in returns]) and self.warn_on_4xx: |
333 | 330 |
# only 4xx errors, not a user cell, report the cell as invalid |
... | ... | |
409 | 406 |
wcs_site = get_wcs_services().get(wcs_key) |
410 | 407 |
categories_response_json = get_wcs_json(wcs_site, 'api/categories/') |
411 | 408 | |
412 |
if not categories_response_json: |
|
409 |
if not categories_response_json or categories_response_json.get('err') == 1:
|
|
413 | 410 |
# can not retrieve data, don't report cell as invalid |
414 | 411 |
continue |
415 | 412 | |
416 | 413 |
category_found = any( |
417 | 414 |
[c.get('slug') == category_slug |
418 |
for c in categories_response_json.get('data', [])])
|
|
415 |
for c in categories_response_json.get('data') or []])
|
|
419 | 416 |
if not category_found: |
420 | 417 |
self.mark_as_invalid('wcs_category_not_found') |
421 | 418 |
return |
... | ... | |
616 | 613 |
wcs_site = get_wcs_services().get(wcs_key) |
617 | 614 |
categories_response_json = get_wcs_json(wcs_site, 'api/categories/') |
618 | 615 | |
619 |
if not categories_response_json: |
|
616 |
if not categories_response_json or categories_response_json.get('err') == 1:
|
|
620 | 617 |
# can not retrieve data, don't report cell as invalid |
621 | 618 |
return |
622 | 619 | |
623 | 620 |
category_found = any( |
624 | 621 |
[c.get('slug') == category_slug |
625 |
for c in categories_response_json.get('data', [])])
|
|
622 |
for c in categories_response_json.get('data') or []])
|
|
626 | 623 |
if not category_found: |
627 | 624 |
self.mark_as_invalid('wcs_category_not_found') |
628 | 625 |
return |
... | ... | |
754 | 751 |
wcs_site = get_wcs_services().get(wcs_key) |
755 | 752 |
card_models = get_wcs_json(wcs_site, 'api/cards/@list') |
756 | 753 | |
757 |
if not card_models: |
|
754 |
if not card_models or card_models.get('err') == 1:
|
|
758 | 755 |
# can not retrieve data, don't report cell as invalid |
759 | 756 |
self.mark_as_valid() |
760 | 757 |
return |
761 | 758 | |
762 | 759 |
card_found = False |
763 |
for card in card_models.get('data', []):
|
|
760 |
for card in card_models.get('data') or []:
|
|
764 | 761 |
slug = card['slug'] |
765 | 762 |
if slug == card_slug: |
766 | 763 |
self.cached_title = card['title'] |
... | ... | |
838 | 835 |
if card_schema.get('err') == 1: |
839 | 836 |
if card_schema.get('err_class') == 'Page not found': |
840 | 837 |
self.mark_as_invalid('wcs_card_not_found') |
838 |
else: |
|
839 |
self.mark_as_valid() |
|
841 | 840 |
return |
842 | 841 | |
843 | 842 |
self.cached_title = card_schema['name'] |
... | ... | |
862 | 861 | |
863 | 862 |
wcs_site = get_wcs_services().get(self.wcs_site) |
864 | 863 | |
865 |
response = requests.get( |
|
866 |
api_url, |
|
867 |
remote_service=wcs_site, |
|
868 |
user=getattr(context.get('request'), 'user', None), |
|
869 |
cache_duration=5, |
|
870 |
raise_if_not_cached=not(context.get('synchronous')), |
|
871 |
log_errors=False) |
|
864 |
try: |
|
865 |
response = requests.get( |
|
866 |
api_url, |
|
867 |
remote_service=wcs_site, |
|
868 |
user=getattr(context.get('request'), 'user', None), |
|
869 |
cache_duration=5, |
|
870 |
raise_if_not_cached=not(context.get('synchronous')), |
|
871 |
log_errors=False) |
|
872 |
response.raise_for_status() |
|
873 |
except RequestException: |
|
874 |
return extra_context |
|
875 | ||
872 | 876 |
if response.status_code == 200: |
873 | 877 |
extra_context['card'] = response.json() |
874 | 878 |
combo/apps/wcs/utils.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
from django.conf import settings |
18 | 18 | |
19 |
from requests.exceptions import RequestException |
|
20 | ||
19 | 21 |
from combo.utils import requests |
20 | 22 | |
23 | ||
21 | 24 |
def is_wcs_enabled(cls): |
22 | 25 |
return hasattr(settings, 'KNOWN_SERVICES') and settings.KNOWN_SERVICES.get('wcs') |
23 | 26 | |
27 | ||
24 | 28 |
def get_wcs_services(): |
25 | 29 |
if not is_wcs_enabled(None): |
26 | 30 |
return {} |
... | ... | |
32 | 36 |
# no site specified (probably an import referencing a not yet deployed |
33 | 37 |
# site) |
34 | 38 |
return {'err': 1, 'err_desc': 'no-wcs-site'} |
35 |
response = requests.get(path, remote_service=wcs_site, without_user=True, |
|
39 |
try: |
|
40 |
response = requests.get( |
|
41 |
path, remote_service=wcs_site, without_user=True, |
|
36 | 42 |
headers={'accept': 'application/json'}) |
37 |
if response.status_code != 200:
|
|
38 |
# the exact error will have been logged during request.
|
|
39 |
return {} |
|
43 |
response.raise_for_status()
|
|
44 |
except RequestException:
|
|
45 |
return {'err': 1, 'data': None}
|
|
40 | 46 |
return response.json() |
41 | 47 | |
48 | ||
42 | 49 |
def get_wcs_options(url, include_category_slug=False): |
43 | 50 |
references = [] |
44 | 51 |
for wcs_key, wcs_site in sorted(get_wcs_services().items(), key=lambda x: x[1]['title']): |
45 | 52 |
site_title = wcs_site.get('title') |
46 | 53 |
response_json = get_wcs_json(wcs_site, url) |
47 |
if type(response_json) is dict: |
|
48 |
if response_json.get('err') == 1: |
|
49 |
continue |
|
50 |
response_json = response_json.get('data') |
|
54 |
if response_json.get('err') == 1: |
|
55 |
continue |
|
56 |
response_json = response_json.get('data') |
|
51 | 57 |
if not response_json: |
52 | 58 |
continue |
53 | 59 |
for element in response_json: |
tests/test_wcs.py | ||
---|---|---|
16 | 16 |
from django.utils.six.moves.urllib import parse as urlparse |
17 | 17 | |
18 | 18 |
import mock |
19 |
from requests.exceptions import ConnectionError |
|
20 |
from requests.models import Response |
|
19 | 21 | |
20 | 22 |
from combo.data.library import get_cell_classes |
21 | 23 |
from combo.data.models import CellBase, LinkListCell, Page, ValidityInfo |
... | ... | |
272 | 274 |
cell.save() |
273 | 275 |
assert ValidityInfo.objects.exists() is False |
274 | 276 | |
277 |
# can not retrieve data, don't set cell as invalid |
|
278 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
279 |
mock_resp = Response() |
|
280 |
mock_resp.status_code = 500 |
|
281 |
requests_get.return_value = mock_resp |
|
282 |
cell.save() |
|
283 |
assert ValidityInfo.objects.exists() is False |
|
284 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
285 |
requests_get.side_effect = ConnectionError() |
|
286 |
cell.save() |
|
287 |
assert ValidityInfo.objects.exists() is False |
|
288 | ||
275 | 289 |
# can not retrieve formdefs, don't set cell as invalid |
276 | 290 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
277 |
mock_json = mock.Mock(status_code=404) |
|
278 |
requests_get.return_value = mock_json |
|
291 |
mock_resp = Response() |
|
292 |
mock_resp.status_code = 404 |
|
293 |
requests_get.return_value = mock_resp |
|
279 | 294 |
cell.save() |
280 | 295 |
assert ValidityInfo.objects.exists() is False |
281 | 296 | |
... | ... | |
328 | 343 |
cell.save() |
329 | 344 |
assert ValidityInfo.objects.exists() is False |
330 | 345 | |
346 |
# can not retrieve data, don't set cell as invalid |
|
347 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
348 |
mock_resp = Response() |
|
349 |
mock_resp.status_code = 500 |
|
350 |
requests_get.return_value = mock_resp |
|
351 |
cell.save() |
|
352 |
assert ValidityInfo.objects.exists() is False |
|
353 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
354 |
requests_get.side_effect = ConnectionError() |
|
355 |
cell.save() |
|
356 |
assert ValidityInfo.objects.exists() is False |
|
357 | ||
331 | 358 |
# can not retrieve categories, don't set cell as invalid |
332 | 359 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
333 |
mock_json = mock.Mock(status_code=404) |
|
334 |
requests_get.return_value = mock_json |
|
360 |
mock_resp = Response() |
|
361 |
mock_resp.status_code = 404 |
|
362 |
requests_get.return_value = mock_resp |
|
335 | 363 |
cell.save() |
336 | 364 |
assert ValidityInfo.objects.exists() is False |
337 | 365 | |
... | ... | |
474 | 502 |
cell.get_data(context) |
475 | 503 |
assert ValidityInfo.objects.exists() is False |
476 | 504 | |
505 |
# can not retrieve data, don't set cell as invalid |
|
477 | 506 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
478 |
mock_json = mock.Mock(status_code=404) |
|
479 |
requests_get.return_value = mock_json |
|
507 |
mock_resp = Response() |
|
508 |
mock_resp.status_code = 500 |
|
509 |
requests_get.return_value = mock_resp |
|
510 |
cell.get_data(context) |
|
511 |
assert ValidityInfo.objects.exists() is False |
|
512 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
513 |
requests_get.side_effect = ConnectionError() |
|
514 |
cell.get_data(context) |
|
515 |
assert ValidityInfo.objects.exists() is False |
|
516 | ||
517 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
518 |
mock_resp = Response() |
|
519 |
mock_resp.status_code = 404 |
|
520 |
requests_get.return_value = mock_resp |
|
480 | 521 |
cell.get_data(context) |
481 | 522 |
assert ValidityInfo.objects.exists() is False |
482 | 523 | |
... | ... | |
496 | 537 |
cell.check_validity() |
497 | 538 |
assert ValidityInfo.objects.exists() is False |
498 | 539 | |
540 |
# can not retrieve data, don't set cell as invalid |
|
541 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
542 |
mock_resp = Response() |
|
543 |
mock_resp.status_code = 500 |
|
544 |
requests_get.return_value = mock_resp |
|
545 |
cell.check_validity() |
|
546 |
assert ValidityInfo.objects.exists() is False |
|
547 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
548 |
requests_get.side_effect = ConnectionError() |
|
549 |
cell.check_validity() |
|
550 |
assert ValidityInfo.objects.exists() is False |
|
551 | ||
499 | 552 |
# can not retrieve categories, don't set cell as invalid |
500 | 553 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
501 |
mock_json = mock.Mock(status_code=404) |
|
502 |
requests_get.return_value = mock_json |
|
554 |
mock_resp = Response() |
|
555 |
mock_resp.status_code = 404 |
|
556 |
requests_get.return_value = mock_resp |
|
503 | 557 |
cell.check_validity() |
504 | 558 |
assert ValidityInfo.objects.exists() is False |
505 | 559 | |
... | ... | |
608 | 662 |
cell.get_data(context) |
609 | 663 |
assert ValidityInfo.objects.exists() is False |
610 | 664 | |
665 |
# can not retrieve data, don't set cell as invalid |
|
666 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
667 |
mock_resp = Response() |
|
668 |
mock_resp.status_code = 500 |
|
669 |
requests_get.return_value = mock_resp |
|
670 |
cell.get_data(context) |
|
671 |
assert ValidityInfo.objects.exists() is False |
|
672 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
673 |
requests_get.side_effect = ConnectionError() |
|
674 |
cell.get_data(context) |
|
675 |
assert ValidityInfo.objects.exists() is False |
|
676 | ||
611 | 677 |
# can not retrieve data, don't set cell as invalid |
612 | 678 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
613 | 679 |
mock_json = mock.Mock(status_code=500) |
... | ... | |
723 | 789 |
context.pop('combo_display_even_empty_categories') |
724 | 790 | |
725 | 791 | |
726 |
def test_forms_of_category_cell_validity(context): |
|
792 |
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send) |
|
793 |
def test_forms_of_category_cell_validity(mock_send, context): |
|
727 | 794 |
page = Page.objects.create(title='xxx', slug='test_forms_of_category_cell_render', template_name='standard') |
728 | 795 |
cell = WcsFormsOfCategoryCell.objects.create(page=page, placeholder='content', order=0) |
729 | 796 |
validity_info = ValidityInfo.objects.latest('pk') |
... | ... | |
748 | 815 |
requests_get.return_value = mock_json |
749 | 816 |
cell.render(context) |
750 | 817 |
assert ValidityInfo.objects.exists() is False |
818 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
819 |
requests_get.side_effect = ConnectionError() |
|
820 |
cell.render(context) |
|
821 |
assert ValidityInfo.objects.exists() is False |
|
751 | 822 | |
752 | 823 |
# can not retrieve categories, don't set cell as invalid |
753 | 824 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
754 |
mock_json = mock.Mock(status_code=404) |
|
755 |
requests_get.return_value = mock_json |
|
825 |
mock_resp = Response() |
|
826 |
mock_resp.status_code = 404 |
|
827 |
requests_get.return_value = mock_resp |
|
756 | 828 |
cell.save() |
757 | 829 |
assert ValidityInfo.objects.exists() is False |
758 | 830 | |
... | ... | |
763 | 835 |
assert validity_info.invalid_since is not None |
764 | 836 | |
765 | 837 | |
766 |
def test_forms_of_category_cell_check_validity(context): |
|
838 |
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send) |
|
839 |
def test_forms_of_category_cell_check_validity(mock_send, context): |
|
767 | 840 |
page = Page.objects.create(title='xxx', slug='test_forms_of_category_cell_render', template_name='standard') |
768 | 841 |
cell = WcsFormsOfCategoryCell.objects.create(page=page, placeholder='content', order=0) |
769 | 842 | |
... | ... | |
861 | 934 |
cell.check_validity() |
862 | 935 |
assert ValidityInfo.objects.exists() is False |
863 | 936 | |
864 |
# can not retrieve vategories, don't set cell as invalid
|
|
937 |
# can not retrieve data, don't set cell as invalid
|
|
865 | 938 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
866 |
mock_json = mock.Mock(status_code=404) |
|
867 |
requests_get.return_value = mock_json |
|
939 |
mock_resp = Response() |
|
940 |
mock_resp.status_code = 500 |
|
941 |
requests_get.return_value = mock_resp |
|
942 |
cell.check_validity() |
|
943 |
assert ValidityInfo.objects.exists() is False |
|
944 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
945 |
requests_get.side_effect = ConnectionError() |
|
946 |
cell.check_validity() |
|
947 |
assert ValidityInfo.objects.exists() is False |
|
948 | ||
949 |
# can not retrieve categories, don't set cell as invalid |
|
950 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
951 |
mock_resp = Response() |
|
952 |
mock_resp.status_code = 404 |
|
953 |
requests_get.return_value = mock_resp |
|
868 | 954 |
cell.check_validity() |
869 | 955 |
assert ValidityInfo.objects.exists() is False |
870 | 956 | |
... | ... | |
984 | 1070 |
cell.save() |
985 | 1071 |
assert ValidityInfo.objects.exists() is False |
986 | 1072 | |
1073 |
# can not retrieve data, don't set cell as invalid |
|
1074 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
1075 |
mock_resp = Response() |
|
1076 |
mock_resp.status_code = 500 |
|
1077 |
requests_get.return_value = mock_resp |
|
1078 |
cell.save() |
|
1079 |
assert ValidityInfo.objects.exists() is False |
|
1080 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
1081 |
requests_get.side_effect = ConnectionError() |
|
1082 |
cell.save() |
|
1083 |
assert ValidityInfo.objects.exists() is False |
|
1084 | ||
987 | 1085 |
# can not retrieve carddefs, don't set cell as invalid |
988 | 1086 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
989 |
mock_json = mock.Mock(status_code=404) |
|
990 |
requests_get.return_value = mock_json |
|
1087 |
mock_resp = Response() |
|
1088 |
mock_resp.status_code = 404 |
|
1089 |
requests_get.return_value = mock_resp |
|
991 | 1090 |
cell.save() |
992 | 1091 |
assert ValidityInfo.objects.exists() is False |
993 | 1092 | |
... | ... | |
1081 | 1180 |
cell.save() |
1082 | 1181 |
assert ValidityInfo.objects.exists() is False |
1083 | 1182 | |
1183 |
# can not retrieve data, don't set cell as invalid |
|
1184 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
1185 |
mock_resp = Response() |
|
1186 |
mock_resp.status_code = 500 |
|
1187 |
requests_get.return_value = mock_resp |
|
1188 |
cell.save() |
|
1189 |
assert ValidityInfo.objects.exists() is False |
|
1190 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
1191 |
requests_get.side_effect = ConnectionError() |
|
1192 |
cell.save() |
|
1193 |
assert ValidityInfo.objects.exists() is False |
|
1194 | ||
1084 | 1195 |
# can not retrieve carddefs, don't set cell as invalid |
1085 | 1196 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
1086 |
mock_json = mock.Mock(status_code=404) |
|
1087 |
requests_get.return_value = mock_json |
|
1197 |
mock_resp = Response() |
|
1198 |
mock_resp.status_code = 404 |
|
1199 |
requests_get.return_value = mock_resp |
|
1088 | 1200 |
cell.save() |
1089 | 1201 |
assert ValidityInfo.objects.exists() is False |
1090 | 1202 | |
... | ... | |
1135 | 1247 | |
1136 | 1248 |
context['synchronous'] = True # to get fresh content |
1137 | 1249 | |
1250 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
1251 |
mock_resp = Response() |
|
1252 |
mock_resp.status_code = 500 |
|
1253 |
requests_get.return_value = mock_resp |
|
1254 |
result = cell.render(context) |
|
1255 |
assert '<p>Unknown Card</p>' in result |
|
1256 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
1257 |
requests_get.side_effect = ConnectionError() |
|
1258 |
result = cell.render(context) |
|
1259 |
assert '<p>Unknown Card</p>' in result |
|
1260 | ||
1138 | 1261 |
result = cell.render(context) |
1139 | 1262 |
assert '<h2>Card Model 1 - aa</h2>' in result |
1140 | 1263 |
assert '<span class="label">Field A</span>\n \n <span class="value">a</span>' in result |
1141 |
- |