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

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

Finally make the new converter work. API-wise it is as good as the old one (can import everyting, the old one could),
but design-wise it might be much more powerfull. Basically it can handle/convert all content-types for which one can
create an Add- or EditForm? successfully. In other words: if you manage to write an edit form for some content type,
then you can also create an importer for that content-type. Still finetuning needed (for dates, bool data, etc.) but
the main things work.

File size: 10.4 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_int(self):
174        contact = Contact()
175        input_data = dict(age='99')
176        converter = IObjectConverter(IContact) # a converter to IContact
177        err, inv_err, data = converter.fromStringDict(
178            input_data, contact)
179        assert data['age'] == 99
180        return
181
182    def test_int_invalid(self):
183        contact = Contact()
184        input_data = dict(age='sweet sixteen')
185        converter = IObjectConverter(IContact) # a converter to IContact
186        err, inv_err, new_contact = converter.fromStringDict(
187            input_data, contact)
188        self.assertEqual(err, [('age', u'Invalid integer data')])
189        return
190
191    def test_textline(self):
192        contact = Contact()
193        input_data = dict(name='Rudi')
194        converter = IObjectConverter(IContact) # a converter to IContact
195        err, inv_err, data = converter.fromStringDict(
196            input_data, contact)
197        self.assertEqual(data['name'], u'Rudi')
198        assert isinstance(data['name'], unicode)
199        return
200
201    def test_invariant(self):
202        contact = Contact()
203        input_data = dict(name='Kevin', age='22')
204        converter = IObjectConverter(IContact) # a converter to IContact
205        err, inv_err, new_contact = converter.fromStringDict(
206            input_data, contact)
207        self.assertEqual(inv_err, ['Kevins are age 16 or below.'])
208        return
209
210    def test_date(self):
211        contact = Contact()
212        converter = IObjectConverter(IContact) # a converter to IContact
213        err, inv_err, data = converter.fromStringDict(
214            dict(birthday='1945/12/23'), contact)
215        assert data['birthday'] == datetime.date(1945, 12, 23)
216        assert isinstance(data['birthday'], datetime.date)
217
218        err, inv_err, data = converter.fromStringDict(
219            dict(birthday='1945/23/12'), contact)
220        assert data['birthday'] == datetime.date(1945, 12, 23)
221
222        #err, inv_err, data = converter.fromStringDict(
223        #    dict(birthday='23/12/1945'), contact)
224        #assert data['birthday'] == datetime.date(1945, 12, 23)
225
226        #err, inv_err, data = converter.fromStringDict(
227        #    dict(birthday='23.12.1945'), contact)
228        #assert data['birthday'] == datetime.date(1945, 12, 23)
229
230        #err, inv_err, data = converter.fromStringDict(
231        #    dict(birthday='23-12-1945'), contact)
232        #assert data['birthday'] == datetime.date(1945, 12, 23)
233        return
234
235    def test_date_invalid(self):
236        contact = Contact()
237        converter = IObjectConverter(IContact) # a converter to IContact
238        err, inv_err, data = converter.fromStringDict(
239            dict(birthday='not-a-date'), contact)
240        self.assertEqual(err, [('birthday', u'Invalid datetime data')])
241
242    def test_inject_formfields_select(self):
243        # We can use our own formfields and select only a subset of fields
244        contact = Contact()
245        converter = IObjectConverter(IContact) # a converter to IContact
246        input_data = dict(name='Bruno', age='99', vip='on')
247        err, inv_err, data = converter.fromStringDict(
248            input_data, contact, form_fields=form_fields_select)
249        self.assertEqual(data['name'], 'Bruno')
250        assert 'age' not in data.keys()
251        assert data['vip'] is True
252        return
253
254    def test_inject_formfields_omit(self):
255        # We can use our own formfields and omit some fields
256        contact = Contact()
257        converter = IObjectConverter(IContact) # a converter to IContact
258        input_data = dict(name='Bruno', age='99', vip='on')
259        err, inv_err, data = converter.fromStringDict(
260            input_data, contact, form_fields=form_fields_omit)
261        self.assertEqual(data['age'], 99)
262        assert 'name' not in data.keys()
263        assert 'vip' not in data.keys()
264        return
265
266    def test_factory(self):
267        # We can use factories to convert values
268        converter = IObjectConverter(IContact) # a converter to IContact
269        # pass string ``contact`` instead of a real object
270        err, inv_err, data = converter.fromStringDict(
271            dict(name='Gabi', age='23'), 'contact')
272        self.assertEqual(data['age'], 23)
273        self.assertEqual(data['name'], u'Gabi')
274        return
275
276    def test_choice_vocab(self):
277        # We can handle vocabularies
278        converter = IObjectConverter(IContact) # a converter to IContact
279        err, inv_err, data = converter.fromStringDict(
280            dict(fav_color='blue'), 'contact')
281        assert data['fav_color'] == u'blue'
282        assert isinstance(data['fav_color'], unicode)
283        return
284
285    def test_choice_vocab_invalid_value(self):
286        # We can handle vocabularies
287        converter = IObjectConverter(IContact) # a converter to IContact
288        err, inv_err, data = converter.fromStringDict(
289            dict(fav_color='magenta'), 'contact')
290        self.assertEqual(err, [('fav_color', u'Invalid value')])
291        assert 'fav_color' not in data.keys()
292        return
293
294    def test_non_string_choice(self):
295        # We can handle vocabs with non-string values
296        converter = IObjectConverter(IContact) # a converter to IContact
297        err, inv_err, data = converter.fromStringDict(
298            dict(num_cars='1'), 'contact')
299        assert data['num_cars'] == 1
300        return
301
302
303def test_suite():
304    suite = unittest.TestSuite()
305    for testcase in [
306        ConverterTests,
307        ]:
308        suite.addTest(unittest.TestLoader().loadTestsFromTestCase(
309                testcase
310                )
311        )
312    return suite
313
Note: See TracBrowser for help on using the repository browser.