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@…>, 11 years ago

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

File size: 23.1 KB
  • wokkel/data_form.py

    diff -r 3ef9bc7a0d70 wokkel/data_form.py
    a b  
    251251            field['var'] = self.var
    252252
    253253        for value in self.values:
    254             if self.fieldType == 'boolean':
     254            if isinstance(value, bool):
    255255                value = unicode(value).lower()
    256             elif self.fieldType in ('jid-single', 'jid-multi'):
    257                 value = value.full()
     256            else:
     257                value = unicode(value)
    258258
    259259            field.addElement('value', content=value)
    260260
     
    343343    """
    344344    Data Form.
    345345
    346     There are two similarly named properties of forms. The L{formType} is the
     346    There are two similarly named properties of forms. The C{formType} is the
    347347    the so-called type of the form, and is set as the C{'type'} attribute
    348348    on the form's root element.
    349349
     
    351351    provide a context for the field names used in this form, by setting a
    352352    special hidden field named C{'FORM_TYPE'}, to put the names of all
    353353    other fields in the namespace of the value of that field. This namespace
    354     is recorded in the L{formNamespace} instance variable.
     354    is recorded in the C{formNamespace} instance variable.
    355355
    356356    @ivar formType: Type of form. One of C{'form'}, C{'submit'}, {'cancel'},
    357357                    or {'result'}.
    358     @type formType: C{str}.
     358    @type formType: C{str}
     359
     360    @ivar title: Natural language title of the form.
     361    @type title: C{unicode}
     362
     363    @ivar instructions: Natural language instructions as a list of C{unicode}
     364        strings without line breaks.
     365    @type instructions: C{list}
     366
    359367    @ivar formNamespace: The optional namespace of the field names for this
    360                          form. This goes in the special field named
    361                          C{'FORM_TYPE'}, if set.
     368        form. This goes in the special field named C{'FORM_TYPE'}, if set.
    362369    @type formNamespace: C{str}.
    363     @ivar fields: Dictionary of fields that have a name. Note that this is
    364                   meant to be used for reading, only. One should use
    365                   L{addField} for adding fields.
     370
     371    @ivar fields: Dictionary of named fields. Note that this is meant to be
     372        used for reading, only. One should use L{addField} or L{makeFields} and
     373        L{removeField} for adding and removing fields.
    366374    @type fields: C{dict}
     375
     376    @ivar fieldList: List of all fields, in the order they are added. Like
     377        C{fields}, this is meant to be used for reading, only.
     378    @type fieldList: C{list}
    367379    """
    368380
    369381    def __init__(self, formType, title=None, instructions=None,
     
    392404        if self.formNamespace:
    393405            r.append(", formNamespace=")
    394406            r.append(repr(self.formNamespace))
    395         if self.fields:
     407        if self.fieldList:
    396408            r.append(", fields=")
    397409            r.append(repr(self.fieldList))
    398410        r.append(")")
     
    424436            form.addElement('title', content=self.title)
    425437
    426438        for instruction in self.instructions:
    427             form.addElement('instruction', content=instruction)
     439            form.addElement('instructions', content=instruction)
    428440
    429441        if self.formNamespace is not None:
    430442            field = Field('hidden', 'FORM_TYPE', self.formNamespace)
     
    477489
    478490        return form
    479491
     492
    480493    def getValues(self):
     494        """
     495        Extract values from the named form fields.
     496
     497        For all named fields, the corresponding value or values are
     498        returned in a dictionary keyed by the field name. For multi-value
     499        fields, the dictionary value is a list, otherwise a single value.
     500
     501        If a field has no type, and the field has multiple values, the value of
     502        the dictionary entry is the list of values. Otherwise, it will be a
     503        single value.
     504
     505        @rtype: C{dict}
     506        """
    481507        values = {}
    482508
    483509        for name, field in self.fields.iteritems():
    484             if len(field.values) > 1:
     510            if (field.fieldType in ('jid-multi', 'list-multi', 'text-multi') or
     511                (field.fieldType is None and len(field.values) > 1)):
    485512                value = field.values
    486513            else:
    487514                value = field.value
  • wokkel/test/test_data_form.py

    diff -r 3ef9bc7a0d70 wokkel/test/test_data_form.py
    a b  
    1919    """
    2020
    2121    def test_toElement(self):
     22        option = data_form.Option('value')
     23        element = option.toElement()
     24
     25        self.assertEqual('option', element.name)
     26        self.assertEqual(NS_X_DATA, element.uri)
     27        self.assertEqual(NS_X_DATA, element.value.uri)
     28        self.assertEqual('value', unicode(element.value))
     29        self.assertFalse(element.hasAttribute('label'))
     30
     31
     32    def test_toElementLabel(self):
    2233        option = data_form.Option('value', 'label')
    2334        element = option.toElement()
    24         self.assertEquals('option', element.name)
    25         self.assertEquals(NS_X_DATA, element.uri)
    26         self.assertEquals('label', element['label'])
    27         self.assertEquals('value', element.value.name)
    28         self.assertEquals(NS_X_DATA, element.value.uri)
    29         self.assertEquals('value', unicode(element.value))
     35
     36        self.assertEqual('option', element.name)
     37        self.assertEqual(NS_X_DATA, element.uri)
     38        self.assertEqual(NS_X_DATA, element.value.uri)
     39        self.assertEqual('value', unicode(element.value))
     40        self.assertEqual('label', element['label'])
     41
     42
     43    def test_fromElement(self):
     44        """
     45        An option has a child element with the option value.
     46        """
     47        element = domish.Element((NS_X_DATA, 'option'))
     48        element.addElement('value', content='value')
     49        option = data_form.Option.fromElement(element)
     50
     51        self.assertEqual('value', option.value)
     52        self.assertIdentical(None, option.label)
     53
     54
     55    def test_fromElementLabel(self):
     56        """
     57        An option label is an attribute on the option element.
     58        """
     59
     60        element = domish.Element((NS_X_DATA, 'option'))
     61        element.addElement('value', content='value')
     62        element['label'] = 'label'
     63        option = data_form.Option.fromElement(element)
     64
     65        self.assertEqual('label', option.label)
     66
     67
     68    def test_fromElementNoValue(self):
     69        """
     70        An option MUST have a value.
     71        """
     72        element = domish.Element((NS_X_DATA, 'option'))
     73        self.assertRaises(data_form.Error,
     74                          data_form.Option.fromElement, element)
     75
     76
     77    def test_repr(self):
     78        """
     79        The representation of an Option is equal to how it is created.
     80        """
     81        option = data_form.Option('value', 'label')
     82        self.assertEqual("""Option('value', 'label')""", repr(option))
    3083
    3184
    3285
     
    4497        self.assertEqual('test', field.var)
    4598
    4699
     100    def test_repr(self):
     101        """
     102        The repr of a field should be equal to its initialization.
     103        """
     104        field = data_form.Field('list-single', var='test', label='label',
     105                               desc='desc', required=True, value='test',
     106                               options=[data_form.Option('test')])
     107        self.assertEqual("""Field(fieldType='list-single', """
     108                         """var='test', label='label', """
     109                         """desc='desc', required=True, """
     110                         """values=['test'], """
     111                         """options=[Option('test')])""",
     112                         repr(field))
     113
     114
    47115    def test_toElement(self):
    48116        """
    49117        Test rendering to a DOM.
     
    130198
    131199
    132200    def test_toElementJID(self):
     201        """
     202        A JID value should render to text.
     203        """
    133204        field = data_form.Field(fieldType='jid-single', var='test',
    134205                                value=jid.JID(u'test@example.org'))
    135206        element = field.toElement()
    136207        self.assertEqual(u'test@example.org', unicode(element.value))
    137208
    138209
     210    def test_toElementJIDTextSingle(self):
     211        """
     212        A JID value should render to text if field type is text-single.
     213        """
     214        field = data_form.Field(fieldType='text-single', var='test',
     215                                value=jid.JID(u'test@example.org'))
     216        element = field.toElement()
     217        self.assertEqual(u'test@example.org', unicode(element.value))
     218
     219
     220    def test_toElementBoolean(self):
     221        """
     222        A boolean value should render to text.
     223        """
     224        field = data_form.Field(fieldType='boolean', var='test',
     225                                value=True)
     226        element = field.toElement()
     227        self.assertEqual(u'true', unicode(element.value))
     228
     229
     230    def test_toElementBooleanTextSingle(self):
     231        """
     232        A boolean value should render to text if the field type is text-single.
     233        """
     234        field = data_form.Field(var='test', value=True)
     235        element = field.toElement()
     236        self.assertEqual(u'true', unicode(element.value))
     237
     238
    139239    def test_typeCheckNoFieldName(self):
    140240        """
    141241        A field not of type fixed must have a var.
     
    250350        field = data_form.Field.fromElement(element)
    251351        self.assertEquals(u'user@example.org', field.value)
    252352
     353
    253354    def test_fromElementValueJIDMalformed(self):
    254355        """
    255356        Parsed jid-single field values should be of type C{unicode}.
     
    275376        self.assertEquals(u'false', field.value)
    276377
    277378
     379    def test_fromElementDesc(self):
     380        """
     381        Field descriptions are in a desc child element.
     382        """
     383        element = domish.Element((NS_X_DATA, 'field'))
     384        element.addElement('desc', content=u'My description')
     385        field = data_form.Field.fromElement(element)
     386        self.assertEqual(u'My description', field.desc)
     387
     388
     389    def test_fromElementOption(self):
     390        """
     391        Field descriptions are in a desc child element.
     392        """
     393        element = domish.Element((NS_X_DATA, 'field'))
     394        element.addElement('option').addElement('value', content=u'option1')
     395        element.addElement('option').addElement('value', content=u'option2')
     396        field = data_form.Field.fromElement(element)
     397        self.assertEqual(2, len(field.options))
     398
     399
     400    def test_fromElementRequired(self):
     401        """
     402        Required fields have a required child element.
     403        """
     404        element = domish.Element((NS_X_DATA, 'field'))
     405        element.addElement('required')
     406        field = data_form.Field.fromElement(element)
     407        self.assertTrue(field.required)
     408
     409
     410    def test_fromElementChildOtherNamespace(self):
     411        """
     412        Child elements from another namespace are ignored.
     413        """
     414        element = domish.Element((NS_X_DATA, 'field'))
     415        element['var'] = 'test'
     416        child = element.addElement(('myns', 'value'))
     417        field = data_form.Field.fromElement(element)
     418
     419        self.assertIdentical(None, field.value)
     420
     421
     422    def test_fromDict(self):
     423        """
     424        A named field with a value can be created by providing a dictionary.
     425        """
     426        fieldDict = {'var': 'test', 'value': 'text'}
     427        field = data_form.Field.fromDict(fieldDict)
     428        self.assertEqual('test', field.var)
     429        self.assertEqual('text', field.value)
     430
     431
     432    def test_fromDictFieldType(self):
     433        """
     434        The field type is set using the key 'type'.
     435        """
     436        fieldDict = {'type': 'boolean'}
     437        field = data_form.Field.fromDict(fieldDict)
     438        self.assertEqual('boolean', field.fieldType)
     439
     440
     441    def test_fromDictOptions(self):
     442        """
     443        The field options are set using the key 'options'.
     444
     445        The options are represented as a dictionary keyed by option,
     446        with the optional label as value.
     447        """
     448        fieldDict = {'options': {'value1': 'label1',
     449                                 'value2': 'label2'}}
     450        field = data_form.Field.fromDict(fieldDict)
     451        self.assertEqual(2, len(field.options))
     452        options = {}
     453        for option in field.options:
     454            options[option.value] = option.label
     455
     456        self.assertEqual(options, fieldDict['options'])
     457
    278458
    279459class FormTest(unittest.TestCase):
    280460    """
     
    289469        form = data_form.Form('result')
    290470        self.assertEqual('result', form.formType)
    291471
     472
    292473    def test_toElement(self):
    293474        """
    294475        The toElement method returns a form's DOM representation.
    295476        """
    296477        form = data_form.Form('result')
     478
    297479        element = form.toElement()
    298480
    299481        self.assertTrue(domish.IElement.providedBy(element))
     
    303485        self.assertEquals([], element.children)
    304486
    305487
     488    def test_toElementTitle(self):
     489        """
     490        A title is rendered as a child element with the title as CDATA.
     491        """
     492        form = data_form.Form('form', title='Bot configuration')
     493        element = form.toElement()
     494
     495        elements = list(element.elements())
     496        self.assertEqual(1, len(elements))
     497        title = elements[0]
     498        self.assertEqual('title', title.name)
     499        self.assertEqual(NS_X_DATA, title.uri)
     500        self.assertEqual('Bot configuration', unicode(title))
     501
     502
     503    def test_toElementInstructions(self):
     504        """
     505        Instructions are rendered as child elements with CDATA.
     506        """
     507        form = data_form.Form('form', instructions=['Fill out this form!'])
     508        element = form.toElement()
     509
     510        elements = list(element.elements())
     511        self.assertEqual(1, len(elements))
     512        instructions = elements[0]
     513        self.assertEqual('instructions', instructions.name)
     514        self.assertEqual(NS_X_DATA, instructions.uri)
     515        self.assertEqual('Fill out this form!', unicode(instructions))
     516
     517
     518    def test_toElementInstructionsMultiple(self):
     519        """
     520        Instructions render as one element per instruction, in order.
     521        """
     522        form = data_form.Form('form', instructions=['Fill out this form!',
     523                                                    'no really'])
     524        element = form.toElement()
     525
     526        elements = list(element.elements())
     527        self.assertEqual(2, len(elements))
     528        instructions1 = elements[0]
     529        instructions2 = elements[1]
     530        self.assertEqual('instructions', instructions1.name)
     531        self.assertEqual(NS_X_DATA, instructions1.uri)
     532        self.assertEqual('Fill out this form!', unicode(instructions1))
     533        self.assertEqual('instructions', instructions2.name)
     534        self.assertEqual(NS_X_DATA, instructions2.uri)
     535        self.assertEqual('no really', unicode(instructions2))
     536
     537
     538    def test_toElementFormType(self):
     539        """
     540        The form type is rendered as a hidden field with name FORM_TYPE.
     541        """
     542        form = data_form.Form('form', formNamespace='jabber:bot')
     543        element = form.toElement()
     544
     545        elements = list(element.elements())
     546        self.assertEqual(1, len(elements))
     547        formTypeField = elements[0]
     548        self.assertEqual('field', formTypeField.name)
     549        self.assertEqual(NS_X_DATA, formTypeField.uri)
     550        self.assertEqual('FORM_TYPE', formTypeField['var'])
     551        self.assertEqual('hidden', formTypeField['type'])
     552        self.assertEqual('jabber:bot', unicode(formTypeField.value))
     553
     554
     555    def test_toElementFields(self):
     556        """
     557        Fields are rendered as child elements, in order.
     558        """
     559        fields = [data_form.Field('fixed', value='Section 1'),
     560                  data_form.Field('text-single',
     561                                  var='botname',
     562                                  label='The name of your bot'),
     563                  data_form.Field('text-multi',
     564                                  var='description',
     565                                  label='Helpful description of your bot'),
     566                  data_form.Field('boolean',
     567                                  var='public',
     568                                  label='Public bot?',
     569                                  required=True)
     570                 ]
     571        form = data_form.Form('form', fields=fields)
     572        element = form.toElement()
     573
     574        elements = list(element.elements())
     575        self.assertEqual(4, len(elements))
     576        for field in elements:
     577            self.assertEqual('field', field.name)
     578            self.assertEqual(NS_X_DATA, field.uri)
     579
     580        # Check order
     581        self.assertEqual('fixed', elements[0]['type'])
     582        self.assertEqual('botname', elements[1]['var'])
     583        self.assertEqual('description', elements[2]['var'])
     584        self.assertEqual('public', elements[3]['var'])
     585
     586
    306587    def test_fromElement(self):
    307588        """
    308589        C{fromElement} creates a L{data_form.Form} from a DOM representation.
     
    348629
    349630        self.assertEquals(['instruction'], form.instructions)
    350631
     632
    351633    def test_fromElementInstructions2(self):
    352634        element = domish.Element((NS_X_DATA, 'x'))
    353635        element.addElement('instructions', content='instruction 1')
     
    377659        self.assertEquals('field1', form.fieldList[0].var)
    378660        self.assertIn('field2', form.fields)
    379661        self.assertEquals('field2', form.fieldList[1].var)
     662
     663
     664    def test_fromElementFormType(self):
     665        """
     666        The form type is a hidden field named FORM_TYPE.
     667        """
     668        element = domish.Element((NS_X_DATA, 'x'))
     669        field = element.addElement('field')
     670        field['var'] = 'FORM_TYPE'
     671        field['type'] = 'hidden'
     672        field.addElement('value', content='myns')
     673        form = data_form.Form.fromElement(element)
     674
     675        self.assertNotIn('FORM_TYPE', form.fields)
     676        self.assertEqual('myns', form.formNamespace)
     677
     678    def test_fromElementFormTypeNotHidden(self):
     679        """
     680        A non-hidden field named FORM_TYPE does not set the form type.
     681        """
     682        element = domish.Element((NS_X_DATA, 'x'))
     683        field = element.addElement('field')
     684        field['var'] = 'FORM_TYPE'
     685        field.addElement('value', content='myns')
     686        form = data_form.Form.fromElement(element)
     687
     688        self.assertIn('FORM_TYPE', form.fields)
     689        self.assertIdentical(None, form.formNamespace)
     690
     691
     692    def test_fromElementChildOtherNamespace(self):
     693        """
     694        Child elements from another namespace are ignored.
     695        """
     696        element = domish.Element((NS_X_DATA, 'x'))
     697        element['type'] = 'result'
     698        field = element.addElement(('myns', 'field'))
     699        field['var'] = 'test'
     700        form = data_form.Form.fromElement(element)
     701
     702        self.assertEqual(0, len(form.fields))
     703
     704
     705    def test_repr(self):
     706        """
     707        The repr of a form should be equal to its initialization.
     708        """
     709        form = data_form.Form('form', title='title', instructions=['instr'],
     710                                      formNamespace='myns',
     711                                      fields=[data_form.Field('fixed',
     712                                                              value='test')])
     713        self.assertEqual("""Form(formType='form', title='title', """
     714                         """instructions=['instr'], formNamespace='myns', """
     715                         """fields=[Field(fieldType='fixed', """
     716                         """values=['test'])])""",
     717                         repr(form))
     718
     719
     720    def test_addField(self):
     721        """
     722        A field should occur in fieldList.
     723        """
     724        form = data_form.Form('result')
     725        field = data_form.Field('fixed', value='Section 1')
     726        form.addField(field)
     727        self.assertEqual([field], form.fieldList)
     728
     729
     730    def test_addFieldTwice(self):
     731        """
     732        Fields occur in fieldList in the order they were added.
     733        """
     734        form = data_form.Form('result')
     735        field1 = data_form.Field('fixed', value='Section 1')
     736        field2 = data_form.Field('fixed', value='Section 2')
     737        form.addField(field1)
     738        form.addField(field2)
     739        self.assertEqual([field1, field2], form.fieldList)
     740
     741
     742    def test_addFieldNotNamed(self):
     743        """
     744        A non-named field should not occur in fields.
     745        """
     746        form = data_form.Form('result')
     747        field = data_form.Field('fixed', value='Section 1')
     748        form.addField(field)
     749        self.assertEqual({}, form.fields)
     750
     751
     752    def test_addFieldNamed(self):
     753        """
     754        A named field should occur in fields.
     755        """
     756        form = data_form.Form('result')
     757        field = data_form.Field(var='test')
     758        form.addField(field)
     759        self.assertEqual({'test': field}, form.fields)
     760
     761
     762    def test_addFieldTwiceNamed(self):
     763        """
     764        A second named field should occur in fields.
     765        """
     766        form = data_form.Form('result')
     767        field1 = data_form.Field(var='test')
     768        field2 = data_form.Field(var='test2')
     769        form.addField(field2)
     770        form.addField(field1)
     771        self.assertEqual({'test': field1, 'test2': field2}, form.fields)
     772
     773
     774    def test_addFieldSameName(self):
     775        """
     776        A named field cannot occur twice.
     777        """
     778        form = data_form.Form('result')
     779        field1 = data_form.Field(var='test', value='value')
     780        field2 = data_form.Field(var='test', value='value2')
     781        form.addField(field1)
     782        self.assertRaises(data_form.Error, form.addField, field2)
     783
     784
     785    def test_getValues(self):
     786        """
     787        Each named field is represented in the values, keyed by name.
     788        """
     789        fields = [data_form.Field(var='botname', value='The Jabber Bot'),
     790                  data_form.Field('boolean', var='public', value=True),
     791                  data_form.Field('list-multi', var='features',
     792                                                values=['news', 'search'])]
     793        form = data_form.Form('submit', fields=fields)
     794        values = form.getValues()
     795        self.assertEqual({'botname': 'The Jabber Bot',
     796                          'public': True,
     797                          'features': ['news', 'search']},
     798                         values)
     799
     800
     801    def test_getValuesOneValueTypeMulti(self):
     802        """
     803        A single value for a multi-value field type is returned in a list.
     804        """
     805        fields = [data_form.Field('list-multi', var='features',
     806                                                values=['news'])]
     807        form = data_form.Form('submit', fields=fields)
     808        values = form.getValues()
     809        self.assertEqual({'features': ['news']}, values)
     810
     811
     812    def test_getValuesMultipleValuesNoType(self):
     813        """
     814        Multiple values for a field without type are returned in a list.
     815        """
     816        fields = [data_form.Field(None, var='features',
     817                                        values=['news', 'search'])]
     818        form = data_form.Form('submit', fields=fields)
     819        values = form.getValues()
     820        self.assertEqual({'features': ['news', 'search']}, values)
     821
     822
     823    def test_getValuesMultipleValuesTypeSingle(self):
     824        """
     825        Multiple values for a single-value field type returns the first value.
     826        """
     827        fields = [data_form.Field('text-single', var='features',
     828                                        values=['news', 'search'])]
     829        form = data_form.Form('submit', fields=fields)
     830        values = form.getValues()
     831        self.assertEqual({'features': 'news'}, values)
Note: See TracBrowser for help on using the repository browser.