Serve branded footer JSON/HTML/CSS/JS from an API endpoint in the branding app. Refactor OpenEdX and EdX.org footer templates to use the Python version of the API, ensuring that the API values are consistent with the footer included in main.html. Detailed changes: * Added footer API end-point to the branding app. * Footer API allows the language to be set with querystring parameters. * Footer API allows showing/hiding of the OpenEdX logo using querystring parameters. * Deprecate ENABLE_FOOTER_V3 in favor of the branding API configuration flag. * Move no referrer script into main.html from the edx footer template. * Rename rwd_header_footer.js to rwd_header.js * Cache API responses. Authors: Awais Qureshi, Aamir Khan, Will Daly
215 lines
7.1 KiB
Python
215 lines
7.1 KiB
Python
# encoding: utf-8
|
|
"""Tests of Branding API views. """
|
|
import contextlib
|
|
import json
|
|
import urllib
|
|
from django.test import TestCase
|
|
from django.core.urlresolvers import reverse
|
|
from django.conf import settings
|
|
|
|
import mock
|
|
import ddt
|
|
from config_models.models import cache
|
|
from branding.models import BrandingApiConfig
|
|
|
|
|
|
@ddt.ddt
|
|
class TestFooter(TestCase):
|
|
"""Test API end-point for retrieving the footer. """
|
|
|
|
def setUp(self):
|
|
"""Clear the configuration cache. """
|
|
super(TestFooter, self).setUp()
|
|
cache.clear()
|
|
|
|
@ddt.data("*/*", "text/html", "application/json")
|
|
def test_feature_flag(self, accepts):
|
|
self._set_feature_flag(False)
|
|
resp = self._get_footer(accepts=accepts)
|
|
self.assertEqual(resp.status_code, 404)
|
|
|
|
@ddt.data(
|
|
# Open source version
|
|
(False, "application/json", "application/json; charset=utf-8", "Open edX"),
|
|
(False, "text/html", "text/html; charset=utf-8", "lms-footer.css"),
|
|
(False, "text/html", "text/html; charset=utf-8", "Open edX"),
|
|
|
|
# EdX.org version
|
|
(True, "application/json", "application/json; charset=utf-8", "edX Inc"),
|
|
(True, "text/html", "text/html; charset=utf-8", "lms-footer-edx.css"),
|
|
(True, "text/html", "text/html; charset=utf-8", "edX Inc"),
|
|
)
|
|
@ddt.unpack
|
|
def test_footer_content_types(self, is_edx_domain, accepts, content_type, content):
|
|
self._set_feature_flag(True)
|
|
with self._set_is_edx_domain(is_edx_domain):
|
|
resp = self._get_footer(accepts=accepts)
|
|
|
|
self.assertEqual(resp.status_code, 200)
|
|
self.assertEqual(resp["Content-Type"], content_type)
|
|
self.assertIn(content, resp.content)
|
|
|
|
@mock.patch.dict(settings.FEATURES, {'ENABLE_FOOTER_MOBILE_APP_LINKS': True})
|
|
@ddt.data(True, False)
|
|
def test_footer_json(self, is_edx_domain):
|
|
self._set_feature_flag(True)
|
|
with self._set_is_edx_domain(is_edx_domain):
|
|
resp = self._get_footer()
|
|
|
|
self.assertEqual(resp.status_code, 200)
|
|
json_data = json.loads(resp.content)
|
|
self.assertTrue(isinstance(json_data, dict))
|
|
|
|
# Logo
|
|
self.assertIn("logo_image", json_data)
|
|
|
|
# Links
|
|
self.assertIn("navigation_links", json_data)
|
|
for link in json_data["navigation_links"]:
|
|
self.assertIn("name", link)
|
|
self.assertIn("title", link)
|
|
self.assertIn("url", link)
|
|
|
|
# Social links
|
|
self.assertIn("social_links", json_data)
|
|
for link in json_data["social_links"]:
|
|
self.assertIn("name", link)
|
|
self.assertIn("title", link)
|
|
self.assertIn("url", link)
|
|
self.assertIn("icon-class", link)
|
|
|
|
# Mobile links
|
|
self.assertIn("mobile_links", json_data)
|
|
for link in json_data["mobile_links"]:
|
|
self.assertIn("name", link)
|
|
self.assertIn("title", link)
|
|
self.assertIn("url", link)
|
|
self.assertIn("image", link)
|
|
|
|
# Legal links
|
|
self.assertIn("legal_links", json_data)
|
|
for link in json_data["legal_links"]:
|
|
self.assertIn("name", link)
|
|
self.assertIn("title", link)
|
|
self.assertIn("url", link)
|
|
|
|
# OpenEdX
|
|
self.assertIn("openedx_link", json_data)
|
|
self.assertIn("url", json_data["openedx_link"])
|
|
self.assertIn("title", json_data["openedx_link"])
|
|
self.assertIn("image", json_data["openedx_link"])
|
|
|
|
# Copyright
|
|
self.assertIn("copyright", json_data)
|
|
|
|
@ddt.data(
|
|
("en", "registered trademarks"),
|
|
("eo", u"régïstéréd trädémärks"), # Dummy language string
|
|
("unknown", "registered trademarks"), # default to English
|
|
)
|
|
@ddt.unpack
|
|
def test_language_override_translation(self, language, expected_copyright):
|
|
self._set_feature_flag(True)
|
|
|
|
# Load the footer with the specified language
|
|
resp = self._get_footer(params={'language': language})
|
|
self.assertEqual(resp.status_code, 200)
|
|
json_data = json.loads(resp.content)
|
|
|
|
# Verify that the translation occurred
|
|
self.assertIn(expected_copyright, json_data['copyright'])
|
|
|
|
@ddt.data(
|
|
# OpenEdX
|
|
(False, "en", "lms-footer.css"),
|
|
(False, "ar", "lms-footer-rtl.css"),
|
|
|
|
# EdX.org
|
|
(True, "en", "lms-footer-edx.css"),
|
|
(True, "ar", "lms-footer-edx-rtl.css"),
|
|
)
|
|
@ddt.unpack
|
|
def test_language_rtl(self, is_edx_domain, language, static_path):
|
|
self._set_feature_flag(True)
|
|
|
|
with self._set_is_edx_domain(is_edx_domain):
|
|
resp = self._get_footer(accepts="text/html", params={'language': language})
|
|
|
|
self.assertEqual(resp.status_code, 200)
|
|
self.assertIn(static_path, resp.content)
|
|
|
|
@ddt.data(
|
|
# OpenEdX
|
|
(False, True),
|
|
(False, False),
|
|
|
|
# EdX.org
|
|
(True, True),
|
|
(True, False),
|
|
)
|
|
@ddt.unpack
|
|
def test_show_openedx_logo(self, is_edx_domain, show_logo):
|
|
self._set_feature_flag(True)
|
|
|
|
with self._set_is_edx_domain(is_edx_domain):
|
|
params = {'show-openedx-logo': 1} if show_logo else {}
|
|
resp = self._get_footer(accepts="text/html", params=params)
|
|
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
if show_logo:
|
|
self.assertIn(settings.FOOTER_OPENEDX_URL, resp.content)
|
|
else:
|
|
self.assertNotIn(settings.FOOTER_OPENEDX_URL, resp.content)
|
|
|
|
@ddt.data(
|
|
# OpenEdX
|
|
(False, False),
|
|
(False, True),
|
|
|
|
# EdX.org
|
|
(True, False),
|
|
(True, True),
|
|
)
|
|
@ddt.unpack
|
|
def test_include_dependencies(self, is_edx_domain, include_dependencies):
|
|
self._set_feature_flag(True)
|
|
with self._set_is_edx_domain(is_edx_domain):
|
|
params = {'include-dependencies': 1} if include_dependencies else {}
|
|
resp = self._get_footer(accepts="text/html", params=params)
|
|
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
if include_dependencies:
|
|
self.assertIn("vendor", resp.content)
|
|
else:
|
|
self.assertNotIn("vendor", resp.content)
|
|
|
|
def test_no_supported_accept_type(self):
|
|
self._set_feature_flag(True)
|
|
resp = self._get_footer(accepts="application/x-shockwave-flash")
|
|
self.assertEqual(resp.status_code, 406)
|
|
|
|
def _set_feature_flag(self, enabled):
|
|
"""Enable or disable the feature flag for the branding API end-points. """
|
|
config = BrandingApiConfig(enabled=enabled)
|
|
config.save()
|
|
|
|
def _get_footer(self, accepts="application/json", params=None):
|
|
"""Retrieve the footer. """
|
|
url = reverse("branding_footer")
|
|
|
|
if params is not None:
|
|
url = u"{url}?{params}".format(
|
|
url=url,
|
|
params=urllib.urlencode(params)
|
|
)
|
|
|
|
return self.client.get(url, HTTP_ACCEPT=accepts)
|
|
|
|
@contextlib.contextmanager
|
|
def _set_is_edx_domain(self, is_edx_domain):
|
|
"""Configure whether this an EdX-controlled domain. """
|
|
with mock.patch.dict(settings.FEATURES, {'IS_EDX_DOMAIN': is_edx_domain}):
|
|
yield
|