dynamicweb/cms/tests/test_menu_utils.py

179 lines
7.3 KiB
Python

from urllib.parse import urlencode
from django.http import HttpResponse
from cms.api import create_page, create_page_content
from cms.test_utils.testcases import CMSTestCase
from cms.test_utils.util.mock import AttributeObject
from cms.toolbar.toolbar import CMSToolbar
from cms.utils.i18n import get_language_list
from menus.templatetags.menu_tags import PageLanguageUrl
from menus.utils import (
DefaultLanguageChanger,
find_selected,
language_changer_decorator,
)
class DumbPageLanguageUrl(PageLanguageUrl):
def __init__(self):
pass
class MenuUtilsTests(CMSTestCase):
def get_simple_view(self):
def myview(request):
return HttpResponse('')
return myview
def test_reverse_in_changer(self):
response = self.client.get('/en/sample/login/')
self.assertContains(response, '<h1>/fr/sample/login/</h1>')
response = self.client.get('/en/sample/login_other/')
self.assertContains(response, '<h1>/fr/sample/login_other/</h1>')
response = self.client.get('/en/sample/login3/')
self.assertContains(response, '<h1>/fr/sample/login3/</h1>')
def test_default_language_changer(self):
"""
The DefaultLanguageChanger should not try to resolve the url
for languages not configured.
"""
cms_page = create_page('en-page', 'nav_playground.html', 'en')
for language in get_language_list(site_id=1):
if language not in ('en', 'pt-br', 'es-mx'):
create_page_content(language, '%s-page' % language, cms_page)
request = self.get_request(
path=cms_page.get_absolute_url(),
language='en',
page=cms_page,
)
urls_expected = [
'/en/en-page/',
'/de/de-page/',
'/fr/fr-page/',
'/en/en-page/', # the pt-br url is en because that's a fallback
'/en/en-page/', # the es-mx url is en because that's a fallback
]
urls_found = [DefaultLanguageChanger(request)(code)
for code in get_language_list(site_id=1)]
self.assertSequenceEqual(urls_expected, urls_found)
def test_default_language_changer_uses_cms_path(self):
"""
On asynchronous toolbar/structure requests ``request.path_info`` points at
an internal admin/AJAX endpoint, while the viewed page is reported via the
``cms_path`` GET query. The language changer must build URLs for the viewed
page rather than the AJAX endpoint (#8465).
"""
cms_page = create_page('en-page', 'nav_playground.html', 'en')
for language in get_language_list(site_id=1):
if language not in ('en', 'pt-br', 'es-mx'):
create_page_content(language, '%s-page' % language, cms_page)
page_url = cms_page.get_absolute_url()
# Simulate the async toolbar endpoint: ``path_info`` is an admin endpoint
# and the viewed page is reported via the ``cms_path`` GET query.
async_path = '/admin/cms/placeholder/object/{pk}/structure/?{query}'.format(
pk=cms_page.pk,
query=urlencode({'cms_path': page_url}),
)
request = self.get_request(path=async_path, language='en', page=cms_page)
request.toolbar = CMSToolbar(request)
urls_expected = [
'/en/en-page/',
'/de/de-page/',
'/fr/fr-page/',
'/en/en-page/', # the pt-br url is en because that's a fallback
'/en/en-page/', # the es-mx url is en because that's a fallback
]
urls_found = [DefaultLanguageChanger(request)(code)
for code in get_language_list(site_id=1)]
self.assertSequenceEqual(urls_expected, urls_found)
def test_language_changer_request_path_prefers_toolbar(self):
"""
``DefaultLanguageChanger.request_path`` prefers the toolbar's
``request_path`` (the viewed page) and falls back to ``path_info``.
"""
request = self.get_request(path='/admin/some/endpoint/', language='en')
# No toolbar attached -> falls back to the actual request path.
self.assertEqual(
DefaultLanguageChanger(request).request_path,
'/admin/some/endpoint/',
)
# Toolbar request_path (viewed page) takes precedence.
request.toolbar = CMSToolbar(request, request_path='/en/viewed-page/')
self.assertEqual(
DefaultLanguageChanger(request).request_path,
'/en/viewed-page/',
)
def test_toolbar_request_path_honours_cms_path(self):
"""
``CMSToolbar.request_path`` is derived from the ``cms_path`` GET query when
present, falls back to ``path_info`` otherwise, and an explicit
``request_path`` always wins.
"""
cms_page = create_page('en-page', 'nav_playground.html', 'en')
page_url = cms_page.get_absolute_url()
async_path = '/admin/cms/placeholder/object/{pk}/structure/?{query}'.format(
pk=cms_page.pk,
query=urlencode({'cms_path': page_url}),
)
request = self.get_request(path=async_path, language='en', page=cms_page)
self.assertEqual(CMSToolbar(request).request_path, page_url)
# A cms_path that carries its own query string/fragment is reduced to the
# bare path (``_get_request_path`` uses ``urlparse(cms_path).path``).
async_path_with_query = '/admin/cms/placeholder/object/{pk}/structure/?{query}'.format(
pk=cms_page.pk,
query=urlencode({'cms_path': '%s?foo=bar#frag' % page_url}),
)
request = self.get_request(path=async_path_with_query, language='en', page=cms_page)
self.assertEqual(CMSToolbar(request).request_path, page_url)
# Without a cms_path query it falls back to the request path.
request = self.get_request(path=page_url, language='en', page=cms_page)
self.assertEqual(CMSToolbar(request).request_path, page_url)
# An explicitly passed request_path always wins.
self.assertEqual(
CMSToolbar(request, request_path='/explicit/').request_path,
'/explicit/',
)
def test_language_changer_decorator(self):
def lang_changer(lang):
return "/%s/dummy/" % lang
decorated_view = language_changer_decorator(lang_changer)(self.get_simple_view())
request = self.get_request('/some/path/', 'en')
response = decorated_view(request)
self.assertEqual(response.content, b'')
fake_context = {'request': request}
tag = DumbPageLanguageUrl()
output = tag.get_context(fake_context, 'en')
url = output['content']
self.assertEqual(url, '/en/dummy/')
output = tag.get_context(fake_context, 'ja')
url = output['content']
self.assertEqual(url, '/ja/dummy/')
def test_find_selected(self):
subchild = AttributeObject()
firstchild = AttributeObject(ancestor=True, children=[subchild])
selectedchild = AttributeObject(selected=True)
secondchild = AttributeObject(ancestor=True, children=[selectedchild])
root = AttributeObject(ancestor=True, children=[firstchild, secondchild])
nodes = [root]
selected = find_selected(nodes)
self.assertEqual(selected, selectedchild)