1from __future__ import unicode_literals 2 3from unittest import TestCase 4 5from wtforms.form import BaseForm, Form 6from wtforms.meta import DefaultMeta 7from wtforms.fields import TextField, IntegerField 8from wtforms.validators import ValidationError 9from tests.common import DummyPostData 10 11 12class BaseFormTest(TestCase): 13 def get_form(self, **kwargs): 14 def validate_test(form, field): 15 if field.data != 'foobar': 16 raise ValidationError('error') 17 18 return BaseForm({'test': TextField(validators=[validate_test])}, **kwargs) 19 20 def test_data_proxy(self): 21 form = self.get_form() 22 form.process(test='foo') 23 self.assertEqual(form.data, {'test': 'foo'}) 24 25 def test_errors_proxy(self): 26 form = self.get_form() 27 form.process(test='foobar') 28 form.validate() 29 self.assertEqual(form.errors, {}) 30 31 form = self.get_form() 32 form.process() 33 form.validate() 34 self.assertEqual(form.errors, {'test': ['error']}) 35 36 def test_contains(self): 37 form = self.get_form() 38 self.assertTrue('test' in form) 39 self.assertTrue('abcd' not in form) 40 41 def test_field_removal(self): 42 form = self.get_form() 43 del form['test'] 44 self.assertRaises(AttributeError, getattr, form, 'test') 45 self.assertTrue('test' not in form) 46 47 def test_field_adding(self): 48 form = self.get_form() 49 self.assertEqual(len(list(form)), 1) 50 form['foo'] = TextField() 51 self.assertEqual(len(list(form)), 2) 52 form.process(DummyPostData(foo=['hello'])) 53 self.assertEqual(form['foo'].data, 'hello') 54 form['test'] = IntegerField() 55 self.assertTrue(isinstance(form['test'], IntegerField)) 56 self.assertEqual(len(list(form)), 2) 57 self.assertRaises(AttributeError, getattr, form['test'], 'data') 58 form.process(DummyPostData(test=['1'])) 59 self.assertEqual(form['test'].data, 1) 60 self.assertEqual(form['foo'].data, '') 61 62 def test_populate_obj(self): 63 m = type(str('Model'), (object, ), {}) 64 form = self.get_form() 65 form.process(test='foobar') 66 form.populate_obj(m) 67 self.assertEqual(m.test, 'foobar') 68 self.assertEqual([k for k in dir(m) if not k.startswith('_')], ['test']) 69 70 def test_prefixes(self): 71 form = self.get_form(prefix='foo') 72 self.assertEqual(form['test'].name, 'foo-test') 73 self.assertEqual(form['test'].short_name, 'test') 74 self.assertEqual(form['test'].id, 'foo-test') 75 form = self.get_form(prefix='foo.') 76 form.process(DummyPostData({'foo.test': ['hello'], 'test': ['bye']})) 77 self.assertEqual(form['test'].data, 'hello') 78 self.assertEqual(self.get_form(prefix='foo[')['test'].name, 'foo[-test') 79 80 def test_formdata_wrapper_error(self): 81 form = self.get_form() 82 self.assertRaises(TypeError, form.process, []) 83 84 85class FormMetaTest(TestCase): 86 def test_monkeypatch(self): 87 class F(Form): 88 a = TextField() 89 90 self.assertEqual(F._unbound_fields, None) 91 F() 92 self.assertEqual(F._unbound_fields, [('a', F.a)]) 93 F.b = TextField() 94 self.assertEqual(F._unbound_fields, None) 95 F() 96 self.assertEqual(F._unbound_fields, [('a', F.a), ('b', F.b)]) 97 del F.a 98 self.assertRaises(AttributeError, lambda: F.a) 99 F() 100 self.assertEqual(F._unbound_fields, [('b', F.b)]) 101 F._m = TextField() 102 self.assertEqual(F._unbound_fields, [('b', F.b)]) 103 104 def test_subclassing(self): 105 class A(Form): 106 a = TextField() 107 c = TextField() 108 109 class B(A): 110 b = TextField() 111 c = TextField() 112 A() 113 B() 114 115 self.assertTrue(A.a is B.a) 116 self.assertTrue(A.c is not B.c) 117 self.assertEqual(A._unbound_fields, [('a', A.a), ('c', A.c)]) 118 self.assertEqual(B._unbound_fields, [('a', B.a), ('b', B.b), ('c', B.c)]) 119 120 def test_class_meta_reassign(self): 121 class MetaA: 122 pass 123 124 class MetaB: 125 pass 126 127 class F(Form): 128 Meta = MetaA 129 130 self.assertEqual(F._wtforms_meta, None) 131 assert isinstance(F().meta, MetaA) 132 assert issubclass(F._wtforms_meta, MetaA) 133 F.Meta = MetaB 134 self.assertEqual(F._wtforms_meta, None) 135 assert isinstance(F().meta, MetaB) 136 assert issubclass(F._wtforms_meta, MetaB) 137 138 139class FormTest(TestCase): 140 class F(Form): 141 test = TextField() 142 143 def validate_test(form, field): 144 if field.data != 'foobar': 145 raise ValidationError('error') 146 147 def test_validate(self): 148 form = self.F(test='foobar') 149 self.assertEqual(form.validate(), True) 150 151 form = self.F() 152 self.assertEqual(form.validate(), False) 153 154 def test_field_adding_disabled(self): 155 form = self.F() 156 self.assertRaises(TypeError, form.__setitem__, 'foo', TextField()) 157 158 def test_field_removal(self): 159 form = self.F() 160 del form.test 161 self.assertTrue('test' not in form) 162 self.assertEqual(form.test, None) 163 self.assertEqual(len(list(form)), 0) 164 # Try deleting a nonexistent field 165 self.assertRaises(AttributeError, form.__delattr__, 'fake') 166 167 def test_delattr_idempotency(self): 168 form = self.F() 169 del form.test 170 self.assertEqual(form.test, None) 171 172 # Make sure deleting a normal attribute works 173 form.foo = 9 174 del form.foo 175 self.assertRaises(AttributeError, form.__delattr__, 'foo') 176 177 # Check idempotency 178 del form.test 179 self.assertEqual(form.test, None) 180 181 def test_ordered_fields(self): 182 class MyForm(Form): 183 strawberry = TextField() 184 banana = TextField() 185 kiwi = TextField() 186 187 self.assertEqual([x.name for x in MyForm()], ['strawberry', 'banana', 'kiwi']) 188 MyForm.apple = TextField() 189 self.assertEqual([x.name for x in MyForm()], ['strawberry', 'banana', 'kiwi', 'apple']) 190 del MyForm.banana 191 self.assertEqual([x.name for x in MyForm()], ['strawberry', 'kiwi', 'apple']) 192 MyForm.strawberry = TextField() 193 self.assertEqual([x.name for x in MyForm()], ['kiwi', 'apple', 'strawberry']) 194 # Ensure sort is stable: two fields with the same creation counter 195 # should be subsequently sorted by name. 196 MyForm.cherry = MyForm.kiwi 197 self.assertEqual([x.name for x in MyForm()], ['cherry', 'kiwi', 'apple', 'strawberry']) 198 199 def test_data_arg(self): 200 data = {'test': 'foo'} 201 form = self.F(data=data) 202 self.assertEqual(form.test.data, 'foo') 203 form = self.F(data=data, test='bar') 204 self.assertEqual(form.test.data, 'bar') 205 206 207class MetaTest(TestCase): 208 class F(Form): 209 class Meta: 210 foo = 9 211 212 test = TextField() 213 214 class G(Form): 215 class Meta: 216 foo = 12 217 bar = 8 218 219 class H(F, G): 220 class Meta: 221 quux = 42 222 223 class I(F, G): 224 pass 225 226 def test_basic(self): 227 form = self.H() 228 meta = form.meta 229 self.assertEqual(meta.foo, 9) 230 self.assertEqual(meta.bar, 8) 231 self.assertEqual(meta.csrf, False) 232 assert isinstance(meta, self.F.Meta) 233 assert isinstance(meta, self.G.Meta) 234 self.assertEqual(type(meta).__bases__, ( 235 self.H.Meta, 236 self.F.Meta, 237 self.G.Meta, 238 DefaultMeta 239 )) 240 241 def test_missing_diamond(self): 242 meta = self.I().meta 243 self.assertEqual(type(meta).__bases__, ( 244 self.F.Meta, 245 self.G.Meta, 246 DefaultMeta 247 )) 248