source: wokkel/test/test_data_form.py

Last change on this file was 196:80e9a80845ba, checked in by Ralph Meijer <ralphm@…>, 5 years ago

imported patch py3-dataforms.patch

  • Property exe set to *
File size: 47.1 KB
Line 
1# Copyright (c) Ralph Meijer.
2# See LICENSE for details.
3
4"""
5Tests for {wokkel.data_form}.
6"""
7
8from __future__ import division, absolute_import
9
10from zope.interface import verify
11from zope.interface.common.mapping import IIterableMapping
12
13from twisted.python.compat import unicode, _PY3
14from twisted.trial import unittest
15from twisted.words.xish import domish
16from twisted.words.protocols.jabber import jid
17
18from wokkel import data_form
19
20NS_X_DATA = 'jabber:x:data'
21
22class OptionTest(unittest.TestCase):
23    """
24    Tests for L{data_form.Option}.
25    """
26
27    def test_toElement(self):
28        """
29        An option is an option element with a value child with the option value.
30        """
31        option = data_form.Option('value')
32        element = option.toElement()
33
34        self.assertEqual('option', element.name)
35        self.assertEqual(NS_X_DATA, element.uri)
36        self.assertEqual(NS_X_DATA, element.value.uri)
37        self.assertEqual('value', unicode(element.value))
38        self.assertFalse(element.hasAttribute('label'))
39
40
41    def test_toElementLabel(self):
42        """
43        A label is rendered as an attribute on the option element.
44        """
45        option = data_form.Option('value', 'label')
46        element = option.toElement()
47
48        self.assertEqual('option', element.name)
49        self.assertEqual(NS_X_DATA, element.uri)
50        self.assertEqual(NS_X_DATA, element.value.uri)
51        self.assertEqual('value', unicode(element.value))
52        self.assertEqual('label', element['label'])
53
54
55    def test_fromElement(self):
56        """
57        An option has a child element with the option value.
58        """
59        element = domish.Element((NS_X_DATA, 'option'))
60        element.addElement('value', content='value')
61        option = data_form.Option.fromElement(element)
62
63        self.assertEqual('value', option.value)
64        self.assertIdentical(None, option.label)
65
66
67    def test_fromElementLabel(self):
68        """
69        An option label is an attribute on the option element.
70        """
71
72        element = domish.Element((NS_X_DATA, 'option'))
73        element.addElement('value', content='value')
74        element['label'] = 'label'
75        option = data_form.Option.fromElement(element)
76
77        self.assertEqual('label', option.label)
78
79
80    def test_fromElementNoValue(self):
81        """
82        An option MUST have a value.
83        """
84        element = domish.Element((NS_X_DATA, 'option'))
85        self.assertRaises(data_form.Error,
86                          data_form.Option.fromElement, element)
87
88
89    def test_repr(self):
90        """
91        The representation of an Option is equal to how it is created.
92        """
93        option = data_form.Option('value', 'label')
94        self.assertEqual("""Option('value', 'label')""", repr(option))
95
96
97
98class FieldTest(unittest.TestCase):
99    """
100    Tests for L{data_form.Field}.
101    """
102
103    def test_basic(self):
104        """
105        Test basic field initialization.
106        """
107        field = data_form.Field(var='test')
108        self.assertEqual('text-single', field.fieldType)
109        self.assertEqual('test', field.var)
110
111
112    def test_labelAndOptions(self):
113        """
114        The label should be set, even if there are options with labels as dict.
115        """
116        field = data_form.Field(label='test',
117                                options={'test2': 'test 2', 'test3': 'test 3'})
118        self.assertEqual('test', field.label)
119
120
121    def test_repr(self):
122        """
123        The repr of a field should be equal to its initialization.
124        """
125        field = data_form.Field('list-single', var='test', label='label',
126                               desc='desc', required=True, value='test',
127                               options=[data_form.Option('test')])
128        self.assertEqual("""Field(fieldType='list-single', """
129                         """var='test', label='label', """
130                         """desc='desc', required=True, """
131                         """values=['test'], """
132                         """options=[Option('test')])""",
133                         repr(field))
134
135
136    def test_toElement(self):
137        """
138        Test rendering to a DOM.
139        """
140        field = data_form.Field(var='test')
141        element = field.toElement()
142
143        self.assertTrue(domish.IElement.providedBy(element))
144        self.assertEquals('field', element.name)
145        self.assertEquals(NS_X_DATA, element.uri)
146        self.assertEquals('text-single',
147                          element.getAttribute('type', 'text-single'))
148        self.assertEquals('test', element['var'])
149        self.assertEquals([], element.children)
150
151
152    def test_toElementTypeNotTextSingle(self):
153        """
154        Always render the field type, if different from text-single.
155        """
156        field = data_form.Field('hidden', var='test')
157        element = field.toElement()
158
159        self.assertEquals('hidden', element.getAttribute('type'))
160
161
162    def test_toElementSingleValue(self):
163        """
164        A single value should yield only one value element.
165        """
166        field = data_form.Field('list-multi', var='test', value='test')
167        element = field.toElement()
168
169        children = list(element.elements())
170        self.assertEqual(1, len(children))
171
172
173    def test_toElementMultipleValues(self):
174        """
175        A field with no type and multiple values should render all values.
176        """
177        field = data_form.Field('list-multi', var='test',
178                                values=['test', 'test2'])
179        element = field.toElement()
180
181        children = list(element.elements())
182        self.assertEqual(2, len(children))
183
184
185    def test_toElementAsForm(self):
186        """
187        Always render the field type, if asForm is True.
188        """
189        field = data_form.Field(var='test')
190        element = field.toElement(True)
191
192        self.assertEquals('text-single', element.getAttribute('type'))
193
194
195    def test_toElementOptions(self):
196        """
197        Test rendering to a DOM with options.
198        """
199        field = data_form.Field('list-single', var='test')
200        field.options = [data_form.Option(u'option1'),
201                         data_form.Option(u'option2')]
202        element = field.toElement(True)
203
204        self.assertEqual(2, len(element.children))
205
206
207    def test_toElementLabel(self):
208        """
209        Test rendering to a DOM with a label.
210        """
211        field = data_form.Field(var='test', label=u'my label')
212        element = field.toElement(True)
213
214        self.assertEqual(u'my label', element.getAttribute('label'))
215
216
217    def test_toElementDescription(self):
218        """
219        Test rendering to a DOM with options.
220        """
221        field = data_form.Field(var='test', desc=u'My desc')
222        element = field.toElement(True)
223
224        self.assertEqual(1, len(element.children))
225        child = element.children[0]
226        self.assertEqual('desc', child.name)
227        self.assertEqual(NS_X_DATA, child.uri)
228        self.assertEqual(u'My desc', unicode(child))
229
230
231    def test_toElementRequired(self):
232        """
233        Test rendering to a DOM with options.
234        """
235        field = data_form.Field(var='test', required=True)
236        element = field.toElement(True)
237
238        self.assertEqual(1, len(element.children))
239        child = element.children[0]
240        self.assertEqual('required', child.name)
241        self.assertEqual(NS_X_DATA, child.uri)
242
243
244    def test_toElementJID(self):
245        """
246        A JID value should render to text.
247        """
248        field = data_form.Field(fieldType='jid-single', var='test',
249                                value=jid.JID(u'test@example.org'))
250        element = field.toElement()
251        self.assertEqual(u'test@example.org', unicode(element.value))
252
253
254    def test_toElementJIDTextSingle(self):
255        """
256        A JID value should render to text if field type is text-single.
257        """
258        field = data_form.Field(fieldType='text-single', var='test',
259                                value=jid.JID(u'test@example.org'))
260        element = field.toElement()
261        self.assertEqual(u'test@example.org', unicode(element.value))
262
263
264    def test_toElementBoolean(self):
265        """
266        A boolean value should render to text.
267        """
268        field = data_form.Field(fieldType='boolean', var='test',
269                                value=True)
270        element = field.toElement()
271        self.assertEqual(u'true', unicode(element.value))
272
273
274    def test_toElementBooleanTextSingle(self):
275        """
276        A boolean value should render to text if the field type is text-single.
277        """
278        field = data_form.Field(var='test', value=True)
279        element = field.toElement()
280        self.assertEqual(u'true', unicode(element.value))
281
282
283    def test_toElementNoType(self):
284        """
285        A field with no type should not have a type attribute.
286        """
287        field = data_form.Field(None, var='test', value='test')
288        element = field.toElement()
289        self.assertFalse(element.hasAttribute('type'))
290
291
292    def test_toElementNoTypeMultipleValues(self):
293        """
294        A field with no type and multiple values should render all values.
295        """
296        field = data_form.Field(None, var='test', values=['test', 'test2'])
297        element = field.toElement()
298
299        self.assertFalse(element.hasAttribute('type'))
300        children = list(element.elements())
301        self.assertEqual(2, len(children))
302
303
304    def test_typeCheckNoFieldName(self):
305        """
306        A field not of type fixed must have a var.
307        """
308        field = data_form.Field(fieldType='list-single')
309        self.assertRaises(data_form.FieldNameRequiredError, field.typeCheck)
310
311
312    def test_typeCheckTooManyValues(self):
313        """
314        Expect an exception if too many values are set, depending on type.
315        """
316        field = data_form.Field(fieldType='list-single', var='test',
317                                values=[u'value1', u'value2'])
318        self.assertRaises(data_form.TooManyValuesError, field.typeCheck)
319
320
321    def test_typeCheckBooleanFalse(self):
322        """
323        Test possible False values for a boolean field.
324        """
325        field = data_form.Field(fieldType='boolean', var='test')
326
327        for value in (False, 0, '0', 'false', 'False', []):
328            field.value = value
329            field.typeCheck()
330            self.assertIsInstance(field.value, bool)
331            self.assertFalse(field.value)
332
333
334    def test_typeCheckBooleanTrue(self):
335        """
336        Test possible True values for a boolean field.
337        """
338        field = data_form.Field(fieldType='boolean', var='test')
339
340        for value in (True, 1, '1', 'true', 'True', ['test']):
341            field.value = value
342            field.typeCheck()
343            self.assertIsInstance(field.value, bool)
344            self.assertTrue(field.value)
345
346
347    def test_typeCheckBooleanBad(self):
348        """
349        A bad value for a boolean field should raise a ValueError
350        """
351        field = data_form.Field(fieldType='boolean', var='test')
352        field.value = 'test'
353        self.assertRaises(ValueError, field.typeCheck)
354
355
356    def test_typeCheckJID(self):
357        """
358        The value of jid field should be a JID or coercable to one.
359        """
360        field = data_form.Field(fieldType='jid-single', var='test',
361                                value=jid.JID('test@example.org'))
362        field.typeCheck()
363
364
365    def test_typeCheckJIDString(self):
366        """
367        The string value of jid field should be coercable into a JID.
368        """
369        field = data_form.Field(fieldType='jid-single', var='test',
370                                value='test@example.org')
371        field.typeCheck()
372        self.assertEquals(jid.JID(u'test@example.org'), field.value)
373
374
375    def test_typeCheckJIDBad(self):
376        """
377        An invalid JID string should raise an exception.
378        """
379        field = data_form.Field(fieldType='jid-single', var='test',
380                                value='test@@example.org')
381        self.assertRaises(jid.InvalidFormat, field.typeCheck)
382
383
384    def test_fromElementType(self):
385        element = domish.Element((NS_X_DATA, 'field'))
386        element['type'] = 'fixed'
387        field = data_form.Field.fromElement(element)
388        self.assertEquals('fixed', field.fieldType)
389
390
391    def test_fromElementNoType(self):
392        element = domish.Element((NS_X_DATA, 'field'))
393        field = data_form.Field.fromElement(element)
394        self.assertEquals(None, field.fieldType)
395
396
397    def test_fromElementValueTextSingle(self):
398        """
399        Parsed text-single field values should be of type C{unicode}.
400        """
401        element = domish.Element((NS_X_DATA, 'field'))
402        element['type'] = 'text-single'
403        element.addElement('value', content=u'text')
404        field = data_form.Field.fromElement(element)
405        self.assertEquals('text', field.value)
406
407
408    def test_fromElementValueJID(self):
409        """
410        Parsed jid-single field values should be of type C{unicode}.
411        """
412        element = domish.Element((NS_X_DATA, 'field'))
413        element['type'] = 'jid-single'
414        element.addElement('value', content=u'user@example.org')
415        field = data_form.Field.fromElement(element)
416        self.assertEquals(u'user@example.org', field.value)
417
418
419    def test_fromElementValueJIDMalformed(self):
420        """
421        Parsed jid-single field values should be of type C{unicode}.
422
423        No validation should be done at this point, so invalid JIDs should
424        also be passed as-is.
425        """
426        element = domish.Element((NS_X_DATA, 'field'))
427        element['type'] = 'jid-single'
428        element.addElement('value', content=u'@@')
429        field = data_form.Field.fromElement(element)
430        self.assertEquals(u'@@', field.value)
431
432
433    def test_fromElementValueBoolean(self):
434        """
435        Parsed boolean field values should be of type C{unicode}.
436        """
437        element = domish.Element((NS_X_DATA, 'field'))
438        element['type'] = 'boolean'
439        element.addElement('value', content=u'false')
440        field = data_form.Field.fromElement(element)
441        self.assertEquals(u'false', field.value)
442
443
444    def test_fromElementDesc(self):
445        """
446        Field descriptions are in a desc child element.
447        """
448        element = domish.Element((NS_X_DATA, 'field'))
449        element.addElement('desc', content=u'My description')
450        field = data_form.Field.fromElement(element)
451        self.assertEqual(u'My description', field.desc)
452
453
454    def test_fromElementOption(self):
455        """
456        Field descriptions are in a desc child element.
457        """
458        element = domish.Element((NS_X_DATA, 'field'))
459        element.addElement('option').addElement('value', content=u'option1')
460        element.addElement('option').addElement('value', content=u'option2')
461        field = data_form.Field.fromElement(element)
462        self.assertEqual(2, len(field.options))
463
464
465    def test_fromElementRequired(self):
466        """
467        Required fields have a required child element.
468        """
469        element = domish.Element((NS_X_DATA, 'field'))
470        element.addElement('required')
471        field = data_form.Field.fromElement(element)
472        self.assertTrue(field.required)
473
474
475    def test_fromElementChildOtherNamespace(self):
476        """
477        Child elements from another namespace are ignored.
478        """
479        element = domish.Element((NS_X_DATA, 'field'))
480        element['var'] = 'test'
481        element.addElement(('myns', 'value'))
482        field = data_form.Field.fromElement(element)
483
484        self.assertIdentical(None, field.value)
485
486
487    def test_fromDict(self):
488        """
489        A named field with a value can be created by providing a dictionary.
490        """
491        fieldDict = {'var': 'test', 'value': 'text'}
492        field = data_form.Field.fromDict(fieldDict)
493        self.assertEqual('test', field.var)
494        self.assertEqual('text', field.value)
495
496
497    def test_fromDictFieldType(self):
498        """
499        The field type is set using the key 'type'.
500        """
501        fieldDict = {'type': 'boolean'}
502        field = data_form.Field.fromDict(fieldDict)
503        self.assertEqual('boolean', field.fieldType)
504
505
506    def test_fromDictOptions(self):
507        """
508        The field options are set using the key 'options'.
509
510        The options are represented as a dictionary keyed by option,
511        with the optional label as value.
512        """
513        fieldDict = {'options': {'value1': 'label1',
514                                 'value2': 'label2'}}
515        field = data_form.Field.fromDict(fieldDict)
516        self.assertEqual(2, len(field.options))
517        options = {}
518        for option in field.options:
519            options[option.value] = option.label
520
521        self.assertEqual(options, fieldDict['options'])
522
523
524class FormTest(unittest.TestCase):
525    """
526    Tests for L{data_form.Form}.
527    """
528
529    def test_formType(self):
530        """
531        A form has a type.
532        """
533
534        form = data_form.Form('result')
535        self.assertEqual('result', form.formType)
536
537
538    def test_toElement(self):
539        """
540        The toElement method returns a form's DOM representation.
541        """
542        form = data_form.Form('result')
543        element = form.toElement()
544
545        self.assertTrue(domish.IElement.providedBy(element))
546        self.assertEquals('x', element.name)
547        self.assertEquals(NS_X_DATA, element.uri)
548        self.assertEquals('result', element['type'])
549        self.assertEquals([], element.children)
550
551
552    def test_toElementTitle(self):
553        """
554        A title is rendered as a child element with the title as CDATA.
555        """
556        form = data_form.Form('form', title='Bot configuration')
557        element = form.toElement()
558
559        elements = list(element.elements())
560        self.assertEqual(1, len(elements))
561        title = elements[0]
562        self.assertEqual('title', title.name)
563        self.assertEqual(NS_X_DATA, title.uri)
564        self.assertEqual('Bot configuration', unicode(title))
565
566
567    def test_toElementInstructions(self):
568        """
569        Instructions are rendered as child elements with CDATA.
570        """
571        form = data_form.Form('form', instructions=['Fill out this form!'])
572        element = form.toElement()
573
574        elements = list(element.elements())
575        self.assertEqual(1, len(elements))
576        instructions = elements[0]
577        self.assertEqual('instructions', instructions.name)
578        self.assertEqual(NS_X_DATA, instructions.uri)
579        self.assertEqual('Fill out this form!', unicode(instructions))
580
581
582    def test_toElementInstructionsMultiple(self):
583        """
584        Instructions render as one element per instruction, in order.
585        """
586        form = data_form.Form('form', instructions=['Fill out this form!',
587                                                    'no really'])
588        element = form.toElement()
589
590        elements = list(element.elements())
591        self.assertEqual(2, len(elements))
592        instructions1 = elements[0]
593        instructions2 = elements[1]
594        self.assertEqual('instructions', instructions1.name)
595        self.assertEqual(NS_X_DATA, instructions1.uri)
596        self.assertEqual('Fill out this form!', unicode(instructions1))
597        self.assertEqual('instructions', instructions2.name)
598        self.assertEqual(NS_X_DATA, instructions2.uri)
599        self.assertEqual('no really', unicode(instructions2))
600
601
602    def test_toElementFormType(self):
603        """
604        The form type is rendered as a hidden field with name FORM_TYPE.
605        """
606        form = data_form.Form('form', formNamespace='jabber:bot')
607        element = form.toElement()
608
609        elements = list(element.elements())
610        self.assertEqual(1, len(elements))
611        formTypeField = elements[0]
612        self.assertEqual('field', formTypeField.name)
613        self.assertEqual(NS_X_DATA, formTypeField.uri)
614        self.assertEqual('FORM_TYPE', formTypeField['var'])
615        self.assertEqual('hidden', formTypeField['type'])
616        self.assertEqual('jabber:bot', unicode(formTypeField.value))
617
618
619    def test_toElementFields(self):
620        """
621        Fields are rendered as child elements, in order.
622        """
623        fields = [data_form.Field('fixed', value='Section 1'),
624                  data_form.Field('text-single',
625                                  var='botname',
626                                  label='The name of your bot'),
627                  data_form.Field('text-multi',
628                                  var='description',
629                                  label='Helpful description of your bot'),
630                  data_form.Field('boolean',
631                                  var='public',
632                                  label='Public bot?',
633                                  required=True)
634                 ]
635        form = data_form.Form('form', fields=fields)
636        element = form.toElement()
637
638        elements = list(element.elements())
639        self.assertEqual(4, len(elements))
640        for field in elements:
641            self.assertEqual('field', field.name)
642            self.assertEqual(NS_X_DATA, field.uri)
643
644        # Check order
645        self.assertEqual('fixed', elements[0]['type'])
646        self.assertEqual('botname', elements[1]['var'])
647        self.assertEqual('description', elements[2]['var'])
648        self.assertEqual('public', elements[3]['var'])
649
650
651    def test_fromElement(self):
652        """
653        C{fromElement} creates a L{data_form.Form} from a DOM representation.
654        """
655        element = domish.Element((NS_X_DATA, 'x'))
656        element['type'] = 'result'
657        form = data_form.Form.fromElement(element)
658
659        self.assertEquals('result', form.formType)
660        self.assertEquals(None, form.title)
661        self.assertEquals([], form.instructions)
662        self.assertEquals({}, form.fields)
663
664
665    def test_fromElementInvalidElementName(self):
666        """
667        Bail if the passed element does not have the correct name.
668        """
669        element = domish.Element((NS_X_DATA, 'form'))
670        self.assertRaises(Exception, data_form.Form.fromElement, element)
671
672
673    def test_fromElementInvalidElementURI(self):
674        """
675        Bail if the passed element does not have the correct namespace.
676        """
677        element = domish.Element(('myns', 'x'))
678        self.assertRaises(Exception, data_form.Form.fromElement, element)
679
680
681    def test_fromElementTitle(self):
682        element = domish.Element((NS_X_DATA, 'x'))
683        element.addElement('title', content='My title')
684        form = data_form.Form.fromElement(element)
685
686        self.assertEquals('My title', form.title)
687
688
689    def test_fromElementInstructions(self):
690        element = domish.Element((NS_X_DATA, 'x'))
691        element.addElement('instructions', content='instruction')
692        form = data_form.Form.fromElement(element)
693
694        self.assertEquals(['instruction'], form.instructions)
695
696
697    def test_fromElementInstructions2(self):
698        element = domish.Element((NS_X_DATA, 'x'))
699        element.addElement('instructions', content='instruction 1')
700        element.addElement('instructions', content='instruction 2')
701        form = data_form.Form.fromElement(element)
702
703        self.assertEquals(['instruction 1', 'instruction 2'], form.instructions)
704
705
706    def test_fromElementOneField(self):
707        element = domish.Element((NS_X_DATA, 'x'))
708        element.addElement('field')
709        form = data_form.Form.fromElement(element)
710
711        self.assertEquals(1, len(form.fieldList))
712        self.assertNotIn('field', form.fields)
713
714
715    def test_fromElementTwoFields(self):
716        element = domish.Element((NS_X_DATA, 'x'))
717        element.addElement('field')['var'] = 'field1'
718        element.addElement('field')['var'] = 'field2'
719        form = data_form.Form.fromElement(element)
720
721        self.assertEquals(2, len(form.fieldList))
722        self.assertIn('field1', form.fields)
723        self.assertEquals('field1', form.fieldList[0].var)
724        self.assertIn('field2', form.fields)
725        self.assertEquals('field2', form.fieldList[1].var)
726
727
728    def test_fromElementFormType(self):
729        """
730        The form type is a hidden field named FORM_TYPE.
731        """
732        element = domish.Element((NS_X_DATA, 'x'))
733        field = element.addElement('field')
734        field['var'] = 'FORM_TYPE'
735        field['type'] = 'hidden'
736        field.addElement('value', content='myns')
737        form = data_form.Form.fromElement(element)
738
739        self.assertNotIn('FORM_TYPE', form.fields)
740        self.assertEqual('myns', form.formNamespace)
741
742    def test_fromElementFormTypeNotHidden(self):
743        """
744        A non-hidden field named FORM_TYPE does not set the form type.
745        """
746        element = domish.Element((NS_X_DATA, 'x'))
747        field = element.addElement('field')
748        field['var'] = 'FORM_TYPE'
749        field.addElement('value', content='myns')
750        form = data_form.Form.fromElement(element)
751
752        self.assertIn('FORM_TYPE', form.fields)
753        self.assertIdentical(None, form.formNamespace)
754
755
756    def test_fromElementChildOtherNamespace(self):
757        """
758        Child elements from another namespace are ignored.
759        """
760        element = domish.Element((NS_X_DATA, 'x'))
761        element['type'] = 'result'
762        field = element.addElement(('myns', 'field'))
763        field['var'] = 'test'
764        form = data_form.Form.fromElement(element)
765
766        self.assertEqual(0, len(form.fields))
767
768
769    def test_repr(self):
770        """
771        The repr of a form should be equal to its initialization.
772        """
773        form = data_form.Form('form', title='title', instructions=['instr'],
774                                      formNamespace='myns',
775                                      fields=[data_form.Field('fixed',
776                                                              value='test')])
777        self.assertEqual("""Form(formType='form', title='title', """
778                         """instructions=['instr'], formNamespace='myns', """
779                         """fields=[Field(fieldType='fixed', """
780                         """values=['test'])])""",
781                         repr(form))
782
783
784    def test_addField(self):
785        """
786        A field should occur in fieldList.
787        """
788        form = data_form.Form('result')
789        field = data_form.Field('fixed', value='Section 1')
790        form.addField(field)
791        self.assertEqual([field], form.fieldList)
792
793
794    def test_addFieldTwice(self):
795        """
796        Fields occur in fieldList in the order they were added.
797        """
798        form = data_form.Form('result')
799        field1 = data_form.Field('fixed', value='Section 1')
800        field2 = data_form.Field('fixed', value='Section 2')
801        form.addField(field1)
802        form.addField(field2)
803        self.assertEqual([field1, field2], form.fieldList)
804
805
806    def test_addFieldNotNamed(self):
807        """
808        A non-named field should not occur in fields.
809        """
810        form = data_form.Form('result')
811        field = data_form.Field('fixed', value='Section 1')
812        form.addField(field)
813        self.assertEqual({}, form.fields)
814
815
816    def test_addFieldNamed(self):
817        """
818        A named field should occur in fields.
819        """
820        form = data_form.Form('result')
821        field = data_form.Field(var='test')
822        form.addField(field)
823        self.assertEqual({'test': field}, form.fields)
824
825
826    def test_addFieldTwiceNamed(self):
827        """
828        A second named field should occur in fields.
829        """
830        form = data_form.Form('result')
831        field1 = data_form.Field(var='test')
832        field2 = data_form.Field(var='test2')
833        form.addField(field2)
834        form.addField(field1)
835        self.assertEqual({'test': field1, 'test2': field2}, form.fields)
836
837
838    def test_addFieldSameName(self):
839        """
840        A named field cannot occur twice.
841        """
842        form = data_form.Form('result')
843        field1 = data_form.Field(var='test', value='value')
844        field2 = data_form.Field(var='test', value='value2')
845        form.addField(field1)
846        self.assertRaises(data_form.Error, form.addField, field2)
847
848
849    def test_removeField(self):
850        """
851        A removed field should not occur in fieldList.
852        """
853        form = data_form.Form('result')
854        field = data_form.Field('fixed', value='Section 1')
855        form.addField(field)
856        form.removeField(field)
857        self.assertNotIn(field, form.fieldList)
858
859
860    def test_removeFieldNamed(self):
861        """
862        A removed named field should not occur in fields.
863        """
864        form = data_form.Form('result')
865        field = data_form.Field(var='test', value='test1')
866        form.addField(field)
867        form.removeField(field)
868        self.assertNotIn('test', form.fields)
869
870
871    def test_makeField(self):
872        """
873        Fields can be created from a dict of values and a dict of field defs.
874        """
875        fieldDefs = {
876                "pubsub#persist_items":
877                    {"type": "boolean",
878                     "label": "Persist items to storage"},
879                "pubsub#deliver_payloads":
880                    {"type": "boolean",
881                     "label": "Deliver payloads with event notifications"},
882                "pubsub#creator":
883                    {"type": "jid-single",
884                     "label": "The JID of the node creator"},
885                "pubsub#description":
886                    {"type": "text-single",
887                     "label": "A description of the node"},
888                "pubsub#owner":
889                    {"type": "jid-single",
890                     "label": "Owner of the node"},
891                }
892        values = {'pubsub#deliver_payloads': '0',
893                  'pubsub#persist_items': True,
894                  'pubsub#description': 'a great node',
895                  'pubsub#owner': jid.JID('user@example.org'),
896                  'x-myfield': ['a', 'b']}
897
898        form = data_form.Form('submit')
899        form.makeFields(values, fieldDefs)
900
901        # Check that the expected fields have been created
902        self.assertIn('pubsub#deliver_payloads', form.fields)
903        self.assertIn('pubsub#persist_items', form.fields)
904        self.assertIn('pubsub#description', form.fields)
905        self.assertIn('pubsub#owner', form.fields)
906
907        # This field is not created because there is no value for it.
908        self.assertNotIn('pubsub#creator', form.fields)
909
910        # This field is not created because it does not appear in fieldDefs
911        # and filterUnknown defaults to True
912        self.assertNotIn('x-myfield', form.fields)
913
914        # Check properties the created fields
915        self.assertEqual('boolean',
916                         form.fields['pubsub#deliver_payloads'].fieldType)
917        self.assertEqual('0',
918                         form.fields['pubsub#deliver_payloads'].value)
919        self.assertEqual('Deliver payloads with event notifications',
920                         form.fields['pubsub#deliver_payloads'].label)
921        self.assertEqual(True,
922                         form.fields['pubsub#persist_items'].value)
923
924
925    def test_makeFieldNotFilterUnknown(self):
926        """
927        Fields can be created from a dict of values and a dict of field defs.
928        """
929        fieldDefs = {
930                "pubsub#persist_items":
931                    {"type": "boolean",
932                     "label": "Persist items to storage"},
933                }
934        values = {'x-myfield': ['a', 'b']}
935
936        form = data_form.Form('submit')
937        form.makeFields(values, fieldDefs, filterUnknown=False)
938
939        field = form.fields['x-myfield']
940        self.assertEqual(None, field.fieldType)
941        self.assertEqual(values, form.getValues())
942
943
944    def test_makeFieldsUnknownTypeJID(self):
945        """
946        Without type, a single JID value sets field type jid-single.
947        """
948        values = {'pubsub#creator': jid.JID('user@example.org')}
949        form = data_form.Form('result')
950        form.makeFields(values)
951
952        field = form.fields['pubsub#creator']
953        self.assertEqual(None, field.fieldType)
954        self.assertEqual(values, form.getValues())
955
956
957    def test_makeFieldsUnknownTypeJIDMulti(self):
958        """
959        Without type, multiple JID values sets field type jid-multi.
960        """
961        values = {'pubsub#contact': [jid.JID('user@example.org'),
962                                     jid.JID('other@example.org')]}
963        form = data_form.Form('result')
964        form.makeFields(values)
965
966        field = form.fields['pubsub#contact']
967        self.assertEqual(None, field.fieldType)
968        self.assertEqual(values, form.getValues())
969
970
971    def test_makeFieldsUnknownTypeBoolean(self):
972        """
973        Without type, a boolean value sets field type boolean.
974        """
975        values = {'pubsub#persist_items': True}
976        form = data_form.Form('result')
977        form.makeFields(values)
978
979        field = form.fields['pubsub#persist_items']
980        self.assertEqual(None, field.fieldType)
981        self.assertEqual(values, form.getValues())
982
983
984    def test_makeFieldsUnknownTypeListMulti(self):
985        """
986        Without type, multiple values sets field type list-multi.
987        """
988        values = {'pubsub#show-values': ['chat', 'online', 'away']}
989        form = data_form.Form('result')
990        form.makeFields(values)
991
992        field = form.fields['pubsub#show-values']
993        self.assertEqual(None, field.fieldType)
994        self.assertEqual(values, form.getValues())
995
996
997    def test_interface(self):
998        """
999        L{Form}s act as a read-only dictionary.
1000        """
1001        form = data_form.Form('submit')
1002        verify.verifyObject(IIterableMapping, form)
1003
1004
1005    def test_getitem(self):
1006        """
1007        Using Form as a mapping will yield the value of fields keyed by name.
1008        """
1009        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1010                  data_form.Field('boolean', var='public', value=True),
1011                  data_form.Field('list-multi', var='features',
1012                                                values=['news', 'search'])]
1013        form = data_form.Form('submit', fields=fields)
1014        self.assertEqual('The Jabber Bot', form['botname'])
1015        self.assertTrue(form['public'])
1016        self.assertEqual(['news', 'search'], form['features'])
1017
1018
1019    def test_getitemOneValueTypeMulti(self):
1020        """
1021        A single value for a multi-value field type is returned in a list.
1022        """
1023        fields = [data_form.Field('list-multi', var='features',
1024                                                values=['news'])]
1025        form = data_form.Form('submit', fields=fields)
1026        self.assertEqual(['news'], form['features'])
1027
1028
1029    def test_getitemMultipleValuesNoType(self):
1030        """
1031        Multiple values for a field without type are returned in a list.
1032        """
1033        fields = [data_form.Field(None, var='features',
1034                                        values=['news', 'search'])]
1035        form = data_form.Form('submit', fields=fields)
1036        self.assertEqual(['news', 'search'], form['features'])
1037
1038
1039    def test_getitemMultipleValuesTypeSingle(self):
1040        """
1041        Multiple values for a single-value field type returns the first value.
1042        """
1043        fields = [data_form.Field('text-single', var='features',
1044                                        values=['news', 'search'])]
1045        form = data_form.Form('submit', fields=fields)
1046        self.assertEqual('news', form['features'])
1047
1048
1049    def test_get(self):
1050        """
1051        Getting the value of a known field succeeds.
1052        """
1053        fields = [data_form.Field(var='botname', value='The Jabber Bot')]
1054        form = data_form.Form('submit', fields=fields)
1055        self.assertEqual('The Jabber Bot', form.get('botname'))
1056
1057
1058    def test_getUnknownNone(self):
1059        """
1060        Getting the value of a unknown field returns None.
1061        """
1062        fields = [data_form.Field(var='botname', value='The Jabber Bot')]
1063        form = data_form.Form('submit', fields=fields)
1064        self.assertIdentical(None, form.get('features'))
1065
1066
1067    def test_getUnknownDefault(self):
1068        """
1069        Getting the value of a unknown field returns specified default.
1070        """
1071        fields = [data_form.Field(var='botname', value='The Jabber Bot')]
1072        form = data_form.Form('submit', fields=fields)
1073        self.assertTrue(form.get('public', True))
1074
1075
1076    def test_contains(self):
1077        """
1078        A form contains a known field.
1079        """
1080        fields = [data_form.Field(var='botname', value='The Jabber Bot')]
1081        form = data_form.Form('submit', fields=fields)
1082        self.assertIn('botname', form)
1083
1084
1085    def test_containsNot(self):
1086        """
1087        A form does not contains an unknown field.
1088        """
1089        fields = [data_form.Field(var='botname', value='The Jabber Bot')]
1090        form = data_form.Form('submit', fields=fields)
1091        self.assertNotIn('features', form)
1092
1093
1094    def test_iterkeys(self):
1095        """
1096        Iterating over the keys of a form yields all field names.
1097        """
1098        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1099                  data_form.Field('boolean', var='public', value=True),
1100                  data_form.Field('list-multi', var='features',
1101                                                values=['news', 'search'])]
1102        form = data_form.Form('submit', fields=fields)
1103        self.assertEqual(set(['botname', 'public', 'features']),
1104                         set(form.iterkeys()))
1105
1106
1107    def test_itervalues(self):
1108        """
1109        Iterating over the values of a form yields all field values.
1110        """
1111        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1112                  data_form.Field('boolean', var='public', value=True)]
1113        form = data_form.Form('submit', fields=fields)
1114        self.assertEqual(set(['The Jabber Bot', True]),
1115                         set(form.itervalues()))
1116
1117
1118    def test_iteritems(self):
1119        """
1120        Iterating over the values of a form yields all item tuples.
1121        """
1122        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1123                  data_form.Field('boolean', var='public', value=True)]
1124        form = data_form.Form('submit', fields=fields)
1125        self.assertEqual(set([('botname', 'The Jabber Bot'),
1126                              ('public', True)]),
1127                         set(form.iteritems()))
1128
1129
1130    def test_keys(self):
1131        """
1132        Getting the keys of a form yields a list of field names.
1133        """
1134        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1135                  data_form.Field('boolean', var='public', value=True),
1136                  data_form.Field('list-multi', var='features',
1137                                                values=['news', 'search'])]
1138        form = data_form.Form('submit', fields=fields)
1139        keys = form.keys()
1140        if not _PY3:
1141            self.assertIsInstance(keys, list)
1142        self.assertEqual(set(['botname', 'public', 'features']),
1143                         set(keys))
1144
1145
1146    def test_values(self):
1147        """
1148        Getting the values of a form yields a list of field values.
1149        """
1150        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1151                  data_form.Field('boolean', var='public', value=True)]
1152        form = data_form.Form('submit', fields=fields)
1153        values = form.values()
1154        if not _PY3:
1155            self.assertIsInstance(values, list)
1156        self.assertEqual(set(['The Jabber Bot', True]), set(values))
1157
1158
1159    def test_items(self):
1160        """
1161        Iterating over the values of a form yields a list of all item tuples.
1162        """
1163        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1164                  data_form.Field('boolean', var='public', value=True)]
1165        form = data_form.Form('submit', fields=fields)
1166        items = form.items()
1167        if not _PY3:
1168            self.assertIsInstance(items, list)
1169        self.assertEqual(set([('botname', 'The Jabber Bot'),
1170                              ('public', True)]),
1171                         set(items))
1172
1173
1174    def test_getValues(self):
1175        """
1176        L{Form.getValues} returns a dict of all field values.
1177        """
1178        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
1179                  data_form.Field('boolean', var='public', value=True),
1180                  data_form.Field('list-multi', var='features',
1181                                                values=['news', 'search'])]
1182        form = data_form.Form('submit', fields=fields)
1183        self.assertEqual({'botname': 'The Jabber Bot',
1184                          'public': True,
1185                          'features': ['news', 'search']},
1186                         form.getValues())
1187
1188
1189    def test_typeCheckKnownFieldChecked(self):
1190        """
1191        Known fields are type checked.
1192        """
1193        checked = []
1194        fieldDefs = {"pubsub#description":
1195                        {"type": "text-single",
1196                         "label": "A description of the node"}}
1197        form = data_form.Form('submit')
1198        form.addField(data_form.Field(var='pubsub#description',
1199                                      value='a node'))
1200        field = form.fields['pubsub#description']
1201        field.typeCheck = lambda : checked.append(None)
1202        form.typeCheck(fieldDefs)
1203
1204        self.assertEqual([None], checked)
1205
1206
1207    def test_typeCheckKnownFieldNoType(self):
1208        """
1209        Known fields without a type get the type of the field definition.
1210        """
1211        checked = []
1212        fieldDefs = {"pubsub#description":
1213                        {"type": "text-single",
1214                         "label": "A description of the node"}}
1215        form = data_form.Form('submit')
1216        form.addField(data_form.Field(None, var='pubsub#description',
1217                                            value='a node'))
1218        field = form.fields['pubsub#description']
1219        field.typeCheck = lambda : checked.append(None)
1220        form.typeCheck(fieldDefs)
1221
1222        self.assertEqual('text-single', field.fieldType)
1223        self.assertEqual([None], checked)
1224
1225
1226    def test_typeCheckWrongFieldType(self):
1227        """
1228        A field should have the same type as the field definition.
1229        """
1230        checked = []
1231        fieldDefs = {"pubsub#description":
1232                        {"type": "text-single",
1233                         "label": "A description of the node"}}
1234        form = data_form.Form('submit')
1235        form.addField(data_form.Field('list-single', var='pubsub#description',
1236                                                     value='a node'))
1237        field = form.fields['pubsub#description']
1238        field.typeCheck = lambda : checked.append(None)
1239
1240        self.assertRaises(TypeError, form.typeCheck, fieldDefs)
1241        self.assertEqual([], checked)
1242
1243
1244    def test_typeCheckDefaultTextSingle(self):
1245        """
1246        If a field definition has no type, use text-single.
1247        """
1248        checked = []
1249        fieldDefs = {"pubsub#description":
1250                        {"label": "A description of the node"}}
1251        form = data_form.Form('submit')
1252        form.addField(data_form.Field('text-single', var='pubsub#description',
1253                                                     value='a node'))
1254        field = form.fields['pubsub#description']
1255        field.typeCheck = lambda : checked.append(None)
1256        form.typeCheck(fieldDefs)
1257
1258        self.assertEqual([None], checked)
1259
1260
1261    def test_typeCheckUnknown(self):
1262        """
1263        Unknown fields are checked, not removed if filterUnknown False.
1264        """
1265        checked = []
1266        fieldDefs = {}
1267        form = data_form.Form('submit')
1268        form.addField(data_form.Field('list-single', var='pubsub#description',
1269                                                     value='a node'))
1270        field = form.fields['pubsub#description']
1271        field.typeCheck = lambda : checked.append(None)
1272        form.typeCheck(fieldDefs, filterUnknown=False)
1273
1274        self.assertIn('pubsub#description', form.fields)
1275        self.assertEqual([None], checked)
1276
1277
1278    def test_typeCheckUnknownNoType(self):
1279        """
1280        Unknown fields without type are not checked.
1281        """
1282        checked = []
1283        fieldDefs = {}
1284        form = data_form.Form('submit')
1285        form.addField(data_form.Field(None, var='pubsub#description',
1286                                            value='a node'))
1287        field = form.fields['pubsub#description']
1288        field.typeCheck = lambda : checked.append(None)
1289        form.typeCheck(fieldDefs, filterUnknown=False)
1290
1291        self.assertIn('pubsub#description', form.fields)
1292        self.assertEqual([], checked)
1293
1294
1295    def test_typeCheckUnknownRemoved(self):
1296        """
1297        Unknown fields are not checked, and removed if filterUnknown True.
1298        """
1299        checked = []
1300        fieldDefs = {}
1301        form = data_form.Form('submit')
1302        form.addField(data_form.Field('list-single', var='pubsub#description',
1303                                                     value='a node'))
1304        field = form.fields['pubsub#description']
1305        field.typeCheck = lambda : checked.append(None)
1306        form.typeCheck(fieldDefs, filterUnknown=True)
1307
1308        self.assertNotIn('pubsub#description', form.fields)
1309        self.assertEqual([], checked)
1310
1311
1312
1313class FindFormTest(unittest.TestCase):
1314    """
1315    Tests for L{data_form.findForm}.
1316    """
1317
1318    def test_findForm(self):
1319        element = domish.Element((None, 'test'))
1320        theForm = data_form.Form('submit', formNamespace='myns')
1321        element.addChild(theForm.toElement())
1322        form = data_form.findForm(element, 'myns')
1323        self.assertEqual('myns', form.formNamespace)
1324
1325
1326    def test_noFormType(self):
1327        element = domish.Element((None, 'test'))
1328        otherForm = data_form.Form('submit')
1329        element.addChild(otherForm.toElement())
1330        form = data_form.findForm(element, 'myns')
1331        self.assertIdentical(None, form)
1332
1333
1334    def test_noFormTypeCancel(self):
1335        """
1336        Cancelled forms don't have a FORM_TYPE field, the first is returned.
1337        """
1338        element = domish.Element((None, 'test'))
1339        cancelledForm = data_form.Form('cancel')
1340        element.addChild(cancelledForm.toElement())
1341        form = data_form.findForm(element, 'myns')
1342        self.assertEqual('cancel', form.formType)
1343
1344
1345    def test_otherFormType(self):
1346        """
1347        Forms with other FORM_TYPEs are ignored.
1348        """
1349        element = domish.Element((None, 'test'))
1350        otherForm = data_form.Form('submit', formNamespace='otherns')
1351        element.addChild(otherForm.toElement())
1352        form = data_form.findForm(element, 'myns')
1353        self.assertIdentical(None, form)
1354
1355
1356    def test_otherFormTypeCancel(self):
1357        """
1358        Cancelled forms with another FORM_TYPE are ignored.
1359        """
1360        element = domish.Element((None, 'test'))
1361        cancelledForm = data_form.Form('cancel', formNamespace='otherns')
1362        element.addChild(cancelledForm.toElement())
1363        form = data_form.findForm(element, 'myns')
1364        self.assertIdentical(None, form)
1365
1366
1367    def test_noElement(self):
1368        """
1369        When None is passed as element, None is returned.
1370        """
1371        element = None
1372        form = data_form.findForm(element, 'myns')
1373        self.assertIdentical(None, form)
1374
1375
1376    def test_noForm(self):
1377        """
1378        When no child element is a form, None is returned.
1379        """
1380        element = domish.Element((None, 'test'))
1381        form = data_form.findForm(element, 'myns')
1382        self.assertIdentical(None, form)
1383    def test_typeCheckNoFieldDefs(self):
1384        """
1385        If there are no field defs, an empty dictionary is assumed.
1386        """
1387        checked = []
1388        form = data_form.Form('submit')
1389        form.addField(data_form.Field('list-single', var='pubsub#description',
1390                                                     value='a node'))
1391        field = form.fields['pubsub#description']
1392        field.typeCheck = lambda : checked.append(None)
1393        form.typeCheck()
1394
1395        self.assertIn('pubsub#description', form.fields)
1396        self.assertEqual([None], checked)
Note: See TracBrowser for help on using the repository browser.