source: wokkel/test/test_data_form.py @ 171:4f5ee7b81ebf

Last change on this file since 171:4f5ee7b81ebf was 105:5d8f1609aaf3, checked in by Ralph Meijer <ralphm@…>, 11 years ago

Allow wokkel.data_form.Form to be used as a read-only dict.

In [1334124db2fd] wokkel.pubsub.PubSubRequest.options was changed to be a
Form instead of dictionary, which makes existing code using that field to be
incompatible.

To reduce the impact of that change, this change implements various methods in
wokkel.data_form.Form to emulate a read-only dictionary. It now maps the
name of each field to its value, similar to the dictionary returned from
getValues. The latter is now identical to dict(form).

  • * *

Address incompatible change concerning PubSubRequest?.options.

In changeset [1334124db2fd], PubSubRequest.options was changed to hold the
wokkel.data_form.Form that represents the data form sent in the original
request. This makes it easier to type check the form in a step separate from
parsing the request. However, this is an incompatible change.

To remedy this, we move the form to optionsForm and make options a property
that returns the values of the form.

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