move tests
[odoo/odoo.git] / openerp / addons / test_converter / tests / test_html.py
1 # -*- encoding: utf-8 -*-
2 import json
3 import os
4 import xml.dom.minidom
5 import datetime
6
7 from werkzeug.utils import escape as e
8
9 from openerp.tests import common
10 from openerp.addons.base.ir import ir_qweb
11
12 directory = os.path.dirname(__file__)
13
14 impl = xml.dom.minidom.getDOMImplementation()
15 doc = impl.createDocument(None, None, None)
16
17 class TestExport(common.TransactionCase):
18     _model = None
19
20     def setUp(self):
21         super(TestExport, self).setUp()
22         self.Model = self.registry(self._model)
23         self.columns = self.Model._all_columns
24
25     def get_column(self, name):
26         return self.Model._all_columns[name].column
27
28     def get_converter(self, name, type=None):
29         column = self.get_column(name)
30
31         for postfix in type, column._type, '':
32             fs = ['ir', 'qweb', 'field']
33             if postfix is None: continue
34             if postfix: fs.append(postfix)
35
36             try:
37                 model = self.registry('.'.join(fs))
38                 break
39             except KeyError: pass
40
41         return lambda value, options=None, context=None: e(model.value_to_html(
42             self.cr, self.uid, value, column, options=options, context=context))
43
44 class TestBasicExport(TestExport):
45     _model = 'test_converter.test_model'
46
47 class TestCharExport(TestBasicExport):
48     def test_char(self):
49         converter = self.get_converter('char')
50
51         value = converter('foo')
52         self.assertEqual(value, 'foo')
53
54         value = converter("foo<bar>")
55         self.assertEqual(value, "foo&lt;bar&gt;")
56
57 class TestIntegerExport(TestBasicExport):
58     def test_integer(self):
59         converter = self.get_converter('integer')
60
61         value = converter(42)
62         self.assertEqual(value, "42")
63
64 class TestFloatExport(TestBasicExport):
65     def setUp(self):
66         super(TestFloatExport, self).setUp()
67         self.registry('res.lang').write(self.cr, self.uid, [1], {
68             'grouping': '[3,0]'
69         })
70
71     def test_float(self):
72         converter = self.get_converter('float')
73
74         value = converter(42.0)
75         self.assertEqual(value, "42.0")
76
77         value = converter(42.0100)
78         self.assertEqual(value, "42.01")
79
80         value = converter(42.01234)
81         self.assertEqual(value, "42.01234")
82
83         value = converter(1234567.89)
84         self.assertEqual(value, '1,234,567.89')
85
86     def test_numeric(self):
87         converter = self.get_converter('numeric')
88
89         value = converter(42.0)
90         self.assertEqual(value, '42.00')
91
92         value = converter(42.01234)
93         self.assertEqual(value, '42.01')
94
95 class TestCurrencyExport(TestExport):
96     _model = 'test_converter.monetary'
97
98     def setUp(self):
99         super(TestCurrencyExport, self).setUp()
100         self.Currency = self.registry('res.currency')
101         self.base = self.create(self.Currency, name="Source", symbol=u'source')
102
103     def create(self, model, context=None, **values):
104         return model.browse(
105             self.cr, self.uid,
106             model.create(self.cr, self.uid, values, context=context),
107             context=context)
108
109     def convert(self, obj, dest):
110         converter = self.registry('ir.qweb.field.monetary')
111         options = {
112             'widget': 'monetary',
113             'display_currency': 'c2'
114         }
115         converted = converter.to_html(
116             self.cr, self.uid, 'value', obj, options,
117             doc.createElement('span'),
118             {'field': 'obj.value', 'field-options': json.dumps(options)},
119             '', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }))
120         return converted
121
122     def test_currency_post(self):
123         currency = self.create(self.Currency, name="Test", symbol=u"test")
124         obj = self.create(self.Model, value=0.12)
125
126         converted = self.convert(obj, dest=currency)
127
128         self.assertEqual(
129             converted,
130             '<span data-oe-model="{obj._model._name}" data-oe-id="{obj.id}" '
131                   'data-oe-field="value" data-oe-type="monetary" '
132                   'data-oe-expression="obj.value">'
133                       '<span class="oe_currency_value">0.12</span>'
134                       ' {symbol}</span>'.format(
135                 obj=obj,
136                 symbol=currency.symbol.encode('utf-8')
137             ),)
138
139     def test_currency_pre(self):
140         currency = self.create(
141             self.Currency, name="Test", symbol=u"test", position='before')
142         obj = self.create(self.Model, value=0.12)
143
144         converted = self.convert(obj, dest=currency)
145
146         self.assertEqual(
147             converted,
148             '<span data-oe-model="{obj._model._name}" data-oe-id="{obj.id}" '
149                   'data-oe-field="value" data-oe-type="monetary" '
150                   'data-oe-expression="obj.value">'
151                       '{symbol} '
152                       '<span class="oe_currency_value">0.12</span>'
153                       '</span>'.format(
154                 obj=obj,
155                 symbol=currency.symbol.encode('utf-8')
156             ),)
157
158     def test_currency_precision(self):
159         """ Precision should be the currency's, not the float field's
160         """
161         currency = self.create(self.Currency, name="Test", symbol=u"test",)
162         obj = self.create(self.Model, value=0.1234567)
163
164         converted = self.convert(obj, dest=currency)
165
166         self.assertEqual(
167             converted,
168             '<span data-oe-model="{obj._model._name}" data-oe-id="{obj.id}" '
169                   'data-oe-field="value" data-oe-type="monetary" '
170                   'data-oe-expression="obj.value">'
171                       '<span class="oe_currency_value">0.12</span>'
172                       ' {symbol}</span>'.format(
173                 obj=obj,
174                 symbol=currency.symbol.encode('utf-8')
175             ),)
176
177 class TestTextExport(TestBasicExport):
178     def test_text(self):
179         converter = self.get_converter('text')
180
181         value = converter("This is my text-kai")
182         self.assertEqual(value, "This is my text-kai")
183
184         value = converter("""
185             .  The current line (address) in the buffer.
186             $  The last line in the buffer.
187             n  The nth, line in the buffer where n is a number in the range [0,$].
188             $  The last line in the buffer.
189             -  The previous line. This is equivalent to -1 and may be repeated with cumulative effect.
190             -n The nth previous line, where n is a non-negative number.
191             +  The next line. This is equivalent to +1 and may be repeated with cumulative effect.
192         """)
193         self.assertEqual(value, """<br>
194             .  The current line (address) in the buffer.<br>
195             $  The last line in the buffer.<br>
196             n  The nth, line in the buffer where n is a number in the range [0,$].<br>
197             $  The last line in the buffer.<br>
198             -  The previous line. This is equivalent to -1 and may be repeated with cumulative effect.<br>
199             -n The nth previous line, where n is a non-negative number.<br>
200             +  The next line. This is equivalent to +1 and may be repeated with cumulative effect.<br>
201         """)
202
203         value = converter("""
204         fgdkls;hjas;lj <b>fdslkj</b> d;lasjfa lkdja <a href=http://spam.com>lfks</a>
205         fldkjsfhs <i style="color: red"><a href="http://spamspam.com">fldskjh</a></i>
206         """)
207         self.assertEqual(value, """<br>
208         fgdkls;hjas;lj &lt;b&gt;fdslkj&lt;/b&gt; d;lasjfa lkdja &lt;a href=http://spam.com&gt;lfks&lt;/a&gt;<br>
209         fldkjsfhs &lt;i style=&quot;color: red&quot;&gt;&lt;a href=&quot;http://spamspam.com&quot;&gt;fldskjh&lt;/a&gt;&lt;/i&gt;<br>
210         """)
211
212 class TestMany2OneExport(TestBasicExport):
213     def test_many2one(self):
214         Sub = self.registry('test_converter.test_model.sub')
215
216
217         id0 = self.Model.create(self.cr, self.uid, {
218             'many2one': Sub.create(self.cr, self.uid, {'name': "Foo"})
219         })
220         id1 = self.Model.create(self.cr, self.uid, {
221             'many2one': Sub.create(self.cr, self.uid, {'name': "Fo<b>o</b>"})
222         })
223
224         def converter(record):
225             column = self.get_column('many2one')
226             model = self.registry('ir.qweb.field.many2one')
227
228             return e(model.record_to_html(
229                 self.cr, self.uid, 'many2one', record, column))
230
231         value = converter(self.Model.browse(self.cr, self.uid, id0))
232         self.assertEqual(value, "Foo")
233
234         value = converter(self.Model.browse(self.cr, self.uid, id1))
235         self.assertEqual(value, "Fo&lt;b&gt;o&lt;/b&gt;")
236
237 class TestBinaryExport(TestBasicExport):
238     def test_image(self):
239         column = self.get_column('binary')
240         converter = self.registry('ir.qweb.field.image')
241
242         with open(os.path.join(directory, 'test_vectors', 'image'), 'rb') as f:
243             content = f.read()
244
245         encoded_content = content.encode('base64')
246         value = e(converter.value_to_html(
247             self.cr, self.uid, encoded_content, column))
248         self.assertEqual(
249             value, '<img src="data:image/jpeg;base64,%s">' % (
250                 encoded_content
251             ))
252
253         with open(os.path.join(directory, 'test_vectors', 'pdf'), 'rb') as f:
254             content = f.read()
255
256         with self.assertRaises(ValueError):
257             e(converter.value_to_html(
258                 self.cr, self.uid, 'binary', content.encode('base64'), column))
259
260         with open(os.path.join(directory, 'test_vectors', 'pptx'), 'rb') as f:
261             content = f.read()
262
263         with self.assertRaises(ValueError):
264             e(converter.value_to_html(
265                 self.cr, self.uid, 'binary', content.encode('base64'), column))
266
267 class TestSelectionExport(TestBasicExport):
268     def test_selection(self):
269         [record] = self.Model.browse(self.cr, self.uid, [self.Model.create(self.cr, self.uid, {
270             'selection': 2,
271             'selection_str': 'C',
272         })])
273
274         column_name = 'selection'
275         column = self.get_column(column_name)
276         converter = self.registry('ir.qweb.field.selection')
277
278         value = converter.record_to_html(
279             self.cr, self.uid, column_name, record, column)
280         self.assertEqual(value, "rĂ©ponse B")
281
282         column_name = 'selection_str'
283         column = self.get_column(column_name)
284         value = converter.record_to_html(
285             self.cr, self.uid, column_name, record, column)
286         self.assertEqual(value, "Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?")
287
288 class TestHTMLExport(TestBasicExport):
289     def test_html(self):
290         converter = self.get_converter('html')
291
292         input = '<span>span</span>'
293         value = converter(input)
294         self.assertEqual(value, input)
295
296 class TestDatetimeExport(TestBasicExport):
297     def setUp(self):
298         super(TestDatetimeExport, self).setUp()
299         # set user tz to known value
300         Users = self.registry('res.users')
301         Users.write(self.cr, self.uid, self.uid, {
302             'tz': 'Pacific/Niue'
303         }, context=None)
304
305     def test_date(self):
306         converter = self.get_converter('date')
307
308         value = converter('2011-05-03')
309
310         # default lang/format is US
311         self.assertEqual(value, '05/03/2011')
312
313     def test_datetime(self):
314         converter = self.get_converter('datetime')
315
316         value = converter('2011-05-03 11:12:13')
317
318         # default lang/format is US
319         self.assertEqual(value, '05/03/2011 00:12:13')
320
321     def test_custom_format(self):
322         converter = self.get_converter('datetime')
323         converter2 = self.get_converter('date')
324         opts = {'format': 'MMMM d'}
325
326         value = converter('2011-03-02 11:12:13', options=opts)
327         value2 = converter2('2001-03-02', options=opts)
328         self.assertEqual(
329             value,
330             'March 2'
331         )
332         self.assertEqual(
333             value2,
334             'March 2'
335         )
336
337 class TestDurationExport(TestBasicExport):
338     def setUp(self):
339         super(TestDurationExport, self).setUp()
340         # needs to have lang installed otherwise falls back on en_US
341         self.registry('res.lang').load_lang(self.cr, self.uid, 'fr_FR')
342
343     def test_negative(self):
344         converter = self.get_converter('float', 'duration')
345
346         with self.assertRaises(ValueError):
347             converter(-4)
348
349     def test_missing_unit(self):
350         converter = self.get_converter('float', 'duration')
351
352         with self.assertRaises(ValueError):
353             converter(4)
354
355     def test_basic(self):
356         converter = self.get_converter('float', 'duration')
357
358         result = converter(4, {'unit': 'hour'}, {'lang': 'fr_FR'})
359         self.assertEqual(result, u'4 heures')
360
361         result = converter(50, {'unit': 'second'}, {'lang': 'fr_FR'})
362         self.assertEqual(result, u'50 secondes')
363
364     def test_multiple(self):
365         converter = self.get_converter('float', 'duration')
366
367         result = converter(1.5, {'unit': 'hour'}, {'lang': 'fr_FR'})
368         self.assertEqual(result, u"1 heure 30 minutes")
369
370         result = converter(72, {'unit': 'second'}, {'lang': 'fr_FR'})
371         self.assertEqual(result, u"1 minute 12 secondes")
372
373 class TestRelativeDatetime(TestBasicExport):
374     # not sure how a test based on "current time" should be tested. Even less
375     # so as it would mostly be a test of babel...
376
377     def setUp(self):
378         super(TestRelativeDatetime, self).setUp()
379         # needs to have lang installed otherwise falls back on en_US
380         self.registry('res.lang').load_lang(self.cr, self.uid, 'fr_FR')
381
382     def test_basic(self):
383         converter = self.get_converter('datetime', 'relative')
384         t = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
385
386         result = converter(t, context={'lang': 'fr_FR'})
387         self.assertEqual(result, u"il y a 1 heure")