Remove the DarkLang middleware from the LMS Created and basic routing to the update_lang page for the GET Request TNL-4742 Basic form functionality Working example in LMS of the form to set the language Login now required to change the preview language, and corrected some minor bugs Updates to move the template code to lms and to correct minor defects TNL-4742 Added template for preview_lang.html to cms TNL-4742 Changed filename of darklang.py to api.py to match convention TNL-4742 Updated and refactored the Darklang tests TNL-4742 Updated comments in tests TNL-4742 Formating updates TNL-4742 Updated comments and formatting TNL-4742 Corrected i18n tests and corrected PEP8 format issues TNL-4742 Code Lint/PEP-8 corrections and upates TNL-4742 Removed constant that was not needed (to be squashed) TNL-4742 Added init method to clear up PEP8 Warnings (will squash) TNL-4742 PEP-8/Lint issue resolved (squash) Updated for i18n TNL-4742 Refactored the preview_lang.html page to use a common included template Refactoring and changes from PR comments TNL-4742 Correction for safecommit violation (Squash) TNL-4742 PR changes and refactoring (Squash) Updates to reduce changes made in the urls used TNL-4742 Removed unneeded aria-described by and bug in MAKO Template (squash) TNK-4742 Updated docstring comments Clarified form response text Minor PR request (Squash) Refactoring of how the responses are generated within the DarkLang views file A series of refactors in response to PR comments Method name change for clarity in reponse to PR comments (Squash) Updates to tests per PR requests (Squash) Minor comment updates for clarity and PR requests (Squash) Updated per PR comments and added a test for empty preview_language Layout and code style updates (Squash) Updated test to contain method in the request. Removed the Darklang preview-lang and clear-lang parameters and added the new DarkLang settings form at /update_lang Refactored tests and added some tests for coverage, corrected defect with empty input codes Removed unused and obsolete code Corrected test errors, resolved PR comments, and updated comments to clarify testing TNL-4742 Updated tests to deal with Pylint quality issue (Squash) Updated tests to better reflect test case and PR updates (Squash)
362 lines
12 KiB
Python
362 lines
12 KiB
Python
"""
|
|
Tests of DarkLangMiddleware
|
|
"""
|
|
import unittest
|
|
|
|
import ddt
|
|
from django.http import HttpRequest
|
|
from django.test import TestCase
|
|
from django.test.client import Client
|
|
from django.utils.translation import LANGUAGE_SESSION_KEY
|
|
from mock import Mock
|
|
|
|
from dark_lang.middleware import DarkLangMiddleware
|
|
from dark_lang.models import DarkLangConfig
|
|
from student.tests.factories import UserFactory
|
|
UNSET = object()
|
|
|
|
|
|
def set_if_set(dct, key, value):
|
|
"""
|
|
Sets ``key`` in ``dct`` to ``value``
|
|
unless ``value`` is ``UNSET``
|
|
"""
|
|
if value is not UNSET:
|
|
dct[key] = value
|
|
|
|
|
|
@ddt.ddt
|
|
class DarkLangMiddlewareTests(TestCase):
|
|
"""
|
|
Tests of DarkLangMiddleware
|
|
"""
|
|
def setUp(self):
|
|
super(DarkLangMiddlewareTests, self).setUp()
|
|
self.user = UserFactory.build(username='test', email='test@edx.org', password='test_password')
|
|
self.user.save()
|
|
self.client = Client()
|
|
self.client.login(username=self.user.username, password='test_password')
|
|
DarkLangConfig(
|
|
released_languages='rel',
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
def process_middleware_request(self, language_session_key=UNSET, accept=UNSET):
|
|
"""
|
|
Build a request and then process it using the ``DarkLangMiddleware``.
|
|
|
|
Args:
|
|
language_session_key (str): The language code to set in request.session[LANUGAGE_SESSION_KEY]
|
|
accept (str): The accept header to set in request.META['HTTP_ACCEPT_LANGUAGE']
|
|
"""
|
|
session = {}
|
|
set_if_set(session, LANGUAGE_SESSION_KEY, language_session_key)
|
|
|
|
meta = {}
|
|
set_if_set(meta, 'HTTP_ACCEPT_LANGUAGE', accept)
|
|
|
|
request = Mock(
|
|
spec=HttpRequest,
|
|
session=session,
|
|
META=meta,
|
|
GET={},
|
|
method='GET',
|
|
user=self.user
|
|
)
|
|
|
|
# Process it through the Middleware to ensure the language is available as expected.
|
|
self.assertIsNone(DarkLangMiddleware().process_request(request))
|
|
return request
|
|
|
|
def assertAcceptEquals(self, value, request):
|
|
"""
|
|
Assert that the HTML_ACCEPT_LANGUAGE header in request
|
|
is equal to value
|
|
"""
|
|
self.assertEquals(
|
|
value,
|
|
request.META.get('HTTP_ACCEPT_LANGUAGE', UNSET)
|
|
)
|
|
|
|
def test_empty_accept(self):
|
|
self.assertAcceptEquals(UNSET, self.process_middleware_request())
|
|
|
|
def test_wildcard_accept(self):
|
|
self.assertAcceptEquals('*', self.process_middleware_request(accept='*'))
|
|
|
|
def test_malformed_accept(self):
|
|
self.assertAcceptEquals('', self.process_middleware_request(accept='xxxxxxxxxxxx'))
|
|
self.assertAcceptEquals('', self.process_middleware_request(accept='en;q=1.0, es-419:q-0.8'))
|
|
|
|
def test_released_accept(self):
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0',
|
|
self.process_middleware_request(accept='rel;q=1.0')
|
|
)
|
|
|
|
def test_unreleased_accept(self):
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0',
|
|
self.process_middleware_request(accept='rel;q=1.0, unrel;q=0.5')
|
|
)
|
|
|
|
def test_accept_with_syslang(self):
|
|
self.assertAcceptEquals(
|
|
'en;q=1.0, rel;q=0.8',
|
|
self.process_middleware_request(accept='en;q=1.0, rel;q=0.8, unrel;q=0.5')
|
|
)
|
|
|
|
def test_accept_multiple_released_langs(self):
|
|
DarkLangConfig(
|
|
released_languages=('rel, unrel'),
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0, unrel;q=0.5',
|
|
self.process_middleware_request(accept='rel;q=1.0, unrel;q=0.5')
|
|
)
|
|
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0, unrel;q=0.5',
|
|
self.process_middleware_request(accept='rel;q=1.0, notrel;q=0.3, unrel;q=0.5')
|
|
)
|
|
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0, unrel;q=0.5',
|
|
self.process_middleware_request(accept='notrel;q=0.3, rel;q=1.0, unrel;q=0.5')
|
|
)
|
|
|
|
def test_accept_released_territory(self):
|
|
# We will munge 'rel-ter' to be 'rel', so the 'rel-ter'
|
|
# user will actually receive the released language 'rel'
|
|
# (Otherwise, the user will actually end up getting the server default)
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0, rel;q=0.5',
|
|
self.process_middleware_request(accept='rel-ter;q=1.0, rel;q=0.5')
|
|
)
|
|
|
|
def test_accept_mixed_case(self):
|
|
self.assertAcceptEquals(
|
|
'rel;q=1.0, rel;q=0.5',
|
|
self.process_middleware_request(accept='rel-TER;q=1.0, REL;q=0.5')
|
|
)
|
|
|
|
DarkLangConfig(
|
|
released_languages='REL-TER',
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
# Since we have only released "rel-ter", the requested code "rel" will
|
|
# fuzzy match to "rel-ter", in addition to "rel-ter" exact matching "rel-ter"
|
|
self.assertAcceptEquals(
|
|
'rel-ter;q=1.0, rel-ter;q=0.5',
|
|
self.process_middleware_request(accept='rel-ter;q=1.0, rel;q=0.5')
|
|
)
|
|
|
|
@ddt.data(
|
|
('es;q=1.0, pt;q=0.5', 'es-419;q=1.0'), # 'es' should get 'es-419', not English
|
|
('es-AR;q=1.0, pt;q=0.5', 'es-419;q=1.0'), # 'es-AR' should get 'es-419', not English
|
|
)
|
|
@ddt.unpack
|
|
def test_partial_match_es419(self, accept_header, expected):
|
|
# Release es-419
|
|
DarkLangConfig(
|
|
released_languages=('es-419, en'),
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
self.assertAcceptEquals(
|
|
expected,
|
|
self.process_middleware_request(accept=accept_header)
|
|
)
|
|
|
|
def test_partial_match_esar_es(self):
|
|
# If I release 'es', 'es-AR' should get 'es', not English
|
|
DarkLangConfig(
|
|
released_languages=('es, en'),
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
self.assertAcceptEquals(
|
|
'es;q=1.0',
|
|
self.process_middleware_request(accept='es-AR;q=1.0, pt;q=0.5')
|
|
)
|
|
|
|
@ddt.data(
|
|
# Test condition: If I release 'es-419, es, es-es'...
|
|
('es;q=1.0, pt;q=0.5', 'es;q=1.0'), # 1. es should get es
|
|
('es-419;q=1.0, pt;q=0.5', 'es-419;q=1.0'), # 2. es-419 should get es-419
|
|
('es-es;q=1.0, pt;q=0.5', 'es-es;q=1.0'), # 3. es-es should get es-es
|
|
)
|
|
@ddt.unpack
|
|
def test_exact_match_gets_priority(self, accept_header, expected):
|
|
# Release 'es-419, es, es-es'
|
|
DarkLangConfig(
|
|
released_languages=('es-419, es, es-es'),
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
self.assertAcceptEquals(
|
|
expected,
|
|
self.process_middleware_request(accept=accept_header)
|
|
)
|
|
|
|
@unittest.skip("This won't work until fallback is implemented for LA country codes. See LOC-86")
|
|
@ddt.data(
|
|
'es-AR', # Argentina
|
|
'es-PY', # Paraguay
|
|
)
|
|
def test_partial_match_es_la(self, latin_america_code):
|
|
# We need to figure out the best way to implement this. There are a ton of LA country
|
|
# codes that ought to fall back to 'es-419' rather than 'es-es'.
|
|
# http://unstats.un.org/unsd/methods/m49/m49regin.htm#americas
|
|
# If I release 'es, es-419'
|
|
# Latin American codes should get es-419
|
|
DarkLangConfig(
|
|
released_languages=('es, es-419'),
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
self.assertAcceptEquals(
|
|
'es-419;q=1.0',
|
|
self.process_middleware_request(accept='{};q=1.0, pt;q=0.5'.format(latin_america_code))
|
|
)
|
|
|
|
def assert_session_lang_equals(self, value, session):
|
|
"""
|
|
Assert that the LANGUAGE_SESSION_KEY set in session is equal to value
|
|
"""
|
|
self.assertEquals(
|
|
value,
|
|
session.get(LANGUAGE_SESSION_KEY, UNSET)
|
|
)
|
|
|
|
def _post_set_preview_lang(self, preview_language):
|
|
"""
|
|
Sends a post request to set the preview language
|
|
"""
|
|
return self.client.post('/update_lang/', {'preview_lang': preview_language, 'set_language': 'set_language'})
|
|
|
|
def _post_clear_preview_lang(self):
|
|
"""
|
|
Sends a post request to Clear the preview language
|
|
"""
|
|
return self.client.post('/update_lang/', {'reset': 'reset'})
|
|
|
|
def _set_client_session_language(self, session_language):
|
|
"""
|
|
Set the session language in the Client
|
|
"""
|
|
session = self.client.session
|
|
session[LANGUAGE_SESSION_KEY] = session_language
|
|
session.save()
|
|
|
|
def test_preview_lang_with_released_language(self):
|
|
# Preview lang should always override selection
|
|
self._post_set_preview_lang('rel')
|
|
# Refresh the page with a get request to confirm the preview language was set
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'rel',
|
|
self.client.session
|
|
)
|
|
|
|
# Set the session language and ensure that the preview language overrides
|
|
self._set_client_session_language('notrel')
|
|
self._post_set_preview_lang('rel')
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'rel',
|
|
self.client.session
|
|
)
|
|
|
|
def test_preview_lang_with_dark_language(self):
|
|
self._post_set_preview_lang('unrel')
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'unrel',
|
|
self.client.session
|
|
)
|
|
|
|
# Test a clear and then a set of the preview language
|
|
self._post_clear_preview_lang()
|
|
self._post_set_preview_lang('unrel')
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'unrel',
|
|
self.client.session
|
|
)
|
|
|
|
def test_empty_preview_language(self):
|
|
# When posting an empty preview_language the currently set language should not change
|
|
self._set_client_session_language('rel')
|
|
self._post_set_preview_lang(' ')
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'rel',
|
|
self.client.session
|
|
)
|
|
|
|
def test_clear_lang(self):
|
|
# Clear a language when no language was set
|
|
self._post_clear_preview_lang()
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
UNSET,
|
|
self.client.session
|
|
)
|
|
|
|
# Set a language and clear it to ensure the clear is working as expected
|
|
self._post_set_preview_lang('notclear')
|
|
self._post_clear_preview_lang()
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
UNSET,
|
|
self.client.session
|
|
)
|
|
|
|
def test_disabled(self):
|
|
DarkLangConfig(enabled=False, changed_by=self.user).save()
|
|
|
|
self.assertAcceptEquals(
|
|
'notrel;q=0.3, rel;q=1.0, unrel;q=0.5',
|
|
self.process_middleware_request(accept='notrel;q=0.3, rel;q=1.0, unrel;q=0.5')
|
|
)
|
|
|
|
# With DarkLang disabled the clear should not change the session language
|
|
self._set_client_session_language('rel')
|
|
self._post_clear_preview_lang()
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'rel',
|
|
self.client.session
|
|
)
|
|
|
|
# Test that setting the preview language with DarkLang disabled does nothing
|
|
self._set_client_session_language('unrel')
|
|
self._post_set_preview_lang('rel')
|
|
self.client.get('/home')
|
|
self.assert_session_lang_equals(
|
|
'unrel',
|
|
self.client.session
|
|
)
|
|
|
|
def test_accept_chinese_language_codes(self):
|
|
DarkLangConfig(
|
|
released_languages=('zh-cn, zh-hk, zh-tw'),
|
|
changed_by=self.user,
|
|
enabled=True
|
|
).save()
|
|
|
|
self.assertAcceptEquals(
|
|
'zh-cn;q=1.0, zh-tw;q=0.5, zh-hk;q=0.3',
|
|
self.process_middleware_request(accept='zh-Hans;q=1.0, zh-Hant-TW;q=0.5, zh-HK;q=0.3')
|
|
)
|