[22] | 1 | diff -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] | 112 | diff -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) |
---|