Commit 0ef0a747 by Omar Khan

Fix cross-domain images and images with relative urls or without explicit protocol

parent 6660f982
...@@ -4,7 +4,7 @@ machine: ...@@ -4,7 +4,7 @@ machine:
dependencies: dependencies:
override: override:
- "pip install -U pip wheel setuptools" - "pip install -U pip wheel setuptools"
- "pip install -e git://github.com/edx/xblock-sdk.git@22c1b2f173919bef22f2d9d9295ec5396d02dffd#egg=xblock-sdk" - "pip install -e git://github.com/edx/xblock-sdk.git@bddf9f4a2c6e4df28a411c8f632cc2250170ae9d#egg=xblock-sdk"
- "pip install -r requirements.txt" - "pip install -r requirements.txt"
- "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/base.txt" - "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/base.txt"
- "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/test.txt" - "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/test.txt"
......
...@@ -8,6 +8,18 @@ function ExportBase(runtime, element, initData) { ...@@ -8,6 +8,18 @@ function ExportBase(runtime, element, initData) {
var generateDataUriFromImageURL = function(imgURL) { var generateDataUriFromImageURL = function(imgURL) {
// Given the URL to an image, IF the image has already been cached by the browser, // Given the URL to an image, IF the image has already been cached by the browser,
// returns a data: URI with the contents of the image (image will be converted to PNG) // returns a data: URI with the contents of the image (image will be converted to PNG)
// Expand relative urls and urls without an explicit protocol into absolute urls
var a = document.createElement('a');
a.href = imgURL;
imgURL = a.href;
// If the image is from another domain, just return its URL. We can't
// create a data URL from cross-domain images:
// https://html.spec.whatwg.org/multipage/scripting.html#dom-canvas-todataurl
if (a.origin !== window.location.origin)
return imgURL;
var img = new Image(); var img = new Image();
img.src = imgURL; img.src = imgURL;
if (!img.complete) if (!img.complete)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
# along with this program in a file in the toplevel directory called # along with this program in a file in the toplevel directory called
# "AGPLv3". If not, see <http://www.gnu.org/licenses/>. # "AGPLv3". If not, see <http://www.gnu.org/licenses/>.
# #
import json
from functools import wraps from functools import wraps
from textwrap import dedent from textwrap import dedent
from mock import Mock, patch from mock import Mock, patch
...@@ -53,7 +54,7 @@ class MockSubmissionsAPI(object): ...@@ -53,7 +54,7 @@ class MockSubmissionsAPI(object):
return [] return []
def check_dashboard_and_report(fixture, set_mentoring_values=True): def check_dashboard_and_report(fixture, set_mentoring_values=True, **kwargs):
""" """
Decorator for dashboard test methods. Decorator for dashboard test methods.
...@@ -62,11 +63,18 @@ def check_dashboard_and_report(fixture, set_mentoring_values=True): ...@@ -62,11 +63,18 @@ def check_dashboard_and_report(fixture, set_mentoring_values=True):
- Clicks the download link - Clicks the download link
- Opens the report - Opens the report
- Runs the decorated test again against the report - Runs the decorated test again against the report
Any extra keyword arguments are passed to the dashboard XBlock.
""" """
def wrapper(test): def wrapper(test):
@wraps(test) @wraps(test)
def wrapped(test_case): def wrapped(test_case):
test_case._install_fixture(fixture) test_case._install_fixture(fixture)
if kwargs:
dashboard = test_case.vertical.get_child('test-scenario.pb-dashboard.d0.u0')
for key, value in kwargs.items():
setattr(dashboard, key, value)
dashboard.save()
if set_mentoring_values: if set_mentoring_values:
test_case._set_mentoring_values() test_case._set_mentoring_values()
test_case.go_to_view('student_view') test_case.go_to_view('student_view')
...@@ -103,6 +111,9 @@ class TestDashboardBlock(ProblemBuilderBaseTest): ...@@ -103,6 +111,9 @@ class TestDashboardBlock(ProblemBuilderBaseTest):
/> />
""") """)
# Clean up screenshots if the tests pass
cleanup_on_success = True
def setUp(self): def setUp(self):
super(TestDashboardBlock, self).setUp() super(TestDashboardBlock, self).setUp()
...@@ -215,6 +226,51 @@ class TestDashboardBlock(ProblemBuilderBaseTest): ...@@ -215,6 +226,51 @@ class TestDashboardBlock(ProblemBuilderBaseTest):
expected_average = {0: "2", 1: "3", 2: "1"}[step_num] expected_average = {0: "2", 1: "3", 2: "1"}[step_num]
self._assert_cell_contents(right_col, expected_average, self._format_sr_text(expected_average)) self._assert_cell_contents(right_col, expected_average, self._format_sr_text(expected_average))
@check_dashboard_and_report(SIMPLE_DASHBOARD, visual_rules=json.dumps({
'background': '/static/test/swoop-bg.png',
}))
def test_dashboard_image(self):
"""
Test that the dashboard image is displayed correctly, both on the page
and it the report. We allow minor differences here as the report
screenshot is not a perfect match.
"""
self.assertScreenshot('.pb-dashboard-visual svg', 'dashboard-image', threshold=100)
@check_dashboard_and_report(SIMPLE_DASHBOARD, visual_rules=json.dumps({
'background': ('//raw.githubusercontent.com/open-craft/problem-builder/omar/report-download/'
'problem_builder/static/test/swoop-bg.png'),
}))
def test_dashboard_image_cross_domain(self):
"""
Test that cross-domain dashboard images are displayed correctly. We
allow minor differences here as the report screenshot is not a perfect
match.
"""
self.assertScreenshot('.pb-dashboard-visual svg', 'dashboard-image', threshold=100)
@check_dashboard_and_report(
SIMPLE_DASHBOARD,
visual_rules=json.dumps({
'background': '/static/test/swoop-bg.png',
'images': [
'/static/test/swoop-step1.png',
'/static/test/swoop-step2.png',
],
}),
color_rules='\n'.join([
'0: grey',
'x <= 2: #aa2626',
'x <= 3: #e7ce76',
'#84b077',
]),
)
def test_dashboard_image_overlay(self):
"""
Test that image overlays are displayed correctly on the dashboard.
"""
self.assertScreenshot('.pb-dashboard-visual svg', 'dashboard-image-overlay', threshold=100)
@check_dashboard_and_report(ALTERNATIVE_DASHBOARD) @check_dashboard_and_report(ALTERNATIVE_DASHBOARD)
def test_dashboard_alternative(self): def test_dashboard_alternative(self):
""" """
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment