# -*- coding: utf-8 -*- from __future__ import unicode_literals import re from django.test import TestCase from django import forms from django.template import Template, Context from .text import text_value, text_concat from .exceptions import BootstrapError from .utils import add_css_class RADIO_CHOICES = ( ('1', 'Radio 1'), ('2', 'Radio 2'), ) MEDIA_CHOICES = ( ('Audio', ( ('vinyl', 'Vinyl'), ('cd', 'CD'), ) ), ('Video', ( ('vhs', 'VHS Tape'), ('dvd', 'DVD'), ) ), ('unknown', 'Unknown'), ) class TestForm(forms.Form): """ Form with a variety of widgets to test bootstrap3 rendering. """ date = forms.DateField(required=False) subject = forms.CharField( max_length=100, help_text='my_help_text', required=True, widget=forms.TextInput(attrs={'placeholder': 'placeholdertest'}), ) message = forms.CharField(required=False, help_text='my_help_text') sender = forms.EmailField(label='Sender © unicode') secret = forms.CharField(initial=42, widget=forms.HiddenInput) cc_myself = forms.BooleanField( required=False, help_text='You will get a copy in your mailbox.') select1 = forms.ChoiceField(choices=RADIO_CHOICES) select2 = forms.MultipleChoiceField( choices=RADIO_CHOICES, help_text='Check as many as you like.', ) select3 = forms.ChoiceField(choices=MEDIA_CHOICES) select4 = forms.MultipleChoiceField( choices=MEDIA_CHOICES, help_text='Check as many as you like.', ) category1 = forms.ChoiceField( choices=RADIO_CHOICES, widget=forms.RadioSelect) category2 = forms.MultipleChoiceField( choices=RADIO_CHOICES, widget=forms.CheckboxSelectMultiple, help_text='Check as many as you like.', ) category3 = forms.ChoiceField( widget=forms.RadioSelect, choices=MEDIA_CHOICES) category4 = forms.MultipleChoiceField( choices=MEDIA_CHOICES, widget=forms.CheckboxSelectMultiple, help_text='Check as many as you like.', ) addon = forms.CharField( widget=forms.TextInput(attrs={'addon_before': 'before', 'addon_after': 'after'}), ) required_css_class = 'bootstrap3-req' def clean(self): cleaned_data = super(TestForm, self).clean() raise forms.ValidationError( "This error was added to show the non field errors styling.") return cleaned_data class TestFormWithoutRequiredClass(TestForm): required_css_class = '' def render_template(text, **context_args): """ Create a template ``text`` that first loads bootstrap3. """ template = Template("{% load bootstrap3 %}" + text) if 'form' not in context_args: context_args['form'] = TestForm() return template.render(Context(context_args)) def render_formset(formset=None, **context_args): """ Create a template that renders a formset """ context_args['formset'] = formset return render_template('{% bootstrap_formset formset %}', **context_args) def render_form(form=None, **context_args): """ Create a template that renders a form """ if form: context_args['form'] = form return render_template('{% bootstrap_form form %}', **context_args) def render_form_field(field, **context_args): """ Create a template that renders a field """ form_field = 'form.%s' % field return render_template( '{% bootstrap_field ' + form_field + ' %}', **context_args) def render_field(field, **context_args): """ Create a template that renders a field """ context_args['field'] = field return render_template('{% bootstrap_field field %}', **context_args) class SettingsTest(TestCase): def test_settings(self): from .bootstrap import BOOTSTRAP3 self.assertTrue(BOOTSTRAP3) def test_settings_filter(self): res = render_template( '{% load bootstrap3 %}' + '{{ "required_css_class"|bootstrap_setting }}') self.assertEqual(res.strip(), 'bootstrap3-req') res = render_template( '{% load bootstrap3 %}' + '{% if "javascript_in_head"|bootstrap_setting %}' + 'head{% else %}body{% endif %}' ) self.assertEqual(res.strip(), 'head') def test_required_class(self): form = TestForm() res = render_template('{% bootstrap_form form %}', form=form) self.assertIn('bootstrap3-req', res) def test_error_class(self): form = TestForm({}) res = render_template('{% bootstrap_form form %}', form=form) self.assertIn('bootstrap3-err', res) def test_bound_class(self): form = TestForm({'sender': 'sender'}) res = render_template('{% bootstrap_form form %}', form=form) self.assertIn('bootstrap3-bound', res) class TemplateTest(TestCase): def test_empty_template(self): res = render_template('') self.assertEqual(res.strip(), '') def test_text_template(self): res = render_template('some text') self.assertEqual(res.strip(), 'some text') def test_bootstrap_template(self): template = Template(( '{% extends "bootstrap3/bootstrap3.html" %}' + '{% block bootstrap3_content %}' + 'test_bootstrap3_content' + '{% endblock %}' )) res = template.render(Context({})) self.assertIn('test_bootstrap3_content', res) def test_javascript_without_jquery(self): res = render_template('{% bootstrap_javascript jquery=0 %}') self.assertIn('bootstrap', res) self.assertNotIn('jquery', res) def test_javascript_with_jquery(self): res = render_template('{% bootstrap_javascript jquery=1 %}') self.assertIn('bootstrap', res) self.assertIn('jquery', res) class FormSetTest(TestCase): def test_illegal_formset(self): with self.assertRaises(BootstrapError): render_formset(formset='illegal') class FormTest(TestCase): def test_illegal_form(self): with self.assertRaises(BootstrapError): render_form(form='illegal') def test_field_names(self): form = TestForm() res = render_form(form) for field in form: self.assertIn('name="%s"' % field.name, res) def test_field_addons(self): form = TestForm() res = render_form(form) self.assertIn('
beforeafter
', res) def test_exclude(self): form = TestForm() res = render_template( '{% bootstrap_form form exclude="cc_myself" %}', form=form) self.assertNotIn('cc_myself', res) def test_layout_horizontal(self): form = TestForm() res = render_template( '{% bootstrap_form form layout="horizontal" %}', form=form) self.assertIn('col-md-2', res) self.assertIn('col-md-4', res) res = render_template( '{% bootstrap_form form layout="horizontal" ' + 'horizontal_label_class="hlabel" ' + 'horizontal_field_class="hfield" %}', form=form ) self.assertIn('hlabel', res) self.assertIn('hfield', res) def test_buttons_tag(self): form = TestForm() res = render_template( '{% buttons layout="horizontal" %}{% endbuttons %}', form=form) self.assertIn('col-md-2', res) self.assertIn('col-md-4', res) class FieldTest(TestCase): def test_illegal_field(self): with self.assertRaises(BootstrapError): render_field(field='illegal') def test_show_help(self): res = render_form_field('subject') self.assertIn('my_help_text', res) self.assertNotIn('my_help_text', res) res = render_template('{% bootstrap_field form.subject show_help=0 %}') self.assertNotIn('my_help_text', res) def test_subject(self): res = render_form_field('subject') self.assertIn('type="text"', res) self.assertIn('placeholder="placeholdertest"', res) def test_required_field(self): required_field = render_form_field('subject') self.assertIn('required', required_field) self.assertIn('bootstrap3-req', required_field) not_required_field = render_form_field('message') self.assertNotIn('required', not_required_field) # Required field with required=0 form_field = 'form.subject' rendered = render_template( '{% bootstrap_field ' + form_field + ' set_required=0 %}') self.assertNotIn('required', rendered) # Required settings in field form_field = 'form.subject' rendered = render_template( '{% bootstrap_field ' + form_field + ' required_css_class="test-required" %}') self.assertIn('test-required', rendered) def test_empty_permitted(self): form = TestForm() res = render_form_field('subject', form=form) self.assertIn('required', res) form.empty_permitted = True res = render_form_field('subject', form=form) self.assertNotIn('required', res) def test_input_group(self): res = render_template( '{% bootstrap_field form.subject addon_before="$" ' + 'addon_after=".00" %}' ) self.assertIn('class="input-group"', res) self.assertIn('class="input-group-addon">$', res) self.assertIn('class="input-group-addon">.00', res) def test_size(self): def _test_size(param, klass): res = render_template( '{% bootstrap_field form.subject size="' + param + '" %}') self.assertIn(klass, res) def _test_size_medium(param): res = render_template( '{% bootstrap_field form.subject size="' + param + '" %}') self.assertNotIn('input-lg', res) self.assertNotIn('input-sm', res) self.assertNotIn('input-md', res) _test_size('sm', 'input-sm') _test_size('small', 'input-sm') _test_size('lg', 'input-lg') _test_size('large', 'input-lg') _test_size_medium('md') _test_size_medium('medium') _test_size_medium('') class ComponentsTest(TestCase): def test_icon(self): res = render_template('{% bootstrap_icon "star" %}') self.assertEqual( res.strip(), '') res = render_template( '{% bootstrap_icon "star" title="alpha centauri" %}') self.assertEqual( res.strip(), '') def test_alert(self): res = render_template( '{% bootstrap_alert "content" alert_type="danger" %}') self.assertEqual( res.strip(), '
' + 'content
' ) class MessagesTest(TestCase): def test_messages(self): class FakeMessage(object): """ Follows the `django.contrib.messages.storage.base.Message` API. """ def __init__(self, message, tags): self.tags = tags self.message = message def __str__(self): return self.message pattern = re.compile(r'\s+') messages = [FakeMessage("hello", "warning")] res = render_template( '{% bootstrap_messages messages %}', messages=messages) expected = """
hello
""" self.assertEqual( re.sub(pattern, '', res), re.sub(pattern, '', expected) ) messages = [FakeMessage("hello", "error")] res = render_template( '{% bootstrap_messages messages %}', messages=messages) expected = """
hello
""" self.assertEqual( re.sub(pattern, '', res), re.sub(pattern, '', expected) ) messages = [FakeMessage("hello", None)] res = render_template( '{% bootstrap_messages messages %}', messages=messages) expected = """
hello
""" self.assertEqual( re.sub(pattern, '', res), re.sub(pattern, '', expected) ) class TextTest(TestCase): def test_add_css_class(self): css_classes = "one two" css_class = "three four" classes = add_css_class(css_classes, css_class) self.assertEqual(classes, "one two three four") classes = add_css_class(css_classes, css_class, prepend=True) self.assertEqual(classes, "three four one two") class HtmlTest(TestCase): def test_text_value(self): self.assertEqual(text_value(''), "") self.assertEqual(text_value(' '), " ") self.assertEqual(text_value(None), "") self.assertEqual(text_value(1), "1") def test_text_concat(self): self.assertEqual(text_concat(1, 2), "12") self.assertEqual(text_concat(1, 2, separator='='), "1=2") self.assertEqual(text_concat(None, 2, separator='='), "2") class ButtonTest(TestCase): def test_button(self): res = render_template( "{% bootstrap_button 'button' size='lg' %}") self.assertEqual( res.strip(), '') res = render_template( "{% bootstrap_button 'button' size='lg' href='#' %}") self.assertIn( res.strip(), 'buttonbutton')