summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJannis Leidel <jannis@leidel.info>2010-10-01 02:02:58 +0000
committerJannis Leidel <jannis@leidel.info>2010-10-01 02:02:58 +0000
commit392d992f8295f96632179e01e790465cc9c8d3ec (patch)
treebc1d6e3b0819f1b2a58a91d146fa6eb112d8396d /tests
parenta64e96c227b36c701a86ded75d839b1cd2442713 (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.py2
-rw-r--r--tests/regressiontests/forms/fields.py4
-rw-r--r--tests/regressiontests/forms/tests.py2
-rw-r--r--tests/regressiontests/forms/widgets.py74
-rw-r--r--tests/regressiontests/model_fields/models.py6
-rw-r--r--tests/regressiontests/model_fields/tests.py39
-rw-r--r--tests/regressiontests/model_forms_regress/models.py3
-rw-r--r--tests/regressiontests/model_forms_regress/tests.py72
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)