Skip to content
Snippets Groups Projects
Commit ee02c062 authored by Valera Rozuvan's avatar Valera Rozuvan Committed by Alexander Kryklia
Browse files

Add Learning Tools Interoperability (LTI) blade.

LTI blade allows to include LTI components to courses.
Python integration, Jasmine and acceptance tests are included.
parent dc42e1f9
No related merge requests found
"""LTI integration tests"""
import requests
from . import BaseTestXmodule
from collections import OrderedDict
import mock
class TestLTI(BaseTestXmodule):
"""
Integration test for lti xmodule.
It checks overall code, by assuring that context that goes to template is correct.
As part of that, checks oauth signature generation by mocking signing function of `requests` library.
"""
CATEGORY = "lti"
def setUp(self):
"""
Mock oauth1 signing of requests library for testing.
"""
super(TestLTI, self).setUp()
mocked_nonce = u'135685044251684026041377608307'
mocked_timestamp = u'1234567890'
mocked_signature_after_sign = u'my_signature%3D'
mocked_decoded_signature = u'my_signature='
self.correct_headers = {
u'oauth_callback': u'about:blank',
u'lis_outcome_service_url': '',
u'lis_result_sourcedid': '',
u'launch_presentation_return_url': '',
u'lti_message_type': u'basic-lti-launch-request',
u'lti_version': 'LTI-1p0',
u'oauth_nonce': mocked_nonce,
u'oauth_timestamp': mocked_timestamp,
u'oauth_consumer_key': u'',
u'oauth_signature_method': u'HMAC-SHA1',
u'oauth_version': u'1.0',
u'user_id': self.runtime.anonymous_student_id,
u'role': u'student',
u'oauth_signature': mocked_decoded_signature
}
saved_sign = requests.auth.Client.sign
def mocked_sign(self, *args, **kwargs):
"""
Mocked oauth1 sign function.
"""
# self is <oauthlib.oauth1.rfc5849.Client object> here:
__, headers, __ = saved_sign(self, *args, **kwargs)
# we should replace nonce, timestamp and signed_signature in headers:
old = headers[u'Authorization']
old_parsed = OrderedDict([param.strip().replace('"', '').split('=') for param in old.split(',')])
old_parsed[u'OAuth oauth_nonce'] = mocked_nonce
old_parsed[u'oauth_timestamp'] = mocked_timestamp
old_parsed[u'oauth_signature'] = mocked_signature_after_sign
headers[u'Authorization'] = ', '.join([k+'="'+v+'"' for k, v in old_parsed.items()])
return None, headers, None
patcher = mock.patch.object(requests.auth.Client, "sign", mocked_sign)
patcher.start()
self.addCleanup(patcher.stop)
def test_lti_constructor(self):
"""
Makes sure that all parameters extracted.
"""
self.runtime.render_template = lambda template, context: context
generated_context = self.item_module.get_html()
expected_context = {
'input_fields': self.correct_headers,
'element_class': self.item_module.location.category,
'element_id': self.item_module.location.html_id(),
'launch_url': '', # default value
}
self.assertDictEqual(generated_context, expected_context)
<div id="${element_id}" class="${element_class}">
## This form will be hidden. Once available on the client, the LTI
## module JavaScript will trigget a "submit" on the form, and the
## result will be rendered to the below iFrame.
<form
action="${launch_url}"
name="ltiLaunchForm"
class="ltiLaunchForm"
method="post"
target="ltiLaunchFrame"
encType="application/x-www-form-urlencoded"
>
% for param_name, param_value in input_fields.items():
<input name="${param_name}" value="${param_value}" />
%endfor
<input type="submit" value="Press to Launch" />
</form>
<h3 class="error_message">
Please provide launch_url. Click "Edit", and fill in the
required fields.
</h3>
## The result of the form submit will be rendered here.
<iframe
name="ltiLaunchFrame"
class="ltiLaunchFrame"
src=""
></iframe>
</div>
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