Skip to content
Snippets Groups Projects
Commit 36930ee4 authored by Shimul Chowdhury's avatar Shimul Chowdhury Committed by Ned Batchelder
Browse files

Add support for image content type

parent 8b16aad3
No related branches found
No related tags found
No related merge requests found
...@@ -56,7 +56,7 @@ LTI_DEEP_LINKING_ACCEPTED_TYPES = [ ...@@ -56,7 +56,7 @@ LTI_DEEP_LINKING_ACCEPTED_TYPES = [
'ltiResourceLink', 'ltiResourceLink',
'link', 'link',
'html', 'html',
# TODO: implement "image" support, 'image',
# TODO: implement "file" support, # TODO: implement "file" support,
] ]
......
...@@ -5,6 +5,7 @@ from .serializers import ( ...@@ -5,6 +5,7 @@ from .serializers import (
LtiDlLtiResourceLinkSerializer, LtiDlLtiResourceLinkSerializer,
LtiDlLinkSerializer, LtiDlLinkSerializer,
LtiDlHtmlSerializer, LtiDlHtmlSerializer,
LtiDlImageSerializer,
) )
...@@ -12,4 +13,5 @@ LTI_DL_CONTENT_TYPE_SERIALIZER_MAP = { ...@@ -12,4 +13,5 @@ LTI_DL_CONTENT_TYPE_SERIALIZER_MAP = {
"ltiResourceLink": LtiDlLtiResourceLinkSerializer, "ltiResourceLink": LtiDlLtiResourceLinkSerializer,
"link": LtiDlLinkSerializer, "link": LtiDlLinkSerializer,
"html": LtiDlHtmlSerializer, "html": LtiDlHtmlSerializer,
"image": LtiDlImageSerializer,
} }
...@@ -345,3 +345,22 @@ class LtiDlHtmlSerializer(serializers.Serializer): ...@@ -345,3 +345,22 @@ class LtiDlHtmlSerializer(serializers.Serializer):
html = serializers.CharField() html = serializers.CharField()
title = serializers.CharField(max_length=255, required=False) title = serializers.CharField(max_length=255, required=False)
text = serializers.CharField(required=False) text = serializers.CharField(required=False)
# pylint: disable=abstract-method
class LtiDlImageSerializer(serializers.Serializer):
"""
LTI Deep Linking - image Serializer.
This serializer implements validation for the Image content type.
Reference:
http://www.imsglobal.org/spec/lti-dl/v2p0#image
"""
url = serializers.URLField(max_length=500)
title = serializers.CharField(max_length=255, required=False)
text = serializers.CharField(required=False)
icon = LtiDLIconPropertySerializer(required=False)
thumbnail = LtiDLIconPropertySerializer(required=False)
width = serializers.IntegerField(min_value=1, required=False)
height = serializers.IntegerField(min_value=1, required=False)
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
{% include "html/lti-dl/render_link.html" with item=item attrs=item.attributes %} {% include "html/lti-dl/render_link.html" with item=item attrs=item.attributes %}
{% elif item.content_type == 'html' %} {% elif item.content_type == 'html' %}
{% include "html/lti-dl/render_html.html" with item=item attrs=item.attributes %} {% include "html/lti-dl/render_html.html" with item=item attrs=item.attributes %}
{% elif item.content_type == 'image' %}
{% include "html/lti-dl/render_image.html" with item=item attrs=item.attributes %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</body> </body>
......
{% if attrs.title %}<h2>{{ attrs.title }}</h2>{% endif %}
{% if attrs.text %}<p>{{ attrs.text }}</p>{% endif %}
{% if attrs.thumbnail %}
<a href="{{ attrs.url }}" {% if attrs.title %}alt="{{ attrs.title }}"{% endif %}>
<img src="{{ attrs.thumbnail.url }}" {% if attrs.title %}alt="{{ attrs.title }}"{% endif %} width="{{ attrs.thumbnail.width }}" height="{{ attrs.thumbnail.height }}" />
</a>
{% elif attrs.icon %}
<a href="{{ attrs.url }}" {% if attrs.title %}alt="{{ attrs.title }}"{% endif %}>
<img src="{{ attrs.icon.url }}" {% if attrs.title %}alt="{{ attrs.title }}"{% endif %} width="{{ attrs.icon.width }}" height="{{ attrs.icon.height }}" />
</a>
{% else %}
<img src="{{ attrs.url }}" {% if attrs.title %}alt="{{ attrs.title }}" {% endif %}{% if attrs.width %}width="{{ attrs.width }}" {% endif %}{% if attrs.height %}height="{{ attrs.height }}"{% endif %} />
{% endif %}
...@@ -350,6 +350,46 @@ class LtiDeepLinkingResponseEndpointTestCase(LtiDeepLinkingTestCase): ...@@ -350,6 +350,46 @@ class LtiDeepLinkingResponseEndpointTestCase(LtiDeepLinkingTestCase):
content_item, is_valid = test_data content_item, is_valid = test_data
self._content_type_validation_test_helper(content_item, is_valid) self._content_type_validation_test_helper(content_item, is_valid)
@ddt.data(
({"type": "image"}, False),
({"type": "image", "url": "http://ex.com/image"}, True),
({
"type": "image",
"url": "http://ex.com/image",
"text": "This is a link",
"title": "This is a link"
}, True),
# invalid icon
({"type": "image", "url": "https://example.com/image", "icon": {}}, False),
# valid icon
({
"type": "image",
"url": "https://example.com/image",
"icon": {"url": "https://ex.com/icon", "width": 20, "height": 20}
}, True),
# invalid thumbnail
({"type": "image", "url": "https://example.com/image", "thumbnail": {}}, False),
# valid thumbnail
({
"type": "image",
"url": "https://example.com/image",
"thumbnail": {"url": "https://ex.com/icon", "width": 20, "height": 20}
}, True),
)
def test_image_content_type(self, test_data):
"""
Tests validation for `image` content type.
Args:
self
test_data (tuple): 1st element is the datastructure to test,
and the second one indicates wether it's valid or not.
"""
content_item, is_valid = test_data
self._content_type_validation_test_helper(content_item, is_valid)
@ddt.ddt @ddt.ddt
class LtiDeepLinkingContentEndpointTestCase(LtiDeepLinkingTestCase): class LtiDeepLinkingContentEndpointTestCase(LtiDeepLinkingTestCase):
...@@ -508,3 +548,59 @@ class LtiDeepLinkingContentEndpointTestCase(LtiDeepLinkingTestCase): ...@@ -508,3 +548,59 @@ class LtiDeepLinkingContentEndpointTestCase(LtiDeepLinkingTestCase):
self.assertContains(resp, '<p>{}</p>'.format(test_data['text'])) self.assertContains(resp, '<p>{}</p>'.format(test_data['text']))
self.assertContains(resp, test_data['html']) self.assertContains(resp, test_data['html'])
@ddt.data(
{'url': 'https://path.to.image'},
{'url': 'https://path.to.image', 'title': 'With Title'},
{'url': 'https://path.to.image', 'title': 'With Title', 'text': 'With Text'},
{
'url': 'https://path.to.image', 'title': 'With Title', 'text': 'With Text',
'width': '400px', 'height': '200px',
},
{
'url': 'https://path.to.image', 'title': 'With Title', 'text': 'With Text',
'icon': {'url': 'https://path.to.icon', 'width': '20px', 'height': '20px'},
},
{
'url': 'https://path.to.image', 'title': 'With Title', 'text': 'With Text',
'thumbnail': {'url': 'https://path.to.thumbnail', 'width': '20px', 'height': '20px'},
},
)
@patch('lti_consumer.plugin.views.has_block_access', return_value=True)
def test_dl_content_type_image(self, test_data, has_block_access): # pylint: disable=unused-argument
"""
Test if image content type successfully rendered.
"""
attributes = {'type': LtiDlContentItem.IMAGE}
attributes.update(test_data)
LtiDlContentItem.objects.create(
lti_configuration=self.lti_config,
content_type=LtiDlContentItem.IMAGE,
attributes=attributes
)
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 200)
if test_data.get('title'):
self.assertContains(resp, '<h2>{}</h2>'.format(test_data['title']))
self.assertContains(resp, 'alt="{}"'.format(test_data['title']))
if test_data.get('text'):
self.assertContains(resp, '<p>{}</p>'.format(test_data['text']))
if test_data.get('thumbnail'):
self.assertContains(resp, '<a href="{}"'.format(test_data['url']))
self.assertContains(resp, '<img src="{}"'.format(test_data['thumbnail']['url']))
elif test_data.get('icon'):
self.assertContains(resp, '<a href="{}"'.format(test_data['url']))
self.assertContains(resp, '<img src="{}"'.format(test_data['icon']['url']))
else:
self.assertContains(resp, '<img src="{}"'.format(test_data['url']))
if test_data.get('width'):
self.assertContains(resp, 'width="{}"'.format(test_data['width']))
if test_data.get('height'):
self.assertContains(resp, 'height="{}"'.format(test_data['height']))
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