# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.core.urlresolvers import reverse
from django.forms import (
CheckboxSelectMultiple, ClearableFileInput, RadioSelect, TextInput,
)
from django.forms.widgets import (
ChoiceFieldRenderer, ChoiceInput, RadioFieldRenderer,
)
from django.test import SimpleTestCase, override_settings
from django.utils import six
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.safestring import SafeData
from ..models import Article
class FormsWidgetTests(SimpleTestCase):
def test_radiofieldrenderer(self):
# RadioSelect uses a RadioFieldRenderer to render the individual radio inputs.
# You can manipulate that object directly to customize the way the RadioSelect
# is rendered.
w = RadioSelect()
r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
inp_set1 = []
inp_set2 = []
inp_set3 = []
inp_set4 = []
for inp in r:
inp_set1.append(str(inp))
inp_set2.append('%s ' % inp)
inp_set3.append('
""")
self.assertHTMLEqual('\n'.join(inp_set4), """beatle J J John True
beatle J P Paul False
beatle J G George False
beatle J R Ringo False""")
# A RadioFieldRenderer object also allows index access to individual RadioChoiceInput
w = RadioSelect()
r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
self.assertHTMLEqual(str(r[1]), '')
self.assertHTMLEqual(
str(r[0]),
''
)
self.assertTrue(r[0].is_checked())
self.assertFalse(r[1].is_checked())
self.assertEqual((r[1].name, r[1].value, r[1].choice_value, r[1].choice_label), ('beatle', 'J', 'P', 'Paul'))
# These individual widgets can accept extra attributes if manually rendered.
self.assertHTMLEqual(
r[1].render(attrs={'extra': 'value'}),
''
)
with self.assertRaises(IndexError):
r[10]
# You can create your own custom renderers for RadioSelect to use.
class MyRenderer(RadioFieldRenderer):
def render(self):
return ' \n'.join(six.text_type(choice) for choice in self)
w = RadioSelect(renderer=MyRenderer)
self.assertHTMLEqual(
w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
"""
"""
)
# Or you can use custom RadioSelect fields that use your custom renderer.
class CustomRadioSelect(RadioSelect):
renderer = MyRenderer
w = CustomRadioSelect()
self.assertHTMLEqual(
w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
"""
"""
)
# You can customize rendering with outer_html/inner_html renderer variables (#22950)
class MyRenderer(RadioFieldRenderer):
# str is just to test some Python 2 issue with bytestrings
outer_html = str('
""")
def test_subwidget(self):
# Each subwidget tag gets a separate ID when the widget has an ID specified
self.assertHTMLEqual("\n".join(c.tag() for c in CheckboxSelectMultiple(attrs={'id': 'abc'}).subwidgets('letters', list('ac'), choices=zip(list('abc'), list('ABC')))), """
""")
# Each subwidget tag does not get an ID if the widget does not have an ID specified
self.assertHTMLEqual("\n".join(c.tag() for c in CheckboxSelectMultiple().subwidgets('letters', list('ac'), choices=zip(list('abc'), list('ABC')))), """
""")
# The id_for_label property of the subwidget should return the ID that is used on the subwidget's tag
self.assertHTMLEqual("\n".join('' % (c.choice_value, c.id_for_label) for c in CheckboxSelectMultiple(attrs={'id': 'abc'}).subwidgets('letters', [], choices=zip(list('abc'), list('ABC')))), """
""")
def test_sub_widget_html_safe(self):
widget = TextInput()
subwidget = next(widget.subwidgets('username', 'John Doe'))
self.assertTrue(hasattr(subwidget, '__html__'))
self.assertEqual(force_text(subwidget), subwidget.__html__())
def test_choice_input_html_safe(self):
widget = ChoiceInput('choices', 'CHOICE1', {}, ('CHOICE1', 'first choice'), 0)
self.assertTrue(hasattr(ChoiceInput, '__html__'))
self.assertEqual(force_text(widget), widget.__html__())
def test_choice_field_renderer_html_safe(self):
renderer = ChoiceFieldRenderer('choices', 'CHOICE1', {}, [('CHOICE1', 'first_choice')])
renderer.choice_input_class = lambda *args: args
self.assertTrue(hasattr(ChoiceFieldRenderer, '__html__'))
self.assertEqual(force_text(renderer), renderer.__html__())
@override_settings(ROOT_URLCONF='forms_tests.urls')
class LiveWidgetTests(AdminSeleniumWebDriverTestCase):
available_apps = ['forms_tests'] + AdminSeleniumWebDriverTestCase.available_apps
def test_textarea_trailing_newlines(self):
"""
Test that a roundtrip on a ModelForm doesn't alter the TextField value
"""
article = Article.objects.create(content="\nTst\n")
self.selenium.get('%s%s' % (self.live_server_url,
reverse('article_form', args=[article.pk])))
self.selenium.find_element_by_id('submit').submit()
article = Article.objects.get(pk=article.pk)
# Should be "\nTst\n" after #19251 is fixed
self.assertEqual(article.content, "\r\nTst\r\n")
@python_2_unicode_compatible
class FakeFieldFile(object):
"""
Quacks like a FieldFile (has a .url and unicode representation), but
doesn't require us to care about storages etc.
"""
url = 'something'
def __str__(self):
return self.url
class ClearableFileInputTests(SimpleTestCase):
def test_render_custom_template(self):
widget = ClearableFileInput()
widget.template_with_initial = (
'%(initial_text)s: '
'%(clear_template)s %(input_text)s: %(input)s'
)
self.assertHTMLEqual(
widget.render('myfile', FakeFieldFile()),
'Currently: '
' '
' Change: '
)