Source

django-selectable / selectable / tests / functests.py

Full commit
"""
Larger functional tests for fields and widgets.
"""
from __future__ import unicode_literals

from django import forms

from selectable.forms import AutoCompleteSelectField, AutoCompleteSelectMultipleField
from selectable.forms import AutoCompleteSelectWidget, AutoComboboxSelectWidget
from selectable.tests import ManyThing, OtherThing, ThingLookup
from selectable.tests.base import BaseSelectableTestCase, parsed_inputs


__all__ = (
    'FuncAutoCompleteSelectTestCase',
    'FuncSelectModelChoiceTestCase',
    'FuncComboboxModelChoiceTestCase',
    'FuncManytoManyMultipleSelectTestCase',
    'FuncFormTestCase',
)


class OtherThingForm(forms.ModelForm):

    thing = AutoCompleteSelectField(lookup_class=ThingLookup)

    class Meta(object):
        model = OtherThing


class FuncAutoCompleteSelectTestCase(BaseSelectableTestCase):

    def setUp(self):
        self.test_thing = self.create_thing()

    def test_valid_form(self):
        "Valid form using an AutoCompleteSelectField."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': self.test_thing.pk, # Hidden input
        }
        form = OtherThingForm(data=data)
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_invalid_form_missing_selected_pk(self):
        "Invalid form using an AutoCompleteSelectField."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': '', # Hidden input
        }
        form = OtherThingForm(data=data)
        self.assertFalse(form.is_valid(), 'Form should not be valid')
        self.assertFalse('name' in form.errors)
        self.assertTrue('thing' in form.errors)

    def test_invalid_form_missing_name(self):
        "Invalid form using an AutoCompleteSelectField."
        data = {
            'name': '',
            'thing_0': self.test_thing.name, # Text input
            'thing_1': self.test_thing.pk, # Hidden input
        }
        form = OtherThingForm(data=data)
        self.assertFalse(form.is_valid(), 'Form should not be valid')
        self.assertTrue('name' in form.errors)
        self.assertFalse('thing' in form.errors)

    def test_invalid_but_still_selected(self):
        "Invalid form should keep selected item."
        data = {
            'name': '',
            'thing_0': self.test_thing.name, # Text input
            'thing_1': self.test_thing.pk, # Hidden input
        }
        form = OtherThingForm(data=data)
        self.assertFalse(form.is_valid(), 'Form should not be valid')
        rendered_form = form.as_p()
        inputs = parsed_inputs(rendered_form)
        # Selected text should be populated
        thing_0 = inputs['thing_0'][0]
        self.assertEqual(thing_0.attributes['value'].value, self.test_thing.name)
        # Selected pk should be populated
        thing_1 = inputs['thing_1'][0]
        self.assertEqual(int(thing_1.attributes['value'].value), self.test_thing.pk)

    def test_populate_from_model(self):
        "Populate from existing model."
        other_thing = OtherThing.objects.create(thing=self.test_thing, name='a')
        form = OtherThingForm(instance=other_thing)
        rendered_form = form.as_p()
        inputs = parsed_inputs(rendered_form)
        # Selected text should be populated
        thing_0 = inputs['thing_0'][0]
        self.assertEqual(thing_0.attributes['value'].value, self.test_thing.name)
        # Selected pk should be populated
        thing_1 = inputs['thing_1'][0]
        self.assertEqual(int(thing_1.attributes['value'].value), self.test_thing.pk)


class SelectWidgetForm(forms.ModelForm):

    class Meta(object):
        model = OtherThing
        widgets = {
            'thing': AutoCompleteSelectWidget(lookup_class=ThingLookup)
        }


class FuncSelectModelChoiceTestCase(BaseSelectableTestCase):
    """
    Functional tests for AutoCompleteSelectWidget compatibility
    with a ModelChoiceField.
    """

    def setUp(self):
        self.test_thing = self.create_thing()

    def test_valid_form(self):
        "Valid form using an AutoCompleteSelectWidget."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': self.test_thing.pk, # Hidden input
        }
        form = SelectWidgetForm(data=data)
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_missing_pk(self):
        "Invalid form (missing required pk) using an AutoCompleteSelectWidget."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': '', # Hidden input missing
        }
        form = SelectWidgetForm(data=data)
        self.assertFalse(form.is_valid())
        self.assertTrue('thing' in form.errors)

    def test_invalid_pk(self):
        "Invalid form (invalid pk value) using an AutoCompleteSelectWidget."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': 'XXX', # Hidden input doesn't match a PK
        }
        form = SelectWidgetForm(data=data)
        self.assertFalse(form.is_valid())
        self.assertTrue('thing' in form.errors)


class ComboboxSelectWidgetForm(forms.ModelForm):

    class Meta(object):
        model = OtherThing
        widgets = {
            'thing': AutoComboboxSelectWidget(lookup_class=ThingLookup)
        }


