combo/tests/test_wcs.py

2564 lines
101 KiB
Python

import copy
import json
import re
import urllib.parse
from unittest import mock
import pytest
from django.apps import apps
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.core.cache import cache
from django.db import connection
from django.test.client import RequestFactory
from django.test.utils import CaptureQueriesContext
from django.urls import reverse
from pyquery import PyQuery
from requests.exceptions import ConnectionError
from requests.models import Response
from combo.apps.search.engines import engines
from combo.apps.search.models import SearchCell
from combo.apps.search.utils import index_site, search_site
from combo.apps.wcs.context_processors import Cards
from combo.apps.wcs.models import (
BackofficeSubmissionCell,
CategoriesCell,
TrackingCodeInputCell,
WcsCardInfosCell,
WcsCardsCell,
WcsCareFormsCell,
WcsCategoryCell,
WcsCurrentDraftsCell,
WcsCurrentFormsCell,
WcsFormCell,
WcsFormsOfCategoryCell,
)
from combo.data.library import get_cell_classes
from combo.data.models import CellBase, LinkListCell, Page, ValidityInfo
from combo.utils import NothingInCacheException
from .test_manager import login
pytestmark = pytest.mark.django_db
WCS_FORMDEFS_DATA = [
{'slug': 'a-private-form', 'title': 'a private form', 'url': '/a-private-form/'},
{'slug': 'a-second-form-title', 'title': 'a second form title', 'url': '/a-second-form-title/'},
{'slug': 'form-title', 'title': 'form title', 'url': '/form-title/', 'keywords': ['foo', 'bar']},
{'slug': 'third-form-title', 'title': 'Third form title', 'url': '/third-form-title/'},
]
WCS_CATEGORIES_DATA = [
{'slug': 'test-%s' % i, 'title': 'Test %s' % i, 'url': '/test-%s/' % i} for i in [3, 9]
]
WCS_CATEGORIES_FORMDEFS_DATA = [
{
'slug': 'form-title',
'title': 'form title',
'url': '/form-title/',
'keywords': ['foo', 'bar'],
'count': 42,
},
{
'slug': 'a-second-form-title',
'title': 'a second form title',
'url': '/a-second-form-title/',
'count': 35,
},
]
WCS_USER_FORMS_DATA = [
{
'name': 'name',
'title': 'Title',
'url': '/form/1/',
'form_receipt_datetime': '2015-01-01T00:00:00',
'readable': True,
'category_slug': 'test-9',
},
{'name': 'name', 'url': '/form/2/', 'form_receipt_datetime': '2015-01-01T00:00:00', 'readable': True},
{'name': 'name', 'title': 'Title', 'url': '/form/3/', 'form_receipt_datetime': '2015-01-01T00:00:00'},
]
WCS_FORMS_DATA = [
{
'form_receipt_datetime': '2019-10-17T16:46:03',
'form_url_backoffice': '/backoffice/management/foobar/1/',
},
{
'form_receipt_datetime': '2019-10-17T16:46:04',
'form_url_backoffice': '/backoffice/management/foobar/2/',
},
]
WCS_USER_DRAFTS_DATA = [
{
'name': 'name',
'title': 'Title',
'url': '/form/1/',
'form_receipt_datetime': '2015-01-01T00:00:00',
'category_slug': 'test-9',
},
{'name': 'name', 'url': '/form/2/', 'form_receipt_datetime': '2015-01-01T00:00:00'},
{'name': 'name', 'title': 'Title', 'url': '/form/3/', 'form_receipt_datetime': '2015-01-01T00:00:00'},
{
'name': 'name',
'title': 'Title',
'url': '/form/4/',
'form_receipt_datetime': '2015-01-01T00:00:00',
'form_status_is_endpoint': True,
'category_slug': 'test-9',
},
]
WCS_CARDDEFS_DATA = [
{'title': 'Card Model 1', 'slug': 'card_model_1', 'custom_views': [{'id': 'foo', 'text': 'bar'}]},
{'title': 'Card Model 2', 'slug': 'card_model_2'},
{'title': 'Card Model 3', 'slug': 'card_model_3'},
]
WCS_CARDS_DATA = [
{
'id': 11,
'display_id': '10-11',
'display_name': 'Card Model 1 - n°10-11',
'digest': 'a a a',
'text': 'aa',
'url': '/backoffice/data/card_model_1/11/',
},
{
'id': 12,
'display_id': '10-12',
'display_name': 'Card Model 1 - n°10-12',
'digest': 'b b b',
'text': 'bb',
'url': '/backoffice/data/card_model_1/12/',
},
{
'id': 13,
'display_id': '10-13',
'display_name': 'Card Model 1 - n°10-13',
'digest': 'c c c',
'text': 'cc',
'url': '/backoffice/data/card_model_1/13/',
},
]
WCS_CARDS_CUSTOM_VIEW_DATA = [
{
'id': 11,
'display_id': '10-11',
'display_name': 'Card Model 1 - n°10-11',
'digest': 'a a a',
'text': 'aa',
'url': '/backoffice/data/card_model_1/11/',
},
{
'id': 12,
'display_id': '10-12',
'display_name': 'Card Model 1 - n°10-12',
'digest': 'b b b',
'text': 'bb',
'url': '/backoffice/data/card_model_1/12/',
},
]
WCS_CARDDEF_SCHEMA = {
'name': 'Card Model 1',
'fields': [
{'label': 'Field A', 'varname': 'fielda', 'type': 'string'},
{'label': 'Field B', 'varname': 'fieldb', 'type': 'bool'},
{'label': 'Field C', 'varname': 'fieldc', 'type': 'date'},
{'label': 'Field D', 'varname': 'fieldd', 'type': 'file'},
{'label': 'Field E', 'varname': 'fielde', 'type': 'text'},
{'label': 'Field F', 'varname': 'fieldf', 'type': 'text', 'pre': True},
{'label': 'Related', 'varname': 'related', 'type': 'item'},
{'label': 'Page', 'type': 'page'},
{'label': 'Comment', 'type': 'comment'},
{'label': 'Title', 'type': 'title'},
{'label': 'Subtitle', 'type': 'subtitle'},
{'label': 'Empty', 'varname': None, 'type': 'string'},
],
}
WCS_CARD_DATA = {
'id': 11,
'display_id': '10-11',
'display_name': 'Card Model 1 - n°10-11',
'digest': 'a a a',
'text': 'aa',
'url': '/backoffice/data/card_model_1/11/',
'fields': {
'fielda': 'a',
'fieldb': True,
'fieldc': '2020-09-28',
'fieldd': {'filename': 'file.pdf', 'url': 'http://some-url.com/download?f=42'},
'fielde': 'lorem<strong>ipsum\n\nhello world',
'fieldf': 'lorem<strong>ipsum\n\nhello world',
'related': 'Foo Bar',
'related_raw': 42,
'related_structured': {'id': 42, 'text': 'blah'},
},
}
class MockUser:
email = 'foo@example.net'
is_authenticated = True
is_anonymous = False
def get_name_id(self):
return None
class MockUserWithNameId:
email = 'foo@example.net'
is_authenticated = True
is_anonymous = False
def get_name_id(self):
return 'xyz'
class MockedRequestResponse(mock.Mock):
status_code = 200
def json(self):
return json.loads(self.content)
def get_data_from_url(url):
if '/api/formdefs/' in url:
return WCS_FORMDEFS_DATA
if '/api/categories/' in url:
if '/formdefs/' in url:
return WCS_CATEGORIES_FORMDEFS_DATA
return WCS_CATEGORIES_DATA
if '/api/user/forms' in url:
return WCS_USER_FORMS_DATA
if '/api/forms' in url:
return WCS_FORMS_DATA
if '/api/user/drafts' in url:
return WCS_USER_DRAFTS_DATA
if '/api/cards/@list' in url:
return WCS_CARDDEFS_DATA
if '/api/cards/card_model_1/@schema' in url:
return WCS_CARDDEF_SCHEMA
if 'api/cards/card_model_1/11/' in url:
return WCS_CARD_DATA
if 'api/cards/card_model_1/list/foo' in url:
return WCS_CARDS_CUSTOM_VIEW_DATA
if 'api/cards/card_model_1/list' in url:
return WCS_CARDS_DATA
return []
def mocked_requests_send(request, **kwargs):
request_url = urllib.parse.urlparse(request.url)
data = copy.deepcopy(get_data_from_url(request_url.path))
if not isinstance(data, list):
return MockedRequestResponse(content=json.dumps(data))
for elem in data:
for key in ['url', 'form_url_backoffice']:
if key not in elem:
continue
elem_url = elem[key]
elem[key] = '{scheme}://{netloc}{url}'.format(
scheme=request_url.scheme, netloc=request_url.netloc, url=elem_url
)
return MockedRequestResponse(content=json.dumps({'data': data}))
@pytest.fixture
def context():
ctx = {'request': RequestFactory().get('/')}
ctx['request'].user = None
ctx['request'].session = {}
return ctx
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_form_cell_setup(mock_send):
cell = WcsFormCell()
form_class = cell.get_default_form_class()
form = form_class()
assert form.fields['formdef_reference'].widget.choices == [
('default:a-private-form', 'test : a private form'),
('default:a-second-form-title', 'test : a second form title'),
('default:form-title', 'test : form title'),
('default:third-form-title', 'test : Third form title'),
('other:a-private-form', 'test2 : a private form'),
('other:a-second-form-title', 'test2 : a second form title'),
('other:form-title', 'test2 : form title'),
('other:third-form-title', 'test2 : Third form title'),
]
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_form_cell_save_cache(mock_send):
page = Page(title='xxx', slug='test_form_cell_save_cache', template_name='standard')
page.save()
cell = WcsFormCell(page=page, placeholder='content', order=0)
assert cell.get_additional_label() is None
cell.formdef_reference = 'default:form-title'
cell.save()
assert cell.cached_title == 'form title'
assert cell.get_additional_label() == 'form title'
# make sure cached attributes are removed from serialized pages
assert 'cached_' not in json.dumps(page.get_serialized_page())
# check content provided to search engine
assert cell.render_for_search() == ''
assert cell.get_external_links_data() == [
{'title': 'form title', 'url': 'http://127.0.0.1:8999/form-title/', 'text': 'foo bar'}
]
# artificially change title
WcsFormCell.objects.filter(id=cell.id).update(cached_title='XXX')
assert WcsFormCell.objects.get(id=cell.id).cached_title == 'XXX'
# run update db cache
appconfig = apps.get_app_config('wcs')
appconfig.update_db_cache()
assert WcsFormCell.objects.get(id=cell.id).cached_title == 'form title'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_form_cell_validity(mock_send):
page = Page.objects.create(title='xxx', slug='test_form_cell_save_cache', template_name='standard')
cell = WcsFormCell.objects.create(page=page, placeholder='content', order=0)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_form_not_defined'
assert validity_info.invalid_since is not None
cell.formdef_reference = 'default:form-title'
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve formdefs, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
cell.formdef_reference = 'default:foobar'
cell.save()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_form_not_found'
assert validity_info.invalid_since is not None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_form_cell_load(mock_send):
page = Page(title='xxx', slug='test_form_cell_save_cache', template_name='standard')
page.save()
cell = WcsFormCell(page=page, placeholder='content', order=0)
cell.formdef_reference = 'default:form-title'
cell.save()
site_export = [page.get_serialized_page()]
cell.delete()
assert not Page.objects.get(id=page.id).get_cells()
Page.load_serialized_pages(site_export)
page = Page.objects.get(slug='test_form_cell_save_cache')
cells = page.get_cells()
assert len(cells) == 1
cell = cells[0]
assert cell.cached_title == 'form title'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_category_cell_save_cache(mock_send):
page = Page(title='xxx', slug='test_category_cell_save_cache', template_name='standard')
page.save()
cell = WcsCategoryCell(page=page, placeholder='content', order=0)
assert cell.get_additional_label() is None
cell.category_reference = 'default:test-3'
cell.save()
assert cell.cached_title == 'Test 3'
assert cell.get_additional_label() == 'Test 3'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_category_cell_validity(mock_send):
page = Page.objects.create(title='xxx', slug='test_category_cell_save_cache', template_name='standard')
cell = WcsCategoryCell.objects.create(page=page, placeholder='content', order=0)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_defined'
assert validity_info.invalid_since is not None
cell.category_reference = 'default:test-3'
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve categories, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
cell.category_reference = 'default:foobar'
cell.save()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_categories_cell_check_validity(mock_send):
page = Page.objects.create(title='xxx', slug='test', template_name='standard')
cell = CategoriesCell.objects.create(page=page, placeholder='content', order=0)
# invalid wcs_site
cell.wcs_site = 'invalid'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_site_not_found'
assert validity_info.invalid_since is not None
# valid wcs_site
cell.wcs_site = 'default'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_form_cell_render(mock_send):
page = Page(title='xxx', slug='test_form_cell_render', template_name='standard')
page.save()
cell = WcsFormCell(page=page, placeholder='content', order=0)
cell.formdef_reference = 'default:form-title'
cell.save()
result = cell.render({})
assert 'http://127.0.0.1:8999/form-title/tryauth' in result
assert 'form title' in result
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_forms_cell_setup(mock_send):
cell = WcsCurrentFormsCell()
form_class = cell.get_default_form_class()
form = form_class()
assert form.fields['wcs_site'].widget.choices == [
('', 'All'),
('default', 'test'),
('other', 'test2'),
]
assert 'current_forms' in form.fields
assert cell.get_additional_label() == 'All Sites - Current Forms'
cell.wcs_site = 'default'
assert cell.get_additional_label() == 'test - Current Forms'
cell.wcs_site = None
cell.current_forms = True
cell.done_forms = True
assert cell.get_additional_label() == 'All Sites - All Forms'
cell.current_forms = False
cell.done_forms = True
assert cell.get_additional_label() == 'All Sites - Done Forms'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_forms_cell_render(mock_send, context):
page = Page(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
page.save()
cell = WcsCurrentFormsCell(page=page, placeholder='content', order=0)
cell.save()
context['request'].user = MockUser()
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
result = cell.render(context)
context['synchronous'] = True # to get fresh content
result = cell.render(context)
assert 'http://127.0.0.1:8999/form/1/' in result
assert 'http://127.0.0.1:8999/form/2/' not in result # no title
assert 'http://127.0.0.1:8999/form/3/' not in result # not readable
assert 'http://127.0.0.2:8999/form/1/' in result
assert 'http://127.0.0.2:8999/form/2/' not in result
assert 'http://127.0.0.2:8999/form/3/' not in result
# limit to categories
cell.categories = {'data': ['default:test-3', 'other:test-6']}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert (
requests_get.call_args_list[0][0][0]
== '/api/user/forms/?status=open&limit=100&sort=desc&category_slugs=test-3'
)
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert (
requests_get.call_args_list[1][0][0]
== '/api/user/forms/?status=open&limit=100&sort=desc&category_slugs=test-6'
)
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
# check include drafts
cell.categories = None
cell.include_drafts = False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
cell.include_drafts = True
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert (
requests_get.call_args_list[0][0][0]
== '/api/user/forms/?status=open&include-drafts=on&limit=100&sort=desc'
)
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert (
requests_get.call_args_list[1][0][0]
== '/api/user/forms/?status=open&include-drafts=on&limit=100&sort=desc'
)
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
cell.categories = {'data': ['default:test-3']}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 1
assert (
requests_get.call_args_list[0][0][0]
== '/api/user/forms/?status=open&include-drafts=on&limit=100&sort=desc&category_slugs=test-3'
)
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
cell.categories = {'data': []}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
# current_forms only
cell.include_drafts = False
cell.current_forms = True
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
# all forms
cell.done_forms = True
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=all&limit=100&sort=desc'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=all&limit=100&sort=desc'
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
# done forms only
cell.current_forms = False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=done&limit=100&sort=desc'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=done&limit=100&sort=desc'
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
# include forms user can see
cell.include_forms_user_can_access = True
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert (
requests_get.call_args_list[0][0][0]
== '/api/user/forms/?status=done&include-accessible=on&limit=100&sort=desc'
)
# check empty messages
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.current_forms = True
cell.done_forms = False
cell.include_drafts = False
result = cell.render(context)
assert 'There are no current forms.' in result
cell.done_forms = True
result = cell.render(context)
assert 'There are no forms.' in result
cell.current_forms = False
result = cell.render(context)
assert 'There are no done forms' in result
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_forms_cell_validity(mock_send, context):
page = Page.objects.create(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
cell = WcsCurrentFormsCell.objects.create(page=page, placeholder='content', order=0)
context['request'].user = MockUser()
context['synchronous'] = True # to get fresh content
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_forms_cell_check_validity(mock_send, context):
page = Page.objects.create(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
cell = WcsCurrentFormsCell.objects.create(page=page, placeholder='content', order=0)
# no category
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# valid categories
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve categories, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# invalid category
cell.categories = {'data': ['default:foobar', 'default:test-9']}
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
# invalid wcs_site
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.wcs_site = 'invalid'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_site_not_found'
assert validity_info.invalid_since is not None
# valid wcs_site
cell.wcs_site = 'default'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_forms_cell_render_single_site(mock_send, context):
page = Page(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
page.save()
cell = WcsCurrentFormsCell(page=page, placeholder='content', order=0)
cell.wcs_site = 'default'
cell.save()
context['request'].user = MockUser()
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
result = cell.render(context)
context['synchronous'] = True # to get fresh content
result = cell.render(context)
assert 'http://127.0.0.1:8999/form/1/' in result
assert 'http://127.0.0.2:8999/form/1/' not in result
def test_current_forms_name_id(context):
page = Page(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
page.save()
cell = WcsCurrentFormsCell(page=page, placeholder='content', order=0)
cell.wcs_site = 'default'
cell.save()
context['request'].user = MockUserWithNameId()
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
cell.render(context)
context['synchronous'] = True # to get fresh content
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert requests_get.call_args_list[0][0][0] == '/api/users/xyz/forms?status=open&limit=100&sort=desc'
def test_care_forms_cell_setup():
cell = WcsCareFormsCell()
form_class = cell.get_default_form_class()
form = form_class()
assert form.fields['wcs_site'].widget.choices == [
('', 'All'),
('default', 'test'),
('other', 'test2'),
]
assert cell.get_additional_label() == 'All Sites'
cell.wcs_site = 'default'
assert cell.get_additional_label() == 'test'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_care_forms_cell_render(mock_send, context):
page = Page(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
page.save()
cell = WcsCareFormsCell(page=page, placeholder='content', order=0)
cell.save()
context['request'].user = MockUser()
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
result = cell.render(context)
context['synchronous'] = True # to get fresh content
result = cell.render(context)
assert 'http://127.0.0.1:8999/backoffice/management/foobar/1' in result
assert 'http://127.0.0.1:8999/backoffice/management/foobar/2' in result
assert '"http://127.0.0.1:8999/backoffice/management/listing"' in result
assert 'http://127.0.0.2:8999/backoffice/management/foobar/1' in result
assert 'http://127.0.0.2:8999/backoffice/management/foobar/2' in result
assert '"http://127.0.0.2:8999/backoffice/management/listing"' in result
data = cell.get_data(context)
assert 'default' in data
assert 'other' in data
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10'
assert requests_get.call_args_list[1][0][0] == '/api/forms/?limit=10'
# limit to a list of categories
cell.categories = {'data': ['default:test-3', 'other:test-4']}
result = cell.render(context)
assert '"http://127.0.0.1:8999/backoffice/management/listing?category_slugs=test-3"' in result
assert '"http://127.0.0.2:8999/backoffice/management/listing?category_slugs=test-4"' in result
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10&category_slugs=test-3'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert requests_get.call_args_list[1][0][0] == '/api/forms/?limit=10&category_slugs=test-4'
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
# limit to a single category
cell.categories = {'data': ['default:test-3']}
result = cell.render(context)
assert '"http://127.0.0.1:8999/backoffice/management/listing?category_slugs=test-3"' in result
assert '"http://127.0.0.2:8999/backoffice/management/listing' not in result
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert len(requests_get.call_args_list) == 1
assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10&category_slugs=test-3'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
# no category selected: call all sites
cell.categories = {'data': []}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert len(requests_get.call_args_list) == 2
def test_care_forms_cell_validity(context):
page = Page.objects.create(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
cell = WcsCareFormsCell.objects.create(page=page, placeholder='content', order=0)
context['synchronous'] = True # to get fresh content
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=500)
requests_get.return_value = mock_json
cell.get_data(context)
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=404)
requests_get.return_value = mock_json
cell.get_data(context)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_data_failure'
assert validity_info.invalid_since is not None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_care_forms_cell_check_validity(mock_send, context):
page = Page.objects.create(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
cell = WcsCareFormsCell.objects.create(page=page, placeholder='content', order=0)
# no category
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# valid categories
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve categories, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# invalid category
cell.categories = {'data': ['default:foobar', 'default:test-9']}
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
# invalid wcs_site
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.wcs_site = 'invalid'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_site_not_found'
assert validity_info.invalid_since is not None
# valid wcs_site
cell.wcs_site = 'default'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_care_forms_cell_render_single_site(mock_send, context):
page = Page(title='xxx', slug='test_care_forms_cell_render', template_name='standard')
page.save()
cell = WcsCareFormsCell(page=page, placeholder='content', order=0)
cell.wcs_site = 'default'
cell.save()
context['request'].user = MockUser()
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
result = cell.render(context)
context['synchronous'] = True # to get fresh content
result = cell.render(context)
assert '"http://127.0.0.1:8999/backoffice/management/listing"' in result
assert '"http://127.0.0.2:8999/backoffice/management/listing"' not in result
data = cell.get_data(context)
assert 'default' in data
assert 'other' not in data
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_forms_of_category_cell_setup(mock_send):
cell = WcsFormsOfCategoryCell()
form_class = cell.get_default_form_class()
form = form_class()
assert form.fields['category_reference'].widget.choices == [
('default:test-3', 'test : Test 3'),
('default:test-9', 'test : Test 9'),
('other:test-3', 'test2 : Test 3'),
('other:test-9', 'test2 : Test 9'),
]
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_forms_of_category_cell_render(mock_send, context):
page = Page(title='xxx', slug='test_forms_of_category_cell_render', template_name='standard')
page.save()
cell = WcsFormsOfCategoryCell(page=page, placeholder='content', order=0)
cell.category_reference = 'default:test-9'
cell.ordering = 'alpha'
cell.save()
context['synchronous'] = True # to get fresh content
result = cell.render(context)
assert 'form title' in result and 'a second form title' in result
assert result.index('form title') > result.index('a second form title')
assert 'http://127.0.0.1:8999/form-title/tryauth' in result
assert 'http://127.0.0.1:8999/a-second-form-title/tryauth' in result
assert 'keyword-foo' in result
assert 'keyword-bar' in result
cell.ordering = 'popularity'
cell.save()
result = cell.render(context)
assert 'form title' in result and 'a second form title' in result
assert result.index('form title') < result.index('a second form title')
cell.ordering = 'manual'
cell.save()
result = cell.render(context)
# by default all forms should be present, in alphabetical order
assert result.index('form title') > result.index('a second form title')
# set a manual order
cell.manual_order = {'data': ['default:test-9:a-second-form-title', 'default:test-9:form-title']}
cell.save()
result = cell.render(context)
assert result.index('form title') > result.index('a second form title')
# make sure all forms are displayed even if the manual order only specify
# some.
cell.manual_order = {'data': ['default:test-9:a-second-form-title']}
cell.save()
result = cell.render(context)
assert result.index('form title') > result.index('a second form title')
assert 'form title' in result and 'a second form title' in result
# check content provided to search engine
assert cell.render_for_search() == ''
assert len(list(cell.get_external_links_data())) == 2
# existing category, but empty
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
result = cell.render(context)
assert '<h2>' not in result
context['combo_display_even_empty_categories'] = True
assert len(requests_get.call_args_list) == 1
assert requests_get.call_args_list[0][0][0] == '/api/categories/test-9/formdefs/'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
result = cell.render(context)
assert '<h2>' in result
context.pop('combo_display_even_empty_categories')
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_forms_of_category_cell_validity(mock_send, context):
page = Page.objects.create(
title='xxx', slug='test_forms_of_category_cell_render', template_name='standard'
)
cell = WcsFormsOfCategoryCell.objects.create(page=page, placeholder='content', order=0)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_defined'
assert validity_info.invalid_since is not None
cell.category_reference = 'default:test-9'
cell.save()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=404)
requests_get.return_value = mock_json
cell.render(context)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_data_failure'
assert validity_info.invalid_since is not None
cell.mark_as_valid()
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=500)
requests_get.return_value = mock_json
cell.render(context)
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.render(context)
assert ValidityInfo.objects.exists() is False
# can not retrieve categories, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
cell.category_reference = 'default:foobar'
cell.save()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_forms_of_category_cell_check_validity(mock_send, context):
page = Page.objects.create(
title='xxx', slug='test_forms_of_category_cell_render', template_name='standard'
)
cell = WcsFormsOfCategoryCell.objects.create(page=page, placeholder='content', order=0)
# valid category
cell.category_reference = 'default:test-9'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# valid category but empty
cell.category_reference = 'default:test-1'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
def test_current_drafts_cell_render_unlogged(context):
page = Page(title='xxx', slug='test_current_drafts_cell_render', template_name='standard')
page.save()
cell = WcsCurrentDraftsCell(page=page, placeholder='content', order=0)
cell.save()
context['synchronous'] = True # to get fresh content
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
result = cell.render(context)
assert requests_get.call_args_list[0][0][0] == '/api/user/drafts'
assert 'http://127.0.0.1:8999/third-form-title' not in result # no form
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_drafts_cell_render_logged_in(mock_send, context):
page = Page(title='xxx', slug='test_current_drafts_cell_render', template_name='standard')
page.save()
cell = WcsCurrentDraftsCell(page=page, placeholder='content', order=0)
cell.save()
context['synchronous'] = True # to get fresh content
context['request'].user = MockUser()
# default is to get current forms from all wcs sites
result = cell.render(context)
assert 'http://127.0.0.1:8999/form/1/' in result
assert 'http://127.0.0.1:8999/form/2/' not in result # no title
assert 'http://127.0.0.1:8999/form/3/' in result
assert 'http://127.0.0.1:8999/form/4/' not in result # done
assert 'http://127.0.0.2:8999/form/1/' in result
assert 'http://127.0.0.2:8999/form/2/' not in result
assert 'http://127.0.0.2:8999/form/3/' in result
assert 'http://127.0.0.2:8999/form/4/' not in result
# check flat list
extra_context = cell.get_cell_extra_context(context)
assert len(extra_context['drafts']) == 8
assert len([x for x in extra_context['drafts'] if x['site_slug'] == 'default']) == 4
assert len([x for x in extra_context['drafts'] if x['site_slug'] == 'other']) == 4
# limit to categories
cell.categories = {'data': ['default:test-3', 'other:test-6']}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/user/drafts?category_slugs=test-3'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert requests_get.call_args_list[1][0][0] == '/api/user/drafts?category_slugs=test-6'
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
cell.categories = {'data': ['default:test-3']}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 1
assert requests_get.call_args_list[0][0][0] == '/api/user/drafts?category_slugs=test-3'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
cell.categories = {'data': []}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.get_cell_extra_context(context)
assert len(requests_get.call_args_list) == 2
# check empty message
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
result = cell.render(context)
assert 'There are no current drafts.' in result
context['request'].user = MockUserWithNameId()
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert requests_get.call_args_list[0][0][0] == '/api/users/xyz/drafts'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_current_drafts_cell_check_validity(mock_send, context):
page = Page.objects.create(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
cell = WcsCurrentDraftsCell.objects.create(page=page, placeholder='content', order=0)
# no category
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# valid categories
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve categories, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# invalid category
cell.categories = {'data': ['default:foobar', 'default:test-9']}
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
# invalid wcs_site
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.wcs_site = 'invalid'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_site_not_found'
assert validity_info.invalid_since is not None
# valid wcs_site
cell.wcs_site = 'default'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_manager_forms_of_category_cell(mock_send, app, admin_user):
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = app.get(
resp.html.find('option', **{'data-add-url': re.compile('wcsformsofcategorycell')})['data-add-url']
)
cells = Page.objects.get(id=page.id).get_cells()
assert len(cells) == 1
assert isinstance(cells[0], WcsFormsOfCategoryCell)
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
resp.forms[0]['c%s-ordering' % cells[0].get_reference()].value = 'manual'
resp = resp.forms[0].submit()
assert resp.status_int == 302
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_manager_current_forms(mock_send, settings, app, admin_user):
page = Page(title='One', slug='one', template_name='standard')
page.save()
app = login(app)
resp = app.get('/manage/pages/%s/' % page.id)
resp = app.get(
resp.html.find('option', **{'data-add-url': re.compile('wcscurrentformscell')})['data-add-url']
)
cells = Page.objects.get(id=page.id).get_cells()
assert len(cells) == 1
assert isinstance(cells[0], WcsCurrentFormsCell)
resp = app.get('/manage/pages/%s/' % page.id)
assert ('data-cell-reference="%s"' % cells[0].get_reference()) in resp.text
assert len(resp.form['c%s-categories' % cells[0].get_reference()].options) == 4
resp.form['c%s-categories' % cells[0].get_reference()].value = ['default:test-3', 'default:test-9']
resp = resp.form.submit().follow()
assert resp.form['c%s-categories' % cells[0].get_reference()].value == [
'default:test-3',
'default:test-9',
]
resp.form['c%s-current_forms' % cells[0].get_reference()] = False
resp.form['c%s-done_forms' % cells[0].get_reference()] = False
resp = resp.form.submit()
assert 'Please choose at least one option among the following: Current Forms, Done Forms' in resp
resp = app.get('/manage/pages/%s/' % page.id)
resp.form['c%s-done_forms' % cells[0].get_reference()] = True
resp = resp.form.submit().follow()
# check wcs_site field is a select box
assert resp.form['c%s-wcs_site' % cells[0].get_reference()].tag == 'select'
default = settings.KNOWN_SERVICES['wcs']['default']
settings.KNOWN_SERVICES = {'wcs': {'default': default}}
resp = app.get('/manage/pages/%s/' % page.id)
assert resp.form['c%s-wcs_site' % cells[0].get_reference()].attrs['type'] == 'hidden'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_manager_cards_cell(mock_send, app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cards_cell_save_cache', template_name='standard')
cell = WcsCardsCell.objects.create(page=page, placeholder='content', order=0)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert ('data-cell-reference="%s"' % cell.get_reference()) in resp.text
assert cell.without_user is False
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value == 'on'
resp.forms[0]['c%s-with_user' % cell.get_reference()].value = False
resp.forms[0].submit().follow()
cell.refresh_from_db()
assert cell.without_user is True
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value is None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_setup(mock_send):
cell = WcsCardsCell()
form_class = cell.get_default_form_class()
form = form_class(instance=cell)
assert form.fields['carddef_reference'].widget.choices == [
('default:card_model_1', 'test : Card Model 1'),
('default:card_model_1:foo', 'test : Card Model 1 - bar'),
('default:card_model_2', 'test : Card Model 2'),
('default:card_model_3', 'test : Card Model 3'),
('other:card_model_1', 'test2 : Card Model 1'),
('other:card_model_1:foo', 'test2 : Card Model 1 - bar'),
('other:card_model_2', 'test2 : Card Model 2'),
('other:card_model_3', 'test2 : Card Model 3'),
]
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_save_cache(mock_send):
page = Page.objects.create(title='xxx', slug='test_cards_cell_save_cache', template_name='standard')
cell = WcsCardsCell(page=page, placeholder='content', order=0)
assert cell.get_additional_label() is None
cell.carddef_reference = 'default:card_model_1'
cell.save()
assert cell.cached_title == 'Card Model 1'
assert cell.get_additional_label() == 'Card Model 1'
# make sure cached attributes are removed from serialized pages
assert 'cached_' not in json.dumps(page.get_serialized_page())
cell.carddef_reference = 'default:card_model_1:foo'
cell.save()
assert cell.cached_title == 'Card Model 1 - bar'
assert cell.get_additional_label() == 'Card Model 1 - bar'
# check content provided to search engine
assert cell.render_for_search() == ''
# artificially change title
WcsCardsCell.objects.filter(pk=cell.pk).update(cached_title='XXX')
assert WcsCardsCell.objects.get(pk=cell.pk).cached_title == 'XXX'
# run update db cache
appconfig = apps.get_app_config('wcs')
appconfig.update_db_cache()
assert WcsCardsCell.objects.get(pk=cell.pk).cached_title == 'Card Model 1 - bar'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_validity(mock_send):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardsCell.objects.create(page=page, placeholder='content', order=0)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_card_not_defined'
assert validity_info.invalid_since is not None
cell.carddef_reference = 'default:card_model_1'
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve carddefs, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
cell.carddef_reference = 'default:foobar'
cell.save()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_card_not_found'
assert validity_info.invalid_since is not None
cell.carddef_reference = 'default:card_model_1:foo'
cell.save()
assert ValidityInfo.objects.exists() is False
cell.carddef_reference = 'default:card_model_1:bar'
cell.save()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_card_not_found'
assert validity_info.invalid_since is not None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_load(mock_send):
page = Page.objects.create(title='xxx', slug='test_cards', template_name='standard')
cell = WcsCardsCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
site_export = [page.get_serialized_page()]
cell.delete()
assert not Page.objects.get(pk=page.pk).get_cells()
Page.load_serialized_pages(site_export)
page = Page.objects.get(slug='test_cards')
cells = page.get_cells()
assert len(cells) == 1
cell = cells[0]
assert cell.cached_title == 'Card Model 1'
cell.carddef_reference = 'default:card_model_1:foo'
cell.save()
site_export = [page.get_serialized_page()]
cell.delete()
assert not Page.objects.get(pk=page.pk).get_cells()
Page.load_serialized_pages(site_export)
page = Page.objects.get(slug='test_cards')
cells = page.get_cells()
assert len(cells) == 1
cell = cells[0]
assert cell.cached_title == 'Card Model 1 - bar'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_render(mock_send, context):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardsCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
result = cell.render(context)
context['synchronous'] = True # to get fresh content
context['cell'] = cell
result = cell.render(context)
assert '<h2>Card Model 1</h2>' in result
assert 'cards-card_model_1' in result
assert (
'<a href="http://127.0.0.1:8999/backoffice/data/card_model_1/11/"><span class="card-title">aa</span></a>'
in result
)
assert (
'<a href="http://127.0.0.1:8999/backoffice/data/card_model_1/12/"><span class="card-title">bb</span></a>'
in result
)
assert (
'<a href="http://127.0.0.1:8999/backoffice/data/card_model_1/13/"><span class="card-title">cc</span></a>'
in result
)
assert 'data-paginate-by="10"' in result
# create a page with the correct subslug
page = Page.objects.create(slug='foo', title='Foo', sub_slug='(?P<card_model_1_id>[a-z0-9]+)')
result = cell.render(context)
assert '<h2>Card Model 1</h2>' in result
assert '<a href="/foo/11"><span class="card-title">aa</span></a>' in result
assert '<a href="/foo/12"><span class="card-title">bb</span></a>' in result
assert '<a href="/foo/13"><span class="card-title">cc</span></a>' in result
cell.carddef_reference = 'default:card_model_1:foo'
cell.limit = 42
cell.save()
page.sub_slug = 'card_model_1_id'
page.save()
result = cell.render(context)
assert '<h2>Card Model 1 - bar</h2>' in result
assert '<a href="/foo/11"><span class="card-title">aa</span></a>' in result
assert '<a href="/foo/12"><span class="card-title">bb</span></a>' in result
assert '<a href="/foo/13"><span class="card-title">cc</span></a>' not in result
assert 'data-paginate-by="42"' in result
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
cell.render(context)
assert len(requests_get.call_args_list) == 1
assert requests_get.call_args_list[0][0][0] == '/api/cards/card_model_1/list/foo'
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
cell.custom_title = 'Foo bar'
cell.save()
result = cell.render(context)
assert '<h2>Card Model 1 - bar</h2>' not in result
assert '<h2>Foo bar</h2>' in result
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_only_for_user(mock_send, context):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardsCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.only_for_user = False
cell.save()
assert cell.is_visible(user=None) is True
assert cell.is_visible(user=MockUserWithNameId()) is True
cell.only_for_user = True
cell.save()
assert cell.is_visible(user=None) is False
assert cell.is_visible(user=MockUserWithNameId()) is True
cache.clear()
context['synchronous'] = True # to get fresh content
mock_send.reset_mock()
cell.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
cell.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
cell.render(context)
assert 'filter-user-uuid=xyz' in mock_send.call_args_list[0][0][0].url
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cards_cell_render_user(mock_send, context, nocache):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardsCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
context['card_model_1_id'] = 11
context['synchronous'] = True # to get fresh content
assert context['request'].user is None
mock_send.reset_mock()
cell.render(context)
assert 'NameID=&' in mock_send.call_args_list[0][0][0].url
assert 'email=&' in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
cell.render(context)
assert 'email=foo%40example.net' in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
cell.render(context)
assert 'NameID=xyz' in mock_send.call_args_list[0][0][0].url
cell.without_user = True
cell.save()
context['request'].user = None
mock_send.reset_mock()
cell.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
cell.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
cell.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_setup(mock_send, app, admin_user):
page = Page.objects.create(title='xxx', slug='test_card_cell_save_cache', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
form_class = cell.get_default_form_class()
form = form_class(instance=cell)
assert form.fields['carddef_reference'].widget.choices == [
('default:card_model_1', 'test : Card Model 1'),
('default:card_model_2', 'test : Card Model 2'),
('default:card_model_3', 'test : Card Model 3'),
('other:card_model_1', 'test2 : Card Model 1'),
('other:card_model_2', 'test2 : Card Model 2'),
('other:card_model_3', 'test2 : Card Model 3'),
]
assert 'customize_display' not in form.fields
assert 'custom_schema' not in form.fields
cell.save()
assert 'customize_display' not in form.fields
assert 'custom_schema' not in form.fields
cell.carddef_reference = 'default:card_model_1'
cell.save()
form = form_class(instance=cell)
assert 'customize_display' in form.fields
assert 'custom_schema' in form.fields
assert 'customize_display' not in form.initial
assert form.initial['custom_schema'] == {}
cell.custom_schema = {'foo': 'bar'}
cell.save()
form = form_class(instance=cell)
assert 'customize_display' in form.fields
assert 'custom_schema' in form.fields
assert form.initial['customize_display'] is True
assert form.initial['custom_schema'] == {'foo': 'bar'}
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert resp.forms[0]['c%s-customize_display' % cell.get_reference()].value == 'on'
resp.forms[0]['c%s-customize_display' % cell.get_reference()].value = False
resp.forms[0].submit().follow()
cell.refresh_from_db()
assert cell.custom_schema == {}
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_save_cache(mock_send):
page = Page.objects.create(title='xxx', slug='test_card_cell_save_cache', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
assert cell.get_additional_label() is None
cell.carddef_reference = 'default:card_model_1'
cell.save()
assert cell.cached_title == 'Card Model 1'
assert cell.cached_json != {}
assert cell.get_additional_label() == 'Card Model 1'
# make sure cached attributes are removed from serialized pages
assert 'cached_' not in json.dumps(page.get_serialized_page())
# artificially change title and json
WcsCardInfosCell.objects.filter(pk=cell.pk).update(cached_title='XXX', cached_json={})
assert WcsCardInfosCell.objects.get(pk=cell.pk).cached_title == 'XXX'
assert WcsCardInfosCell.objects.get(pk=cell.pk).cached_json == {}
# run update db cache
appconfig = apps.get_app_config('wcs')
appconfig.update_db_cache()
assert WcsCardInfosCell.objects.get(pk=cell.pk).cached_title == 'Card Model 1'
assert WcsCardInfosCell.objects.get(pk=cell.pk).cached_json != {}
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_validity(mock_send):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardInfosCell.objects.create(page=page, placeholder='content', order=0)
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_card_not_defined'
assert validity_info.invalid_since is not None
cell.carddef_reference = 'default:card_model_1'
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.save()
assert ValidityInfo.objects.exists() is False
# can not retrieve carddefs, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.save()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.json = lambda *a, **k: {'err': 1, 'err_class': 'Page not found'}
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.carddef_reference = 'default:foobar'
cell.save()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_card_not_found'
assert validity_info.invalid_since is not None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_manager_card_cell(mock_send, app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cards', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
assert 'application/json' not in resp
cell.carddef_reference = 'default:card_model_1'
cell.save()
resp = app.get('/manage/pages/%s/' % page.pk)
assert '<script id="cell-%s-card-schema-default:card_model_1" type="application/json">' % cell.pk in resp
assert ('data-cell-reference="%s"' % cell.get_reference()) in resp.text
assert cell.without_user is False
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value == 'on'
resp.forms[0]['c%s-with_user' % cell.get_reference()].value = False
resp = resp.forms[0].submit().follow()
cell.refresh_from_db()
assert cell.without_user is True
assert resp.forms[0]['c%s-with_user' % cell.get_reference()].value is None
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_load(mock_send):
page = Page.objects.create(title='xxx', slug='test_cards', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
site_export = [page.get_serialized_page()]
cell.delete()
assert not Page.objects.get(pk=page.pk).get_cells()
Page.load_serialized_pages(site_export)
page = Page.objects.get(slug='test_cards')
cells = page.get_cells()
assert len(cells) == 1
cell = cells[0]
assert cell.cached_title == 'Card Model 1'
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_render(mock_send, context):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.title_type = 'manual'
cell.custom_title = 'Foo bar {{ card.fields.title }}'
cell.save()
# card id not in context
assert 'card_model_1_id' not in context
result = cell.render(context)
assert '<h2>Card Model 1</h2>' in result # default value
assert '<p>Unknown Card</p>' in result
context['card_model_1_id'] = 11
# query should fail as nothing is cached
cache.clear()
with pytest.raises(NothingInCacheException):
result = cell.render(context)
context['synchronous'] = True # to get fresh content
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
result = cell.render(context)
assert '<h2>Card Model 1</h2>' in result # default value
assert '<p>Unknown Card</p>' in result
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
result = cell.render(context)
assert '<h2>Card Model 1</h2>' in result # default value
assert '<p>Unknown Card</p>' in result
context.pop('title')
cell.title_type = 'auto'
cell.save()
mock_send.reset_mock()
result = cell.render(context)
assert '<h2>Card Model 1 - aa</h2>' in result
assert PyQuery(result).find('span.label:contains("Field A") + span').text() == 'a'
assert PyQuery(result).find('span.label:contains("Field B") + span').text() == 'yes'
assert PyQuery(result).find('span.label:contains("Field C") + span').text() == 'Sept. 28, 2020'
assert PyQuery(result).find('span.label:contains("Related") + span').text() == 'Foo Bar'
assert 'related_raw' not in result
assert 'related_structured' not in result
assert 'Field D' not in result
context.pop('title')
cell.title_type = 'manual'
cell.custom_title = 'Foo bar {{ card.fields.fielda }}'
cell.save()
result = cell.render(context)
assert '<h2>Foo bar a</h2>' in result
context.pop('title')
cell.custom_title = '{{ foobar }}'
cell.save()
result = cell.render(context)
assert '<h2>Card Model 1 - aa</h2>' in result # empty value from template, default value
context.pop('title')
cell.custom_title = '{% if %}'
cell.save()
result = cell.render(context)
assert '<h2>Card Model 1 - aa</h2>' in result # template error, default value
context.pop('title')
cell.title_type = 'empty'
cell.save()
result = cell.render(context)
assert '<h2>' not in result
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_render_text_field(mock_send, context):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.custom_title = 'Foo bar {{ card.fields.title }}'
cell.save()
context['card_model_1_id'] = 11
context['synchronous'] = True # to get fresh content
result = cell.render(context)
# field E is split in paragraphs
assert (
PyQuery(result).find('span.label:contains("Field E") + div.value p:first-child').text().strip()
== 'lorem<strong>ipsum'
)
assert (
PyQuery(result).find('span.label:contains("Field E") + div.value p:last-child').text().strip()
== 'hello world'
)
# field F is put in a <pre>
assert (
PyQuery(result).find('span.label:contains("Field F") + div.value pre').text()
== 'lorem<strong>ipsum hello world'
)
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_render_identifier(mock_send, context, nocache):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
context['card_model_1_id'] = 11
context['synchronous'] = True # to get fresh content
# check url called
mock_send.reset_mock()
cell.render(context)
assert '/api/cards/card_model_1/11/' in mock_send.call_args_list[0][0][0].url
# with identifier
cell.card_id = '42'
cell.save()
mock_send.reset_mock()
cell.render(context)
assert '/api/cards/card_model_1/42/' in mock_send.call_args_list[0][0][0].url
context['cards'] = Cards()
cell.card_id = '{% cards|objects:"card_model_1"|last|get:"id" %}' # syntax error
cell.save()
mock_send.reset_mock()
cell.render(context)
assert mock_send.call_args_list == []
cell.card_id = '{{ cards|objects:"card_model_1"|last|get:"id" }}'
cell.save()
mock_send.reset_mock()
cell.render(context)
assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
assert '/api/cards/card_model_1/13/' in mock_send.call_args_list[1][0][0].url
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_card_cell_render_user(mock_send, context, nocache):
page = Page.objects.create(title='xxx', template_name='standard')
cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
cell.carddef_reference = 'default:card_model_1'
cell.save()
context['card_model_1_id'] = 11
context['synchronous'] = True # to get fresh content
assert context['request'].user is None
mock_send.reset_mock()
cell.render(context)
assert 'NameID=&' in mock_send.call_args_list[0][0][0].url
assert 'email=&' in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
cell.render(context)
assert 'email=foo%40example.net' in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
cell.render(context)
assert 'NameID=xyz' in mock_send.call_args_list[0][0][0].url
cell.without_user = True
cell.save()
context['request'].user = None
mock_send.reset_mock()
cell.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUser()
mock_send.reset_mock()
cell.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
cell.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
def test_tracking_code_cell(app, nocache):
page = Page(title='One', slug='index', template_name='standard')
page.save()
cell = TrackingCodeInputCell(page=page, placeholder='content', order=0)
cell.save()
resp = app.get('/')
resp.form['code'] = 'FOOBAR'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
resp = resp.form.submit()
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/code/FOOBAR'
assert requests_get.call_args_list[1][0][0] == '/api/code/FOOBAR'
remote_service_urls = [c[1]['remote_service']['url'] for c in requests_get.call_args_list]
assert set(remote_service_urls) == {'http://127.0.0.1:8999/', 'http://127.0.0.2:8999/'}
assert resp.status_code == 302
resp = resp.follow()
assert '<li class="error">The tracking code could not been found.</li>' in resp.text
resp = app.get('/')
resp.form['code'] = 'FOO?BAR?bad<code>'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
resp = resp.form.submit()
assert requests_get.call_args_list[0][0][0] == '/api/code/FOO%3FBAR%3FBAD%3CCODE%3E'
assert resp.status_code == 302
resp = resp.follow()
assert '<li class="error">The tracking code could not been found.</li>' in resp.text
resp = app.get('/')
resp.form['code'] = 'CNPHNTFB'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.return_value = MockedRequestResponse(
content=json.dumps({'err': 0, 'load_url': 'http://127.0.0.2:8999/code/CNPHNTFB/load'})
)
resp = resp.form.submit()
assert resp.status_code == 302
assert resp.location == 'http://127.0.0.2:8999/code/CNPHNTFB/load'
# space/case
resp = app.get('/')
resp.form['code'] = ' cnphntfb'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = [
mock.Mock(status_code=200),
MockedRequestResponse(
content=json.dumps({'err': 0, 'load_url': 'http://127.0.0.2:8999/code/CNPHNTFB/load'})
),
]
resp = resp.form.submit()
assert requests_get.call_args_list[0][0][0] == '/api/code/CNPHNTFB'
assert requests_get.call_args_list[1][0][0] == '/api/code/CNPHNTFB'
assert resp.status_code == 302
assert resp.location == 'http://127.0.0.2:8999/code/CNPHNTFB/load'
# lock cell to a single site
cell.wcs_site = 'default'
cell.save()
resp = app.get('/')
resp.form['code'] = 'CNPHNTFB'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
resp = resp.form.submit()
assert len(requests_get.call_args_list) == 1
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
resp = resp.follow()
assert '<li class="error">The tracking code could not been found.</li>' in resp.text
# unknown wcs_site
cell.wcs_site = 'unknown'
cell.save()
resp = app.get('/')
resp.form['code'] = 'CNPHNTFB'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
resp = resp.form.submit()
assert len(requests_get.call_args_list) == 0
resp = resp.follow()
assert '<li class="error">The tracking code could not been found.</li>' in resp.text
# simulate cell being displayed on a different site
resp = app.get('/')
resp.form['url'] = 'http://example.org/'
resp.form['code'] = 'CNPHNTFB'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
resp = resp.form.submit()
assert resp.location == 'http://example.org/?unknown-tracking-code'
resp = app.get('/')
resp.form['url'] = 'http://example.org/?foo=bar'
resp.form['code'] = 'CNPHNTFB'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
resp = resp.form.submit()
assert resp.location == 'http://example.org/?foo=bar&unknown-tracking-code'
# redirect to an unknown site
resp = app.get('/')
resp.form['url'] = 'http://example.net/'
resp.form['code'] = 'CNPHNTFB'
resp = resp.form.submit(status=400)
# error handling
resp = app.get('/')
resp.form['cell'] = '9999'
resp.form['code'] = 'CNPHNTFB'
resp = resp.form.submit(status=400)
resp = app.get('/')
resp.form['cell'] = 'xxxx'
resp.form['code'] = 'CNPHNTFB'
resp = resp.form.submit(status=400)
resp = app.post(reverse('wcs-tracking-code'), params={'cell': cell.id}, status=400)
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_tracking_code_cell_check_validity(mock_send):
page = Page.objects.create(title='xxx', slug='test', template_name='standard')
cell = TrackingCodeInputCell.objects.create(page=page, placeholder='content', order=0)
# invalid wcs_site
cell.wcs_site = 'invalid'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_site_not_found'
assert validity_info.invalid_since is not None
# valid wcs_site
cell.wcs_site = 'default'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_cell_assets(mock_send, settings, app, admin_user):
page = Page.objects.create(title='xxx', slug='test_cell_assets', template_name='standard')
cell1 = WcsFormCell.objects.create(
page=page, placeholder='content', order=0, formdef_reference='default:form-title'
)
cell2 = WcsFormsOfCategoryCell.objects.create(
page=page, placeholder='content', order=0, category_reference='default:test-9', ordering='alpha'
)
app = login(app)
settings.WCS_CATEGORY_ASSET_SLOTS = {}
settings.WCS_FORM_ASSET_SLOTS = {}
settings.COMBO_CELL_ASSET_SLOTS = {}
resp = app.get('/manage/assets/')
assert 'have any asset yet.' in resp.text
# Old settings have priority
settings.WCS_CATEGORY_ASSET_SLOTS = {'logo': {'prefix': 'Logo'}}
settings.WCS_FORM_ASSET_SLOTS = {'picture': {'prefix': 'Picture'}}
settings.COMBO_CELL_ASSET_SLOTS = {
'wcs_wcsformcell': {'picture': {'prefix': 'Picture blabla', 'suffix': 'test'}},
'wcs_wcsformsofcategorycell': {'logo': {'prefix': 'Logo blabla', 'suffix': 'test'}},
}
resp = app.get('/manage/assets/')
assert 'Logo — %s' % cell2.get_label_for_asset() in resp.text
assert 'Logo blabla — %s' % cell2.get_label_for_asset() not in resp.text
assert 'Picture — %s' % cell1.get_label_for_asset() in resp.text
assert 'Picture blabla — %s' % cell1.get_label_for_asset() not in resp.text
# New settings
settings.WCS_CATEGORY_ASSET_SLOTS = {}
settings.WCS_FORM_ASSET_SLOTS = {}
settings.COMBO_CELL_ASSET_SLOTS = {
'wcs_wcsformcell': {'picture': {'prefix': 'Picture'}},
'wcs_wcsformsofcategorycell': {'logo': {'prefix': 'Logo'}},
}
resp = app.get('/manage/assets/')
assert 'Logo — %s' % cell2.get_label_for_asset() in resp.text
assert 'Picture — %s' % cell1.get_label_for_asset() in resp.text
# test suffix
settings.COMBO_CELL_ASSET_SLOTS = {
'wcs_wcsformcell': {'picture': {'prefix': 'Picture', 'suffix': 'test'}},
'wcs_wcsformsofcategorycell': {'logo': {'prefix': 'Logo', 'suffix': 'test'}},
}
resp = app.get('/manage/assets/')
assert 'Logo — %s (test)' % cell2.get_label_for_asset() in resp.text
assert 'Picture — %s (test)' % cell1.get_label_for_asset() in resp.text
def test_tracking_code_search(settings, app, nocache):
settings.TEMPLATE_VARS['is_portal_agent'] = True
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
result = app.get('/api/search/tracking-code/').json
assert len(result.get('data')) == 0
assert result.get('err') == 0
assert requests_get.called is False # no code
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
assert len(app.get('/api/search/tracking-code/?q=123').json.get('data')) == 0
assert requests_get.called is False # no letters
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
assert len(app.get('/api/search/tracking-code/?q=BBCCDFF').json.get('data')) == 0
assert requests_get.called is False # too short
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
assert len(app.get('/api/search/tracking-code/?q=BBCCDDFF').json.get('data')) == 0
assert len(requests_get.call_args_list) == 2
assert requests_get.call_args_list[0][0][0] == '/api/code/BBCCDDFF'
assert requests_get.call_args_list[1][0][0] == '/api/code/BBCCDDFF'
remote_service_urls = [c[1]['remote_service']['url'] for c in requests_get.call_args_list]
assert set(remote_service_urls) == {'http://127.0.0.1:8999/', 'http://127.0.0.2:8999/'}
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.return_value = MockedRequestResponse(
content=json.dumps({'err': 0, 'load_url': 'http://127.0.0.2:8999/code/CNPHNTFB/load'})
)
assert len(app.get('/api/search/tracking-code/?q=CNPHNTFB').json.get('data')) == 1
assert requests_get.call_args_list[0][0][0] == '/api/code/CNPHNTFB'
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
assert len(app.get('/api/search/tracking-code/?q=BBCCDDFFG').json.get('data')) == 0
assert requests_get.called is False # too long
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = [
mock.Mock(status_code=200),
MockedRequestResponse(
content=json.dumps({'err': 0, 'load_url': 'http://127.0.0.2:8999/code/CNPHNTFB/load'})
),
]
assert len(app.get('/api/search/tracking-code/?q= cnphntfb').json.get('data')) == 1
assert requests_get.call_args_list[0][0][0] == '/api/code/CNPHNTFB'
def test_tracking_code_search_rate_limit(settings, app):
settings.TEMPLATE_VARS['is_portal_agent'] = True
settings.WCS_TRACKING_CODE_RATE_LIMIT = '0/s'
assert app.get('/api/search/tracking-code/?q=BBCCDDFF').json.get('err') == 1
page = Page(title='One', slug='index', template_name='standard')
page.save()
cell = TrackingCodeInputCell(page=page, placeholder='content', order=0)
cell.save()
resp = app.get('/')
resp.form['code'] = 'FOOBAR'
resp = resp.form.submit()
assert resp.status_code == 302
resp = resp.follow()
assert '<li class="error">Looking up tracking code is currently rate limited.</li>' in resp.text
resp = app.get('/')
resp.form['code'] = 'FOOBAR'
resp.form['url'] = 'http://example.org/'
resp = resp.form.submit(status=403)
def test_wcs_search_engines(app):
settings.TEMPLATE_VARS['is_portal_agent'] = True
search_engines = engines.get_engines()
assert 'tracking-code' in search_engines
assert len([x for x in search_engines if x.startswith('formdata:')]) == 2
settings.TEMPLATE_VARS['is_portal_agent'] = False
search_engines = engines.get_engines()
assert 'tracking-code' not in search_engines
assert len([x for x in search_engines if x.startswith('formdata:')]) == 0
def test_backoffice_submission_cell_render(context):
page = Page(title='xxx', slug='test_backoffice_submission_cell_render', template_name='standard')
page.save()
cell = BackofficeSubmissionCell.objects.create(page=page, placeholder='content', order=0)
context['synchronous'] = True # to get fresh content
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_json = mock.Mock(status_code=200)
requests_get.return_value = mock_json
result = cell.render(context)
assert requests_get.call_args_list[0][0][0] == '/api/formdefs/?backoffice-submission=on'
assert context['all_formdefs'] == {}
assert 'h2' not in result
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.return_value = MockedRequestResponse(
content=json.dumps(
{
'data': [
{
'backoffice_submission_url': '/backoffice/submission/a-private-form/',
'title': 'Foo',
}
]
}
)
)
result = cell.render(context)
assert '/backoffice/submission/a-private-form/' in result
assert list(context['all_formdefs'].keys()) == ['default', 'other']
assert 'h2' in result
# limit to categories
requests_get.reset_mock()
cell.categories = {'data': ['default:test-3', 'other:test-6']}
result = cell.render(context)
assert len(requests_get.call_args_list) == 2
assert (
requests_get.call_args_list[0][0][0]
== '/api/formdefs/?backoffice-submission=on&category_slugs=test-3'
)
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
assert (
requests_get.call_args_list[1][0][0]
== '/api/formdefs/?backoffice-submission=on&category_slugs=test-6'
)
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
requests_get.reset_mock()
cell.categories = {'data': ['default:test-3']}
result = cell.render(context)
assert len(requests_get.call_args_list) == 1
assert (
requests_get.call_args_list[0][0][0]
== '/api/formdefs/?backoffice-submission=on&category_slugs=test-3'
)
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
requests_get.reset_mock()
cell.categories = {'data': []}
result = cell.render(context)
assert len(requests_get.call_args_list) == 2
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_backoffice_submission_cell_check_validity(mock_send, context):
page = Page.objects.create(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
cell = BackofficeSubmissionCell.objects.create(page=page, placeholder='content', order=0)
# no category
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# valid categories
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve data, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# can not retrieve categories, don't set cell as invalid
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
cell.check_validity()
assert ValidityInfo.objects.exists() is False
# invalid category
cell.categories = {'data': ['default:foobar', 'default:test-9']}
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_category_not_found'
assert validity_info.invalid_since is not None
# invalid wcs_site
cell.categories = {'data': ['default:test-3', 'default:test-9']}
cell.wcs_site = 'invalid'
cell.save()
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'wcs_site_not_found'
assert validity_info.invalid_since is not None
# valid wcs_site
cell.wcs_site = 'default'
cell.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
def test_manager_link_list_cell_duplicate():
page = Page.objects.create(title='xxx', slug='new', template_name='standard')
cell = LinkListCell.objects.create(order=0, page=page)
item = WcsFormCell.objects.create(
page=page,
placeholder=cell.link_placeholder,
cached_title='A title',
cached_url='http://example.com',
cached_json={'foo': 'bar'},
order=1,
)
new_cell = cell.duplicate()
assert WcsFormCell.objects.count() == 2
assert len(new_cell.get_items()) == 1
new_item = new_cell.get_items()[0]
assert new_item.page == page
assert new_item.placeholder == new_cell.link_placeholder
assert new_item.pk != item.pk
assert new_item.cached_title == item.cached_title
assert new_item.cached_url == item.cached_url
assert new_item.cached_json == item.cached_json
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_manager_add_edit_delete_list_link_item(mock_send, app, admin_user):
page = Page.objects.create(title='One', slug='one', template_name='standard')
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
app = login(app)
resp = app.get('/manage/pages/%s/' % page.pk)
resp = resp.click(href='.*/add-link/form-link$')
resp.forms[0]['formdef_reference'] = 'default:form-title'
resp = resp.forms[0].submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
assert WcsFormCell.objects.count() == 1
item = WcsFormCell.objects.get()
assert item.formdef_reference == 'default:form-title'
assert item.page == page
assert item.placeholder == cell.link_placeholder
resp = resp.follow()
resp = resp.click(href='.*/link/%s/$' % item.get_reference())
resp.forms[0]['formdef_reference'] = 'default:a-private-form'
resp = resp.forms[0].submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
assert WcsFormCell.objects.count() == 1
item.refresh_from_db()
assert item.formdef_reference == 'default:a-private-form'
resp = resp.follow()
resp = resp.click(href='.*/link/%s/delete' % item.get_reference())
resp = resp.forms[0].submit()
assert resp.status_int == 302
assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.pk, cell.get_reference()))
assert WcsFormCell.objects.count() == 0
def test_import_export_pages_with_links():
page = Page(title='bar', slug='bar', order=1)
page.save()
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
item = WcsFormCell.objects.create(
page=page,
placeholder=cell.link_placeholder,
cached_title='A title',
cached_url='http://example.com',
cached_json={'foo': 'bar'},
order=0,
)
site_export = [x.get_serialized_page() for x in Page.objects.all()]
Page.load_serialized_pages(site_export)
new_page = Page.objects.get()
new_cells = CellBase.get_cells(page_id=new_page.id, placeholder='content')
assert len(new_cells[0].get_items()) == 1
new_item = new_cells[0].get_items()[0]
assert isinstance(new_item, WcsFormCell)
assert new_item.cached_title == item.cached_title
assert new_item.cached_url == item.cached_url
assert new_item.cached_json == item.cached_json
def test_list_of_links_with_form_render(app):
page = Page(title='xxx', slug='test_list_of_links_with_form_render', template_name='standard')
page.save()
cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
WcsFormCell.objects.create(
page=page,
placeholder=cell.link_placeholder,
cached_title='A title',
cached_url='http://example.com',
cached_json={'keywords': ['bar']},
order=0,
)
resp = app.get('/test_list_of_links_with_form_render/')
assert 'A title' in resp
assert 'keyword-bar' in resp
def test_view_page_with_wcs_cells_num_queries(app, admin_user):
page = Page.objects.create(title='bar', slug='index', order=1)
for i in range(0, 15):
WcsCurrentDraftsCell.objects.create(page=page, placeholder='content', order=i)
for i in range(15, 50):
WcsCurrentFormsCell.objects.create(page=page, placeholder='content', order=i)
app = login(app)
app.get('/') # load once to populate caches
with CaptureQueriesContext(connection) as ctx:
app.get('/')
assert len(ctx.captured_queries) == 62
def test_hourly():
appconfig = apps.get_app_config('wcs')
page = Page.objects.create(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
cell_classes = [c for c in appconfig.get_models() if c in get_cell_classes()]
for klass in cell_classes:
klass.objects.create(page=page, placeholder='content', order=0)
for klass in cell_classes:
if klass in [
WcsCareFormsCell,
WcsCurrentFormsCell,
WcsCurrentDraftsCell,
WcsFormsOfCategoryCell,
BackofficeSubmissionCell,
CategoriesCell,
TrackingCodeInputCell,
]:
with mock.patch('combo.apps.wcs.models.%s.check_validity' % klass.__name__) as check_validity:
appconfig.hourly()
assert check_validity.call_args_list == [mock.call()]
else:
assert hasattr(klass, 'check_validity') is False
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
def test_search_external_forms_links(mock_send, context):
page = Page(title='xxx', slug='test_forms_of_category_cell_search', template_name='standard')
page.save()
cell = SearchCell(page=page, _search_services={'data': ['_text']}, order=0)
cell.save()
index_site()
request = RequestFactory().get('/')
request.user = AnonymousUser()
hits = search_site(request, 'form')
assert len(hits) == 0
cell = WcsFormsOfCategoryCell(page=page, placeholder='content', order=1)
cell.category_reference = 'default:test-9'
cell.ordering = 'alpha'
cell.save()
context['synchronous'] = True # to get fresh content
result = cell.render(context)
assert 'form title' in result and 'a second form title' in result
assert 'http://127.0.0.1:8999/form-title/tryauth' in result
assert 'http://127.0.0.1:8999/a-second-form-title/tryauth' in result
index_site()
request = RequestFactory().get('/')
request.user = AnonymousUser()
hits = search_site(request, 'form')
assert len(hits) == 2