source: main/waeup.sirp/trunk/src/waeup/sirp/utils/tests/test_converters.py @ 6279

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

Check whether the preferred date format ('YYYY-MM-DD') is accepted by
converters.

File size: 12.0 KB
Line 
1##
2## test_converters.py
3## Login : <uli@pu.smp.net>
4## Started on  Tue May 31 08:34:44 2011 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2011 Uli Fouquet
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""
23Tests for converterts.
24"""
25import datetime
26import os
27import shutil
28import tempfile
29import unittest
30from zope import schema
31from zope.app.testing.functional import FunctionalTestCase
32from zope.component import provideUtility
33from zope.component.factory import Factory
34from zope.component.hooks import setSite, clearSite
35from zope.component.interfaces import IFactory
36from zope.formlib import form
37from zope.interface import (
38    Interface, implements, invariant, Invalid, implementedBy)
39from zope.interface.verify import verifyClass, verifyObject
40
41from waeup.sirp.app import University
42from waeup.sirp.testing import FunctionalLayer, doctestsuite_for_module
43from waeup.sirp.utils.converters import IObjectConverter
44from waeup.sirp.utils.helpers import attrs_to_fields
45from waeup.sirp.interfaces import SimpleWAeUPVocabulary
46
47colors = SimpleWAeUPVocabulary(
48    ('Red', u'red'),
49    ('Green', u'green'),
50    ('Blue', u'blue'),
51    )
52car_nums = SimpleWAeUPVocabulary(
53    ('None', 0),
54    ('One', 1),
55    ('Two', 2),
56    ('Three', 3),
57    )
58class IContact(Interface):
59    """Sample interface for sample content type used here in tests.
60    """
61    name = schema.TextLine(
62        title = u'Name',
63        default = u'Manfred',
64        readonly = True,
65        )
66    age = schema.Int(
67        title = u'Age',
68        default = 23,
69        required = True,
70        )
71    city = schema.TextLine(
72        title = u'City',
73        required = True,
74        )
75    vip = schema.Bool(
76        title = u'Celebrity',
77        default = False,
78        required = True,
79        )
80    birthday = schema.Date(
81        title = u'Birthday',
82        default = None,
83        )
84    fav_color = schema.Choice(
85        title = u'Favourite color',
86        default = u'red',
87        vocabulary = colors,
88        )
89    num_cars = schema.Choice(
90        title = u'Number of cars owned',
91        default = None,
92        vocabulary = car_nums,
93        )
94    @invariant
95    def kevinIsYoung(contact):
96        if contact.age > 16 and contact.name == 'Kevin':
97            raise Invalid('Kevins are age 16 or below.')
98
99class Contact(object):
100    """Sample content type.
101    """
102    implements(IContact)
103Contact = attrs_to_fields(Contact)
104
105form_fields_select = form.Fields(IContact).select('name', 'vip')
106form_fields_omit = form.Fields(IContact).omit('name', 'vip')
107
108class ContactFactory(object):
109    """A factory for faculty containers.
110    """
111    implements(IContact)
112
113    def __call__(self, *args, **kw):
114        return Faculty()
115
116    def getInterfaces(self):
117        return implementedBy(Faculty)
118
119class ConverterTests(FunctionalTestCase):
120
121    layer = FunctionalLayer
122
123    def setUp(self):
124        super(ConverterTests, self).setUp()
125
126        # Setup a sample site for each test
127        app = University()
128        self.dc_root = tempfile.mkdtemp()
129        app['datacenter'].setStoragePath(self.dc_root)
130
131        # Prepopulate the ZODB...
132        self.getRootFolder()['app'] = app
133        self.app = self.getRootFolder()['app']
134
135        self.workdir = tempfile.mkdtemp()
136
137        # Create a factory for contacts and register it as global utility
138        factory = Factory(Contact)
139        provideUtility(factory, IFactory, 'contact')
140        return
141
142    def tearDown(self):
143        super(ConverterTests, self).tearDown()
144        shutil.rmtree(self.workdir)
145        shutil.rmtree(self.dc_root)
146        clearSite()
147        return
148
149    def test_valid_data(self):
150        contact = Contact()
151        contact.age = 33
152        input_data = dict(name='Rudi', age='99')
153        converter = IObjectConverter(IContact) # a converter to IContact
154        err, inv_err, data = converter.fromStringDict(
155            input_data, contact)
156        assert data['name'] == 'Rudi'
157        assert data['age'] == 99
158        return
159
160    def test_bool(self):
161        contact1 = Contact()
162        contact2 = Contact()
163        input_data1 = dict(vip='on')
164        input_data2 = dict(vip='')
165        converter = IObjectConverter(IContact) # a converter to IContact
166        err1, inv_err1, data1 = converter.fromStringDict(
167            input_data1, contact1)
168        err2, inv_err2, data2 = converter.fromStringDict(
169            input_data2, contact2)
170        assert data1['vip'] is True
171        assert data2['vip'] is False
172
173    def test_bool_nonstandard_values1(self):
174        # We accept 'true', 'True', 'tRuE', 'faLSE' and similar.
175        contact1 = Contact()
176        contact2 = Contact()
177        input_data1 = dict(vip='True')
178        input_data2 = dict(vip='false')
179        converter = IObjectConverter(IContact) # a converter to IContact
180        err1, inv_err1, data1 = converter.fromStringDict(
181            input_data1, contact1)
182        err2, inv_err2, data2 = converter.fromStringDict(
183            input_data2, contact2)
184        assert data1['vip'] is True
185        assert data2['vip'] is False
186
187    def test_bool_nonstandard_values2(self):
188        # We accept '1' and '0' as bool values.
189        contact1 = Contact()
190        contact2 = Contact()
191        input_data1 = dict(vip='1')
192        input_data2 = dict(vip='0')
193        converter = IObjectConverter(IContact) # a converter to IContact
194        err1, inv_err1, data1 = converter.fromStringDict(
195            input_data1, contact1)
196        err2, inv_err2, data2 = converter.fromStringDict(
197            input_data2, contact2)
198        assert data1['vip'] is True
199        assert data2['vip'] is False
200
201    def test_bool_nonstandard_values3(self):
202        # We accept 'yEs', 'no' and similar as bool values.
203        contact1 = Contact()
204        contact2 = Contact()
205        input_data1 = dict(vip='Yes')
206        input_data2 = dict(vip='no')
207        converter = IObjectConverter(IContact) # a converter to IContact
208        err1, inv_err1, data1 = converter.fromStringDict(
209            input_data1, contact1)
210        err2, inv_err2, data2 = converter.fromStringDict(
211            input_data2, contact2)
212        assert data1['vip'] is True
213        assert data2['vip'] is False
214
215    def test_int(self):
216        contact = Contact()
217        input_data = dict(age='99')
218        converter = IObjectConverter(IContact) # a converter to IContact
219        err, inv_err, data = converter.fromStringDict(
220            input_data, contact)
221        assert data['age'] == 99
222        return
223
224    def test_int_invalid(self):
225        contact = Contact()
226        input_data = dict(age='sweet sixteen')
227        converter = IObjectConverter(IContact) # a converter to IContact
228        err, inv_err, new_contact = converter.fromStringDict(
229            input_data, contact)
230        self.assertEqual(err, [('age', u'Invalid integer data')])
231        return
232
233    def test_textline(self):
234        contact = Contact()
235        input_data = dict(name='Rudi')
236        converter = IObjectConverter(IContact) # a converter to IContact
237        err, inv_err, data = converter.fromStringDict(
238            input_data, contact)
239        self.assertEqual(data['name'], u'Rudi')
240        assert isinstance(data['name'], unicode)
241        return
242
243    def test_invariant(self):
244        contact = Contact()
245        input_data = dict(name='Kevin', age='22')
246        converter = IObjectConverter(IContact) # a converter to IContact
247        err, inv_err, new_contact = converter.fromStringDict(
248            input_data, contact)
249        self.assertEqual(inv_err, ['Kevins are age 16 or below.'])
250        return
251
252    def test_date(self):
253        contact = Contact()
254        converter = IObjectConverter(IContact) # a converter to IContact
255        err, inv_err, data = converter.fromStringDict(
256            dict(birthday='1945/12/23'), contact)
257        assert data['birthday'] == datetime.date(1945, 12, 23)
258        assert isinstance(data['birthday'], datetime.date)
259
260        err, inv_err, data = converter.fromStringDict(
261            dict(birthday='1945/23/12'), contact)
262        assert data['birthday'] == datetime.date(1945, 12, 23)
263
264        # The preferred input format for dates: YYYY-MM-DD
265        err, inv_err, data = converter.fromStringDict(
266            dict(birthday='1945-12-23'), contact)
267        assert data['birthday'] == datetime.date(1945, 12, 23)
268
269        # '08' is not interpreted as octal number
270        err, inv_err, data = converter.fromStringDict(
271            dict(birthday='1945-12-08'), contact)
272        assert data['birthday'] == datetime.date(1945, 12, 8)
273        return
274
275    def test_date_invalid(self):
276        contact = Contact()
277        converter = IObjectConverter(IContact) # a converter to IContact
278        err, inv_err, data = converter.fromStringDict(
279            dict(birthday='not-a-date'), contact)
280        self.assertEqual(err, [('birthday', u'Invalid datetime data')])
281
282    def test_inject_formfields_select(self):
283        # We can use our own formfields and select only a subset of fields
284        contact = Contact()
285        converter = IObjectConverter(IContact) # a converter to IContact
286        input_data = dict(name='Bruno', age='99', vip='on')
287        err, inv_err, data = converter.fromStringDict(
288            input_data, contact, form_fields=form_fields_select)
289        self.assertEqual(data['name'], 'Bruno')
290        assert 'age' not in data.keys()
291        assert data['vip'] is True
292        return
293
294    def test_inject_formfields_omit(self):
295        # We can use our own formfields and omit some fields
296        contact = Contact()
297        converter = IObjectConverter(IContact) # a converter to IContact
298        input_data = dict(name='Bruno', age='99', vip='on')
299        err, inv_err, data = converter.fromStringDict(
300            input_data, contact, form_fields=form_fields_omit)
301        self.assertEqual(data['age'], 99)
302        assert 'name' not in data.keys()
303        assert 'vip' not in data.keys()
304        return
305
306    def test_factory(self):
307        # We can use factories to convert values
308        converter = IObjectConverter(IContact) # a converter to IContact
309        # pass string ``contact`` instead of a real object
310        err, inv_err, data = converter.fromStringDict(
311            dict(name='Gabi', age='23'), 'contact')
312        self.assertEqual(data['age'], 23)
313        self.assertEqual(data['name'], u'Gabi')
314        return
315
316    def test_choice_vocab(self):
317        # We can handle vocabularies
318        converter = IObjectConverter(IContact) # a converter to IContact
319        err, inv_err, data = converter.fromStringDict(
320            dict(fav_color='blue'), 'contact')
321        assert data['fav_color'] == u'blue'
322        assert isinstance(data['fav_color'], unicode)
323        return
324
325    def test_choice_vocab_invalid_value(self):
326        # We can handle vocabularies
327        converter = IObjectConverter(IContact) # a converter to IContact
328        err, inv_err, data = converter.fromStringDict(
329            dict(fav_color='magenta'), 'contact')
330        self.assertEqual(err, [('fav_color', u'Invalid value')])
331        assert 'fav_color' not in data.keys()
332        return
333
334    def test_non_string_choice(self):
335        # We can handle vocabs with non-string values
336        converter = IObjectConverter(IContact) # a converter to IContact
337        err, inv_err, data = converter.fromStringDict(
338            dict(num_cars='1'), 'contact')
339        assert data['num_cars'] == 1
340        return
341
342
343def test_suite():
344    suite = unittest.TestSuite()
345    for testcase in [
346        ConverterTests,
347        ]:
348        suite.addTest(unittest.TestLoader().loadTestsFromTestCase(
349                testcase
350                )
351        )
352    return suite
353
Note: See TracBrowser for help on using the repository browser.