From 1293af7f18264b81f2ccae39840dfbc6b703ee3f Mon Sep 17 00:00:00 2001 From: KuldeepArbisoft Date: Fri, 13 Jul 2018 17:27:30 +0500 Subject: [PATCH] Change relative urls to absolute for student view data --- image_explorer/image_explorer.py | 34 ++++++++++++++++--------- requirements.txt | 1 + tests/unit/test_image_explorer.py | 41 +++++++++++++++++++++++++------ tests/utils.py | 20 +++++++++++++++ 4 files changed, 78 insertions(+), 18 deletions(-) diff --git a/image_explorer/image_explorer.py b/image_explorer/image_explorer.py index 0739446..02238d6 100644 --- a/image_explorer/image_explorer.py +++ b/image_explorer/image_explorer.py @@ -8,6 +8,8 @@ import textwrap from lxml import etree, html from urlparse import urljoin +from parsel import Selector + from django.conf import settings from xblock.core import XBlock @@ -155,11 +157,10 @@ def student_view_data(self, context=None): """ xmltree = etree.fromstring(self.data) - description = self._get_description(xmltree) + description = self._get_description(xmltree, absolute_urls=True) background = self._get_background(xmltree) background['src'] = self._replace_static_from_url(background['src']) - hotspots = self._get_hotspots(xmltree) - + hotspots = self._get_hotspots(xmltree, absolute_urls=True) return { 'description': description, 'background': background, @@ -279,24 +280,36 @@ def _make_url_absolute(self, url): lms_base = '{}://{}'.format(scheme, lms_base) return urljoin(lms_base, url) - def _inner_content(self, tag): + def _inner_content(self, tag, absolute_urls=False): """ Helper met """ if tag is not None: - return u''.join(html.tostring(e) for e in tag) + tag_content = u''.join(html.tostring(e) for e in tag) + if absolute_urls: + return self._change_relative_url_to_absolute(tag_content) + else: + return tag_content return None - def _get_description(self, xmltree): + def _get_description(self, xmltree, absolute_urls=False): """ Parse the XML to get the description information """ description = xmltree.find('description') if description is not None: - return self._inner_content(description) + description = self._inner_content(description, absolute_urls) + return description return None - def _get_hotspots(self, xmltree): + def _change_relative_url_to_absolute(self, text): + if text: + relative_urls = Selector(text=text).css('::attr(href),::attr(src)').extract() + for url in relative_urls: + text = text.replace(url, self._replace_static_from_url(url)) + return text + + def _get_hotspots(self, xmltree, absolute_urls=False): """ Parse the XML to get the hotspot information """ @@ -310,15 +323,14 @@ def _get_hotspots(self, xmltree): feedback.width = feedback_element.get('width') feedback.height = feedback_element.get('height') feedback.max_height = feedback_element.get('max-height') - feedback.header = self._inner_content(feedback_element.find('header')) - + feedback.header = self._inner_content(feedback_element.find('header'), absolute_urls) feedback.side = hotspot_element.get('side', 'auto') feedback.body = None body_element = feedback_element.find('body') if body_element is not None: feedback.type = 'text' - feedback.body = self._inner_content(body_element) + feedback.body = self._inner_content(body_element, absolute_urls) feedback.youtube = None youtube_element = feedback_element.find('youtube') diff --git a/requirements.txt b/requirements.txt index e407da7..70d9095 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -e . -e git+https://github.com/edx/xblock-utils.git@v1.1.0#egg=xblock-utils==1.1.0 lxml==3.0.1 +parsel==1.2.0 diff --git a/tests/unit/test_image_explorer.py b/tests/unit/test_image_explorer.py index 4da1a27..b9b55b7 100644 --- a/tests/unit/test_image_explorer.py +++ b/tests/unit/test_image_explorer.py @@ -1,10 +1,14 @@ import unittest from lxml import etree +from parsel import Selector + +from django.test import override_settings from xblock.field_data import DictFieldData from image_explorer.image_explorer import ImageExplorerBlock -from ..utils import MockRuntime +from ..utils import MockRuntime, patch_static_replace_module + class TestImageExplorerBlock(unittest.TestCase): """ @@ -16,8 +20,11 @@ def setUp(self): """ super(TestImageExplorerBlock, self).setUp() self.runtime = MockRuntime() - self.image_url = 'http://example.com/test.jpg' - self.image_explorer_description = '

Test Descrption

' + patch_static_replace_module() + + self.processed_absolute_url = 'https://lms/a/dynamic/url' + self.image_url = '/static/test.jpg' + self.image_explorer_description = '

Test Descrption

' self.image_explorer_xml = """ @@ -26,7 +33,10 @@ def setUp(self):

Test Header

-

Test Body

+ +

Test Body

+ +
@@ -54,17 +64,19 @@ def setUp(self): DictFieldData(self.image_explorer_data), None ) + self.image_explorer_block.course_id = 'abc/xyz/123' + @override_settings(ENV_TOKENS={'LMS_BASE': 'lms'}, HTTPS='on') def test_student_view_data(self): """ Test the student_view_data results. """ xmltree = etree.fromstring(self.image_explorer_xml) - hotspots = self.image_explorer_block._get_hotspots(xmltree) + hotspots = self.image_explorer_block._get_hotspots(xmltree, absolute_urls=True) expected_image_explorer_data = { - 'description': self.image_explorer_description, + 'description': self.image_explorer_block._get_description(xmltree, absolute_urls=True), 'background': { - 'src': self.image_url, + 'src': self.processed_absolute_url, 'height': None, 'width': None }, @@ -74,6 +86,21 @@ def test_student_view_data(self): student_view_data = self.image_explorer_block.student_view_data() self.assertEqual(student_view_data, expected_image_explorer_data) + @override_settings(ENV_TOKENS={'LMS_BASE': 'lms'}, HTTPS='on') + def test_static_urls_conversion(self): + """ + Test static urls are processed to absolute if + `absolute_urls` is set + """ + xmltree = etree.fromstring(self.image_explorer_xml) + description = self.image_explorer_block._inner_content( + xmltree.find('description'), absolute_urls=True + ) + + relative_urls = Selector(text=description).css('::attr(href),::attr(src)').extract() + for url in relative_urls: + self.assertEqual(url, self.processed_absolute_url) + def test_student_view_multi_device_support(self): """ Test student_view multi device support is set diff --git a/tests/utils.py b/tests/utils.py index 9a755b7..3c09294 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,4 +1,6 @@ # Test mocks and helpers +from mock import patch, MagicMock + from xblock.runtime import DictKeyValueStore, KvsFieldData from xblock.test.tools import TestRuntime @@ -10,3 +12,21 @@ class MockRuntime(TestRuntime): def __init__(self, **kwargs): field_data = kwargs.get('field_data', KvsFieldData(DictKeyValueStore())) super(MockRuntime, self).__init__(field_data=field_data) + + +def patch_static_replace_module(): + """ + patchs platform's `static_replace` module as it's + unavailable in test environment + """ + mocked_static_replace = MagicMock() + mocked_static_replace.replace_static_urls = _mocked_replace_static_urls + + patch.dict('sys.modules', static_replace=mocked_static_replace).start() + + +def _mocked_replace_static_urls(*args, **kwargs): + """ + fake `replace_static_urls` method + """ + return '/a/dynamic/url'