From 845817b039fc059955bb1eafa5fd78565a49159d Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Fri, 6 Mar 2015 12:45:53 -0500 Subject: Fixed #24466 -- Added JavaScript escaping in a couple places in the admin. Thanks Aymeric Augustin and Florian Apolloner for work on the patch. --- tests/admin_inlines/test_templates.py | 21 +++++++++++++++++++++ tests/admin_inlines/tests.py | 12 ++++++------ tests/admin_views/tests.py | 25 +++++++++++++++++++++++++ tests/admin_widgets/tests.py | 14 ++++++++++---- 4 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 tests/admin_inlines/test_templates.py (limited to 'tests') diff --git a/tests/admin_inlines/test_templates.py b/tests/admin_inlines/test_templates.py new file mode 100644 index 0000000000..1ed52c9115 --- /dev/null +++ b/tests/admin_inlines/test_templates.py @@ -0,0 +1,21 @@ +from __future__ import unicode_literals + +from django.template.loader import render_to_string +from django.test import SimpleTestCase + + +class TestTemplates(SimpleTestCase): + def test_javascript_escaping(self): + context = { + 'inline_admin_formset': { + 'formset': {'prefix': 'my-prefix'}, + 'opts': {'verbose_name': 'verbose name\\'}, + }, + } + output = render_to_string('admin/edit_inline/stacked.html', context) + self.assertIn('prefix: "my\\u002Dprefix",', output) + self.assertIn('addText: "Add another Verbose name\\u005C"', output) + + output = render_to_string('admin/edit_inline/tabular.html', context) + self.assertIn('prefix: "my\\u002Dprefix",', output) + self.assertIn('addText: "Add another Verbose name\\u005C"', output) diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index c262de7d27..19260baf4d 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -78,7 +78,7 @@ class TestInline(TestDataMixin, TestCase): # The heading for the m2m inline block uses the right text self.assertContains(response, '

Author-book relationships

') # The "add another" label is correct - self.assertContains(response, 'Add another Author-book relationship') + self.assertContains(response, 'Add another Author\\u002Dbook relationship') # The '+' is dropped from the autogenerated form prefix (Author_books+) self.assertContains(response, 'id="id_Author_books-TOTAL_FORMS"') @@ -524,7 +524,7 @@ class TestInlinePermissions(TestCase): response = self.client.get(reverse('admin:admin_inlines_author_add')) # No change permission on books, so no inline self.assertNotContains(response, '

Author-book relationships

') - self.assertNotContains(response, 'Add another Author-Book Relationship') + self.assertNotContains(response, 'Add another Author\\u002DBook Relationship') self.assertNotContains(response, 'id="id_Author_books-TOTAL_FORMS"') def test_inline_add_fk_noperm(self): @@ -538,7 +538,7 @@ class TestInlinePermissions(TestCase): response = self.client.get(self.author_change_url) # No change permission on books, so no inline self.assertNotContains(response, '

Author-book relationships

') - self.assertNotContains(response, 'Add another Author-Book Relationship') + self.assertNotContains(response, 'Add another Author\\u002DBook Relationship') self.assertNotContains(response, 'id="id_Author_books-TOTAL_FORMS"') def test_inline_change_fk_noperm(self): @@ -554,7 +554,7 @@ class TestInlinePermissions(TestCase): response = self.client.get(reverse('admin:admin_inlines_author_add')) # No change permission on Books, so no inline self.assertNotContains(response, '

Author-book relationships

') - self.assertNotContains(response, 'Add another Author-Book Relationship') + self.assertNotContains(response, 'Add another Author\\u002DBook Relationship') self.assertNotContains(response, 'id="id_Author_books-TOTAL_FORMS"') def test_inline_add_fk_add_perm(self): @@ -573,7 +573,7 @@ class TestInlinePermissions(TestCase): response = self.client.get(self.author_change_url) # No change permission on books, so no inline self.assertNotContains(response, '

Author-book relationships

') - self.assertNotContains(response, 'Add another Author-Book Relationship') + self.assertNotContains(response, 'Add another Author\\u002DBook Relationship') self.assertNotContains(response, 'id="id_Author_books-TOTAL_FORMS"') self.assertNotContains(response, 'id="id_Author_books-0-DELETE"') @@ -583,7 +583,7 @@ class TestInlinePermissions(TestCase): response = self.client.get(self.author_change_url) # We have change perm on books, so we can add/change/delete inlines self.assertContains(response, '

Author-book relationships

') - self.assertContains(response, 'Add another Author-book relationship') + self.assertContains(response, 'Add another Author\\u002Dbook relationship') self.assertContains(response, '', html=True) self.assertContains(response, ' self.assertEqual(response.status_code, 200) self.assertEqual(response.template_name, 'admin/popup_response.html') + def test_popup_template_escaping(self): + context = { + 'new_value': 'new_value\\', + 'obj': 'obj\\', + 'value': 'value\\', + } + output = render_to_string('admin/popup_response.html', context) + self.assertIn( + 'opener.dismissAddRelatedObjectPopup(window, "value\\u005C", "obj\\u005C");', output + ) + + context['action'] = 'change' + output = render_to_string('admin/popup_response.html', context) + self.assertIn( + 'opener.dismissChangeRelatedObjectPopup(window, ' + '"value\\u005C", "obj\\u005C", "new_value\\u005C");', output + ) + + context['action'] = 'delete' + output = render_to_string('admin/popup_response.html', context) + self.assertIn( + 'opener.dismissDeleteRelatedObjectPopup(window, "value\\u005C");', output + ) + @override_settings(PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'], ROOT_URLCONF="admin_views.urls") diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py index 5083295c46..1f0ec00eed 100644 --- a/tests/admin_widgets/tests.py +++ b/tests/admin_widgets/tests.py @@ -264,17 +264,23 @@ class AdminForeignKeyRawIdWidget(TestDataMixin, DjangoTestCase): class FilteredSelectMultipleWidgetTest(DjangoTestCase): def test_render(self): - w = widgets.FilteredSelectMultiple('test', False) + # Backslash in verbose_name to ensure it is JavaScript escaped. + w = widgets.FilteredSelectMultiple('test\\', False) self.assertHTMLEqual( w.render('test', 'test'), - '\n' + '' + '\n' ) def test_stacked_render(self): - w = widgets.FilteredSelectMultiple('test', True) + # Backslash in verbose_name to ensure it is JavaScript escaped. + w = widgets.FilteredSelectMultiple('test\\', True) self.assertHTMLEqual( w.render('test', 'test'), - '\n' + '' + '\n' ) -- cgit v1.2.1