publik-django-templatetags/tests/test_wcs.py

410 lines
16 KiB
Python

import copy
import json
from unittest import mock
import pytest
from django.template import Context, Template
from django.test.client import RequestFactory
from requests.exceptions import ConnectionError
from requests.models import Response
from publik_django_templatetags.wcs.context_processors import Cards
@pytest.fixture
def context():
ctx = Context(
{
'cards': Cards(),
'request': RequestFactory().get('/'),
}
)
ctx['request'].user = None
return ctx
class MockAnonymousUser:
is_authenticated = False
is_anonymous = True
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 mocked_requests_send(request, **kwargs):
data = [{'id': 1, 'fields': {'foo': 'bar'}}, {'id': 2, 'fields': {'foo': 'baz'}}] # fake result
return MockedRequestResponse(content=json.dumps({'data': data}))
def test_context(context):
assert 'cards' in context
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_objects(mock_send, settings, context, nocache):
# lazy filters
t = Template('{{ cards|objects:"foo" }}')
assert t.render(context).startswith(
'<publik_django_templatetags.wcs.context_processors.LazyCardDefObjectsManager object at'
)
assert mock_send.call_args_list == [] # lazy
t = Template('{{ cards|objects:"default:foo" }}')
assert t.render(context).startswith(
'<publik_django_templatetags.wcs.context_processors.LazyCardDefObjectsManager object at'
)
assert mock_send.call_args_list == [] # lazy
# test filters evaluation
t = Template('{% for card in cards|objects:"foo" %}{{ card.id }} {% endfor %}')
assert t.render(context) == "1 2 "
assert mock_send.call_args_list[0][0][0].url.startswith(
'http://127.0.0.1:8999/api/cards/foo/list?'
) # primary service
t = Template('{{ cards|objects:"default:foo"|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith('http://127.0.0.1:8999/api/cards/foo/list?')
mock_send.reset_mock()
t = Template('{{ cards|objects:"other:foo"|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith('http://127.0.0.2:8999/api/cards/foo/list?')
mock_send.reset_mock()
t = Template('{{ cards|objects:"unknown:foo"|list }}')
t.render(context)
assert mock_send.call_args_list == [] # unknown, not evaluated
# test card_id with variable
context['foobar'] = 'some-slug'
mock_send.reset_mock()
t = Template('{{ cards|objects:foobar|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith('http://127.0.0.1:8999/api/cards/some-slug/list?')
# test with no secondary param
KNOWN_SERVICES = copy.deepcopy(settings.KNOWN_SERVICES)
KNOWN_SERVICES['wcs'] = {'default': {'url': 'http://127.0.0.3:8999/'}}
settings.KNOWN_SERVICES = KNOWN_SERVICES
mock_send.reset_mock()
t = Template('{{ cards|objects:"bar"|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith('http://127.0.0.3:8999/api/cards/bar/list?')
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_with_custom_view(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|with_custom_view:"foobar"|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith(
'http://127.0.0.1:8999/api/cards/foo/list/foobar?'
) # primary service
t = Template('{{ cards|objects:"default:foo"|with_custom_view:"foobar"|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith(
'http://127.0.0.1:8999/api/cards/foo/list/foobar?'
)
mock_send.reset_mock()
t = Template('{{ cards|objects:"other:foo"|with_custom_view:"foobar"|list }}')
t.render(context)
assert mock_send.call_args_list[0][0][0].url.startswith(
'http://127.0.0.2:8999/api/cards/foo/list/foobar?'
)
mock_send.reset_mock()
t = Template('{{ cards|objects:"unknown:foo"|with_custom_view:"foobar"|list }}')
t.render(context)
assert mock_send.call_args_list == [] # unknown, not evaluated
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_full(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'full=on&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|get_full|list }}')
t.render(context)
assert 'full=on&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_errors(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|list }}')
with mock.patch('publik_django_templatetags.wcs.context_processors.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
assert t.render(context) == "[]"
with mock.patch('publik_django_templatetags.wcs.context_processors.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
requests_get.return_value = mock_resp
assert t.render(context) == "[]"
with mock.patch('publik_django_templatetags.wcs.context_processors.requests.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
assert t.render(context) == "[]"
mock_send.side_effect = lambda *a, **k: MockedRequestResponse(content=json.dumps({'err': 1}))
assert t.render(context) == "[]"
mock_send.side_effect = lambda *a, **k: MockedRequestResponse(content=json.dumps({}))
assert t.render(context) == "[]"
mock_send.side_effect = lambda *a, **k: MockedRequestResponse(content=json.dumps({'data': None}))
assert t.render(context) == "[]"
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_access_control(mock_send, context, nocache):
# no user in context
t = Template('{{ cards|objects:"foo"|list }}')
t.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_send.reset_mock()
t = Template('{{ cards|objects:"foo"|access_control:request.user|list }}')
t.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
# current user in anonymous
context['request'].user = MockAnonymousUser()
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|list }}')
t.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_send.reset_mock()
t = Template('{{ cards|objects:"foo"|access_control:request.user|list }}')
t.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
# current user with uuid
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|list }}')
t.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_send.reset_mock()
t = Template('{{ cards|objects:"foo"|access_control:request.user|list }}')
t.render(context)
assert 'NameID=xyz&' in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
# current user without uuid
context['request'].user = MockUser()
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|list }}')
t.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_send.reset_mock()
t = Template('{{ cards|objects:"foo"|access_control:request.user|list }}')
t.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email=foo%40example.net&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_count(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|count }}')
assert t.render(context) == "2"
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|filter_by:"foo"|filter_value:"bar"|list }}')
t.render(context)
assert 'filter-foo=bar&' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template(
'{{ cards|objects:"foo"|filter_by:"foo"|filter_value:"bar"|filter_by:"foo2"|filter_value:"bar2"|list }}'
)
t.render(context)
assert 'filter-foo=bar&' in mock_send.call_args_list[0][0][0].url
assert 'filter-foo2=bar2&' in mock_send.call_args_list[0][0][0].url
# check boolean
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by:"foo"|filter_value:True|list }}')
t.render(context)
assert 'filter-foo=true&' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by:"foo"|filter_value:False|list }}')
t.render(context)
assert 'filter-foo=false&' in mock_send.call_args_list[0][0][0].url
# check None
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by:"foo"|filter_value:None|list }}')
t.render(context)
assert 'filter-foo=&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter_by_internal_id(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_internal_id:None|list }}')
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_internal_id:""|list }}')
t.render(context)
assert 'filter-internal-id' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_internal_id:"42"|list }}')
t.render(context)
assert 'filter-internal-id=42&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter_by_number(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_number:None|list }}')
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_number:""|list }}')
t.render(context)
assert 'filter-number' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_number:"42-35"|list }}')
t.render(context)
assert 'filter-number=42-35&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter_by_user(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|filter_by_user:request.user|list }}')
t.render(context)
assert 'filter-user-uuid' not in mock_send.call_args_list[0][0][0].url
context['request'].user = MockAnonymousUser()
mock_send.reset_mock()
t.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()
t.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()
t.render(context)
assert 'filter-user-uuid=xyz&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_filter_by_status(mock_send, context, nocache):
t = Template('{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_status:None|list }}')
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_status:""|list }}')
t.render(context)
assert 'filter=&' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{{ cards|objects:"foo"|filter_by_status:"foobar"|list }}')
t.render(context)
assert 'filter=foobar&' in mock_send.call_args_list[0][0][0].url
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_getlist(mock_send, context, nocache):
t = Template('{% for v in cards|objects:"foo"|getlist:"id" %}{{ v }},{% endfor %}')
t.render(context)
assert t.render(context) == "1,2,"
t = Template('{% for v in cards|objects:"foo"|getlist:"fields" %}{{ v }},{% endfor %}')
t.render(context)
result = t.render(context)
if ''' in result:
# django 2.2
assert result == "{'foo': 'bar'},{'foo': 'baz'},"
else:
# django 3.2
assert result == "{'foo': 'bar'},{'foo': 'baz'},"
t = Template('{% for v in cards|objects:"foo"|getlist:"fields"|getlist:"foo" %}{{ v }},{% endfor %}')
t.render(context)
assert t.render(context) == "bar,baz,"
t = Template('{% for v in cards|objects:"foo"|getlist:"fields"|getlist:"unknown" %}{{ v }},{% endfor %}')
t.render(context)
assert t.render(context) == "None,None,"
@mock.patch('requests.Session.send', side_effect=mocked_requests_send)
def test_order_by(mock_send, context, nocache):
t = Template('{% for v in cards|objects:"foo" %}{{ v }},{% endfor %}')
t.render(context)
assert 'order_by' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% for v in cards|objects:"foo"|order_by:"bar" %}{{ v }},{% endfor %}')
t.render(context)
assert 'order_by=bar' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% for v in cards|objects:"foo"|order_by:"-bar" %}{{ v }},{% endfor %}')
t.render(context)
assert 'order_by=-bar' in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% for v in cards|objects:"foo"|order_by:"" %}{{ v }},{% endfor %}')
t.render(context)
assert 'order_by' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% for v in cards|objects:"foo"|order_by:"bar"|order_by:"" %}{{ v }},{% endfor %}')
t.render(context)
assert 'order_by' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% for v in cards|objects:"foo"|order_by:""|order_by:"bar" %}{{ v }},{% endfor %}')
t.render(context)
assert 'order_by=bar' in mock_send.call_args_list[0][0][0].url