diff options
| author | Jannis Leidel <jannis@leidel.info> | 2010-10-01 02:02:58 +0000 |
|---|---|---|
| committer | Jannis Leidel <jannis@leidel.info> | 2010-10-01 02:02:58 +0000 |
| commit | 392d992f8295f96632179e01e790465cc9c8d3ec (patch) | |
| tree | bc1d6e3b0819f1b2a58a91d146fa6eb112d8396d /tests | |
| parent | a64e96c227b36c701a86ded75d839b1cd2442713 (diff) | |
Fixed #7048 -- Added ClearableFileInput widget to clear file fields. Thanks for report and patch, jarrow and Carl Meyer.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@13968 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/regressiontests/admin_widgets/models.py | 2 | ||||
| -rw-r--r-- | tests/regressiontests/forms/fields.py | 4 | ||||
| -rw-r--r-- | tests/regressiontests/forms/tests.py | 2 | ||||
| -rw-r--r-- | tests/regressiontests/forms/widgets.py | 74 | ||||
| -rw-r--r-- | tests/regressiontests/model_fields/models.py | 6 | ||||
| -rw-r--r-- | tests/regressiontests/model_fields/tests.py | 39 | ||||
| -rw-r--r-- | tests/regressiontests/model_forms_regress/models.py | 3 | ||||
| -rw-r--r-- | tests/regressiontests/model_forms_regress/tests.py | 72 |
8 files changed, 197 insertions, 5 deletions
diff --git a/tests/regressiontests/admin_widgets/models.py b/tests/regressiontests/admin_widgets/models.py index 59d625ba12..20c0df6ee8 100644 --- a/tests/regressiontests/admin_widgets/models.py +++ b/tests/regressiontests/admin_widgets/models.py @@ -116,7 +116,7 @@ HTML escaped. >>> w = AdminFileWidget() >>> print conditional_escape(w.render('test', album.cover_art)) -Currently: <a target="_blank" href="%(STORAGE_URL)salbums/hybrid_theory.jpg">albums\hybrid_theory.jpg</a> <br />Change: <input type="file" name="test" /> +<p class="file-upload">Currently: <a target="_blank" href="%(STORAGE_URL)salbums/hybrid_theory.jpg">albums\hybrid_theory.jpg</a> <span class="clearable-file-input"><input type="checkbox" name="test-clear" id="test-clear_id" /> <label for="test-clear_id">Clear</label></span><br />Change: <input type="file" name="test" /></p> >>> print conditional_escape(w.render('test', SimpleUploadedFile('test', 'content'))) <input type="file" name="test" /> diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py index e4f2c261c9..d29e2e8e43 100644 --- a/tests/regressiontests/forms/fields.py +++ b/tests/regressiontests/forms/fields.py @@ -57,6 +57,10 @@ class FieldsTests(TestCase): except error, e: self.assertEqual(message, str(e)) + def test_field_sets_widget_is_required(self): + self.assertEqual(Field(required=True).widget.is_required, True) + self.assertEqual(Field(required=False).widget.is_required, False) + # CharField ################################################################### def test_charfield_0(self): diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 7a91cb701e..1871d4f89a 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -39,7 +39,7 @@ from media import media_tests from fields import FieldsTests from validators import TestFieldWithValidators -from widgets import WidgetTests +from widgets import WidgetTests, ClearableFileInputTests from input_formats import * diff --git a/tests/regressiontests/forms/widgets.py b/tests/regressiontests/forms/widgets.py index 59b33d5210..10483a7675 100644 --- a/tests/regressiontests/forms/widgets.py +++ b/tests/regressiontests/forms/widgets.py @@ -1269,6 +1269,7 @@ u'<input type="hidden" name="date_0" value="17.09.2007" /><input type="hidden" n from django.utils import copycompat as copy from unittest import TestCase from django import forms +from django.core.files.uploadedfile import SimpleUploadedFile class SelectAndTextWidget(forms.MultiWidget): @@ -1323,3 +1324,76 @@ class WidgetTests(TestCase): self.assertFalse(form.is_valid()) form = SplitDateRequiredForm({'field': ['', '']}) self.assertFalse(form.is_valid()) + + +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 __unicode__(self): + return self.url + +class ClearableFileInputTests(TestCase): + def test_clear_input_renders(self): + """ + A ClearableFileInput with is_required False and rendered with + an initial value that is a file renders a clear checkbox. + + """ + widget = forms.ClearableFileInput() + widget.is_required = False + self.assertEqual(widget.render('myfile', FakeFieldFile()), + u'Currently: <a target="_blank" href="something">something</a> <input type="checkbox" name="myfile-clear" id="myfile-clear_id" /> <label for="myfile-clear_id">Clear</label><br />Change: <input type="file" name="myfile" />') + + def test_clear_input_renders_only_if_not_required(self): + """ + A ClearableFileInput with is_required=False does not render a clear + checkbox. + + """ + widget = forms.ClearableFileInput() + widget.is_required = True + self.assertEqual(widget.render('myfile', FakeFieldFile()), + u'Currently: <a target="_blank" href="something">something</a> <br />Change: <input type="file" name="myfile" />') + + def test_clear_input_renders_only_if_initial(self): + """ + A ClearableFileInput instantiated with no initial value does not render + a clear checkbox. + + """ + widget = forms.ClearableFileInput() + widget.is_required = False + self.assertEqual(widget.render('myfile', None), + u'<input type="file" name="myfile" />') + + def test_clear_input_checked_returns_false(self): + """ + ClearableFileInput.value_from_datadict returns False if the clear + checkbox is checked, if not required. + + """ + widget = forms.ClearableFileInput() + widget.is_required = False + self.assertEqual(widget.value_from_datadict( + data={'myfile-clear': True}, + files={}, + name='myfile'), False) + + def test_clear_input_checked_returns_false_only_if_not_required(self): + """ + ClearableFileInput.value_from_datadict never returns False if the field + is required. + + """ + widget = forms.ClearableFileInput() + widget.is_required = True + f = SimpleUploadedFile('something.txt', 'content') + self.assertEqual(widget.value_from_datadict( + data={'myfile-clear': True}, + files={'myfile': f}, + name='myfile'), f) diff --git a/tests/regressiontests/model_fields/models.py b/tests/regressiontests/model_fields/models.py index 45cd223142..1dc1649f13 100644 --- a/tests/regressiontests/model_fields/models.py +++ b/tests/regressiontests/model_fields/models.py @@ -67,6 +67,12 @@ class BooleanModel(models.Model): string = models.CharField(max_length=10, default='abc') ############################################################################### +# FileField + +class Document(models.Model): + myfile = models.FileField(upload_to='unused') + +############################################################################### # ImageField # If PIL available, do these tests. diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py index 72a7d4d657..58c32b5c0a 100644 --- a/tests/regressiontests/model_fields/tests.py +++ b/tests/regressiontests/model_fields/tests.py @@ -6,8 +6,9 @@ import django.test from django import forms from django.db import models from django.core.exceptions import ValidationError +from django.db.models.fields.files import FieldFile -from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel +from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document # If PIL available, do these tests. if Image: @@ -311,3 +312,39 @@ class TypeCoercionTests(django.test.TestCase): def test_lookup_integer_in_textfield(self): self.assertEquals(Post.objects.filter(body=24).count(), 0) +class FileFieldTests(unittest.TestCase): + def test_clearable(self): + """ + Test that FileField.save_form_data will clear its instance attribute + value if passed False. + + """ + d = Document(myfile='something.txt') + self.assertEqual(d.myfile, 'something.txt') + field = d._meta.get_field('myfile') + field.save_form_data(d, False) + self.assertEqual(d.myfile, '') + + def test_unchanged(self): + """ + Test that FileField.save_form_data considers None to mean "no change" + rather than "clear". + + """ + d = Document(myfile='something.txt') + self.assertEqual(d.myfile, 'something.txt') + field = d._meta.get_field('myfile') + field.save_form_data(d, None) + self.assertEqual(d.myfile, 'something.txt') + + def test_changed(self): + """ + Test that FileField.save_form_data, if passed a truthy value, updates + its instance attribute. + + """ + d = Document(myfile='something.txt') + self.assertEqual(d.myfile, 'something.txt') + field = d._meta.get_field('myfile') + field.save_form_data(d, 'else.txt') + self.assertEqual(d.myfile, 'else.txt') diff --git a/tests/regressiontests/model_forms_regress/models.py b/tests/regressiontests/model_forms_regress/models.py index 4f9811a963..75b8a40938 100644 --- a/tests/regressiontests/model_forms_regress/models.py +++ b/tests/regressiontests/model_forms_regress/models.py @@ -57,3 +57,6 @@ class Author1(models.Model): class Homepage(models.Model): url = models.URLField(verify_exists=False) + +class Document(models.Model): + myfile = models.FileField(upload_to='unused', blank=True) diff --git a/tests/regressiontests/model_forms_regress/tests.py b/tests/regressiontests/model_forms_regress/tests.py index baf769c02a..397651a6b8 100644 --- a/tests/regressiontests/model_forms_regress/tests.py +++ b/tests/regressiontests/model_forms_regress/tests.py @@ -1,3 +1,4 @@ +import unittest from datetime import date from django import db @@ -5,10 +6,11 @@ from django import forms from django.forms.models import modelform_factory, ModelChoiceField from django.conf import settings from django.test import TestCase -from django.core.exceptions import FieldError +from django.core.exceptions import FieldError, ValidationError +from django.core.files.uploadedfile import SimpleUploadedFile from models import Person, RealPerson, Triple, FilePathModel, Article, \ - Publication, CustomFF, Author, Author1, Homepage + Publication, CustomFF, Author, Author1, Homepage, Document class ModelMultipleChoiceFieldTests(TestCase): @@ -333,3 +335,69 @@ class InvalidFieldAndFactory(TestCase): self.assertRaises(FieldError, modelform_factory, Person, fields=['no-field', 'name']) + +class DocumentForm(forms.ModelForm): + class Meta: + model = Document + +class FileFieldTests(unittest.TestCase): + def test_clean_false(self): + """ + If the ``clean`` method on a non-required FileField receives False as + the data (meaning clear the field value), it returns False, regardless + of the value of ``initial``. + + """ + f = forms.FileField(required=False) + self.assertEqual(f.clean(False), False) + self.assertEqual(f.clean(False, 'initial'), False) + + def test_clean_false_required(self): + """ + If the ``clean`` method on a required FileField receives False as the + data, it has the same effect as None: initial is returned if non-empty, + otherwise the validation catches the lack of a required value. + + """ + f = forms.FileField(required=True) + self.assertEqual(f.clean(False, 'initial'), 'initial') + self.assertRaises(ValidationError, f.clean, False) + + def test_full_clear(self): + """ + Integration happy-path test that a model FileField can actually be set + and cleared via a ModelForm. + + """ + form = DocumentForm() + self.assert_('name="myfile"' in unicode(form)) + self.assert_('myfile-clear' not in unicode(form)) + form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', 'content')}) + self.assert_(form.is_valid()) + doc = form.save(commit=False) + self.assertEqual(doc.myfile.name, 'something.txt') + form = DocumentForm(instance=doc) + self.assert_('myfile-clear' in unicode(form)) + form = DocumentForm(instance=doc, data={'myfile-clear': 'true'}) + doc = form.save(commit=False) + self.assertEqual(bool(doc.myfile), False) + + def test_clear_and_file_contradiction(self): + """ + If the user submits a new file upload AND checks the clear checkbox, + they get a validation error, and the bound redisplay of the form still + includes the current file and the clear checkbox. + + """ + form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', 'content')}) + self.assert_(form.is_valid()) + doc = form.save(commit=False) + form = DocumentForm(instance=doc, + files={'myfile': SimpleUploadedFile('something.txt', 'content')}, + data={'myfile-clear': 'true'}) + self.assert_(not form.is_valid()) + self.assertEqual(form.errors['myfile'], + [u'Please either submit a file or check the clear checkbox, not both.']) + rendered = unicode(form) + self.assert_('something.txt' in rendered) + self.assert_('myfile-clear' in rendered) |
