combo/tests/test_wcs_templatetags.py

332 lines
13 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 combo.apps.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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_objects(mock_send, settings, context, nocache):
# lazy filters
t = Template('{% load wcs %}{{ cards|objects:"foo" }}')
assert t.render(context).startswith(
'<combo.apps.wcs.context_processors.LazyCardDefObjectsManager object at'
)
assert mock_send.call_args_list == [] # lazy
t = Template('{% load wcs %}{{ cards|objects:"default:foo" }}')
assert t.render(context).startswith(
'<combo.apps.wcs.context_processors.LazyCardDefObjectsManager object at'
)
assert mock_send.call_args_list == [] # lazy
# test filters evaluation
t = Template('{% load wcs %}{% 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_with_custom_view(mock_send, context, nocache):
t = Template('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ cards|objects:"unknown:foo"|with_custom_view:"foobar"|list }}')
t.render(context)
assert mock_send.call_args_list == [] # unknown, not evaluated
@mock.patch('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_full(mock_send, context, nocache):
t = Template('{% load wcs %}{{ 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('{% load wcs %}{{ cards|objects:"foo"|get_full|list }}')
t.render(context)
assert 'full=on&' 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_errors(mock_send, context, nocache):
t = Template('{% load wcs %}{{ cards|objects:"foo"|list }}')
with mock.patch('combo.apps.wcs.utils.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('combo.apps.wcs.utils.requests.get') as requests_get:
requests_get.side_effect = ConnectionError()
requests_get.return_value = mock_resp
assert t.render(context) == "[]"
with mock.patch('combo.apps.wcs.utils.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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_access_control(mock_send, context, nocache):
# no user in context
t = Template('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_count(mock_send, context, nocache):
t = Template('{% load wcs %}{{ cards|objects:"foo"|count }}')
assert t.render(context) == "2"
@mock.patch('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_filter(mock_send, context, nocache):
t = Template('{% load wcs %}{{ 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(
'{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_filter_by_user(mock_send, context, nocache):
t = Template('{% load wcs %}{{ 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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_filter_by_status(mock_send, context, nocache):
t = Template('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('{% load wcs %}{{ 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('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_getlist(mock_send, context, nocache):
t = Template('{% load wcs %}{% for v in cards|objects:"foo"|getlist:"id" %}{{ v }},{% endfor %}')
t.render(context)
assert t.render(context) == "1,2,"
t = Template('{% load wcs %}{% for v in cards|objects:"foo"|getlist:"fields" %}{{ v }},{% endfor %}')
t.render(context)
assert t.render(context) == "{'foo': 'bar'},{'foo': 'baz'},"
t = Template(
'{% load wcs %}{% for v in cards|objects:"foo"|getlist:"fields"|getlist:"foo" %}{{ v }},{% endfor %}'
)
t.render(context)
assert t.render(context) == "bar,baz,"
t = Template(
'{% load wcs %}{% for v in cards|objects:"foo"|getlist:"fields"|getlist:"unknown" %}{{ v }},{% endfor %}'
)
t.render(context)
assert t.render(context) == "None,None,"