source: ralphm-patches/form-missing-tests.patch @ 24:8116c2eaa96a

Last change on this file since 24:8116c2eaa96a was 24:8116c2eaa96a, checked in by Ralph Meijer <ralphm@…>, 13 years ago

More tests, integrate form-coerce-values.patch.

File size: 23.1 KB
RevLine 
[22]1diff -r 3ef9bc7a0d70 wokkel/data_form.py
2--- a/wokkel/data_form.py       Wed Dec 30 16:53:05 2009 +0100
[24]3+++ b/wokkel/data_form.py       Fri Jan 01 01:21:56 2010 +0100
4@@ -251,10 +251,10 @@
5             field['var'] = self.var
6 
7         for value in self.values:
8-            if self.fieldType == 'boolean':
9+            if isinstance(value, bool):
10                 value = unicode(value).lower()
11-            elif self.fieldType in ('jid-single', 'jid-multi'):
12-                value = value.full()
13+            else:
14+                value = unicode(value)
15 
16             field.addElement('value', content=value)
17 
[22]18@@ -343,7 +343,7 @@
19     """
20     Data Form.
21 
22-    There are two similarly named properties of forms. The L{formType} is the
23+    There are two similarly named properties of forms. The C{formType} is the
24     the so-called type of the form, and is set as the C{'type'} attribute
25     on the form's root element.
26 
27@@ -351,19 +351,31 @@
28     provide a context for the field names used in this form, by setting a
29     special hidden field named C{'FORM_TYPE'}, to put the names of all
30     other fields in the namespace of the value of that field. This namespace
31-    is recorded in the L{formNamespace} instance variable.
32+    is recorded in the C{formNamespace} instance variable.
33 
34     @ivar formType: Type of form. One of C{'form'}, C{'submit'}, {'cancel'},
35                     or {'result'}.
36-    @type formType: C{str}.
37+    @type formType: C{str}
38+
39+    @ivar title: Natural language title of the form.
40+    @type title: C{unicode}
41+
42+    @ivar instructions: Natural language instructions as a list of C{unicode}
43+        strings without line breaks.
44+    @type instructions: C{list}
45+
46     @ivar formNamespace: The optional namespace of the field names for this
47-                         form. This goes in the special field named
48-                         C{'FORM_TYPE'}, if set.
49+        form. This goes in the special field named C{'FORM_TYPE'}, if set.
50     @type formNamespace: C{str}.
51-    @ivar fields: Dictionary of fields that have a name. Note that this is
52-                  meant to be used for reading, only. One should use
53-                  L{addField} for adding fields.
54+
55+    @ivar fields: Dictionary of named fields. Note that this is meant to be
56+        used for reading, only. One should use L{addField} or L{makeFields} and
57+        L{removeField} for adding and removing fields.
58     @type fields: C{dict}
59+
60+    @ivar fieldList: List of all fields, in the order they are added. Like
61+        C{fields}, this is meant to be used for reading, only.
62+    @type fieldList: C{list}
63     """
64 
65     def __init__(self, formType, title=None, instructions=None,
[24]66@@ -392,7 +404,7 @@
67         if self.formNamespace:
68             r.append(", formNamespace=")
69             r.append(repr(self.formNamespace))
70-        if self.fields:
71+        if self.fieldList:
72             r.append(", fields=")
73             r.append(repr(self.fieldList))
74         r.append(")")
[22]75@@ -424,7 +436,7 @@
76             form.addElement('title', content=self.title)
77 
78         for instruction in self.instructions:
79-            form.addElement('instruction', content=instruction)
80+            form.addElement('instructions', content=instruction)
81 
82         if self.formNamespace is not None:
83             field = Field('hidden', 'FORM_TYPE', self.formNamespace)
[24]84@@ -477,11 +489,26 @@
85 
86         return form
87 
88+
89     def getValues(self):
90+        """
91+        Extract values from the named form fields.
92+
93+        For all named fields, the corresponding value or values are
94+        returned in a dictionary keyed by the field name. For multi-value
95+        fields, the dictionary value is a list, otherwise a single value.
96+
97+        If a field has no type, and the field has multiple values, the value of
98+        the dictionary entry is the list of values. Otherwise, it will be a
99+        single value.
100+
101+        @rtype: C{dict}
102+        """
103         values = {}
104 
105         for name, field in self.fields.iteritems():
106-            if len(field.values) > 1:
107+            if (field.fieldType in ('jid-multi', 'list-multi', 'text-multi') or
108+                (field.fieldType is None and len(field.values) > 1)):
109                 value = field.values
110             else:
111                 value = field.value
[22]112diff -r 3ef9bc7a0d70 wokkel/test/test_data_form.py
113--- a/wokkel/test/test_data_form.py     Wed Dec 30 16:53:05 2009 +0100
[24]114+++ b/wokkel/test/test_data_form.py     Fri Jan 01 01:21:56 2010 +0100
[23]115@@ -19,14 +19,67 @@
116     """
117 
118     def test_toElement(self):
119+        option = data_form.Option('value')
120+        element = option.toElement()
121+
122+        self.assertEqual('option', element.name)
123+        self.assertEqual(NS_X_DATA, element.uri)
124+        self.assertEqual(NS_X_DATA, element.value.uri)
125+        self.assertEqual('value', unicode(element.value))
126+        self.assertFalse(element.hasAttribute('label'))
127+
128+
129+    def test_toElementLabel(self):
130         option = data_form.Option('value', 'label')
131         element = option.toElement()
132-        self.assertEquals('option', element.name)
133-        self.assertEquals(NS_X_DATA, element.uri)
134-        self.assertEquals('label', element['label'])
135-        self.assertEquals('value', element.value.name)
136-        self.assertEquals(NS_X_DATA, element.value.uri)
137-        self.assertEquals('value', unicode(element.value))
138+
139+        self.assertEqual('option', element.name)
140+        self.assertEqual(NS_X_DATA, element.uri)
141+        self.assertEqual(NS_X_DATA, element.value.uri)
142+        self.assertEqual('value', unicode(element.value))
143+        self.assertEqual('label', element['label'])
144+
145+
146+    def test_fromElement(self):
147+        """
148+        An option has a child element with the option value.
149+        """
150+        element = domish.Element((NS_X_DATA, 'option'))
151+        element.addElement('value', content='value')
152+        option = data_form.Option.fromElement(element)
153+
154+        self.assertEqual('value', option.value)
155+        self.assertIdentical(None, option.label)
156+
157+
158+    def test_fromElementLabel(self):
159+        """
160+        An option label is an attribute on the option element.
161+        """
162+
163+        element = domish.Element((NS_X_DATA, 'option'))
164+        element.addElement('value', content='value')
165+        element['label'] = 'label'
166+        option = data_form.Option.fromElement(element)
167+
168+        self.assertEqual('label', option.label)
169+
170+
171+    def test_fromElementNoValue(self):
172+        """
173+        An option MUST have a value.
174+        """
175+        element = domish.Element((NS_X_DATA, 'option'))
176+        self.assertRaises(data_form.Error,
177+                          data_form.Option.fromElement, element)
178+
179+
180+    def test_repr(self):
181+        """
182+        The representation of an Option is equal to how it is created.
183+        """
184+        option = data_form.Option('value', 'label')
185+        self.assertEqual("""Option('value', 'label')""", repr(option))
186 
187 
188 
[24]189@@ -44,6 +97,21 @@
190         self.assertEqual('test', field.var)
191 
192 
193+    def test_repr(self):
194+        """
195+        The repr of a field should be equal to its initialization.
196+        """
197+        field = data_form.Field('list-single', var='test', label='label',
198+                               desc='desc', required=True, value='test',
199+                               options=[data_form.Option('test')])
200+        self.assertEqual("""Field(fieldType='list-single', """
201+                         """var='test', label='label', """
202+                         """desc='desc', required=True, """
203+                         """values=['test'], """
204+                         """options=[Option('test')])""",
205+                         repr(field))
206+
207+
208     def test_toElement(self):
209         """
210         Test rendering to a DOM.
211@@ -130,12 +198,44 @@
212 
213 
214     def test_toElementJID(self):
215+        """
216+        A JID value should render to text.
217+        """
218         field = data_form.Field(fieldType='jid-single', var='test',
219                                 value=jid.JID(u'test@example.org'))
220         element = field.toElement()
221         self.assertEqual(u'test@example.org', unicode(element.value))
222 
223 
224+    def test_toElementJIDTextSingle(self):
225+        """
226+        A JID value should render to text if field type is text-single.
227+        """
228+        field = data_form.Field(fieldType='text-single', var='test',
229+                                value=jid.JID(u'test@example.org'))
230+        element = field.toElement()
231+        self.assertEqual(u'test@example.org', unicode(element.value))
232+
233+
234+    def test_toElementBoolean(self):
235+        """
236+        A boolean value should render to text.
237+        """
238+        field = data_form.Field(fieldType='boolean', var='test',
239+                                value=True)
240+        element = field.toElement()
241+        self.assertEqual(u'true', unicode(element.value))
242+
243+
244+    def test_toElementBooleanTextSingle(self):
245+        """
246+        A boolean value should render to text if the field type is text-single.
247+        """
248+        field = data_form.Field(var='test', value=True)
249+        element = field.toElement()
250+        self.assertEqual(u'true', unicode(element.value))
251+
252+
253     def test_typeCheckNoFieldName(self):
254         """
255         A field not of type fixed must have a var.
256@@ -250,6 +350,7 @@
[23]257         field = data_form.Field.fromElement(element)
258         self.assertEquals(u'user@example.org', field.value)
259 
260+
261     def test_fromElementValueJIDMalformed(self):
262         """
263         Parsed jid-single field values should be of type C{unicode}.
[24]264@@ -275,6 +376,85 @@
[23]265         self.assertEquals(u'false', field.value)
266 
267 
268+    def test_fromElementDesc(self):
269+        """
270+        Field descriptions are in a desc child element.
271+        """
272+        element = domish.Element((NS_X_DATA, 'field'))
273+        element.addElement('desc', content=u'My description')
274+        field = data_form.Field.fromElement(element)
275+        self.assertEqual(u'My description', field.desc)
276+
277+
278+    def test_fromElementOption(self):
279+        """
280+        Field descriptions are in a desc child element.
281+        """
282+        element = domish.Element((NS_X_DATA, 'field'))
283+        element.addElement('option').addElement('value', content=u'option1')
284+        element.addElement('option').addElement('value', content=u'option2')
285+        field = data_form.Field.fromElement(element)
286+        self.assertEqual(2, len(field.options))
287+
288+
289+    def test_fromElementRequired(self):
290+        """
291+        Required fields have a required child element.
292+        """
293+        element = domish.Element((NS_X_DATA, 'field'))
294+        element.addElement('required')
295+        field = data_form.Field.fromElement(element)
296+        self.assertTrue(field.required)
297+
298+
299+    def test_fromElementChildOtherNamespace(self):
300+        """
301+        Child elements from another namespace are ignored.
302+        """
303+        element = domish.Element((NS_X_DATA, 'field'))
304+        element['var'] = 'test'
305+        child = element.addElement(('myns', 'value'))
306+        field = data_form.Field.fromElement(element)
307+
308+        self.assertIdentical(None, field.value)
309+
310+
[24]311+    def test_fromDict(self):
312+        """
313+        A named field with a value can be created by providing a dictionary.
314+        """
315+        fieldDict = {'var': 'test', 'value': 'text'}
316+        field = data_form.Field.fromDict(fieldDict)
317+        self.assertEqual('test', field.var)
318+        self.assertEqual('text', field.value)
319+
320+
321+    def test_fromDictFieldType(self):
322+        """
323+        The field type is set using the key 'type'.
324+        """
325+        fieldDict = {'type': 'boolean'}
326+        field = data_form.Field.fromDict(fieldDict)
327+        self.assertEqual('boolean', field.fieldType)
328+
329+
330+    def test_fromDictOptions(self):
331+        """
332+        The field options are set using the key 'options'.
333+
334+        The options are represented as a dictionary keyed by option,
335+        with the optional label as value.
336+        """
337+        fieldDict = {'options': {'value1': 'label1',
338+                                 'value2': 'label2'}}
339+        field = data_form.Field.fromDict(fieldDict)
340+        self.assertEqual(2, len(field.options))
341+        options = {}
342+        for option in field.options:
343+            options[option.value] = option.label
344+
345+        self.assertEqual(options, fieldDict['options'])
346+
[23]347 
348 class FormTest(unittest.TestCase):
349     """
[24]350@@ -289,11 +469,13 @@
[22]351         form = data_form.Form('result')
352         self.assertEqual('result', form.formType)
353 
354+
355     def test_toElement(self):
356         """
357         The toElement method returns a form's DOM representation.
358         """
359         form = data_form.Form('result')
360+
361         element = form.toElement()
362 
363         self.assertTrue(domish.IElement.providedBy(element))
[24]364@@ -303,6 +485,105 @@
[22]365         self.assertEquals([], element.children)
366 
367 
368+    def test_toElementTitle(self):
369+        """
370+        A title is rendered as a child element with the title as CDATA.
371+        """
372+        form = data_form.Form('form', title='Bot configuration')
373+        element = form.toElement()
374+
375+        elements = list(element.elements())
[23]376+        self.assertEqual(1, len(elements))
[22]377+        title = elements[0]
378+        self.assertEqual('title', title.name)
379+        self.assertEqual(NS_X_DATA, title.uri)
380+        self.assertEqual('Bot configuration', unicode(title))
381+
382+
383+    def test_toElementInstructions(self):
384+        """
385+        Instructions are rendered as child elements with CDATA.
386+        """
387+        form = data_form.Form('form', instructions=['Fill out this form!'])
388+        element = form.toElement()
389+
390+        elements = list(element.elements())
[23]391+        self.assertEqual(1, len(elements))
[22]392+        instructions = elements[0]
393+        self.assertEqual('instructions', instructions.name)
394+        self.assertEqual(NS_X_DATA, instructions.uri)
395+        self.assertEqual('Fill out this form!', unicode(instructions))
396+
397+
398+    def test_toElementInstructionsMultiple(self):
399+        """
400+        Instructions render as one element per instruction, in order.
401+        """
402+        form = data_form.Form('form', instructions=['Fill out this form!',
403+                                                    'no really'])
404+        element = form.toElement()
405+
406+        elements = list(element.elements())
[23]407+        self.assertEqual(2, len(elements))
[22]408+        instructions1 = elements[0]
409+        instructions2 = elements[1]
410+        self.assertEqual('instructions', instructions1.name)
411+        self.assertEqual(NS_X_DATA, instructions1.uri)
412+        self.assertEqual('Fill out this form!', unicode(instructions1))
413+        self.assertEqual('instructions', instructions2.name)
414+        self.assertEqual(NS_X_DATA, instructions2.uri)
415+        self.assertEqual('no really', unicode(instructions2))
416+
417+
418+    def test_toElementFormType(self):
419+        """
420+        The form type is rendered as a hidden field with name FORM_TYPE.
421+        """
422+        form = data_form.Form('form', formNamespace='jabber:bot')
423+        element = form.toElement()
424+
425+        elements = list(element.elements())
[23]426+        self.assertEqual(1, len(elements))
[22]427+        formTypeField = elements[0]
428+        self.assertEqual('field', formTypeField.name)
429+        self.assertEqual(NS_X_DATA, formTypeField.uri)
430+        self.assertEqual('FORM_TYPE', formTypeField['var'])
431+        self.assertEqual('hidden', formTypeField['type'])
432+        self.assertEqual('jabber:bot', unicode(formTypeField.value))
433+
434+
435+    def test_toElementFields(self):
436+        """
437+        Fields are rendered as child elements, in order.
438+        """
439+        fields = [data_form.Field('fixed', value='Section 1'),
440+                  data_form.Field('text-single',
441+                                  var='botname',
442+                                  label='The name of your bot'),
443+                  data_form.Field('text-multi',
444+                                  var='description',
445+                                  label='Helpful description of your bot'),
446+                  data_form.Field('boolean',
447+                                  var='public',
448+                                  label='Public bot?',
449+                                  required=True)
450+                 ]
451+        form = data_form.Form('form', fields=fields)
452+        element = form.toElement()
453+
454+        elements = list(element.elements())
[23]455+        self.assertEqual(4, len(elements))
[22]456+        for field in elements:
457+            self.assertEqual('field', field.name)
458+            self.assertEqual(NS_X_DATA, field.uri)
459+
460+        # Check order
461+        self.assertEqual('fixed', elements[0]['type'])
462+        self.assertEqual('botname', elements[1]['var'])
463+        self.assertEqual('description', elements[2]['var'])
464+        self.assertEqual('public', elements[3]['var'])
465+
466+
467     def test_fromElement(self):
468         """
469         C{fromElement} creates a L{data_form.Form} from a DOM representation.
[24]470@@ -348,6 +629,7 @@
[22]471 
472         self.assertEquals(['instruction'], form.instructions)
473 
474+
475     def test_fromElementInstructions2(self):
476         element = domish.Element((NS_X_DATA, 'x'))
477         element.addElement('instructions', content='instruction 1')
[24]478@@ -377,3 +659,173 @@
[22]479         self.assertEquals('field1', form.fieldList[0].var)
480         self.assertIn('field2', form.fields)
481         self.assertEquals('field2', form.fieldList[1].var)
482+
483+
[23]484+    def test_fromElementFormType(self):
485+        """
486+        The form type is a hidden field named FORM_TYPE.
487+        """
488+        element = domish.Element((NS_X_DATA, 'x'))
489+        field = element.addElement('field')
490+        field['var'] = 'FORM_TYPE'
491+        field['type'] = 'hidden'
492+        field.addElement('value', content='myns')
493+        form = data_form.Form.fromElement(element)
494+
495+        self.assertNotIn('FORM_TYPE', form.fields)
496+        self.assertEqual('myns', form.formNamespace)
497+
498+    def test_fromElementFormTypeNotHidden(self):
499+        """
500+        A non-hidden field named FORM_TYPE does not set the form type.
501+        """
502+        element = domish.Element((NS_X_DATA, 'x'))
503+        field = element.addElement('field')
504+        field['var'] = 'FORM_TYPE'
505+        field.addElement('value', content='myns')
506+        form = data_form.Form.fromElement(element)
507+
508+        self.assertIn('FORM_TYPE', form.fields)
509+        self.assertIdentical(None, form.formNamespace)
510+
511+
512+    def test_fromElementChildOtherNamespace(self):
513+        """
514+        Child elements from another namespace are ignored.
515+        """
516+        element = domish.Element((NS_X_DATA, 'x'))
517+        element['type'] = 'result'
518+        field = element.addElement(('myns', 'field'))
519+        field['var'] = 'test'
520+        form = data_form.Form.fromElement(element)
521+
522+        self.assertEqual(0, len(form.fields))
523+
524+
[24]525+    def test_repr(self):
526+        """
527+        The repr of a form should be equal to its initialization.
528+        """
529+        form = data_form.Form('form', title='title', instructions=['instr'],
530+                                      formNamespace='myns',
531+                                      fields=[data_form.Field('fixed',
532+                                                              value='test')])
533+        self.assertEqual("""Form(formType='form', title='title', """
534+                         """instructions=['instr'], formNamespace='myns', """
535+                         """fields=[Field(fieldType='fixed', """
536+                         """values=['test'])])""",
537+                         repr(form))
538+
539+
[22]540+    def test_addField(self):
541+        """
542+        A field should occur in fieldList.
543+        """
544+        form = data_form.Form('result')
545+        field = data_form.Field('fixed', value='Section 1')
546+        form.addField(field)
547+        self.assertEqual([field], form.fieldList)
548+
549+
550+    def test_addFieldTwice(self):
551+        """
552+        Fields occur in fieldList in the order they were added.
553+        """
554+        form = data_form.Form('result')
555+        field1 = data_form.Field('fixed', value='Section 1')
556+        field2 = data_form.Field('fixed', value='Section 2')
557+        form.addField(field1)
558+        form.addField(field2)
559+        self.assertEqual([field1, field2], form.fieldList)
560+
561+
562+    def test_addFieldNotNamed(self):
563+        """
564+        A non-named field should not occur in fields.
565+        """
566+        form = data_form.Form('result')
567+        field = data_form.Field('fixed', value='Section 1')
568+        form.addField(field)
569+        self.assertEqual({}, form.fields)
570+
571+
572+    def test_addFieldNamed(self):
573+        """
574+        A named field should occur in fields.
575+        """
576+        form = data_form.Form('result')
577+        field = data_form.Field(var='test')
578+        form.addField(field)
579+        self.assertEqual({'test': field}, form.fields)
580+
581+
582+    def test_addFieldTwiceNamed(self):
583+        """
584+        A second named field should occur in fields.
585+        """
586+        form = data_form.Form('result')
587+        field1 = data_form.Field(var='test')
588+        field2 = data_form.Field(var='test2')
589+        form.addField(field2)
590+        form.addField(field1)
591+        self.assertEqual({'test': field1, 'test2': field2}, form.fields)
592+
593+
594+    def test_addFieldSameName(self):
595+        """
596+        A named field cannot occur twice.
597+        """
598+        form = data_form.Form('result')
599+        field1 = data_form.Field(var='test', value='value')
600+        field2 = data_form.Field(var='test', value='value2')
601+        form.addField(field1)
602+        self.assertRaises(data_form.Error, form.addField, field2)
[24]603+
604+
605+    def test_getValues(self):
606+        """
607+        Each named field is represented in the values, keyed by name.
608+        """
609+        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
610+                  data_form.Field('boolean', var='public', value=True),
611+                  data_form.Field('list-multi', var='features',
612+                                                values=['news', 'search'])]
613+        form = data_form.Form('submit', fields=fields)
614+        values = form.getValues()
615+        self.assertEqual({'botname': 'The Jabber Bot',
616+                          'public': True,
617+                          'features': ['news', 'search']},
618+                         values)
619+
620+
621+    def test_getValuesOneValueTypeMulti(self):
622+        """
623+        A single value for a multi-value field type is returned in a list.
624+        """
625+        fields = [data_form.Field('list-multi', var='features',
626+                                                values=['news'])]
627+        form = data_form.Form('submit', fields=fields)
628+        values = form.getValues()
629+        self.assertEqual({'features': ['news']}, values)
630+
631+
632+    def test_getValuesMultipleValuesNoType(self):
633+        """
634+        Multiple values for a field without type are returned in a list.
635+        """
636+        fields = [data_form.Field(None, var='features',
637+                                        values=['news', 'search'])]
638+        form = data_form.Form('submit', fields=fields)
639+        values = form.getValues()
640+        self.assertEqual({'features': ['news', 'search']}, values)
641+
642+
643+    def test_getValuesMultipleValuesTypeSingle(self):
644+        """
645+        Multiple values for a single-value field type returns the first value.
646+        """
647+        fields = [data_form.Field('text-single', var='features',
648+                                        values=['news', 'search'])]
649+        form = data_form.Form('submit', fields=fields)
650+        values = form.getValues()
651+        self.assertEqual({'features': 'news'}, values)
Note: See TracBrowser for help on using the repository browser.