class FuncComboboxModelChoiceTestCase(BaseSelectableTestCase):
    """
    Functional tests for AutoComboboxSelectWidget compatibility
    with a ModelChoiceField.
    """

    def setUp(self):
        self.test_thing = self.create_thing()

    def test_valid_form(self):
        "Valid form using an AutoComboboxSelectWidget."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': self.test_thing.pk, # Hidden input
        }
        form = ComboboxSelectWidgetForm(data=data)
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_missing_pk(self):
        "Invalid form (missing required pk) using an AutoComboboxSelectWidget."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': '', # Hidden input missing
        }
        form = SelectWidgetForm(data=data)
        self.assertFalse(form.is_valid())
        self.assertTrue('thing' in form.errors)

    def test_invalid_pk(self):
        "Invalid form (invalid pk value) using an AutoComboboxSelectWidget."
        data = {
            'name': self.get_random_string(),
            'thing_0': self.test_thing.name, # Text input
            'thing_1': 'XXX', # Hidden input doesn't match a PK
        }
        form = SelectWidgetForm(data=data)
        self.assertFalse(form.is_valid())
        self.assertTrue('thing' in form.errors)


class ManyThingForm(forms.ModelForm):

    things = AutoCompleteSelectMultipleField(lookup_class=ThingLookup)

    class Meta(object):
        model = ManyThing


class FuncManytoManyMultipleSelectTestCase(BaseSelectableTestCase):
    """
    Functional tests for AutoCompleteSelectMultipleField compatibility
    with a ManyToManyField.
    """

    def setUp(self):
        self.test_thing = self.create_thing()

    def test_valid_form(self):
        "Valid form using an AutoCompleteSelectMultipleField."
        data = {
            'name': self.get_random_string(),
            'things_0': '', # Text input
            'things_1': [self.test_thing.pk, ], # Hidden inputs
        }
        form = ManyThingForm(data=data)
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_valid_save(self):
        "Saving data from a valid form."
        data = {
            'name': self.get_random_string(),
            'things_0': '', # Text input
            'things_1': [self.test_thing.pk, ], # Hidden inputs
        }
        form = ManyThingForm(data=data)
        manything = form.save()
        self.assertEqual(manything.name, data['name'])
        things = manything.things.all()
        self.assertEqual(things.count(), 1)
        self.assertTrue(self.test_thing in things)

    def test_not_required(self):
        "Valid form where many to many is not required."
        data = {
            'name': self.get_random_string(),
            'things_0': '', # Text input
            'things_1': [], # Hidden inputs
        }
        form = ManyThingForm(data=data)
        form.fields['things'].required = False
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_not_required_save(self):
        "Saving data when many to many is not required."
        data = {
            'name': self.get_random_string(),
            'things_0': '', # Text input
            'things_1': [], # Hidden inputs
        }
        form = ManyThingForm(data=data)
        form.fields['things'].required = False
        manything = form.save()
        self.assertEqual(manything.name, data['name'])
        things = manything.things.all()
        self.assertEqual(things.count(), 0)


class SimpleForm(forms.Form):
    "Non-model form usage."
    thing = AutoCompleteSelectField(lookup_class=ThingLookup)
    new_thing = AutoCompleteSelectField(lookup_class=ThingLookup, allow_new=True)
    things = AutoCompleteSelectMultipleField(lookup_class=ThingLookup)


class FuncFormTestCase(BaseSelectableTestCase):
    """
    Functional tests for using AutoCompleteSelectField
    and AutoCompleteSelectMultipleField outside the context
    of a ModelForm.
    """

    def setUp(self):
        self.test_thing = self.create_thing()

    def test_blank_new_item(self):
        "Regression test for #91. new_thing is required but both are blank."
        data = {
            'thing_0': self.test_thing.name,
            'thing_1': self.test_thing.pk,
            'new_thing_0': '',
            'new_thing_1': '',
            'things_0': '',
            'things_1': [self.test_thing.pk, ]
        }
        form = SimpleForm(data=data)
        self.assertFalse(form.is_valid())
        self.assertTrue('new_thing' in form.errors)

    def test_has_changed_with_empty_permitted(self):
        """
        Regression test for #92. has_changed fails when there is no initial and
        allow_new=False.
        """
        data = {
            'thing_0': '',
            'thing_1': self.test_thing.pk,
            'new_thing_0': self.test_thing.name,
            'new_thing_1': self.test_thing.pk,
            'things_0': '',
            'things_1': [self.test_thing.pk, ]
        }
        form = SimpleForm(data=data, empty_permitted=True)
        self.assertTrue(form.has_changed())
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_not_changed(self):
        """
        Regression test for #92. has_changed fails when there is no initial and
        allow_new=False.
        """
        data = {
            'thing_0': self.test_thing.name,
            'thing_1': self.test_thing.pk,
            'new_thing_0': self.test_thing.name,
            'new_thing_1': self.test_thing.pk,
            'things_0': '',
            'things_1': [self.test_thing.pk, ]
        }
        initial = {
            'thing': self.test_thing.pk,
            'new_thing': self.test_thing.pk,
            'things': [self.test_thing.pk, ]
        }
        form = SimpleForm(data=data, initial=initial)
        self.assertFalse(form.has_changed())
        self.assertTrue(form.is_valid(), str(form.errors))

    def test_not_changed_with_empty_permitted(self):
        """
        Regression test for #92. has_changed fails when there is no initial and
        allow_new=False.
        """
        data = {
            'thing_0': '',
            'thing_1': '',
            'new_thing_0': '',
            'new_thing_1': '',
            'things_0': '',
            'things_1': '',
        }
        initial = {
            'thing': '',
            'new_thing': '',
            'things': '',
        }
        form = SimpleForm(data=data, initial=initial, empty_permitted=True)
        self.assertFalse(form.has_changed())
        self.assertTrue(form.is_valid(), str(form.errors))