source: main/waeup.sirp/trunk/src/waeup/sirp/widgets/tests/test_phonewidget.py @ 7439

Last change on this file since 7439 was 7435, checked in by Henrik Bettermann, 13 years ago

Adapt tests to changes made in phonewidget.pt.

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