1 # -*- encoding: utf-8 -*-
8 from openerp.tests import common
9 from openerp.tools import html_escape as e
10 from openerp.addons.base.ir import ir_qweb
12 directory = os.path.dirname(__file__)
14 class TestExport(common.TransactionCase):
18 super(TestExport, self).setUp()
19 self.Model = self.registry(self._model)
21 def get_field(self, name):
22 return self.Model._fields[name]
24 def get_converter(self, name, type=None):
25 field = self.get_field(name)
27 for postfix in type, field.type, '':
28 fs = ['ir', 'qweb', 'field']
29 if postfix is None: continue
30 if postfix: fs.append(postfix)
33 model = self.registry('.'.join(fs))
37 return lambda value, options=None, context=None: e(model.value_to_html(
38 self.cr, self.uid, value, field, options=options, context=context))
40 class TestBasicExport(TestExport):
41 _model = 'test_converter.test_model'
43 class TestCharExport(TestBasicExport):
45 converter = self.get_converter('char')
47 value = converter('foo')
48 self.assertEqual(value, 'foo')
50 value = converter("foo<bar>")
51 self.assertEqual(value, "foo<bar>")
53 class TestIntegerExport(TestBasicExport):
54 def test_integer(self):
55 converter = self.get_converter('integer')
58 self.assertEqual(value, "42")
60 class TestFloatExport(TestBasicExport):
62 super(TestFloatExport, self).setUp()
63 self.registry('res.lang').write(self.cr, self.uid, [1], {
68 converter = self.get_converter('float')
70 value = converter(42.0)
71 self.assertEqual(value, "42.0")
73 value = converter(42.0100)
74 self.assertEqual(value, "42.01")
76 value = converter(42.01234)
77 self.assertEqual(value, "42.01234")
79 value = converter(1234567.89)
80 self.assertEqual(value, '1,234,567.89')
82 def test_numeric(self):
83 converter = self.get_converter('numeric')
85 value = converter(42.0)
86 self.assertEqual(value, '42.00')
88 value = converter(42.01234)
89 self.assertEqual(value, '42.01')
91 class TestCurrencyExport(TestExport):
92 _model = 'test_converter.monetary'
95 super(TestCurrencyExport, self).setUp()
96 self.Currency = self.registry('res.currency')
97 self.base = self.create(self.Currency, name="Source", symbol=u'source')
99 def create(self, model, context=None, **values):
102 model.create(self.cr, self.uid, values, context=context),
105 def convert(self, obj, dest):
106 converter = self.registry('ir.qweb.field.monetary')
108 'widget': 'monetary',
109 'display_currency': 'c2'
111 context = dict(inherit_branding=True)
112 converted = converter.to_html(
113 self.cr, self.uid, 'value', obj, options,
114 etree.Element('span'),
115 {'field': 'obj.value', 'field-options': json.dumps(options)},
116 '', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }),
121 def test_currency_post(self):
122 currency = self.create(self.Currency, name="Test", symbol=u"test")
123 obj = self.create(self.Model, value=0.12)
125 converted = self.convert(obj, dest=currency)
129 '<span data-oe-model="{obj._model._name}" data-oe-id="{obj.id}" '
130 'data-oe-field="value" data-oe-type="monetary" '
131 'data-oe-expression="obj.value">'
132 '<span class="oe_currency_value">0.12</span>'
133 ' {symbol}</span>'.format(
135 symbol=currency.symbol.encode('utf-8')
138 def test_currency_pre(self):
139 currency = self.create(
140 self.Currency, name="Test", symbol=u"test", position='before')
141 obj = self.create(self.Model, value=0.12)
143 converted = self.convert(obj, dest=currency)
147 '<span data-oe-model="{obj._model._name}" data-oe-id="{obj.id}" '
148 'data-oe-field="value" data-oe-type="monetary" '
149 'data-oe-expression="obj.value">'
151 '<span class="oe_currency_value">0.12</span>'
154 symbol=currency.symbol.encode('utf-8')
157 def test_currency_precision(self):
158 """ Precision should be the currency's, not the float field's
160 currency = self.create(self.Currency, name="Test", symbol=u"test",)
161 obj = self.create(self.Model, value=0.1234567)
163 converted = self.convert(obj, dest=currency)
167 '<span data-oe-model="{obj._model._name}" data-oe-id="{obj.id}" '
168 'data-oe-field="value" data-oe-type="monetary" '
169 'data-oe-expression="obj.value">'
170 '<span class="oe_currency_value">0.12</span>'
171 ' {symbol}</span>'.format(
173 symbol=currency.symbol.encode('utf-8')
176 class TestTextExport(TestBasicExport):
178 converter = self.get_converter('text')
180 value = converter("This is my text-kai")
181 self.assertEqual(value, "This is my text-kai")
183 value = converter("""
184 . The current line (address) in the buffer.
185 $ The last line in the buffer.
186 n The nth, line in the buffer where n is a number in the range [0,$].
187 $ The last line in the buffer.
188 - The previous line. This is equivalent to -1 and may be repeated with cumulative effect.
189 -n The nth previous line, where n is a non-negative number.
190 + The next line. This is equivalent to +1 and may be repeated with cumulative effect.
192 self.assertEqual(value, """<br>
193 . The current line (address) in the buffer.<br>
194 $ The last line in the buffer.<br>
195 n The nth, line in the buffer where n is a number in the range [0,$].<br>
196 $ The last line in the buffer.<br>
197 - The previous line. This is equivalent to -1 and may be repeated with cumulative effect.<br>
198 -n The nth previous line, where n is a non-negative number.<br>
199 + The next line. This is equivalent to +1 and may be repeated with cumulative effect.<br>
202 value = converter("""
203 fgdkls;hjas;lj <b>fdslkj</b> d;lasjfa lkdja <a href=http://spam.com>lfks</a>
204 fldkjsfhs <i style="color: red"><a href="http://spamspam.com">fldskjh</a></i>
206 self.assertEqual(value, """<br>
207 fgdkls;hjas;lj <b>fdslkj</b> d;lasjfa lkdja <a href=http://spam.com>lfks</a><br>
208 fldkjsfhs <i style="color: red"><a href="http://spamspam.com">fldskjh</a></i><br>
211 class TestMany2OneExport(TestBasicExport):
212 def test_many2one(self):
213 Sub = self.registry('test_converter.test_model.sub')
216 id0 = self.Model.create(self.cr, self.uid, {
217 'many2one': Sub.create(self.cr, self.uid, {'name': "Foo"})
219 id1 = self.Model.create(self.cr, self.uid, {
220 'many2one': Sub.create(self.cr, self.uid, {'name': "Fo<b>o</b>"})
223 def converter(record):
224 model = self.registry('ir.qweb.field.many2one')
225 return e(model.record_to_html(self.cr, self.uid, 'many2one', record))
227 value = converter(self.Model.browse(self.cr, self.uid, id0))
228 self.assertEqual(value, "Foo")
230 value = converter(self.Model.browse(self.cr, self.uid, id1))
231 self.assertEqual(value, "Fo<b>o</b>")
233 class TestBinaryExport(TestBasicExport):
234 def test_image(self):
235 field = self.get_field('binary')
236 converter = self.registry('ir.qweb.field.image')
238 with open(os.path.join(directory, 'test_vectors', 'image'), 'rb') as f:
241 encoded_content = content.encode('base64')
242 value = e(converter.value_to_html(
243 self.cr, self.uid, encoded_content, field))
245 value, '<img src="data:image/jpeg;base64,%s">' % (
249 with open(os.path.join(directory, 'test_vectors', 'pdf'), 'rb') as f:
252 with self.assertRaises(ValueError):
253 e(converter.value_to_html(
254 self.cr, self.uid, 'binary', content.encode('base64'), field))
256 with open(os.path.join(directory, 'test_vectors', 'pptx'), 'rb') as f:
259 with self.assertRaises(ValueError):
260 e(converter.value_to_html(
261 self.cr, self.uid, 'binary', content.encode('base64'), field))
263 class TestSelectionExport(TestBasicExport):
264 def test_selection(self):
265 [record] = self.Model.browse(self.cr, self.uid, [self.Model.create(self.cr, self.uid, {
267 'selection_str': 'C',
270 converter = self.registry('ir.qweb.field.selection')
272 field_name = 'selection'
273 value = converter.record_to_html(self.cr, self.uid, field_name, record)
274 self.assertEqual(value, "réponse B")
276 field_name = 'selection_str'
277 value = converter.record_to_html(self.cr, self.uid, field_name, record)
278 self.assertEqual(value, "Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?")
280 class TestHTMLExport(TestBasicExport):
282 converter = self.get_converter('html')
284 input = '<span>span</span>'
285 value = converter(input)
286 self.assertEqual(value, input)
288 class TestDatetimeExport(TestBasicExport):
290 super(TestDatetimeExport, self).setUp()
291 # set user tz to known value
292 Users = self.registry('res.users')
293 Users.write(self.cr, self.uid, self.uid, {
298 converter = self.get_converter('date')
300 value = converter('2011-05-03')
302 # default lang/format is US
303 self.assertEqual(value, '05/03/2011')
305 def test_datetime(self):
306 converter = self.get_converter('datetime')
308 value = converter('2011-05-03 11:12:13')
310 # default lang/format is US
311 self.assertEqual(value, '05/03/2011 00:12:13')
313 def test_custom_format(self):
314 converter = self.get_converter('datetime')
315 converter2 = self.get_converter('date')
316 opts = {'format': 'MMMM d'}
318 value = converter('2011-03-02 11:12:13', options=opts)
319 value2 = converter2('2001-03-02', options=opts)
329 class TestDurationExport(TestBasicExport):
331 super(TestDurationExport, self).setUp()
332 # needs to have lang installed otherwise falls back on en_US
333 self.registry('res.lang').load_lang(self.cr, self.uid, 'fr_FR')
335 def test_negative(self):
336 converter = self.get_converter('float', 'duration')
338 with self.assertRaises(ValueError):
341 def test_missing_unit(self):
342 converter = self.get_converter('float', 'duration')
344 with self.assertRaises(ValueError):
347 def test_basic(self):
348 converter = self.get_converter('float', 'duration')
350 result = converter(4, {'unit': 'hour'}, {'lang': 'fr_FR'})
351 self.assertEqual(result, u'4 heures')
353 result = converter(50, {'unit': 'second'}, {'lang': 'fr_FR'})
354 self.assertEqual(result, u'50 secondes')
356 def test_multiple(self):
357 converter = self.get_converter('float', 'duration')
359 result = converter(1.5, {'unit': 'hour'}, {'lang': 'fr_FR'})
360 self.assertEqual(result, u"1 heure 30 minutes")
362 result = converter(72, {'unit': 'second'}, {'lang': 'fr_FR'})
363 self.assertEqual(result, u"1 minute 12 secondes")
365 class TestRelativeDatetime(TestBasicExport):
366 # not sure how a test based on "current time" should be tested. Even less
367 # so as it would mostly be a test of babel...
370 super(TestRelativeDatetime, self).setUp()
371 # needs to have lang installed otherwise falls back on en_US
372 self.registry('res.lang').load_lang(self.cr, self.uid, 'fr_FR')
374 def test_basic(self):
375 converter = self.get_converter('datetime', 'relative')
376 t = datetime.datetime.utcnow() - datetime.timedelta(hours=1)
378 result = converter(t, context={'lang': 'fr_FR'})
379 self.assertEqual(result, u"il y a 1 heure")