Skip to content
Snippets Groups Projects
Unverified Commit 11152be9 authored by Giovanni Cimolin da Silva's avatar Giovanni Cimolin da Silva Committed by GitHub
Browse files

[BD-24][TNL-7580] BB-3010: Implement app view testing infrastructure (#106)

* Add django url testing support

* Add tests to django views, implement compat layer

* Addressing review comments

* Improve tests and test descriptions

* Nit
parent af0a8b35
No related branches found
No related tags found
No related merge requests found
"""
Compatibility layer to isolate core-platform method calls from implementation.
"""
def run_xblock_handler(*args, **kwargs):
"""
Import and run `handle_xblock_callback` from LMS
"""
# pylint: disable=import-error,import-outside-toplevel
from lms.djangoapps.courseware.module_render import handle_xblock_callback
return handle_xblock_callback(*args, **kwargs)
def run_xblock_handler_noauth(*args, **kwargs):
"""
Import and run `handle_xblock_callback_noauth` from LMS
"""
# pylint: disable=import-error,import-outside-toplevel
from lms.djangoapps.courseware.module_render import handle_xblock_callback_noauth
return handle_xblock_callback_noauth(*args, **kwargs)
...@@ -7,9 +7,9 @@ from django.views.decorators.csrf import csrf_exempt ...@@ -7,9 +7,9 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods from django.views.decorators.http import require_http_methods
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from lms.djangoapps.courseware.module_render import ( # pylint: disable=import-error from lti_consumer.plugin.compat import (
handle_xblock_callback, run_xblock_handler,
handle_xblock_callback_noauth, run_xblock_handler_noauth,
) )
...@@ -25,13 +25,13 @@ def public_keyset_endpoint(request, usage_id=None): ...@@ -25,13 +25,13 @@ def public_keyset_endpoint(request, usage_id=None):
try: try:
usage_key = UsageKey.from_string(usage_id) usage_key = UsageKey.from_string(usage_id)
return handle_xblock_callback_noauth( return run_xblock_handler_noauth(
request=request, request=request,
course_id=str(usage_key.course_key), course_id=str(usage_key.course_key),
usage_id=str(usage_key), usage_id=str(usage_key),
handler='public_keyset_endpoint' handler='public_keyset_endpoint'
) )
except: # pylint: disable=bare-except except Exception: # pylint: disable=broad-except
return HttpResponse(status=404) return HttpResponse(status=404)
...@@ -49,14 +49,14 @@ def launch_gate_endpoint(request, suffix): ...@@ -49,14 +49,14 @@ def launch_gate_endpoint(request, suffix):
request.GET.get('login_hint') request.GET.get('login_hint')
) )
return handle_xblock_callback( return run_xblock_handler(
request=request, request=request,
course_id=str(usage_key.course_key), course_id=str(usage_key.course_key),
usage_id=str(usage_key), usage_id=str(usage_key),
handler='lti_1p3_launch_callback', handler='lti_1p3_launch_callback',
suffix=suffix suffix=suffix
) )
except: # pylint: disable=bare-except except Exception: # pylint: disable=broad-except
return HttpResponse(status=404) return HttpResponse(status=404)
...@@ -69,11 +69,11 @@ def access_token_endpoint(request, usage_id=None): ...@@ -69,11 +69,11 @@ def access_token_endpoint(request, usage_id=None):
try: try:
usage_key = UsageKey.from_string(usage_id) usage_key = UsageKey.from_string(usage_id)
return handle_xblock_callback_noauth( return run_xblock_handler_noauth(
request=request, request=request,
course_id=str(usage_key.course_key), course_id=str(usage_key.course_key),
usage_id=str(usage_key), usage_id=str(usage_key),
handler='lti_1p3_access_token' handler='lti_1p3_access_token'
) )
except: # pylint: disable=bare-except except Exception: # pylint: disable=broad-except
return HttpResponse(status=404) return HttpResponse(status=404)
"""
Tests for LTI 1.3 endpoint views.
"""
from mock import patch
from django.http import HttpResponse
from django.test.testcases import TestCase
class TestLti1p3KeysetEndpoint(TestCase):
"""
Test `public_keyset_endpoint` method.
"""
def setUp(self):
super(TestLti1p3KeysetEndpoint, self).setUp()
self.location = 'block-v1:course+test+2020+type@problem+block@test'
self.url = '/lti_consumer/v1/public_keysets/{}'.format(self.location)
# Patch settings calls to LMS method
xblock_handler_patcher = patch(
'lti_consumer.plugin.views.run_xblock_handler_noauth',
return_value=HttpResponse()
)
self.addCleanup(xblock_handler_patcher.stop)
self._mock_xblock_handler = xblock_handler_patcher.start()
def test_public_keyset_endpoint(self):
"""
Check that the keyset endpoint maps correctly to the
`public_keyset_endpoint` XBlock handler endpoint.
"""
response = self.client.get(self.url)
# Check response
self.assertEqual(response.status_code, 200)
# Check function call arguments
self._mock_xblock_handler.assert_called_once()
kwargs = self._mock_xblock_handler.call_args.kwargs
self.assertEqual(kwargs['usage_id'], self.location)
self.assertEqual(kwargs['handler'], 'public_keyset_endpoint')
def test_invalid_usage_key(self):
"""
Check invalid methods yield HTTP code 404.
"""
response = self.client.get('/lti_consumer/v1/public_keysets/invalid-key')
self.assertEqual(response.status_code, 404)
class TestLti1p3LaunchGateEndpoint(TestCase):
"""
Test `launch_gate_endpoint` method.
"""
def setUp(self):
super(TestLti1p3LaunchGateEndpoint, self).setUp()
self.location = 'block-v1:course+test+2020+type@problem+block@test'
self.url = '/lti_consumer/v1/launch/'
self.request = {'login_hint': self.location}
# Patch settings calls to LMS method
xblock_handler_patcher = patch(
'lti_consumer.plugin.views.run_xblock_handler',
return_value=HttpResponse()
)
self.addCleanup(xblock_handler_patcher.stop)
self._mock_xblock_handler = xblock_handler_patcher.start()
def test_launch_gate(self):
"""
Check that the launch endpoint correctly maps to the
`lti_1p3_launch_callback` XBlock handler.
"""
response = self.client.get(self.url, self.request)
# Check response
self.assertEqual(response.status_code, 200)
# Check function call arguments
self._mock_xblock_handler.assert_called_once()
kwargs = self._mock_xblock_handler.call_args.kwargs
self.assertEqual(kwargs['usage_id'], self.location)
self.assertEqual(kwargs['handler'], 'lti_1p3_launch_callback')
def test_invalid_usage_key(self):
"""
Check that passing a invalid login_hint yields HTTP code 404.
"""
self._mock_xblock_handler.side_effect = Exception()
response = self.client.get(self.url, self.request)
self.assertEqual(response.status_code, 404)
class TestLti1p3AccessTokenEndpoint(TestCase):
"""
Test `access_token_endpoint` method.
"""
def setUp(self):
super(TestLti1p3AccessTokenEndpoint, self).setUp()
self.location = 'block-v1:course+test+2020+type@problem+block@test'
self.url = '/lti_consumer/v1/token/{}'.format(self.location)
# Patch settings calls to LMS method
xblock_handler_patcher = patch(
'lti_consumer.plugin.views.run_xblock_handler_noauth',
return_value=HttpResponse()
)
self.addCleanup(xblock_handler_patcher.stop)
self._mock_xblock_handler = xblock_handler_patcher.start()
def test_access_token_endpoint(self):
"""
Check that the keyset endpoint is correctly mapping to the
`lti_1p3_access_token` XBlock handler.
"""
response = self.client.post(self.url)
# Check response
self.assertEqual(response.status_code, 200)
# Check function call arguments
self._mock_xblock_handler.assert_called_once()
kwargs = self._mock_xblock_handler.call_args.kwargs
self.assertEqual(kwargs['usage_id'], self.location)
self.assertEqual(kwargs['handler'], 'lti_1p3_access_token')
def test_invalid_usage_key(self):
"""
Check invalid methods yield HTTP code 404.
"""
self._mock_xblock_handler.side_effect = Exception()
response = self.client.post(self.url)
self.assertEqual(response.status_code, 404)
...@@ -8,7 +8,7 @@ import os ...@@ -8,7 +8,7 @@ import os
import sys import sys
if __name__ == '__main__': if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', u'workbench.settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', u'test_settings')
try: try:
from django.conf import settings # pylint: disable=wrong-import-position from django.conf import settings # pylint: disable=wrong-import-position
......
"""
Custom testing settings for testing views
"""
from workbench.settings import *
# Usage id pattern (from edx-platform)
USAGE_ID_PATTERN = r'(?P<usage_id>(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))'
# Keep settings, use different ROOT_URLCONF
ROOT_URLCONF = 'test_urls'
"""
Custom URL patterns for testing
"""
from django.conf.urls import include, re_path
urlpatterns = [
re_path(r'^', include('workbench.urls')),
re_path(r'^', include('lti_consumer.plugin.urls')),
]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment