source: main/waeup.sirp/branches/henrik-bootstrap/src/waeup/sirp/widgets/tests/test_phonewidget.py @ 11107

Last change on this file since 11107 was 7440, checked in by uli, 13 years ago

Update tests.

  • Property svn:keywords set to Id
File size: 18.9 KB
Line 
1## $Id: test_phonewidget.py 7440 2011-12-23 10:51:04Z uli $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""
19Tests for PhoneWidget.
20
21Tests in here are an extended reformulation of the tests done in
22z3.widget as doctests for the usphone widget.
23"""
24import unittest
25from zope import schema
26# XXX: could we possibly get rid of zope.app.testing?
27from zope.app.testing.setup import placefulSetUp, placefulTearDown
28from zope.component import provideAdapter
29from zope.formlib.exception import WidgetInputErrorView
30from zope.formlib.interfaces import (
31    WidgetInputError, IInputWidget, IBrowserWidget, IWidgetInputError,
32    IWidgetInputErrorView)
33from zope.formlib.textwidgets import TextWidget
34from zope.interface import verify, Interface, implements
35from zope.publisher.browser import TestRequest
36from zope.publisher.interfaces.browser import IDefaultBrowserLayer
37from zope.schema.interfaces import ITextLine
38from waeup.sirp.widgets.phonewidget import PhoneWidget
39
40# Dummy content
41class ISampleContent(Interface):
42    foo = schema.TextLine(
43        title = u'Phone',
44        description = u'Phone number',
45        required = True)
46
47    bar = schema.TextLine(
48        title = u'Phone',
49        description = u'Phone number (not required)',
50        required = False,)
51
52    baz = schema.TextLine(
53        title = u'Phone',
54        description = u'Required phone with a default',
55        required = True,
56        default=u'234--')
57
58class SampleContent:
59    implements(ISampleContent)
60
61class PhoneWidgetTests(unittest.TestCase):
62    # Tests for phone widget
63
64    def setUp(self):
65        placefulSetUp()
66
67        # register TextLine views (so that subwidgets can be rendered)
68        provideAdapter(
69            TextWidget, (ITextLine, IDefaultBrowserLayer), IInputWidget)
70        # errors in forms
71        provideAdapter(
72            WidgetInputErrorView, (IWidgetInputError, IDefaultBrowserLayer),
73            IWidgetInputErrorView)
74
75        # setup some sample content to bind to (only neccessary for
76        # some of the tests)
77        self.content = SampleContent()
78        self.field = ISampleContent['foo']
79        self.field = self.field.bind(self.content)
80        self.field_nonreq = ISampleContent['bar']
81        self.field_nonreq = self.field_nonreq.bind(self.content)
82        self.field_w_default = ISampleContent['baz']
83        self.field_w_default = self.field_w_default.bind(self.content)
84
85        # create an empty request. We need one to create a widget
86        self.request = TestRequest()
87        self.widget = PhoneWidget(self.field, self.request)
88        self.widget_nonreq = PhoneWidget(self.field_nonreq, self.request)
89        return
90
91    def tearDown(self):
92        placefulTearDown()
93        return
94
95    def test_ifaces(self):
96        # make sure we fullfill interface contracts
97        verify.verifyClass(IBrowserWidget, PhoneWidget)
98        verify.verifyClass(IInputWidget, PhoneWidget)
99        verify.verifyObject(IBrowserWidget, self.widget)
100        verify.verifyObject(IInputWidget, self.widget)
101        return
102
103    def test_attribs_set(self):
104        # make sure the public attributes are set correctly
105        self.assertEqual(self.widget.name, 'field.foo')
106        self.assertEqual(self.widget.label, u'Phone')
107        self.assertEqual(self.widget.hint, u'Phone number')
108        self.assertEqual(self.widget.visible, True)
109        self.assertEqual(self.widget.required, True)
110        self.assertEqual(self.widget_nonreq.required, False)
111        return
112
113    def test_subwidgets_exist(self):
114        # make sure we have three sub widgets
115        sub_widget1 = self.widget.widgets['country']
116        sub_widget2 = self.widget.widgets['area']
117        sub_widget3 = self.widget.widgets['extension']
118        self.assertTrue(isinstance(sub_widget1, TextWidget))
119        self.assertTrue(isinstance(sub_widget2, TextWidget))
120        self.assertTrue(isinstance(sub_widget3, TextWidget))
121        return
122
123    def test_set_rendered_value(self):
124        # make sure we render values correctly
125        self.widget.setRenderedValue(u'123-456-1234567')
126        self.assertEqual(
127            self.widget(),
128            (u'+&nbsp;<input class="textType" id="field.foo.country"'
129             u' name="field.foo.country" size="3" type="text" value="123" '
130             u' />'
131             u'&nbsp;-\n'
132             u'<input class="textType" id="field.foo.area"'
133             u' name="field.foo.area" size="5" type="text" value="456" '
134             u' />'
135             u'&nbsp;-\n'
136             u'<input class="textType" id="field.foo.extension"'
137             u' name="field.foo.extension" size="10" type="text"'
138             u' value="1234567"  />\n'))
139        return
140
141    def test_set_prefix_default(self):
142        # prefix determines the name of widget and its subwidgets.
143        self.assertEqual(self.widget.name, 'field.foo')
144        self.assertEqual(self.widget.widgets['country'].name,
145                         'field.foo.country')
146        self.assertEqual(self.widget.widgets['area'].name,
147                         'field.foo.area')
148        self.assertEqual(self.widget.widgets['extension'].name,
149                         'field.foo.extension')
150        return
151
152    def test_set_prefix_changed(self):
153        # when we set the prefix, widget names change
154        self.widget.setPrefix('test.')
155        self.assertEqual(self.widget.name, 'test.foo')
156        self.assertEqual(self.widget.widgets['country'].name,
157                         'test.foo.country')
158        self.assertEqual(self.widget.widgets['area'].name,
159                         'test.foo.area')
160        self.assertEqual(self.widget.widgets['extension'].name,
161                         'test.foo.extension')
162        return
163
164    def test_set_prefix_changed_no_dot(self):
165        # when we try to set a name without trailing dot, one will be
166        # inserted automatically
167        self.widget.setPrefix('test')
168        self.assertEqual(self.widget.name, 'test.foo')
169        self.assertEqual(self.widget.widgets['country'].name,
170                         'test.foo.country')
171        self.assertEqual(self.widget.widgets['area'].name,
172                         'test.foo.area')
173        self.assertEqual(self.widget.widgets['extension'].name,
174                         'test.foo.extension')
175        return
176
177    def test_get_input_value(self):
178        # we get a string when we want the input value
179        request = TestRequest(
180            form={
181                'field.foo.country': '123',
182                'field.foo.area': '456',
183                'field.foo.extension': '12345'
184                })
185        widget = PhoneWidget(self.field, request)
186        value = widget.getInputValue()
187        self.assertEqual(value, '123-456-12345')
188        return
189
190    def test_get_input_value_invalid(self):
191        # we get errors when valid data is sent
192        request = TestRequest(
193            form={
194                'field.foo.country': 'not-a-number',
195                'field.foo.area': '456',
196                'field.foo.extension': '12345',
197                })
198        widget = PhoneWidget(self.field, request)
199        self.assertRaises(
200            WidgetInputError,
201            widget.getInputValue)
202        return
203
204    def test_apply_changes(self):
205        # we can apply passed-in numbers to content objects. The
206        # widget is smart enough to detect whether the values really
207        # changed.
208        class Content(object):
209            field = None
210        content = Content()
211        request = TestRequest(form={
212                'field.foo.country': '123',
213                'field.foo.area': '456',
214                'field.foo.extension': '7890'})
215        widget = PhoneWidget(self.field, request)
216        result1 = widget.applyChanges(content)
217        result2 = widget.applyChanges(content)
218        self.assertEqual(result1, True)
219        self.assertEqual(content.foo, u'123-456-7890')
220        self.assertEqual(result2, False)
221        return
222
223    def test_has_input(self):
224        # we can check whether there is input without actually validating.
225        request = TestRequest(form={
226                'field.foo.country': '123'})
227        widget = PhoneWidget(self.field, request)
228        result = widget.hasInput()
229        self.assertEqual(result, False)
230
231        request = TestRequest(form={
232                'field.foo.area': '123'})
233        widget = PhoneWidget(self.field, request)
234        result = widget.hasInput()
235        self.assertEqual(result, False)
236
237        request = TestRequest(form={
238                'field.foo.extension': '123567'})
239        widget = PhoneWidget(self.field, request)
240        result = widget.hasInput()
241        self.assertEqual(result, False)
242
243        request = TestRequest(form={
244                'field.foo.country': '123',
245                'field.foo.area': '456',
246                'field.foo.extension': '7890'})
247        widget = PhoneWidget(self.field, request)
248        result = widget.hasInput()
249        self.assertEqual(result, True)
250
251        self.assertEqual(self.widget.hasInput(), False)
252        return
253
254    def test_has_valid_input(self):
255        # we can check for input also including validation
256        request = TestRequest(form={
257                'field.foo.country': '123'})
258        widget = PhoneWidget(self.field, request)
259        result = widget.hasValidInput()
260        self.assertEqual(result, False)
261
262        request = TestRequest(form={
263                'field.foo.area': '123'})
264        widget = PhoneWidget(self.field, request)
265        result = widget.hasValidInput()
266        self.assertEqual(result, False)
267
268        request = TestRequest(form={
269                'field.foo.extension': '123567'})
270        widget = PhoneWidget(self.field, request)
271        result = widget.hasValidInput()
272        self.assertEqual(result, False)
273
274        request = TestRequest(form={
275                'field.foo.country': '123',
276                'field.foo.area': '456',
277                'field.foo.extension': '7890'})
278        widget = PhoneWidget(self.field, request)
279        result = widget.hasValidInput()
280        self.assertEqual(result, True)
281
282        self.assertEqual(self.widget.hasValidInput(), False)
283        return
284
285    def test_hidden(self):
286        # we can render output as hidden field(s)
287        self.widget.setRenderedValue(u'123-456-1234567')
288        self.assertEqual(
289            self.widget.hidden(),
290            (u'<input class="hiddenType" id="field.foo.country"'
291             u' name="field.foo.country" type="hidden" value="123" '
292             u' />'
293             u'\n'
294             u'<input class="hiddenType" id="field.foo.area"'
295             u' name="field.foo.area" type="hidden" value="456" '
296             u' />'
297             u'\n'
298             u'<input class="hiddenType" id="field.foo.extension"'
299             u' name="field.foo.extension" type="hidden"'
300             u' value="1234567"  />'))
301        return
302
303    def test_error_extension(self):
304        # the widget can handle input errors in extension subwidget
305
306        # extension field too short
307        request = TestRequest(form={
308                'field.foo.country': '123',
309                'field.foo.area': '456',
310                'field.foo.extension': '0'})
311        widget = PhoneWidget(self.field, request)
312        try:
313            widget.getInputValue()
314            self.fail('No error raised')
315        except WidgetInputError, e:
316            pass
317        self.assertEqual(
318            e.__repr__(),
319            ("WidgetInputError("
320             "'extension', u'Direct Line', ConstraintNotSatisfied(u'0'))"))
321        self.assertEqual(
322            widget.error(),
323            u'<span class="error">Constraint not satisfied</span>')
324        return
325
326
327    def test_error_area(self):
328        # the widget can handle input errors in area code subwidget
329
330        # area code contains illegal chars
331        request = TestRequest(form={
332                'field.foo.country': '123',
333                'field.foo.area': 'no-number',
334                'field.foo.extension': '12345'})
335        widget = PhoneWidget(self.field, request)
336        try:
337            widget.getInputValue()
338            self.fail('No error raised')
339        except WidgetInputError, e:
340            pass
341        self.assertEqual(
342            e.__repr__(),
343            ("WidgetInputError("
344             "'area', u'Area Code', ConstraintNotSatisfied(u'no-number'))"))
345        self.assertEqual(
346            widget.error(),
347            u'<span class="error">Constraint not satisfied</span>')
348        return
349
350    def test_error_country(self):
351        # the widget can handle input errors in country code subwidget
352
353        # invalid country code
354        request = TestRequest(form={
355                'field.foo.country': 'XXX',
356                'field.foo.area': '456',
357                'field.foo.extension': '12345'})
358        widget = PhoneWidget(self.field, request)
359        try:
360            widget.getInputValue()
361            self.fail('No error raised')
362        except WidgetInputError, e:
363            pass
364        self.assertEqual(
365            e.__repr__(),
366            ("WidgetInputError("
367             "'country', u'Country Code', ConstraintNotSatisfied(u'XXX'))"))
368        self.assertEqual(
369            widget.error(),
370            u'<span class="error">Constraint not satisfied</span>')
371        return
372
373    def test_render_wo_data(self):
374        # when no data was submitted, the content data will be displayed
375        request = TestRequest(form={})
376        self.content.foo = u'11-222-3333'
377        widget = PhoneWidget(self.field, request)
378        self.assertEqual(
379            widget(),
380            (u'+&nbsp;<input class="textType" id="field.foo.country"'
381             u' name="field.foo.country" size="3" type="text" value="11" '
382             u' />'
383             u'&nbsp;-\n'
384             u'<input class="textType" id="field.foo.area"'
385             u' name="field.foo.area" size="5" type="text" value="222" '
386             u' />'
387             u'&nbsp;-\n'
388             u'<input class="textType" id="field.foo.extension"'
389             u' name="field.foo.extension" size="10" type="text"'
390             u' value="3333"  />\n'))
391        return
392
393    def test_render_with_data(self):
394        # when data was in the request, it will override any content value
395        request = TestRequest(form={
396                'field.foo.country': '11',
397                'field.foo.area': '222',
398                'field.foo.extension': '3333'})
399        self.content.foo = u'22-333-4444'
400        widget = PhoneWidget(self.field, request)
401        self.assertEqual(
402            widget(),
403            (u'+&nbsp;<input class="textType" id="field.foo.country"'
404             u' name="field.foo.country" size="3" type="text" value="11" '
405             u' />'
406             u'&nbsp;-\n'
407             u'<input class="textType" id="field.foo.area"'
408             u' name="field.foo.area" size="5" type="text" value="222" '
409             u' />'
410             u'&nbsp;-\n'
411             u'<input class="textType" id="field.foo.extension"'
412             u' name="field.foo.extension" size="10" type="text"'
413             u' value="3333"  />\n'))
414        return
415
416    def test_render_changed_prefix(self):
417        # when the prefix is changed, the subwidgets will reflect that
418        # properly. This tests a regression: if setPrefix was called
419        # on the phone widget, the subwidgets were already assuming
420        # that there is no data in the request
421        request = TestRequest(form={
422                'field.foo.country': '11',
423                'field.foo.area': '222',
424                'field.foo.extension': '3333'})
425        self.content.foo = u'22-333-4444'
426        widget = PhoneWidget(self.field, request)
427        # when setting a wrong prefix (not in the form), subwidgets
428        # will display the content values assuming (correctly) there
429        # is no data sent for them in the request.
430        widget.setPrefix('not-existent.')
431        self.assertTrue('value="4444"' in widget())
432        # when setting the right prefix, subwidgets will display the
433        # sent form values and not the content values.
434        widget.setPrefix('field.')
435        self.assertTrue('value="3333"' in widget())
436        return
437
438    def test_render_changed_prefix(self):
439        # when the prefix is changed, the subwidgets will reflect that
440        # properly. This tests a regression: if setPrefix was called
441        # on the phone widget, the subwidgets were already assuming
442        # that there is no data in the request
443        request = TestRequest(form={
444                'field.foo.country': '11',
445                'field.foo.area': '222',
446                'field.foo.extension': '3333'})
447        self.content.foo = u'22-333-4444'
448        widget = PhoneWidget(self.field, request)
449        # when setting a wrong prefix (not in the form), subwidgets
450        # will display the content values assuming (correctly) there
451        # is no data sent for them in the request.
452        widget.setPrefix('not-existent.')
453        self.assertTrue('value="4444"' in widget())
454        # when setting the right prefix, subwidgets will display the
455        # sent form values and not the content values.
456        widget.setPrefix('field.')
457        self.assertTrue('value="3333"' in widget())
458        return
459
460    def test_non_required_no_input(self):
461        # if the bound field requires no input phone widget will cope
462        # with that.
463        class Content(object):
464            field = None
465
466        content = Content()
467        request = TestRequest(form={
468                'field.bar.country': '',
469                'field.bar.area': '',
470                'field.bar.extension': '',
471                })
472        widget = PhoneWidget(self.field_nonreq, request)
473        result1 = widget.applyChanges(content)
474        result2 = widget.getInputValue()
475        self.assertEqual(result1, True)
476        # without input we get None
477        self.assertTrue(content.bar is None)
478        self.assertTrue(result2 is None)
479        return
480
481    def test_set_rendered_with_empty_context_value(self):
482        # if we set empty string as rendered value, empty fields are
483        # displayed.
484        self.widget.setRenderedValue(u'')
485        self.assertEqual(
486            self.widget(),
487            (u'+&nbsp;<input class="textType" id="field.foo.country"'
488             u' name="field.foo.country" size="3" type="text" value="" '
489             u' />'
490             u'&nbsp;-\n'
491             u'<input class="textType" id="field.foo.area"'
492             u' name="field.foo.area" size="5" type="text" value="" '
493             u' />'
494             u'&nbsp;-\n'
495             u'<input class="textType" id="field.foo.extension"'
496             u' name="field.foo.extension" size="10" type="text"'
497             u' value=""  />\n'))
498        return
Note: See TracBrowser for help on using the repository browser.