summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphael Collet <rco@openerp.com>2016-05-04 14:18:34 +0200
committerRaphael Collet <rco@openerp.com>2016-05-11 11:40:25 +0200
commit214a59845f253e1f6604c4fd737fd3e18a50d8a9 (patch)
tree90c64e84c00b0eda6407c3355bbf3be6aff87234
parent47c44578baea30c75dcfe520bcea858287b2bb7b (diff)
[MIG] base/tests
Convert YAML tests into Python tests: - translation tests moved to test_translate.py - test phases tests moved to test_phase.py - safe_eval tests moved to test_base.py - parent_store tests moved to test_base.py - float rounding tests moved to test_float.py - `ir.rule` tests moved to test_acl.py - search tests moved to test_expression.py
-rw-r--r--addons/mail/tests/test_ir_actions.py11
-rw-r--r--openerp/addons/base/__openerp__.py6
-rw-r--r--openerp/addons/base/tests/__init__.py2
-rw-r--r--openerp/addons/base/tests/base_test.yml337
-rw-r--r--openerp/addons/base/tests/test_acl.py229
-rw-r--r--openerp/addons/base/tests/test_api.py14
-rw-r--r--openerp/addons/base/tests/test_base.py571
-rw-r--r--openerp/addons/base/tests/test_basecase.py100
-rw-r--r--openerp/addons/base/tests/test_db_cursor.py11
-rw-r--r--openerp/addons/base/tests/test_expression.py887
-rw-r--r--openerp/addons/base/tests/test_float.py177
-rw-r--r--openerp/addons/base/tests/test_func.py12
-rw-r--r--openerp/addons/base/tests/test_ir_actions.py342
-rw-r--r--openerp/addons/base/tests/test_ir_attachment.py85
-rw-r--r--openerp/addons/base/tests/test_ir_filters.py137
-rw-r--r--openerp/addons/base/tests/test_ir_rule.yml189
-rw-r--r--openerp/addons/base/tests/test_ir_sequence.py280
-rw-r--r--openerp/addons/base/tests/test_ir_sequence_date_range.py162
-rw-r--r--openerp/addons/base/tests/test_ir_values.py129
-rw-r--r--openerp/addons/base/tests/test_mail.py11
-rw-r--r--openerp/addons/base/tests/test_mail_examples.py4
-rw-r--r--openerp/addons/base/tests/test_menu.py40
-rw-r--r--openerp/addons/base/tests/test_misc.py10
-rw-r--r--openerp/addons/base/tests/test_orm.py432
-rw-r--r--openerp/addons/base/tests/test_ormcache.py9
-rw-r--r--openerp/addons/base/tests/test_osv.py3
-rw-r--r--openerp/addons/base/tests/test_osv_expression.yml632
-rw-r--r--openerp/addons/base/tests/test_phase.py64
-rw-r--r--openerp/addons/base/tests/test_qweb.py83
-rw-r--r--openerp/addons/base/tests/test_res_config.py36
-rw-r--r--openerp/addons/base/tests/test_res_lang.py9
-rw-r--r--openerp/addons/base/tests/test_res_partner_bank.py3
-rw-r--r--openerp/addons/base/tests/test_search.py170
-rw-r--r--openerp/addons/base/tests/test_translate.py59
-rw-r--r--openerp/addons/base/tests/test_uninstall.py99
-rw-r--r--openerp/addons/base/tests/test_user_has_group.py7
-rw-r--r--openerp/addons/base/tests/test_view_validation.py20
-rw-r--r--openerp/addons/base/tests/test_views.py602
-rw-r--r--openerp/addons/base/tests/test_xmlrpc.py10
-rw-r--r--openerp/osv/expression.py2
40 files changed, 2714 insertions, 3272 deletions
diff --git a/addons/mail/tests/test_ir_actions.py b/addons/mail/tests/test_ir_actions.py
index bb08fdc7101..3748fdb715b 100644
--- a/addons/mail/tests/test_ir_actions.py
+++ b/addons/mail/tests/test_ir_actions.py
@@ -12,18 +12,17 @@ class TestServerActionsEmail(TestServerActionsBase):
'name': 'TestTemplate',
'email_from': 'myself@example.com',
'email_to': 'brigitte@example.com',
- 'partner_to': '%s' % self.test_partner_id,
- 'model_id': self.res_partner_model_id,
+ 'partner_to': '%s' % self.test_partner.id,
+ 'model_id': self.res_partner_model.id,
'subject': 'About ${object.name}',
'body_html': '<p>Dear ${object.name}, your parent is ${object.parent_id and object.parent_id.name or "False"}</p>',
})
- action = self.env['ir.actions.server'].browse(self.act_id)
- action.write({'state': 'email', 'template_id': email_template.id})
- run_res = action.with_context(self.context).run()
+ self.action.write({'state': 'email', 'template_id': email_template.id})
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: email server action correctly finished should return False')
# check an email is waiting for sending
mail = self.env['mail.mail'].search([('subject', '=', 'About TestingPartner')])
- self.assertEqual(len(mail.ids), 1, 'ir_actions_server: TODO')
+ self.assertEqual(len(mail), 1, 'ir_actions_server: TODO')
# check email content
self.assertEqual(mail.body, '<p>Dear TestingPartner, your parent is False</p>',
'ir_actions_server: TODO')
diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py
index 58d93fce011..4cd21782039 100644
--- a/openerp/addons/base/__openerp__.py
+++ b/openerp/addons/base/__openerp__.py
@@ -72,11 +72,7 @@ The kernel of Odoo, needed for all installation.
'res/res_partner_demo.yml',
'res/res_partner_image_demo.xml',
],
- 'test': [
- 'tests/base_test.yml',
- 'tests/test_osv_expression.yml',
- 'tests/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules.
- ],
+ 'test': [],
'installable': True,
'auto_install': True,
'post_init_hook': 'post_init',
diff --git a/openerp/addons/base/tests/__init__.py b/openerp/addons/base/tests/__init__.py
index e9414be9011..fbb2375f3c1 100644
--- a/openerp/addons/base/tests/__init__.py
+++ b/openerp/addons/base/tests/__init__.py
@@ -4,6 +4,7 @@ import test_base
import test_basecase
import test_db_cursor
import test_expression
+import test_float
import test_func
import test_ir_actions
import test_ir_attachment
@@ -16,6 +17,7 @@ import test_menu
import test_orm
import test_ormcache
import test_osv
+import test_phase
import test_qweb
import test_res_config
import test_res_lang
diff --git a/openerp/addons/base/tests/base_test.yml b/openerp/addons/base/tests/base_test.yml
deleted file mode 100644
index c7ab7f06ae9..00000000000
--- a/openerp/addons/base/tests/base_test.yml
+++ /dev/null
@@ -1,337 +0,0 @@
-- |
- To check that common dangerous operations are not allowed by the safe_eval mechanism, attempt to
- evaluate unauthorized expressions, and verify that they trigger an error.
--
- 1. Try a few common expressions to verify they work with safe_eval
--
- !python {model: ir.model}: |
- from openerp.tools.safe_eval import safe_eval
- expected = (1, {"a": 9 * 2}, (True, False, None))
- actual = safe_eval('(1, {"a": 9 * 2}, (True, False, None))')
- assert actual == expected, "Simple python expressions are not working with safe_eval"
--
- 2. Try simple literal definition to verify it works with literal_eval
--
- !python {model: ir.model}: |
- import ast
- expected = (1, {"a": 9}, (True, False, None))
- actual = ast.literal_eval('(1, {"a": 9}, (True, False, None))')
- assert actual == expected, "Simple python expressions are not working with literal_eval"
--
- 3. Try arithmetic expression in literal_eval to verify it does not work
--
- !python {model: ir.model}: |
- import ast
- try:
- ast.literal_eval('(1, {"a": 2*9}, (True, False, None))')
- assert False, "literal_eval should not accept arithmetic expressions"
- except ValueError:
- pass
--
- 4. Try forbidden expressions in literal_eval to verify they are not allowed
--
- !python {model: ir.model}: |
- import ast
- try:
- ast.literal_eval('{"a": True.__class__}')
- assert False, "literal_eval should accept only literals"
- except ValueError:
- pass
--
- 5. Try forbidden expressions in safe_eval to verify they are not allowed (open)
--
- !python {model: ir.model}: |
- from openerp.tools.safe_eval import safe_eval
- from openerp.tools.misc import mute_logger
- try:
- with mute_logger('openerp.tools.safe_eval'):
- safe_eval('open("/etc/passwd","r")')
- assert False, "safe_eval should not allow calling open() builtin"
- except ValueError:
- pass
-
--
- "ORM test: verify that parent_store computation are going right"
--
- 0. Emulate normal behavior of tree structure storing
--
- !python {model: res.partner.category}: |
- # pretend the pool has finished loading to avoid deferring parent_store computation
- self.pool._init = False
-
- # Force partner_categ.copy() to copy children
- self._fields['child_ids'].copy = True
- self._columns['child_ids'].copy = True
--
- "1.0 Setup test partner categories: parent root"
--
- !record {model: res.partner.category, id: test_categ_root}:
- name: Root category
--
- "1.1 Setup test partner categories: parent category"
--
- !record {model: res.partner.category, id: test_categ_0}:
- name: Parent category
- parent_id: test_categ_root
--
- "1.2 Setup test partner categories: child 1"
--
- !record {model: res.partner.category, id: test_categ_1}:
- name: Child 1
- parent_id: test_categ_0
--
- "1.3 Setup test partner categories: child 2"
--
- !record {model: res.partner.category, id: test_categ_2}:
- name: Child 2
- parent_id: test_categ_0
--
- "1.4 Setup test partner categories: child 2-1"
--
- !record {model: res.partner.category, id: test_categ_21}:
- name: Child 2-1
- parent_id: test_categ_2
--
- 2. Duplicate the parent category and verify that the children have been duplicated too and are below the new parent
--
- !python {model: res.partner.category}: |
- self._columns['child_ids'].copy = True # force copying children for test
- new_id = self.copy(cr, uid, ref('test_categ_0'))
- new_struct = self.search(cr, uid, [('parent_id', 'child_of', new_id)])
- assert len(new_struct) == 4, "After duplication, the new object must have the childs records"
- old_struct = self.search(cr, uid, [('parent_id', 'child_of', ref('test_categ_0'))])
- assert len(old_struct) == 4, "After duplication, previous record must have old childs records only"
- assert (not set(new_struct).intersection(old_struct)), "After duplication, nodes should not be mixed"
--
- 3. Duplicate the children then reassign them to the new parent (1st method) and check the parent_store structure.
--
- !python {model: res.partner.category}: |
- new_child1_id = self.copy(cr, uid, ref('test_categ_1'))
- new_child2_id = self.copy(cr, uid, ref('test_categ_2'))
- new_id = self.copy(cr, uid, ref('test_categ_0'), {'child_ids': []})
- self.write(cr, uid, [new_child1_id, new_child2_id], {'parent_id': new_id})
- new_struct = self.search(cr, uid, [('parent_id', 'child_of', new_id)])
- assert len(new_struct) == 4, "After duplication, the new object must have the childs records"
- old_struct = self.search(cr, uid, [('parent_id', 'child_of', ref('test_categ_0'))])
- assert len(old_struct) == 4, "After duplication, previous record must have old childs records only"
- assert (not set(new_struct).intersection(old_struct)), "After duplication, nodes should not be mixed"
--
- 4. Duplicate the children then reassign them to the new parent (2nd method) and check the parent_store structure.
--
- !python {model: res.partner.category}: |
- new_child1_id = self.copy(cr, uid, ref('test_categ_1'))
- new_child2_id = self.copy(cr, uid, ref('test_categ_2'))
- old_struct = self.search(cr, uid, [('parent_id', 'child_of', ref('test_categ_0'))])
- new_id = self.copy(cr, uid, ref('test_categ_0'), {'child_ids': [(6,0,[new_child1_id, new_child2_id])]})
- new_struct = self.search(cr, uid, [('parent_id', 'child_of', new_id)])
- assert len(new_struct) == 4, "After duplication, the new object must have the childs records"
- old_struct = self.search(cr, uid, [('parent_id', 'child_of', ref('test_categ_0'))])
- assert len(old_struct) == 4, "After duplication, previous record must have old childs records only"
- assert (not set(new_struct).intersection(old_struct)), "After duplication, nodes should not be mixed"
--
- 5. Duplicate the children then reassign them to the new parent (3rd method) and make sure the parent_store structure is still right.
--
- !python {model: res.partner.category}: |
- new_child1_id = self.copy(cr, uid, ref('test_categ_1'))
- new_child2_id = self.copy(cr, uid, ref('test_categ_2'))
- new_id = self.copy(cr, uid, ref('test_categ_0'), {'child_ids': []})
- self.write(cr, uid, [new_id], {'child_ids': [(4,new_child1_id), (4,new_child2_id)]})
- new_struct = self.search(cr, uid, [('parent_id', 'child_of', new_id)])
- assert len(new_struct) == 4, "After duplication, the new object must have the childs records"
- old_struct = self.search(cr, uid, [('parent_id', 'child_of', ref('test_categ_0'))])
- assert len(old_struct) == 4, "After duplication, previous record must have old childs records only"
- assert (not set(new_struct).intersection(old_struct)), "After duplication, nodes should not be mixed"
--
- 6. Restore pool state after the test
--
- !python {model: res.partner.category}: |
- self.pool._init = True
- self._fields['child_ids'].copy = False
- self._columns['child_ids'].copy = False
-
--
- "Float precision tests: verify that float rounding methods are working correctly via res.currency"
--
- !python {model: res.currency}: |
- from openerp.tools import float_repr
- from math import log10
- currency = self.browse(cr, uid, ref('base.EUR'))
- def try_round(amount, expected, self=self, cr=cr, currency=currency, float_repr=float_repr,
- log10=log10):
- digits = max(0,-int(log10(currency.rounding)))
- result = float_repr(self.round(cr, 1, currency, amount), precision_digits=digits)
- assert result == expected, 'Rounding error: got %s, expected %s' % (result, expected)
- try_round(2.674,'2.67')
- try_round(2.675,'2.68') # in Python 2.7.2, round(2.675,2) gives 2.67
- try_round(-2.675,'-2.68') # in Python 2.7.2, round(2.675,2) gives 2.67
- try_round(0.001,'0.00')
- try_round(-0.001,'-0.00')
- try_round(0.0049,'0.00') # 0.0049 is closer to 0 than to 0.01, so should round down
- try_round(0.005,'0.01') # the rule is to round half away from zero
- try_round(-0.005,'-0.01') # the rule is to round half away from zero
-
- def try_zero(amount, expected, self=self, cr=cr, currency=currency):
- assert self.is_zero(cr, 1, currency, amount) == expected, "Rounding error: %s should be zero!" % amount
- try_zero(0.01, False)
- try_zero(-0.01, False)
- try_zero(0.001, True)
- try_zero(-0.001, True)
- try_zero(0.0046, True)
- try_zero(-0.0046, True)
- try_zero(2.68-2.675, False) # 2.68 - 2.675 = 0.005 -> rounds to 0.01
- try_zero(2.68-2.676, True) # 2.68 - 2.675 = 0.004 -> rounds to 0.0
- try_zero(2.676-2.68, True) # 2.675 - 2.68 = -0.004 -> rounds to -0.0
- try_zero(2.675-2.68, False) # 2.675 - 2.68 = -0.005 -> rounds to -0.01
-
- def try_compare(amount1, amount2, expected, self=self, cr=cr, currency=currency):
- assert self.compare_amounts(cr, 1, currency, amount1, amount2) == expected, \
- "Rounding error, compare_amounts(%s,%s) should be %s" % (amount1, amount2, expected)
- try_compare(0.001, 0.001, 0)
- try_compare(-0.001, -0.001, 0)
- try_compare(0.001, 0.002, 0)
- try_compare(-0.001, -0.002, 0)
- try_compare(2.675, 2.68, 0)
- try_compare(2.676, 2.68, 0)
- try_compare(-2.676, -2.68, 0)
- try_compare(2.674, 2.68, -1)
- try_compare(-2.674, -2.68, 1)
- try_compare(3, 2.68, 1)
- try_compare(-3, -2.68, -1)
- try_compare(0.01, 0, 1)
- try_compare(-0.01, 0, -1)
-
--
- "Float precision tests: verify that float rounding methods are working correctly via tools"
--
- !python {model: res.currency}: |
- from openerp.tools import float_compare, float_is_zero, float_round, float_repr
- def try_round(amount, expected, precision_digits=3, float_round=float_round, float_repr=float_repr, rounding_method='HALF-UP'):
- result = float_repr(float_round(amount, precision_digits=precision_digits, rounding_method=rounding_method),
- precision_digits=precision_digits)
- assert result == expected, 'Rounding error: got %s, expected %s' % (result, expected)
- try_round(2.6745, '2.675')
- try_round(-2.6745, '-2.675')
- try_round(2.6744, '2.674')
- try_round(-2.6744, '-2.674')
- try_round(0.0004, '0.000')
- try_round(-0.0004, '-0.000')
- try_round(357.4555, '357.456')
- try_round(-357.4555, '-357.456')
- try_round(457.4554, '457.455')
- try_round(-457.4554, '-457.455')
-
- # Try some rounding value with rounding method UP instead of HALF-UP
- # We use 8.175 because when normalizing 8.175 with precision_digits=3 it gives
- # us 8175,0000000001234 as value, and if not handle correctly the rounding UP
- # value will be incorrect (should be 8,175 and not 8,176)
- try_round(8.175, '8.175', rounding_method='UP')
- try_round(8.1751, '8.176', rounding_method='UP')
- try_round(-8.175, '-8.175', rounding_method='UP')
- try_round(-8.1751, '-8.176', rounding_method='UP')
- try_round(-6.000, '-6.000', rounding_method='UP')
- try_round(1.8, '2', 0, rounding_method='UP')
- try_round(-1.8, '-2', 0, rounding_method='UP')
-
- # Extended float range test, inspired by Cloves Almeida's test on bug #882036.
- fractions = [.0, .015, .01499, .675, .67499, .4555, .4555, .45555]
- expecteds = ['.00', '.02', '.01', '.68', '.67', '.46', '.456', '.4556']
- precisions = [2, 2, 2, 2, 2, 2, 3, 4]
- # Note: max precision for double floats is 53 bits of precision or
- # 17 significant decimal digits
- for magnitude in range(7):
- for i in xrange(len(fractions)):
- frac, exp, prec = fractions[i], expecteds[i], precisions[i]
- for sign in [-1,1]:
- for x in xrange(0,10000,97):
- n = x * 10**magnitude
- f = sign * (n + frac)
- f_exp = ('-' if f != 0 and sign == -1 else '') + str(n) + exp
- try_round(f, f_exp, precision_digits=prec)
-
-
- def try_zero(amount, expected, float_is_zero=float_is_zero):
- assert float_is_zero(amount, precision_digits=3) == expected, "Rounding error: %s should be zero!" % amount
- try_zero(0.0002, True)
- try_zero(-0.0002, True)
- try_zero(0.00034, True)
- try_zero(0.0005, False)
- try_zero(-0.0005, False)
- try_zero(0.0008, False)
- try_zero(-0.0008, False)
-
- def try_compare(amount1, amount2, expected, float_compare=float_compare):
- assert float_compare(amount1, amount2, precision_digits=3) == expected, \
- "Rounding error, compare_amounts(%s,%s) should be %s" % (amount1, amount2, expected)
- try_compare(0.0003, 0.0004, 0)
- try_compare(-0.0003, -0.0004, 0)
- try_compare(0.0002, 0.0005, -1)
- try_compare(-0.0002, -0.0005, 1)
- try_compare(0.0009, 0.0004, 1)
- try_compare(-0.0009, -0.0004, -1)
- try_compare(557.4555, 557.4556, 0)
- try_compare(-557.4555, -557.4556, 0)
- try_compare(657.4444, 657.445, -1)
- try_compare(-657.4444, -657.445, 1)
-
- # Rounding to unusual rounding units (e.g. coin values)
- def try_round(amount, expected, precision_rounding=None, float_round=float_round, float_repr=float_repr):
- result = float_repr(float_round(amount, precision_rounding=precision_rounding),
- precision_digits=2)
- assert result == expected, 'Rounding error: got %s, expected %s' % (result, expected)
- try_round(-457.4554, '-457.45', precision_rounding=0.05)
- try_round(457.444, '457.50', precision_rounding=0.5)
- try_round(457.3, '455.00', precision_rounding=5)
- try_round(457.5, '460.00', precision_rounding=5)
- try_round(457.1, '456.00', precision_rounding=3)
-
--
- "Float precision tests: check that proper rounding is performed for float persistence"
--
- !python {model: res.currency}: |
- currency = self.browse(cr, uid, ref('base.EUR'))
- res_currency_rate = self.pool.get('res.currency.rate')
- from openerp.tools import float_compare, float_is_zero, float_round, float_repr
- def try_roundtrip(value, expected, self=self, cr=cr, currency=currency,
- res_currency_rate=res_currency_rate):
- rate_id = res_currency_rate.create(cr, 1, {'name':'2000-01-01',
- 'rate': value,
- 'currency_id': currency.id})
- rate = res_currency_rate.read(cr, 1, [rate_id], ['rate'])[0]['rate']
- assert rate == expected, 'Roundtrip error: got %s back from db, expected %s' % (rate, expected)
- # res.currency.rate uses 6 digits of precision by default
- try_roundtrip(2.6748955, 2.674896)
- try_roundtrip(-2.6748955, -2.674896)
- try_roundtrip(10000.999999, 10000.999999)
- try_roundtrip(-10000.999999, -10000.999999)
-
--
- "Float precision tests: verify that invalid parameters are forbidden"
--
- !python {model: res.currency}: |
- from openerp.tools import float_compare, float_is_zero, float_round
- try:
- float_is_zero(0.01, precision_digits=3, precision_rounding=0.01)
- except AssertionError:
- pass
- try:
- float_compare(0.01, 0.02, precision_digits=3, precision_rounding=0.01)
- except AssertionError:
- pass
- try:
- float_round(0.01, precision_digits=3, precision_rounding=0.01)
- except AssertionError:
- pass
--
- Test res.groups name search
--
- !python {model: res.groups}: |
- all_groups = self.search(cr, uid, [])
- full_names = [(group.id, group.full_name) for group in self.browse(cr, uid, all_groups)]
- group_ids = self.search(cr, uid, [('full_name', 'like', '%Sale%')])
- assert set(group_ids) == set([id for (id, full_name) in full_names if 'Sale' in full_name]), "did not match search for 'Sale'"
- group_ids = self.search(cr, uid, [('full_name', 'like', '%Technical%')])
- assert set(group_ids) == set([id for (id, full_name) in full_names if 'Technical' in full_name]), "did not match search for 'Technical'"
- group_ids = self.search(cr, uid, [('full_name', 'like', '%Sales /%')])
- assert set(group_ids) == set([id for (id, full_name) in full_names if 'Sales /' in full_name]), "did not match search for 'Sales /'"
- group_ids = self.search(cr, uid, [('full_name', 'in', ['Administration / Access Rights','Contact Creation'])])
- assert group_ids, "did not match search for 'Administration / Access Rights' and 'Contact Creation'"
diff --git a/openerp/addons/base/tests/test_acl.py b/openerp/addons/base/tests/test_acl.py
index d1f5ccd4771..84e851add5b 100644
--- a/openerp/addons/base/tests/test_acl.py
+++ b/openerp/addons/base/tests/test_acl.py
@@ -1,26 +1,23 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
from lxml import etree
-from openerp.exceptions import AccessError
-from openerp.tools.misc import mute_logger
-from openerp.tests import common
+from odoo.exceptions import AccessError
+from odoo.tests.common import TransactionCase
+from odoo.tools.misc import mute_logger
# test group that demo user should not have
+USER_DEMO = 'base.user_demo'
GROUP_SYSTEM = 'base.group_system'
-GROUP_ERP_MANAGER = 'base.group_erp_manager'
-class TestACL(common.TransactionCase):
+class TestACL(TransactionCase):
def setUp(self):
super(TestACL, self).setUp()
- self.res_currency = self.registry('res.currency')
- self.res_partner = self.registry('res.partner')
- self.res_users = self.registry('res.users')
- self.res_company = self.registry('res.company')
- self.demo_uid = self.env.ref('base.user_demo').id
+ self.demo_user = self.env.ref(USER_DEMO)
self.erp_system_group = self.env.ref(GROUP_SYSTEM)
- self.erp_manager_group = self.env.ref(GROUP_ERP_MANAGER)
def _set_field_groups(self, model, field_name, groups):
field = model._fields[field_name]
@@ -32,109 +29,103 @@ class TestACL(common.TransactionCase):
def test_field_visibility_restriction(self):
"""Check that model-level ``groups`` parameter effectively restricts access to that
field for users who do not belong to one of the explicitly allowed groups"""
+ currency = self.env['res.currency'].sudo(self.demo_user)
+
# Verify the test environment first
- original_fields = self.res_currency.fields_get(self.cr, self.demo_uid, [])
- form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ original_fields = currency.fields_get([])
+ form_view = currency.fields_view_get(False, 'form')
view_arch = etree.fromstring(form_view.get('arch'))
- has_group_system = self.res_users.has_group(self.cr, self.demo_uid, GROUP_SYSTEM)
+ has_group_system = self.demo_user.has_group(GROUP_SYSTEM)
self.assertFalse(has_group_system, "`demo` user should not belong to the restricted group before the test")
- self.assertTrue('decimal_places' in original_fields, "'decimal_places' field must be properly visible before the test")
+ self.assertIn('decimal_places', original_fields, "'decimal_places' field must be properly visible before the test")
self.assertNotEquals(view_arch.xpath("//field[@name='decimal_places']"), [],
"Field 'decimal_places' must be found in view definition before the test")
# restrict access to the field and check it's gone
- self._set_field_groups(self.res_currency, 'decimal_places', GROUP_SYSTEM)
+ self._set_field_groups(currency, 'decimal_places', GROUP_SYSTEM)
- fields = self.res_currency.fields_get(self.cr, self.demo_uid, [])
- form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ fields = currency.fields_get([])
+ form_view = currency.fields_view_get(False, 'form')
view_arch = etree.fromstring(form_view.get('arch'))
- self.assertFalse('decimal_places' in fields, "'decimal_places' field should be gone")
+ self.assertNotIn('decimal_places', fields, "'decimal_places' field should be gone")
self.assertEquals(view_arch.xpath("//field[@name='decimal_places']"), [],
"Field 'decimal_places' must not be found in view definition")
# Make demo user a member of the restricted group and check that the field is back
- self.erp_system_group.write({'users': [(4, self.demo_uid)]})
- has_group_system = self.res_users.has_group(self.cr, self.demo_uid, GROUP_SYSTEM)
- fields = self.res_currency.fields_get(self.cr, self.demo_uid, [])
- form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ self.erp_system_group.users += self.demo_user
+ has_group_system = self.demo_user.has_group(GROUP_SYSTEM)
+ fields = currency.fields_get([])
+ form_view = currency.fields_view_get(False, 'form')
view_arch = etree.fromstring(form_view.get('arch'))
- #import pprint; pprint.pprint(fields); pprint.pprint(form_view)
self.assertTrue(has_group_system, "`demo` user should now belong to the restricted group")
- self.assertTrue('decimal_places' in fields, "'decimal_places' field must be properly visible again")
+ self.assertIn('decimal_places', fields, "'decimal_places' field must be properly visible again")
self.assertNotEquals(view_arch.xpath("//field[@name='decimal_places']"), [],
"Field 'decimal_places' must be found in view definition again")
- #cleanup
- self.erp_system_group.write({'users': [(3, self.demo_uid)]})
-
@mute_logger('openerp.models')
def test_field_crud_restriction(self):
"Read/Write RPC access to restricted field should be forbidden"
+ partner = self.env['res.partner'].browse(1).sudo(self.demo_user)
+
# Verify the test environment first
- has_group_system = self.res_users.has_group(self.cr, self.demo_uid, GROUP_SYSTEM)
+ has_group_system = self.demo_user.has_group(GROUP_SYSTEM)
self.assertFalse(has_group_system, "`demo` user should not belong to the restricted group")
- self.assert_(self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids']))
- self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []}))
+ self.assert_(partner.read(['bank_ids']))
+ self.assert_(partner.write({'bank_ids': []}))
# Now restrict access to the field and check it's forbidden
- self._set_field_groups(self.res_partner, 'bank_ids', GROUP_SYSTEM)
+ self._set_field_groups(partner, 'bank_ids', GROUP_SYSTEM)
with self.assertRaises(AccessError):
- self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids'])
+ partner.read(['bank_ids'])
with self.assertRaises(AccessError):
- self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []})
+ partner.write({'bank_ids': []})
# Add the restricted group, and check that it works again
- self.erp_system_group.write({'users': [(4, self.demo_uid)]})
- has_group_system = self.res_users.has_group(self.cr, self.demo_uid, GROUP_SYSTEM)
+ self.erp_system_group.users += self.demo_user
+ has_group_system = self.demo_user.has_group(GROUP_SYSTEM)
self.assertTrue(has_group_system, "`demo` user should now belong to the restricted group")
- self.assert_(self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids']))
- self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []}))
-
- #cleanup
- self.erp_system_group.write({'users': [(3, self.demo_uid)]})
+ self.assert_(partner.read(['bank_ids']))
+ self.assert_(partner.write({'bank_ids': []}))
@mute_logger('openerp.models')
def test_fields_browse_restriction(self):
"""Test access to records having restricted fields"""
- self._set_field_groups(self.res_partner, 'email', GROUP_SYSTEM)
+ partner = self.env['res.partner'].sudo(self.demo_user)
+ self._set_field_groups(partner, 'email', GROUP_SYSTEM)
- pid = self.res_partner.search(self.cr, self.demo_uid, [], limit=1)[0]
- part = self.res_partner.browse(self.cr, self.demo_uid, pid)
# accessing fields must no raise exceptions...
- part.name
+ partner = partner.search([], limit=1)
+ partner.name
# ... except if they are restricted
- with self.assertRaises(AccessError) as cm:
+ with self.assertRaises(AccessError):
with mute_logger('openerp.models'):
- part.email
-
- #Useless because we get the title in the client side now in the chrome.js file(map_title)
- #self.assertEqual(cm.exception.args[0], 'Access Error')
+ partner.email
def test_view_create_edit_button_invisibility(self):
""" Test form view Create, Edit, Delete button visibility based on access right of model"""
methods = ['create', 'edit', 'delete']
- company_view = self.res_company.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ company = self.env['res.company'].sudo(self.demo_user)
+ company_view = company.fields_view_get(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
for method in methods:
self.assertEqual(view_arch.get(method), 'false')
def test_view_create_edit_button_visibility(self):
""" Test form view Create, Edit, Delete button visibility based on access right of model"""
+ self.erp_system_group.users += self.demo_user
methods = ['create', 'edit', 'delete']
- self.erp_manager_group.write({'users': [(4, self.demo_uid)]})
- company_view = self.res_company.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ company = self.env['res.company'].sudo(self.demo_user)
+ company_view = company.fields_view_get(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
for method in methods:
self.assertIsNone(view_arch.get(method))
- # cleanup
- self.erp_manager_group.write({'users': [(3, self.demo_uid)]})
def test_m2o_field_create_edit_invisibility(self):
""" Test many2one field Create and Edit option visibility based on access rights of relation field"""
methods = ['create', 'write']
-
- company_view = self.res_company.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ company = self.env['res.company'].sudo(self.demo_user)
+ company_view = company.fields_view_get(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
field_node = view_arch.xpath("//field[@name='currency_id']")
self.assertTrue(len(field_node), "currency_id field should be in company from view")
@@ -143,17 +134,125 @@ class TestACL(common.TransactionCase):
def test_m2o_field_create_edit_visibility(self):
""" Test many2one field Create and Edit option visibility based on access rights of relation field"""
+ self.erp_system_group.users += self.demo_user
methods = ['create', 'write']
-
- self.erp_system_group.write({'users': [(4, self.demo_uid)]})
- company_view = self.res_company.fields_view_get(self.cr, self.demo_uid, False, 'form')
+ company = self.env['res.company'].sudo(self.demo_user)
+ company_view = company.fields_view_get(False, 'form')
view_arch = etree.fromstring(company_view['arch'])
field_node = view_arch.xpath("//field[@name='currency_id']")
self.assertTrue(len(field_node), "currency_id field should be in company from view")
for method in methods:
self.assertEqual(field_node[0].get('can_' + method), 'true')
- # cleanup
- self.erp_manager_group.write({'users': [(3, self.demo_uid)]})
-if __name__ == '__main__':
- unittest.main()
+
+class TestIrRule(TransactionCase):
+
+ def test_ir_rule(self):
+ model_res_partner = self.env.ref('base.model_res_partner')
+ group_user = self.env.ref('base.group_user')
+ user_demo = self.env.ref('base.user_demo')
+
+ # create an ir_rule for the Employee group with an blank domain
+ rule1 = self.env['ir.rule'].create({
+ 'name': 'test_rule1',
+ 'model_id': model_res_partner.id,
+ 'domain_force': False,
+ 'groups': [(6, 0, group_user.ids)],
+ })
+
+ # read as demo user the partners (one blank domain)
+ partners_demo = self.env['res.partner'].sudo(user_demo)
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # same with domain 1=1
+ rule1.domain_force = "[(1,'=',1)]"
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # same with domain []
+ rule1.domain_force = "[]"
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # create another ir_rule for the Employee group (to test multiple rules)
+ rule2 = self.env['ir.rule'].create({
+ 'name': 'test_rule2',
+ 'model_id': model_res_partner.id,
+ 'domain_force': False,
+ 'groups': [(6, 0, group_user.ids)],
+ })
+
+ # read as demo user with domains [] and blank
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # same with domains 1=1 and blank
+ rule1.domain_force = "[(1,'=',1)]"
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # same with domains 1=1 and 1=1
+ rule2.domain_force = "[(1,'=',1)]"
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # create another ir_rule for the Employee group (to test multiple rules)
+ rule3 = self.env['ir.rule'].create({
+ 'name': 'test_rule3',
+ 'model_id': model_res_partner.id,
+ 'domain_force': False,
+ 'groups': [(6, 0, group_user.ids)],
+ })
+
+ # read the partners as demo user
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # same with domains 1=1, 1=1 and 1=1
+ rule3.domain_force = "[(1,'=',1)]"
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # modify the global rule on res_company which triggers a recursive check
+ # of the rules on company
+ global_rule = self.env.ref('base.res_company_rule_employee')
+ global_rule.domain_force = "[('id','child_of',[user.company_id.id])]"
+
+ # read as demo user (exercising the global company rule)
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # Modify the ir_rule for employee to have a rule that fordids seeing any
+ # record. We use a domain with implicit AND operator for later tests on
+ # normalization.
+ rule2.domain_force = "[('id','=',False),('name','=',False)]"
+
+ # check that demo user still sees partners, because group-rules are OR'ed
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partner.")
+
+ # create a new group with demo user in it, and a complex rule
+ group_test = self.env['res.groups'].create({
+ 'name': 'Test Group',
+ 'users': [(6, 0, user_demo.ids)],
+ })
+
+ # add the rule to the new group, with a domain containing an implicit
+ # AND operator, which is more tricky because it will have to be
+ # normalized before combining it
+ rule3.write({
+ 'domain_force': "[('name','!=',False),('id','!=',False)]",
+ 'groups': [(6, 0, group_test.ids)],
+ })
+
+ # read the partners again as demo user, which should give results
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see partners even with the combined rules.")
+
+ # delete global domains (to combine only group domains)
+ self.env['ir.rule'].search([('groups', '=', False)]).unlink()
+
+ # read the partners as demo user (several group domains, no global domain)
+ partners = partners_demo.search([])
+ self.assertTrue(partners, "Demo user should see some partners.")
diff --git a/openerp/addons/base/tests/test_api.py b/openerp/addons/base/tests/test_api.py
index 645c5d4ad9b..2c08f9c688c 100644
--- a/openerp/addons/base/tests/test_api.py
+++ b/openerp/addons/base/tests/test_api.py
@@ -1,8 +1,10 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp import models
-from openerp.tools import mute_logger
-from openerp.tests import common
-from openerp.exceptions import AccessError
+from odoo import models
+from odoo.tools import mute_logger
+from odoo.tests import common
+from odoo.exceptions import AccessError
class TestAPI(common.TransactionCase):
@@ -84,7 +86,7 @@ class TestAPI(common.TransactionCase):
ids = map(int, partners)
# modify those partners, and check that partners has not changed
- self.registry('res.partner').write(self.cr, self.uid, ids, {'active': False})
+ partners.write({'active': False})
self.assertEqual(ids, map(int, partners))
# redo the search, and check that the result is now empty
@@ -94,7 +96,7 @@ class TestAPI(common.TransactionCase):
@mute_logger('openerp.models')
def test_06_fields(self):
""" Check that relation fields return records, recordsets or nulls. """
- user = self.registry('res.users').browse(self.cr, self.uid, self.uid)
+ user = self.env.user
self.assertIsRecord(user, 'res.users')
self.assertIsRecord(user.partner_id, 'res.partner')
self.assertIsRecordset(user.groups_id, 'res.groups')
diff --git a/openerp/addons/base/tests/test_base.py b/openerp/addons/base/tests/test_base.py
index bbd54efa2e9..45910803b95 100644
--- a/openerp/addons/base/tests/test_base.py
+++ b/openerp/addons/base/tests/test_base.py
@@ -1,80 +1,113 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import ast
import unittest
-import openerp.tests.common as common
-from openerp.exceptions import ValidationError
+from odoo.exceptions import ValidationError
+from odoo.tests.common import TransactionCase
+from odoo.tools import mute_logger
+from odoo.tools.safe_eval import safe_eval
-class test_base(common.TransactionCase):
- def setUp(self):
- super(test_base,self).setUp()
- self.res_partner = self.registry('res.partner')
- self.res_users = self.registry('res.users')
- self.res_partner_title = self.registry('res.partner.title')
-
- # samples use effective TLDs from the Mozilla public suffix
- # list at http://publicsuffix.org
- self.samples = [
- ('"Raoul Grosbedon" <raoul@chirurgiens-dentistes.fr> ', 'Raoul Grosbedon', 'raoul@chirurgiens-dentistes.fr'),
- ('ryu+giga-Sushi@aizubange.fukushima.jp', '', 'ryu+giga-Sushi@aizubange.fukushima.jp'),
- ('Raoul chirurgiens-dentistes.fr', 'Raoul chirurgiens-dentistes.fr', ''),
- (" Raoul O'hara <!@historicalsociety.museum>", "Raoul O'hara", '!@historicalsociety.museum')
- ]
+class TestSafeEval(unittest.TestCase):
+
+ def test_01_safe_eval(self):
+ """ Try a few common expressions to verify they work with safe_eval """
+ expected = (1, {"a": 9 * 2}, (True, False, None))
+ actual = safe_eval('(1, {"a": 9 * 2}, (True, False, None))')
+ self.assertEqual(actual, expected, "Simple python expressions are not working with safe_eval")
+
+ def test_02_literal_eval(self):
+ """ Try simple literal definition to verify it works with literal_eval """
+ expected = (1, {"a": 9}, (True, False, None))
+ actual = ast.literal_eval('(1, {"a": 9}, (True, False, None))')
+ self.assertEqual(actual, expected, "Simple python expressions are not working with literal_eval")
+
+ def test_03_literal_eval_arithmetic(self):
+ """ Try arithmetic expression in literal_eval to verify it does not work """
+ with self.assertRaises(ValueError):
+ ast.literal_eval('(1, {"a": 2*9}, (True, False, None))')
+
+ def test_04_literal_eval_forbidden(self):
+ """ Try forbidden expressions in literal_eval to verify they are not allowed """
+ with self.assertRaises(ValueError):
+ ast.literal_eval('{"a": True.__class__}')
+
+ @mute_logger('openerp.tools.safe_eval')
+ def test_05_safe_eval_forbiddon(self):
+ """ Try forbidden expressions in safe_eval to verify they are not allowed (open) """
+ with self.assertRaises(ValueError):
+ safe_eval('open("/etc/passwd","r")')
+
+
+# samples use effective TLDs from the Mozilla public suffix
+# list at http://publicsuffix.org
+SAMPLES = [
+ ('"Raoul Grosbedon" <raoul@chirurgiens-dentistes.fr> ', 'Raoul Grosbedon', 'raoul@chirurgiens-dentistes.fr'),
+ ('ryu+giga-Sushi@aizubange.fukushima.jp', '', 'ryu+giga-Sushi@aizubange.fukushima.jp'),
+ ('Raoul chirurgiens-dentistes.fr', 'Raoul chirurgiens-dentistes.fr', ''),
+ (" Raoul O'hara <!@historicalsociety.museum>", "Raoul O'hara", '!@historicalsociety.museum'),
+]
+
+class TestBase(TransactionCase):
def test_00_res_partner_name_create(self):
- cr, uid = self.cr, self.uid
- parse = self.res_partner._parse_partner_name
- for text, name, mail in self.samples:
- self.assertEqual((name,mail), parse(text), 'Partner name parsing failed')
- partner_id, dummy = self.res_partner.name_create(cr, uid, text)
- partner = self.res_partner.browse(cr, uid, partner_id)
+ res_partner = self.env['res.partner']
+ parse = res_partner._parse_partner_name
+ for text, name, mail in SAMPLES:
+ self.assertEqual((name, mail), parse(text), 'Partner name parsing failed')
+ partner_id, dummy = res_partner.name_create(text)
+ partner = res_partner.browse(partner_id)
self.assertEqual(name or mail, partner.name, 'Partner name incorrect')
self.assertEqual(mail or False, partner.email, 'Partner email incorrect')
def test_10_res_partner_find_or_create(self):
- cr,uid = self.cr, self.uid
- email = self.samples[0][0]
- partner_id, dummy = self.res_partner.name_create(cr, uid, email)
- found_id = self.res_partner.find_or_create(cr, uid, email)
+ res_partner = self.env['res.partner']
+ email = SAMPLES[0][0]
+ partner_id, dummy = res_partner.name_create(email)
+ found_id = res_partner.find_or_create(email)
self.assertEqual(partner_id, found_id, 'find_or_create failed')
- partner_id2, dummy2 = self.res_partner.name_create(cr, uid, 'sarah.john@connor.com')
- found_id2 = self.res_partner.find_or_create(cr, uid, 'john@connor.com')
+ partner_id2, dummy2 = res_partner.name_create('sarah.john@connor.com')
+ found_id2 = res_partner.find_or_create('john@connor.com')
self.assertNotEqual(partner_id2, found_id2, 'john@connor.com match sarah.john@connor.com')
- new_id = self.res_partner.find_or_create(cr, uid, self.samples[1][0])
+ new_id = res_partner.find_or_create(SAMPLES[1][0])
self.assertTrue(new_id > partner_id, 'find_or_create failed - should have created new one')
- new_id2 = self.res_partner.find_or_create(cr, uid, self.samples[2][0])
+ new_id2 = res_partner.find_or_create(SAMPLES[2][0])
self.assertTrue(new_id2 > new_id, 'find_or_create failed - should have created new one again')
def test_15_res_partner_name_search(self):
- cr,uid = self.cr, self.uid
- for name, active in [
+ res_partner = self.env['res.partner']
+ DATA = [
('"A Raoul Grosbedon" <raoul@chirurgiens-dentistes.fr>', False),
('B Raoul chirurgiens-dentistes.fr', True),
("C Raoul O'hara <!@historicalsociety.museum>", True),
('ryu+giga-Sushi@aizubange.fukushima.jp', True),
- ]:
- partner_id, dummy = self.res_partner.name_create(cr, uid, name, context={'default_active': active})
- partners = self.res_partner.name_search(cr, uid, 'Raoul')
+ ]
+ for name, active in DATA:
+ partner_id, dummy = res_partner.with_context(default_active=active).name_create(name)
+ partners = res_partner.name_search('Raoul')
self.assertEqual(len(partners), 2, 'Incorrect search number result for name_search')
- partners = self.res_partner.name_search(cr, uid, 'Raoul', limit=1)
+ partners = res_partner.name_search('Raoul', limit=1)
self.assertEqual(len(partners), 1, 'Incorrect search number result for name_search with a limit')
self.assertEqual(partners[0][1], 'B Raoul chirurgiens-dentistes.fr', 'Incorrect partner returned, should be the first active')
def test_20_res_partner_address_sync(self):
- cr, uid = self.cr, self.uid
- ghoststep = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
- {'name': 'GhostStep',
- 'is_company': True,
- 'street': 'Main Street, 10',
- 'phone': '123456789',
- 'email': 'info@ghoststep.com',
- 'vat': 'BE0477472701',
- 'type': 'contact'}))
- p1 = self.res_partner.browse(cr, uid, self.res_partner.name_create(cr, uid, 'Denis Bladesmith <denis.bladesmith@ghoststep.com>')[0])
+ res_partner = self.env['res.partner']
+ ghoststep = res_partner.create({
+ 'name': 'GhostStep',
+ 'is_company': True,
+ 'street': 'Main Street, 10',
+ 'phone': '123456789',
+ 'email': 'info@ghoststep.com',
+ 'vat': 'BE0477472701',
+ 'type': 'contact',
+ })
+ p1 = res_partner.browse(res_partner.name_create('Denis Bladesmith <denis.bladesmith@ghoststep.com>')[0])
self.assertEqual(p1.type, 'contact', 'Default type must be "contact"')
p1phone = '123456789#34'
p1.write({'phone': p1phone,
'parent_id': ghoststep.id})
- p1.refresh()
self.assertEqual(p1.street, ghoststep.street, 'Address fields must be synced')
self.assertEqual(p1.phone, p1phone, 'Phone should be preserved after address sync')
self.assertEqual(p1.type, 'contact', 'Type should be preserved after address sync')
@@ -84,13 +117,11 @@ class test_base(common.TransactionCase):
p1street = 'Different street, 42'
p1.write({'street': p1street,
'type': 'invoice'})
- p1.refresh(), ghoststep.refresh()
self.assertEqual(p1.street, p1street, 'Address fields must not be synced after turning sync off')
self.assertNotEqual(ghoststep.street, p1street, 'Parent address must never be touched')
# turn on sync again
p1.write({'type': 'contact'})
- p1.refresh()
self.assertEqual(p1.street, ghoststep.street, 'Address fields must be synced again')
self.assertEqual(p1.phone, p1phone, 'Phone should be preserved after address sync')
self.assertEqual(p1.type, 'contact', 'Type should be preserved after address sync')
@@ -99,213 +130,197 @@ class test_base(common.TransactionCase):
# Modify parent, sync to children
ghoststreet = 'South Street, 25'
ghoststep.write({'street': ghoststreet})
- p1.refresh()
self.assertEqual(p1.street, ghoststreet, 'Address fields must be synced automatically')
self.assertEqual(p1.phone, p1phone, 'Phone should not be synced')
self.assertEqual(p1.email, 'denis.bladesmith@ghoststep.com', 'Email should be preserved after sync')
p1street = 'My Street, 11'
p1.write({'street': p1street})
- ghoststep.refresh()
self.assertEqual(ghoststep.street, ghoststreet, 'Touching contact should never alter parent')
def test_30_res_partner_first_contact_sync(self):
""" Test initial creation of company/contact pair where contact address gets copied to
company """
- cr, uid = self.cr, self.uid
- ironshield = self.res_partner.browse(cr, uid, self.res_partner.name_create(cr, uid, 'IronShield')[0])
+ res_partner = self.env['res.partner']
+ ironshield = res_partner.browse(res_partner.name_create('IronShield')[0])
self.assertFalse(ironshield.is_company, 'Partners are not companies by default')
self.assertEqual(ironshield.type, 'contact', 'Default type must be "contact"')
ironshield.write({'type': 'contact'})
- p1 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
- {'name': 'Isen Hardearth',
- 'street': 'Strongarm Avenue, 12',
- 'parent_id': ironshield.id}))
+
+ p1 = res_partner.create({
+ 'name': 'Isen Hardearth',
+ 'street': 'Strongarm Avenue, 12',
+ 'parent_id': ironshield.id,
+ })
self.assertEquals(p1.type, 'contact', 'Default type must be "contact", not the copied parent type')
- ironshield.refresh()
self.assertEqual(ironshield.street, p1.street, 'Address fields should be copied to company')
- def test_40_res_partner_address_getc(self):
+ def test_40_res_partner_address_get(self):
""" Test address_get address resolution mechanism: it should first go down through descendants,
stopping when encountering another is_copmany entity, then go up, stopping again at the first
is_company entity or the root ancestor and if nothing matches, it should use the provided partner
itself """
- cr, uid = self.cr, self.uid
- elmtree = self.res_partner.browse(cr, uid, self.res_partner.name_create(cr, uid, 'Elmtree')[0])
- branch1 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Branch 1',
- 'parent_id': elmtree.id,
- 'is_company': True}))
- leaf10 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 10',
- 'parent_id': branch1.id,
- 'type': 'invoice'}))
- branch11 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Branch 11',
- 'parent_id': branch1.id,
- 'type': 'other'}))
- leaf111 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 111',
- 'parent_id': branch11.id,
- 'type': 'delivery'}))
+ res_partner = self.env['res.partner']
+ elmtree = res_partner.browse(res_partner.name_create('Elmtree')[0])
+ branch1 = res_partner.create({'name': 'Branch 1',
+ 'parent_id': elmtree.id,
+ 'is_company': True})
+ leaf10 = res_partner.create({'name': 'Leaf 10',
+ 'parent_id': branch1.id,
+ 'type': 'invoice'})
+ branch11 = res_partner.create({'name': 'Branch 11',
+ 'parent_id': branch1.id,
+ 'type': 'other'})
+ leaf111 = res_partner.create({'name': 'Leaf 111',
+ 'parent_id': branch11.id,
+ 'type': 'delivery'})
branch11.write({'is_company': False}) # force is_company after creating 1rst child
- branch2 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Branch 2',
- 'parent_id': elmtree.id,
- 'is_company': True}))
- leaf21 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 21',
- 'parent_id': branch2.id,
- 'type': 'delivery'}))
- leaf22 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 22',
- 'parent_id': branch2.id}))
- leaf23 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 23',
- 'parent_id': branch2.id,
- 'type': 'contact'}))
+ branch2 = res_partner.create({'name': 'Branch 2',
+ 'parent_id': elmtree.id,
+ 'is_company': True})
+ leaf21 = res_partner.create({'name': 'Leaf 21',
+ 'parent_id': branch2.id,
+ 'type': 'delivery'})
+ leaf22 = res_partner.create({'name': 'Leaf 22',
+ 'parent_id': branch2.id})
+ leaf23 = res_partner.create({'name': 'Leaf 23',
+ 'parent_id': branch2.id,
+ 'type': 'contact'})
# go up, stop at branch1
- self.assertEqual(self.res_partner.address_get(cr, uid, [leaf111.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(leaf111.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf111.id,
'invoice': leaf10.id,
'contact': branch1.id,
'other': branch11.id}, 'Invalid address resolution')
- self.assertEqual(self.res_partner.address_get(cr, uid, [branch11.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(branch11.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf111.id,
'invoice': leaf10.id,
'contact': branch1.id,
'other': branch11.id}, 'Invalid address resolution')
# go down, stop at at all child companies
- self.assertEqual(self.res_partner.address_get(cr, uid, [elmtree.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(elmtree.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': elmtree.id,
'invoice': elmtree.id,
'contact': elmtree.id,
'other': elmtree.id}, 'Invalid address resolution')
# go down through children
- self.assertEqual(self.res_partner.address_get(cr, uid, [branch1.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(branch1.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf111.id,
'invoice': leaf10.id,
'contact': branch1.id,
'other': branch11.id}, 'Invalid address resolution')
- self.assertEqual(self.res_partner.address_get(cr, uid, [branch2.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(branch2.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf21.id,
'invoice': branch2.id,
'contact': branch2.id,
'other': branch2.id}, 'Invalid address resolution. Company is the first encountered contact, therefore default for unfound addresses.')
# go up then down through siblings
- self.assertEqual(self.res_partner.address_get(cr, uid, [leaf21.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(leaf21.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf21.id,
'invoice': branch2.id,
'contact': branch2.id,
'other': branch2.id}, 'Invalid address resolution, should scan commercial entity ancestor and its descendants')
- self.assertEqual(self.res_partner.address_get(cr, uid, [leaf22.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(leaf22.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf21.id,
'invoice': leaf22.id,
'contact': leaf22.id,
'other': leaf22.id}, 'Invalid address resolution, should scan commercial entity ancestor and its descendants')
- self.assertEqual(self.res_partner.address_get(cr, uid, [leaf23.id], ['delivery', 'invoice', 'contact', 'other']),
+ self.assertEqual(leaf23.address_get(['delivery', 'invoice', 'contact', 'other']),
{'delivery': leaf21.id,
'invoice': leaf23.id,
'contact': leaf23.id,
'other': leaf23.id}, 'Invalid address resolution, `default` should only override if no partner with specific type exists')
# empty adr_pref means only 'contact'
- self.assertEqual(self.res_partner.address_get(cr, uid, [elmtree.id], []),
+ self.assertEqual(elmtree.address_get([]),
{'contact': elmtree.id}, 'Invalid address resolution, no contact means commercial entity ancestor')
- self.assertEqual(self.res_partner.address_get(cr, uid, [leaf111.id], []),
+ self.assertEqual(leaf111.address_get([]),
{'contact': branch1.id}, 'Invalid address resolution, no contact means finding contact in ancestors')
branch11.write({'type': 'contact'})
- self.assertEqual(self.res_partner.address_get(cr, uid, [leaf111.id], []),
+ self.assertEqual(leaf111.address_get([]),
{'contact': branch11.id}, 'Invalid address resolution, branch11 should now be contact')
-
- def test_50_res_partner_commercial_sync(self):
- cr, uid = self.cr, self.uid
- p0 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
- {'name': 'Sigurd Sunknife',
- 'email': 'ssunknife@gmail.com'}))
- sunhelm = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
- {'name': 'Sunhelm',
- 'is_company': True,
- 'street': 'Rainbow Street, 13',
- 'phone': '1122334455',
- 'email': 'info@sunhelm.com',
- 'vat': 'BE0477472701',
- 'child_ids': [(4, p0.id),
- (0, 0, {'name': 'Alrik Greenthorn',
- 'email': 'agr@sunhelm.com'})],
- }))
- p1 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
- {'name': 'Otto Blackwood',
- 'email': 'otto.blackwood@sunhelm.com',
- 'parent_id': sunhelm.id}))
- p11 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
- {'name': 'Gini Graywool',
- 'email': 'ggr@sunhelm.com',
- 'parent_id': p1.id}))
- p2 = self.res_partner.browse(cr, uid, self.res_partner.search(cr, uid,
- [('email', '=', 'agr@sunhelm.com')])[0])
- self.res_partner.write(cr, uid, sunhelm.id, {'child_ids': [(0, 0, {'name': 'Ulrik Greenthorn',
- 'email': 'ugr@sunhelm.com'})]})
- p3 = self.res_partner.browse(cr, uid, self.res_partner.search(cr, uid,
- [('email', '=', 'ugr@sunhelm.com')])[0])
+ def test_50_res_partner_commercial_sync(self):
+ res_partner = self.env['res.partner']
+ p0 = res_partner.create({'name': 'Sigurd Sunknife',
+ 'email': 'ssunknife@gmail.com'})
+ sunhelm = res_partner.create({'name': 'Sunhelm',
+ 'is_company': True,
+ 'street': 'Rainbow Street, 13',
+ 'phone': '1122334455',
+ 'email': 'info@sunhelm.com',
+ 'vat': 'BE0477472701',
+ 'child_ids': [(4, p0.id),
+ (0, 0, {'name': 'Alrik Greenthorn',
+ 'email': 'agr@sunhelm.com'})]})
+ p1 = res_partner.create({'name': 'Otto Blackwood',
+ 'email': 'otto.blackwood@sunhelm.com',
+ 'parent_id': sunhelm.id})
+ p11 = res_partner.create({'name': 'Gini Graywool',
+ 'email': 'ggr@sunhelm.com',
+ 'parent_id': p1.id})
+ p2 = res_partner.search([('email', '=', 'agr@sunhelm.com')], limit=1)
+ sunhelm.write({'child_ids': [(0, 0, {'name': 'Ulrik Greenthorn',
+ 'email': 'ugr@sunhelm.com'})]})
+ p3 = res_partner.search([('email', '=', 'ugr@sunhelm.com')], limit=1)
for p in (p0, p1, p11, p2, p3):
- p.refresh()
self.assertEquals(p.commercial_partner_id, sunhelm, 'Incorrect commercial entity resolution')
self.assertEquals(p.vat, sunhelm.vat, 'Commercial fields must be automatically synced')
sunhelmvat = 'BE0123456789'
sunhelm.write({'vat': sunhelmvat})
for p in (p0, p1, p11, p2, p3):
- p.refresh()
self.assertEquals(p.vat, sunhelmvat, 'Commercial fields must be automatically and recursively synced')
p1vat = 'BE0987654321'
p1.write({'vat': p1vat})
for p in (sunhelm, p0, p11, p2, p3):
- p.refresh()
self.assertEquals(p.vat, sunhelmvat, 'Sync to children should only work downstream and on commercial entities')
# promote p1 to commercial entity
- p1.write({
- 'parent_id': sunhelm.id,
- 'is_company': True,
- 'name': 'Sunhelm Subsidiary'})
- p1.refresh()
+ p1.write({'parent_id': sunhelm.id,
+ 'is_company': True,
+ 'name': 'Sunhelm Subsidiary'})
self.assertEquals(p1.vat, p1vat, 'Setting is_company should stop auto-sync of commercial fields')
self.assertEquals(p1.commercial_partner_id, p1, 'Incorrect commercial entity resolution after setting is_company')
# writing on parent should not touch child commercial entities
sunhelmvat2 = 'BE0112233445'
sunhelm.write({'vat': sunhelmvat2})
- p1.refresh()
self.assertEquals(p1.vat, p1vat, 'Setting is_company should stop auto-sync of commercial fields')
- p0.refresh()
self.assertEquals(p0.vat, sunhelmvat2, 'Commercial fields must be automatically synced')
def test_60_read_group(self):
- cr, uid = self.cr, self.uid
- title_sir = self.res_partner_title.create(cr, uid, {'name': 'Sir...'})
- title_lady = self.res_partner_title.create(cr, uid, {'name': 'Lady...'})
+ title_sir = self.env['res.partner.title'].create({'name': 'Sir...'})
+ title_lady = self.env['res.partner.title'].create({'name': 'Lady...'})
test_users = [
- {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend', 'date': '2015-03-28', 'title': title_lady},
- {'name': 'Alice', 'login': 'alice2', 'color': 0, 'function': 'Friend', 'date': '2015-01-28', 'title': title_lady},
- {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend', 'date': '2015-03-02', 'title': title_sir},
- {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper', 'date': '2015-03-20', 'title': title_lady},
- {'name': 'Nab', 'login': 'nab', 'color': -3, 'function': '5$ Wrench', 'date': '2014-09-10', 'title': title_sir},
- {'name': 'Nab', 'login': 'nab-she', 'color': 6, 'function': '5$ Wrench', 'date': '2014-01-02', 'title': title_lady},
+ {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend', 'date': '2015-03-28', 'title': title_lady.id},
+ {'name': 'Alice', 'login': 'alice2', 'color': 0, 'function': 'Friend', 'date': '2015-01-28', 'title': title_lady.id},
+ {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend', 'date': '2015-03-02', 'title': title_sir.id},
+ {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper', 'date': '2015-03-20', 'title': title_lady.id},
+ {'name': 'Nab', 'login': 'nab', 'color': -3, 'function': '5$ Wrench', 'date': '2014-09-10', 'title': title_sir.id},
+ {'name': 'Nab', 'login': 'nab-she', 'color': 6, 'function': '5$ Wrench', 'date': '2014-01-02', 'title': title_lady.id},
]
- ids = [self.res_users.create(cr, uid, u) for u in test_users]
- domain = [('id', 'in', ids)]
+ res_users = self.env['res.users']
+ user_ids = [res_users.create(vals).id for vals in test_users]
+ domain = [('id', 'in', user_ids)]
# group on local char field without domain and without active_test (-> empty WHERE clause)
- groups_data = self.res_users.read_group(cr, uid, [], fields=['login'], groupby=['login'], orderby='login DESC', context={'active_test': False})
+ groups_data = res_users.with_context(active_test=False).read_group([], fields=['login'], groupby=['login'], orderby='login DESC')
self.assertGreater(len(groups_data), 6, "Incorrect number of results when grouping on a field")
# group on local char field with limit
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['login'], groupby=['login'], orderby='login DESC', limit=3, offset=3)
+ groups_data = res_users.read_group(domain, fields=['login'], groupby=['login'], orderby='login DESC', limit=3, offset=3)
self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field with limit")
self.assertEqual(['bob', 'alice2', 'alice'], [g['login'] for g in groups_data], 'Result mismatch')
# group on inherited char field, aggregate on int field (second groupby ignored on purpose)
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color', 'function'], groupby=['function', 'login'])
+ groups_data = res_users.read_group(domain, fields=['name', 'color', 'function'], groupby=['function', 'login'])
self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
self.assertEqual(['5$ Wrench', 'Eavesdropper', 'Friend'], [g['function'] for g in groups_data], 'incorrect read_group order')
for group_data in groups_data:
@@ -313,210 +328,186 @@ class test_base(common.TransactionCase):
self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
# group on inherited char field, reverse order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby='name', orderby='name DESC')
+ groups_data = res_users.read_group(domain, fields=['name', 'color'], groupby='name', orderby='name DESC')
self.assertEqual(['Nab', 'Eve', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
# group on int field, default ordering
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['color'], groupby='color')
+ groups_data = res_users.read_group(domain, fields=['color'], groupby='color')
self.assertEqual([-3, 0, 1, 2, 3, 6], [g['color'] for g in groups_data], 'Incorrect ordering of the list')
# multi group, second level is int field, should still be summed in first level grouping
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby=['name', 'color'], orderby='name DESC')
+ groups_data = res_users.read_group(domain, fields=['name', 'color'], groupby=['name', 'color'], orderby='name DESC')
self.assertEqual(['Nab', 'Eve', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([3, 3, 2, 1], [g['color'] for g in groups_data], 'Incorrect ordering of the list')
# group on inherited char field, multiple orders with directions
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby='name', orderby='color DESC, name')
+ groups_data = res_users.read_group(domain, fields=['name', 'color'], groupby='name', orderby='color DESC, name')
self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
self.assertEqual(['Eve', 'Nab', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([1, 2, 1, 2], [g['name_count'] for g in groups_data], 'Incorrect number of results')
# group on inherited date column (res_partner.date) -> Year-Month, default ordering
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'date'], groupby=['date'])
+ groups_data = res_users.read_group(domain, fields=['function', 'color', 'date'], groupby=['date'])
self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
self.assertEqual(['January 2014', 'September 2014', 'January 2015', 'March 2015'], [g['date'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([1, 1, 1, 3], [g['date_count'] for g in groups_data], 'Incorrect number of results')
# group on inherited date column (res_partner.date) -> Year-Month, custom order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'date'], groupby=['date'], orderby='date DESC')
+ groups_data = res_users.read_group(domain, fields=['function', 'color', 'date'], groupby=['date'], orderby='date DESC')
self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
self.assertEqual(['March 2015', 'January 2015', 'September 2014', 'January 2014'], [g['date'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([3, 1, 1, 1], [g['date_count'] for g in groups_data], 'Incorrect number of results')
# group on inherited many2one (res_partner.title), default order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'])
+ groups_data = res_users.read_group(domain, fields=['function', 'color', 'title'], groupby=['title'])
self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
# m2o is returned as a (id, label) pair
- self.assertEqual([(title_lady, 'Lady...'), (title_sir, 'Sir...')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
+ self.assertEqual([(title_lady.id, 'Lady...'), (title_sir.id, 'Sir...')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([4, 2], [g['title_count'] for g in groups_data], 'Incorrect number of results')
self.assertEqual([10, -1], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
# group on inherited many2one (res_partner.title), reversed natural order
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="title desc")
+ groups_data = res_users.read_group(domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="title desc")
self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
# m2o is returned as a (id, label) pair
- self.assertEqual([(title_sir, 'Sir...'), (title_lady, 'Lady...')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
+ self.assertEqual([(title_sir.id, 'Sir...'), (title_lady.id, 'Lady...')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
# group on inherited many2one (res_partner.title), multiple orders with m2o in second position
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="color desc, title desc")
+ groups_data = res_users.read_group(domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="color desc, title desc")
self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
# m2o is returned as a (id, label) pair
- self.assertEqual([(title_lady, 'Lady...'), (title_sir, 'Sir...')], [g['title'] for g in groups_data], 'Incorrect ordering of the result')
+ self.assertEqual([(title_lady.id, 'Lady...'), (title_sir.id, 'Sir...')], [g['title'] for g in groups_data], 'Incorrect ordering of the result')
self.assertEqual([4, 2], [g['title_count'] for g in groups_data], 'Incorrect number of results')
self.assertEqual([10, -1], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
# group on inherited many2one (res_partner.title), ordered by other inherited field (color)
- groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby='color')
+ groups_data = res_users.read_group(domain, fields=['function', 'color', 'title'], groupby=['title'], orderby='color')
self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
# m2o is returned as a (id, label) pair
- self.assertEqual([(title_sir, 'Sir...'), (title_lady, 'Lady...')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
+ self.assertEqual([(title_sir.id, 'Sir...'), (title_lady.id, 'Lady...')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
-class test_partner_recursion(common.TransactionCase):
+class TestPartnerRecursion(TransactionCase):
def setUp(self):
- super(test_partner_recursion,self).setUp()
- self.res_partner = self.registry('res.partner')
- cr, uid = self.cr, self.uid
- self.p1 = self.res_partner.name_create(cr, uid, 'Elmtree')[0]
- self.p2 = self.res_partner.create(cr, uid, {'name': 'Elmtree Child 1', 'parent_id': self.p1})
- self.p3 = self.res_partner.create(cr, uid, {'name': 'Elmtree Grand-Child 1.1', 'parent_id': self.p2})
+ super(TestPartnerRecursion,self).setUp()
+ res_partner = self.env['res.partner']
+ self.p1 = res_partner.browse(res_partner.name_create('Elmtree')[0])
+ self.p2 = res_partner.create({'name': 'Elmtree Child 1', 'parent_id': self.p1.id})
+ self.p3 = res_partner.create({'name': 'Elmtree Grand-Child 1.1', 'parent_id': self.p2.id})
# split 101, 102, 103 tests to force SQL rollback between them
def test_101_res_partner_recursion(self):
- cr, uid, p1, p3 = self.cr, self.uid, self.p1, self.p3
- self.assertRaises(ValidationError, self.res_partner.write, cr, uid, [p1], {'parent_id': p3})
+ with self.assertRaises(ValidationError):
+ self.p1.write({'parent_id': self.p3.id})
def test_102_res_partner_recursion(self):
- cr, uid, p2, p3 = self.cr, self.uid, self.p2, self.p3
- self.assertRaises(ValidationError, self.res_partner.write, cr, uid, [p2], {'parent_id': p3})
+ with self.assertRaises(ValidationError):
+ self.p2.write({'parent_id': self.p3.id})
def test_103_res_partner_recursion(self):
- cr, uid, p3 = self.cr, self.uid, self.p3
- self.assertRaises(ValidationError, self.res_partner.write, cr, uid, [p3], {'parent_id': p3})
+ with self.assertRaises(ValidationError):
+ self.p3.write({'parent_id': self.p3.id})
def test_104_res_partner_recursion_indirect_cycle(self):
""" Indirect hacky write to create cycle in children """
- cr, uid, p2, p3 = self.cr, self.uid, self.p2, self.p3
- p3b = self.res_partner.create(cr, uid, {'name': 'Elmtree Grand-Child 1.2', 'parent_id': self.p2})
- self.assertRaises(ValidationError, self.res_partner.write, cr, uid, [p2],
- {'child_ids': [(1, p3, {'parent_id': p3b}), (1, p3b, {'parent_id': p3})]})
+ p3b = self.p1.create({'name': 'Elmtree Grand-Child 1.2', 'parent_id': self.p2.id})
+ with self.assertRaises(ValidationError):
+ self.p2.write({'child_ids': [(1, self.p3.id, {'parent_id': p3b.id}),
+ (1, p3b.id, {'parent_id': self.p3.id})]})
def test_110_res_partner_recursion_multi_update(self):
""" multi-write on several partners in same hierarchy must not trigger a false cycle detection """
- cr, uid, p1, p2, p3 = self.cr, self.uid, self.p1, self.p2, self.p3
- self.assertTrue(self.res_partner.write(cr, uid, [p1,p2,p3], {'phone': '123456'}))
+ ps = self.p1 + self.p2 + self.p3
+ self.assertTrue(ps.write({'phone': '123456'}))
+
-class test_translation(common.TransactionCase):
+class TestParentStore(TransactionCase):
+ """ Verify that parent_store computation is done right """
def setUp(self):
- super(test_translation, self).setUp()
- self.res_category = self.registry('res.partner.category')
- self.ir_translation = self.registry('ir.translation')
- cr, uid = self.cr, self.uid
- self.registry('ir.translation').load_module_terms(cr, ['base'], ['fr_FR'])
- self.cat_id = self.res_category.create(cr, uid, {'name': 'Customers'})
- self.ir_translation.create(cr, uid, {'name': 'res.partner.category,name', 'module':'base',
- 'value': 'Clients', 'res_id': self.cat_id, 'lang':'fr_FR', 'state':'translated', 'type': 'model'})
-
- def test_101_create_translated_record(self):
- cr, uid = self.cr, self.uid
-
- no_context_cat = self.res_category.browse(cr, uid, self.cat_id)
- self.assertEqual(no_context_cat.name, 'Customers', "Error in basic name_get")
-
- fr_context_cat = self.res_category.browse(cr, uid, self.cat_id, context={'lang':'fr_FR'})
- self.assertEqual(fr_context_cat.name, 'Clients', "Translation not found")
-
- def test_102_duplicate_record(self):
- cr, uid = self.cr, self.uid
- self.new_cat_id = self.res_category.copy(cr, uid, self.cat_id, context={'lang':'fr_FR'})
-
- no_context_cat = self.res_category.browse(cr, uid, self.new_cat_id)
- self.assertEqual(no_context_cat.name, 'Customers', "Duplication did not set untranslated value")
-
- fr_context_cat = self.res_category.browse(cr, uid, self.new_cat_id, context={'lang':'fr_FR'})
- self.assertEqual(fr_context_cat.name, 'Clients', "Did not found translation for initial value")
-
- def test_103_duplicate_record_fr(self):
- cr, uid = self.cr, self.uid
- self.new_fr_cat_id = self.res_category.copy(cr, uid, self.cat_id, default={'name': 'Clients (copie)'}, context={'lang':'fr_FR'})
-
- no_context_cat = self.res_category.browse(cr, uid, self.new_fr_cat_id)
- self.assertEqual(no_context_cat.name, 'Customers', "Duplication erased original untranslated value")
-
- fr_context_cat = self.res_category.browse(cr, uid, self.new_fr_cat_id, context={'lang':'fr_FR'})
- self.assertEqual(fr_context_cat.name, 'Clients (copie)', "Did not used default value for translated value")
-
- def test_104_orderby_translated_field(self):
- """ Test search ordered by a translated field. """
- # create a category with a French translation
- category = self.env['res.partner.category'].create({'name': 'Padawans'})
- category_fr = category.with_context(lang='fr_FR')
- category_fr.write({'name': 'Apprentis'})
- # search for categories, and sort them by (translated) name
- categories = category_fr.search([('id', 'in', [self.cat_id, category.id])], order='name')
- self.assertEqual(categories.ids, [category.id, self.cat_id],
- "Search ordered by translated name should return Padawans (Apprentis) before Customers (Clients)")
-
-test_state = None
-#: Stores state information across multiple test classes
-def setUpModule():
- global test_state
- test_state = {}
-def tearDownModule():
- global test_state
- test_state = None
-
-class TestPhaseInstall00(unittest.TestCase):
- """
- WARNING: Relies on tests being run in alphabetical order
- """
- @classmethod
- def setUpClass(cls):
- cls.state = None
-
- def test_00_setup(self):
- type(self).state = 'init'
-
- @common.at_install(False)
- def test_01_no_install(self):
- type(self).state = 'error'
-
- def test_02_check(self):
- self.assertEqual(
- self.state, 'init',
- "Testcase state should not have been transitioned from 00")
-
-class TestPhaseInstall01(unittest.TestCase):
- at_install = False
-
- def test_default_norun(self):
- self.fail("An unmarket test in a non-at-install case should not run")
-
- @common.at_install(True)
- def test_set_run(self):
- test_state['set_at_install'] = True
-
-class TestPhaseInstall02(unittest.TestCase):
- """
- Can't put the check for test_set_run in the same class: if
- @common.at_install does not work for test_set_run, it won't work for
- the other one either. Thus move checking of whether test_set_run has
- correctly run indeed to a separate class.
-
- Warning: relies on *classes* being run in alphabetical order in test
- modules
- """
- def test_check_state(self):
- self.assertTrue(
- test_state.get('set_at_install'),
- "The flag should be set if local overriding of runstate")
-
-if __name__ == '__main__':
- unittest.main()
+ super(TestParentStore, self).setUp()
+ # pretend the pool has finished loading to avoid deferring parent_store computation
+ self.patch(self.registry, '_init', False)
+
+ # force res_partner_category.copy() to copy children
+ category = self.env['res.partner.category']
+ self.patch(category._fields['child_ids'], 'copy', True)
+ self.patch(category._columns['child_ids'], 'copy', True)
+
+ # setup categories
+ self.root = category.create({'name': 'Root category'})
+ self.cat0 = category.create({'name': 'Parent category', 'parent_id': self.root.id})
+ self.cat1 = category.create({'name': 'Child 1', 'parent_id': self.cat0.id})
+ self.cat2 = category.create({'name': 'Child 2', 'parent_id': self.cat0.id})
+ self.cat21 = category.create({'name': 'Child 2-1', 'parent_id': self.cat2.id})
+
+ def test_duplicate_parent(self):
+ """ Duplicate the parent category and verify that the children have been duplicated too """
+ new_cat0 = self.cat0.copy()
+ new_struct = new_cat0.search([('parent_id', 'child_of', new_cat0.id)])
+ self.assertEqual(len(new_struct), 4, "After duplication, the new object must have the childs records")
+ old_struct = new_cat0.search([('parent_id', 'child_of', self.cat0.id)])
+ self.assertEqual(len(old_struct), 4, "After duplication, previous record must have old childs records only")
+ self.assertFalse(new_struct & old_struct, "After duplication, nodes should not be mixed")
+
+ def test_duplicate_children_01(self):
+ """ Duplicate the children then reassign them to the new parent (1st method). """
+ new_cat1 = self.cat1.copy()
+ new_cat2 = self.cat2.copy()
+ new_cat0 = self.cat0.copy({'child_ids': []})
+ (new_cat1 + new_cat2).write({'parent_id': new_cat0.id})
+ new_struct = new_cat0.search([('parent_id', 'child_of', new_cat0.id)])
+ self.assertEqual(len(new_struct), 4, "After duplication, the new object must have the childs records")
+ old_struct = new_cat0.search([('parent_id', 'child_of', self.cat0.id)])
+ self.assertEqual(len(old_struct), 4, "After duplication, previous record must have old childs records only")
+ self.assertFalse(new_struct & old_struct, "After duplication, nodes should not be mixed")
+
+ def test_duplicate_children_02(self):
+ """ Duplicate the children then reassign them to the new parent (2nd method). """
+ new_cat1 = self.cat1.copy()
+ new_cat2 = self.cat2.copy()
+ new_cat0 = self.cat0.copy({'child_ids': [(6, 0, (new_cat1 + new_cat2).ids)]})
+ new_struct = new_cat0.search([('parent_id', 'child_of', new_cat0.id)])
+ self.assertEqual(len(new_struct), 4, "After duplication, the new object must have the childs records")
+ old_struct = new_cat0.search([('parent_id', 'child_of', self.cat0.id)])
+ self.assertEqual(len(old_struct), 4, "After duplication, previous record must have old childs records only")
+ self.assertFalse(new_struct & old_struct, "After duplication, nodes should not be mixed")
+
+ def test_duplicate_children_03(self):
+ """ Duplicate the children then reassign them to the new parent (3rd method). """
+ new_cat1 = self.cat1.copy()
+ new_cat2 = self.cat2.copy()
+ new_cat0 = self.cat0.copy({'child_ids': []})
+ new_cat0.write({'child_ids': [(4, new_cat1.id), (4, new_cat2.id)]})
+ new_struct = new_cat0.search([('parent_id', 'child_of', new_cat0.id)])
+ self.assertEqual(len(new_struct), 4, "After duplication, the new object must have the childs records")
+ old_struct = new_cat0.search([('parent_id', 'child_of', self.cat0.id)])
+ self.assertEqual(len(old_struct), 4, "After duplication, previous record must have old childs records only")
+ self.assertFalse(new_struct & old_struct, "After duplication, nodes should not be mixed")
+
+
+class TestGroups(TransactionCase):
+
+ def test_res_groups_fullname_search(self):
+ all_groups = self.env['res.groups'].search([])
+
+ groups = all_groups.search([('full_name', 'like', '%Sale%')])
+ self.assertItemsEqual(groups.ids, [g.id for g in all_groups if 'Sale' in g.full_name],
+ "did not match search for 'Sale'")
+
+ groups = all_groups.search([('full_name', 'like', '%Technical%')])
+ self.assertItemsEqual(groups.ids, [g.id for g in all_groups if 'Technical' in g.full_name],
+ "did not match search for 'Technical'")
+
+ groups = all_groups.search([('full_name', 'like', '%Sales /%')])
+ self.assertItemsEqual(groups.ids, [g.id for g in all_groups if 'Sales /' in g.full_name],
+ "did not match search for 'Sales /'")
+
+ groups = all_groups.search([('full_name', 'in', ['Administration / Access Rights','Contact Creation'])])
+ self.assertTrue(groups, "did not match search for 'Administration / Access Rights' and 'Contact Creation'")
diff --git a/openerp/addons/base/tests/test_basecase.py b/openerp/addons/base/tests/test_basecase.py
index 42b47749bf7..8bd78f860fa 100644
--- a/openerp/addons/base/tests/test_basecase.py
+++ b/openerp/addons/base/tests/test_basecase.py
@@ -1,86 +1,72 @@
# -*- coding: utf-8 -*-
-import unittest
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp.tests import common
+from odoo.tests import common
-class test_single_transaction_case(common.SingleTransactionCase):
+
+class TestSingleTransactionCase(common.SingleTransactionCase):
"""
Check the whole-class transaction behavior of SingleTransactionCase.
"""
def test_00(self):
- """Create a partner."""
- cr, uid = self.cr, self.uid
- self.registry('res.partner').create(cr, uid, {'name': 'test_per_class_teardown_partner'})
- ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
- self.assertEqual(1, len(ids), "Test partner not found.")
+ """ Create a partner. """
+ self.env['res.partner'].create({'name': 'test_per_class_teardown_partner'})
+ partners = self.env['res.partner'].search([('name', '=', 'test_per_class_teardown_partner')])
+ self.assertEqual(1, len(partners), "Test partner not found.")
def test_01(self):
- """Find the created partner."""
- cr, uid = self.cr, self.uid
- ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
- self.assertEqual(1, len(ids), "Test partner not found.")
+ """ Find the created partner. """
+ partners = self.env['res.partner'].search([('name', '=', 'test_per_class_teardown_partner')])
+ self.assertEqual(1, len(partners), "Test partner not found.")
def test_20a(self):
""" Create a partner with a XML ID """
- cr, uid = self.cr, self.uid
- res_partner = self.registry('res.partner')
- ir_model_data = self.registry('ir.model.data')
- pid, _ = res_partner.name_create(cr, uid, 'Mr Blue')
- ir_model_data.create(cr, uid, {'name': 'test_partner_blue',
- 'module': 'base',
- 'model': 'res.partner',
- 'res_id': pid})
+ pid, _ = self.env['res.partner'].name_create('Mr Blue')
+ self.env['ir.model.data'].create({'name': 'test_partner_blue',
+ 'module': 'base',
+ 'model': 'res.partner',
+ 'res_id': pid})
+
def test_20b(self):
""" Resolve xml id with ref() and browse_ref() """
- cr, uid = self.cr, self.uid
- res_partner = self.registry('res.partner')
xid = 'base.test_partner_blue'
- p_ref = self.ref(xid)
- self.assertTrue(p_ref, "ref() should resolve xid to database ID")
- partner = res_partner.browse(cr, uid, p_ref)
- p_browse_ref = self.browse_ref(xid)
- self.assertEqual(partner, p_browse_ref, "browse_ref() should resolve xid to browse records")
-
+ partner = self.env.ref(xid)
+ pid = self.ref(xid)
+ self.assertTrue(pid, "ref() should resolve xid to database ID")
+ self.assertEqual(pid, partner.id, "ref() is not consistent with env.ref()")
+ partner2 = self.browse_ref(xid)
+ self.assertEqual(partner, partner2, "browse_ref() should resolve xid to browse records")
-class test_transaction_case(common.TransactionCase):
+class TestTransactionCase(common.TransactionCase):
"""
Check the per-method transaction behavior of TransactionCase.
"""
def test_00(self):
- """Create a partner."""
- cr, uid = self.cr, self.uid
- ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
- self.assertEqual(0, len(ids), "Test partner found.")
- self.registry('res.partner').create(cr, uid, {'name': 'test_per_class_teardown_partner'})
- ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
- self.assertEqual(1, len(ids), "Test partner not found.")
+ """ Create a partner. """
+ partners = self.env['res.partner'].search([('name', '=', 'test_per_class_teardown_partner')])
+ self.assertEqual(0, len(partners), "Test partner found.")
+ self.env['res.partner'].create({'name': 'test_per_class_teardown_partner'})
+ partners = self.env['res.partner'].search([('name', '=', 'test_per_class_teardown_partner')])
+ self.assertEqual(1, len(partners), "Test partner not found.")
def test_01(self):
- """Don't find the created partner."""
- cr, uid = self.cr, self.uid
- ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
- self.assertEqual(0, len(ids), "Test partner found.")
-
+ """ Don't find the created partner. """
+ partners = self.env['res.partner'].search([('name', '=', 'test_per_class_teardown_partner')])
+ self.assertEqual(0, len(partners), "Test partner found.")
def test_20a(self):
""" Create a partner with a XML ID then resolve xml id with ref() and browse_ref() """
- cr, uid = self.cr, self.uid
- res_partner = self.registry('res.partner')
- ir_model_data = self.registry('ir.model.data')
- pid, _ = res_partner.name_create(cr, uid, 'Mr Yellow')
- ir_model_data.create(cr, uid, {'name': 'test_partner_yellow',
- 'module': 'base',
- 'model': 'res.partner',
- 'res_id': pid})
+ pid, _ = self.env['res.partner'].name_create('Mr Yellow')
+ self.env['ir.model.data'].create({'name': 'test_partner_yellow',
+ 'module': 'base',
+ 'model': 'res.partner',
+ 'res_id': pid})
xid = 'base.test_partner_yellow'
- p_ref = self.ref(xid)
- self.assertEquals(p_ref, pid, "ref() should resolve xid to database ID")
- partner = res_partner.browse(cr, uid, pid)
- p_browse_ref = self.browse_ref(xid)
- self.assertEqual(partner, p_browse_ref, "browse_ref() should resolve xid to browse records")
-
-if __name__ == '__main__':
- unittest.main()
+ partner = self.env.ref(xid)
+ pid = self.ref(xid)
+ self.assertEquals(pid, partner.id, "ref() should resolve xid to database ID")
+ partner2 = self.browse_ref(xid)
+ self.assertEqual(partner, partner2, "browse_ref() should resolve xid to browse records")
diff --git a/openerp/addons/base/tests/test_db_cursor.py b/openerp/addons/base/tests/test_db_cursor.py
index 9fa61493f99..c58c6c3fccc 100644
--- a/openerp/addons/base/tests/test_db_cursor.py
+++ b/openerp/addons/base/tests/test_db_cursor.py
@@ -1,18 +1,19 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
import unittest
-import openerp
-from openerp.tools.misc import mute_logger
-from openerp.tests import common
+import odoo
+from odoo.tests import common
+from odoo.tools.misc import mute_logger
ADMIN_USER_ID = common.ADMIN_USER_ID
def registry():
- return openerp.modules.registry.RegistryManager.get(common.get_db_name())
+ return odoo.registry(common.get_db_name())
-class test_cr_execute(unittest.TestCase):
+class TestExecute(unittest.TestCase):
""" Try cr.execute with wrong parameters """
@mute_logger('openerp.sql_db')
diff --git a/openerp/addons/base/tests/test_expression.py b/openerp/addons/base/tests/test_expression.py
index e3b94aac3b3..62f42f92bdd 100644
--- a/openerp/addons/base/tests/test_expression.py
+++ b/openerp/addons/base/tests/test_expression.py
@@ -1,128 +1,99 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import openerp
-import openerp.osv.expression as expression
-from openerp.osv.expression import get_unaccent_wrapper
-from openerp.osv.orm import BaseModel
-import openerp.tests.common as common
+import psycopg2
-class test_expression(common.TransactionCase):
+from odoo.models import BaseModel
+from odoo.tests.common import TransactionCase
+from odoo.tools import mute_logger
+import odoo.osv.expression as expression
- def _reinit_mock(self):
- self.query_list = list()
-
- def _mock_base_model_where_calc(self, model, *args, **kwargs):
- """ Mock build_email to be able to test its values. Store them into
- some internal variable for latter processing. """
- self.query_list.append(self._base_model_where_calc(model, *args, **kwargs))
- # return the lastly stored query, the one the ORM wants to perform
- return self.query_list[-1]
-
- def setUp(self):
- super(test_expression, self).setUp()
- # Mock BaseModel._where_calc(), to be able to proceed to some tests about generated expression
- self._reinit_mock()
- self._base_model_where_calc = BaseModel._where_calc
- BaseModel._where_calc = lambda model, cr, uid, args, context: self._mock_base_model_where_calc(model, cr, uid, args, context)
- def tearDown(self):
- # Remove mocks
- BaseModel._where_calc = self._base_model_where_calc
- super(test_expression, self).tearDown()
+class TestExpression(TransactionCase):
def test_00_in_not_in_m2m(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
# Create 4 partners with no category, or one or two categories (out of two categories).
+ categories = self.env['res.partner.category']
+ cat_a = categories.create({'name': 'test_expression_category_A'})
+ cat_b = categories.create({'name': 'test_expression_category_B'})
- categories = registry('res.partner.category')
- cat_a = categories.create(cr, uid, {'name': 'test_expression_category_A'})
- cat_b = categories.create(cr, uid, {'name': 'test_expression_category_B'})
-
- partners = registry('res.partner')
- a = partners.create(cr, uid, {'name': 'test_expression_partner_A', 'category_id': [(6, 0, [cat_a])]})
- b = partners.create(cr, uid, {'name': 'test_expression_partner_B', 'category_id': [(6, 0, [cat_b])]})
- ab = partners.create(cr, uid, {'name': 'test_expression_partner_AB', 'category_id': [(6, 0, [cat_a, cat_b])]})
- c = partners.create(cr, uid, {'name': 'test_expression_partner_C'})
+ partners = self.env['res.partner']
+ a = partners.create({'name': 'test_expression_partner_A', 'category_id': [(6, 0, [cat_a.id])]})
+ b = partners.create({'name': 'test_expression_partner_B', 'category_id': [(6, 0, [cat_b.id])]})
+ ab = partners.create({'name': 'test_expression_partner_AB', 'category_id': [(6, 0, [cat_a.id, cat_b.id])]})
+ c = partners.create({'name': 'test_expression_partner_C'})
# The tests.
# On a one2many or many2many field, `in` should be read `contains` (and
# `not in` should be read `doesn't contain`.
- with_a = partners.search(cr, uid, [('category_id', 'in', [cat_a])])
- self.assertEqual(set([a, ab]), set(with_a), "Search for category_id in cat_a failed.")
+ with_a = partners.search([('category_id', 'in', [cat_a.id])])
+ self.assertEqual(a + ab, with_a, "Search for category_id in cat_a failed.")
- with_b = partners.search(cr, uid, [('category_id', 'in', [cat_b])])
- self.assertEqual(set([ab, b]), set(with_b), "Search for category_id in cat_b failed.")
+ with_b = partners.search([('category_id', 'in', [cat_b.id])])
+ self.assertEqual(b + ab, with_b, "Search for category_id in cat_b failed.")
# Partners with the category A or the category B.
- with_a_or_b = partners.search(cr, uid, [('category_id', 'in', [cat_a, cat_b])])
- self.assertEqual(set([ab, a, b]), set(with_a_or_b), "Search for category_id contains cat_a or cat_b failed.")
+ with_a_or_b = partners.search([('category_id', 'in', [cat_a.id, cat_b.id])])
+ self.assertEqual(a + b + ab, with_a_or_b, "Search for category_id contains cat_a or cat_b failed.")
# Show that `contains list` is really `contains element or contains element`.
- with_a_or_with_b = partners.search(cr, uid, ['|', ('category_id', 'in', [cat_a]), ('category_id', 'in', [cat_b])])
- self.assertEqual(set([ab, a, b]), set(with_a_or_with_b), "Search for category_id contains cat_a or contains cat_b failed.")
+ with_a_or_with_b = partners.search(['|', ('category_id', 'in', [cat_a.id]), ('category_id', 'in', [cat_b.id])])
+ self.assertEqual(a + b + ab, with_a_or_with_b, "Search for category_id contains cat_a or contains cat_b failed.")
# If we change the OR in AND...
- with_a_and_b = partners.search(cr, uid, [('category_id', 'in', [cat_a]), ('category_id', 'in', [cat_b])])
- self.assertEqual(set([ab]), set(with_a_and_b), "Search for category_id contains cat_a and cat_b failed.")
+ with_a_and_b = partners.search([('category_id', 'in', [cat_a.id]), ('category_id', 'in', [cat_b.id])])
+ self.assertEqual(ab, with_a_and_b, "Search for category_id contains cat_a and cat_b failed.")
# Partners without category A and without category B.
- without_a_or_b = partners.search(cr, uid, [('category_id', 'not in', [cat_a, cat_b])])
- self.assertTrue(all(i not in without_a_or_b for i in [a, b, ab]), "Search for category_id doesn't contain cat_a or cat_b failed (1).")
+ without_a_or_b = partners.search([('category_id', 'not in', [cat_a.id, cat_b.id])])
+ self.assertFalse(without_a_or_b & (a + b + ab), "Search for category_id doesn't contain cat_a or cat_b failed (1).")
self.assertTrue(c in without_a_or_b, "Search for category_id doesn't contain cat_a or cat_b failed (2).")
# Show that `doesn't contain list` is really `doesn't contain element and doesn't contain element`.
- without_a_and_without_b = partners.search(cr, uid, [('category_id', 'not in', [cat_a]), ('category_id', 'not in', [cat_b])])
- self.assertTrue(all(i not in without_a_and_without_b for i in [a, b, ab]), "Search for category_id doesn't contain cat_a and cat_b failed (1).")
+ without_a_and_without_b = partners.search([('category_id', 'not in', [cat_a.id]), ('category_id', 'not in', [cat_b.id])])
+ self.assertFalse(without_a_and_without_b & (a + b + ab), "Search for category_id doesn't contain cat_a and cat_b failed (1).")
self.assertTrue(c in without_a_and_without_b, "Search for category_id doesn't contain cat_a and cat_b failed (2).")
# We can exclude any partner containing the category A.
- without_a = partners.search(cr, uid, [('category_id', 'not in', [cat_a])])
+ without_a = partners.search([('category_id', 'not in', [cat_a.id])])
self.assertTrue(a not in without_a, "Search for category_id doesn't contain cat_a failed (1).")
self.assertTrue(ab not in without_a, "Search for category_id doesn't contain cat_a failed (2).")
- self.assertTrue(set([b, c]).issubset(set(without_a)), "Search for category_id doesn't contain cat_a failed (3).")
+ self.assertLessEqual(b + c, without_a, "Search for category_id doesn't contain cat_a failed (3).")
# (Obviously we can do the same for cateory B.)
- without_b = partners.search(cr, uid, [('category_id', 'not in', [cat_b])])
+ without_b = partners.search([('category_id', 'not in', [cat_b.id])])
self.assertTrue(b not in without_b, "Search for category_id doesn't contain cat_b failed (1).")
self.assertTrue(ab not in without_b, "Search for category_id doesn't contain cat_b failed (2).")
- self.assertTrue(set([a, c]).issubset(set(without_b)), "Search for category_id doesn't contain cat_b failed (3).")
-
- # We can't express the following: Partners with a category different than A.
- # with_any_other_than_a = ...
- # self.assertTrue(a not in with_any_other_than_a, "Search for category_id with any other than cat_a failed (1).")
- # self.assertTrue(ab in with_any_other_than_a, "Search for category_id with any other than cat_a failed (2).")
+ self.assertLessEqual(a + c, without_b, "Search for category_id doesn't contain cat_b failed (3).")
def test_05_not_str_m2m(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- partners = registry('res.partner')
- categories = registry('res.partner.category')
+ partners = self.env['res.partner']
+ categories = self.env['res.partner.category']
- cats = {}
- for cat in 'A B AB'.split():
- cats[cat] = categories.create(cr, uid, {'name': cat})
+ cids = {}
+ for name in 'A B AB'.split():
+ cids[name] = categories.create({'name': name}).id
- _partners = {
+ partners_config = {
'0': [],
- 'a': [cats['A']],
- 'b': [cats['B']],
- 'ab': [cats['AB']],
- 'a b': [cats['A'], cats['B']],
- 'b ab': [cats['B'], cats['AB']],
+ 'a': [cids['A']],
+ 'b': [cids['B']],
+ 'ab': [cids['AB']],
+ 'a b': [cids['A'], cids['B']],
+ 'b ab': [cids['B'], cids['AB']],
}
pids = {}
- for p in _partners:
- pids[p] = partners.create(cr, uid, {'name': p, 'category_id': [(6, 0, _partners[p])]})
+ for name, cat_ids in partners_config.iteritems():
+ pids[name] = partners.create({'name': name, 'category_id': [(6, 0, cat_ids)]}).id
base_domain = [('id', 'in', pids.values())]
def test(op, value, expected):
- ids = set(partners.search(cr, uid, base_domain + [('category_id', op, value)]))
- expected_ids = set(map(pids.__getitem__, expected))
- self.assertSetEqual(ids, expected_ids, '%s %r should return %r' % (op, value, expected))
+ found_ids = partners.search(base_domain + [('category_id', op, value)]).ids
+ expected_ids = [pids[name] for name in expected]
+ self.assertItemsEqual(found_ids, expected_ids, '%s %r should return %r' % (op, value, expected))
test('=', 'A', ['a', 'a b'])
test('!=', 'B', ['0', 'a', 'ab'])
@@ -130,73 +101,573 @@ class test_expression(common.TransactionCase):
test('not ilike', 'B', ['0', 'a'])
test('not like', 'AB', ['0', 'a', 'b', 'a b'])
- def test_10_expression_parse(self):
+ def test_10_hierarchy_in_m2m(self):
+ Partner = self.env['res.partner']
+ Category = self.env['res.partner.category']
+
+ # search through m2m relation
+ partners = Partner.search([('category_id', 'child_of', self.ref('base.res_partner_category_0'))])
+ self.assertTrue(partners)
+
+ # setup test partner categories
+ categ_root = Category.create({'name': 'Root category'})
+ categ_0 = Category.create({'name': 'Parent category', 'parent_id': categ_root.id})
+ categ_1 = Category.create({'name': 'Child1', 'parent_id': categ_0.id})
+
+ # test hierarchical search in m2m with child id (list of ids)
+ cats = Category.search([('id', 'child_of', categ_root.ids)])
+ self.assertEqual(len(cats), 3)
+
+ # test hierarchical search in m2m with child id (single id)
+ cats = Category.search([('id', 'child_of', categ_root.id)])
+ self.assertEqual(len(cats), 3)
+
+ # test hierarchical search in m2m with child ids
+ cats = Category.search([('id', 'child_of', (categ_0 + categ_1).ids)])
+ self.assertEqual(len(cats), 2)
+
+ # test hierarchical search in m2m with child ids
+ cats = Category.search([('id', 'child_of', categ_0.ids)])
+ self.assertEqual(len(cats), 2)
+
+ # test hierarchical search in m2m with child ids
+ cats = Category.search([('id', 'child_of', categ_1.ids)])
+ self.assertEqual(len(cats), 1)
+
+ # test hierarchical search in m2m with parent id (list of ids)
+ cats = Category.search([('id', 'parent_of', categ_1.ids)])
+ self.assertEqual(len(cats), 3)
+
+ # test hierarchical search in m2m with parent id (single id)
+ cats = Category.search([('id', 'parent_of', categ_1.id)])
+ self.assertEqual(len(cats), 3)
+
+ # test hierarchical search in m2m with parent ids
+ cats = Category.search([('id', 'parent_of', (categ_root + categ_0).ids)])
+ self.assertEqual(len(cats), 2)
+
+ # test hierarchical search in m2m with parent ids
+ cats = Category.search([('id', 'parent_of', categ_0.ids)])
+ self.assertEqual(len(cats), 2)
+
+ # test hierarchical search in m2m with parent ids
+ cats = Category.search([('id', 'parent_of', categ_root.ids)])
+ self.assertEqual(len(cats), 1)
+
+ def test_10_equivalent_id(self):
+ # equivalent queries
+ Currency = self.env['res.currency']
+ non_currency_id = max(Currency.search([]).ids) + 1003
+ res_0 = Currency.search([])
+ res_1 = Currency.search([('name', 'not like', 'probably_unexisting_name')])
+ self.assertEqual(res_0, res_1)
+ res_2 = Currency.search([('id', 'not in', [non_currency_id])])
+ self.assertEqual(res_0, res_2)
+ res_3 = Currency.search([('id', 'not in', [])])
+ self.assertEqual(res_0, res_3)
+ res_4 = Currency.search([('id', '!=', False)])
+ self.assertEqual(res_0, res_4)
+
+ # equivalent queries, integer and string
+ Partner = self.env['res.partner']
+ all_partners = Partner.search([])
+ self.assertTrue(len(all_partners) > 1)
+ one = all_partners[0]
+ others = all_partners[1:]
+
+ res_1 = Partner.search([('id', '=', one.id)])
+ self.assertEqual(one, res_1)
+ # Partner.search([('id', '!=', others)]) # not permitted
+ res_2 = Partner.search([('id', 'not in', others.ids)])
+ self.assertEqual(one, res_2)
+ res_3 = Partner.search(['!', ('id', '!=', one.id)])
+ self.assertEqual(one, res_3)
+ res_4 = Partner.search(['!', ('id', 'in', others.ids)])
+ self.assertEqual(one, res_4)
+ # res_5 = Partner.search([('id', 'in', one)]) # TODO make it permitted, just like for child_of
+ # self.assertEqual(one, res_5)
+ res_6 = Partner.search([('id', 'in', [one.id])])
+ self.assertEqual(one, res_6)
+ res_7 = Partner.search([('name', '=', one.name)])
+ self.assertEqual(one, res_7)
+ res_8 = Partner.search([('name', 'in', [one.name])])
+ # res_9 = Partner.search([('name', 'in', one.name)]) # TODO
+
+ def test_15_m2o(self):
+ Partner = self.env['res.partner']
+
+ # testing equality with name
+ partners = Partner.search([('parent_id', '=', 'Agrolait')])
+ self.assertTrue(partners)
+
+ # testing the in operator with name
+ partners = Partner.search([('parent_id', 'in', 'Agrolait')])
+ self.assertTrue(partners)
+
+ # testing the in operator with a list of names
+ partners = Partner.search([('parent_id', 'in', ['Agrolait', 'ASUStek'])])
+ self.assertTrue(partners)
+
+ # check if many2one works with empty search list
+ partners = Partner.search([('company_id', 'in', [])])
+ self.assertFalse(partners)
+
+ # create new company with partners, and partners with no company
+ company2 = self.env['res.company'].create({'name': 'Acme 2'})
+ for i in xrange(4):
+ Partner.create({'name': 'P of Acme %s' % i, 'company_id': company2.id})
+ for i in xrange(4):
+ Partner.create({'name': 'P of All %s' % i, 'company_id': False})
+
+ # check if many2one works with negative empty list
+ all_partners = Partner.search([])
+ res_partners = Partner.search(['|', ('company_id', 'not in', []), ('company_id', '=', False)])
+ self.assertEqual(all_partners, res_partners, "not in [] fails")
+
+ # check that many2one will pick the correct records with a list
+ partners = Partner.search([('company_id', 'in', [False])])
+ self.assertTrue(len(partners) >= 4, "We should have at least 4 partners with no company")
+
+ # check that many2one will exclude the correct records with a list
+ partners = Partner.search([('company_id', 'not in', [1])])
+ self.assertTrue(len(partners) >= 4, "We should have at least 4 partners not related to company #1")
+
+ # check that many2one will exclude the correct records with a list and False
+ partners = Partner.search(['|', ('company_id', 'not in', [1]),
+ ('company_id', '=', False)])
+ self.assertTrue(len(partners) >= 8, "We should have at least 8 partners not related to company #1")
+
+ # check that multi-level expressions also work
+ partners = Partner.search([('company_id.partner_id', 'in', [])])
+ self.assertFalse(partners)
+
+ # check that multi-level expressions with negative op work
+ all_partners = Partner.search([('company_id', '!=', False)])
+ res_partners = Partner.search([('company_id.partner_id', 'not in', [])])
+ self.assertEqual(all_partners, res_partners, "not in [] fails")
+
+ # Test the '(not) like/in' behavior. res.partner and its parent_id
+ # column are used because parent_id is a many2one, allowing to test the
+ # Null value, and there are actually some null and non-null values in
+ # the demo data.
+ all_partners = Partner.search([])
+ non_partner_id = max(all_partners.ids) + 1
+
+ with_parent = all_partners.filtered(lambda p: p.parent_id)
+ without_parent = all_partners.filtered(lambda p: not p.parent_id)
+ with_website = all_partners.filtered(lambda p: p.website)
+
+ # We treat null values differently than in SQL. For instance in SQL:
+ # SELECT id FROM res_partner WHERE parent_id NOT IN (0)
+ # will return only the records with non-null parent_id.
+ # SELECT id FROM res_partner WHERE parent_id IN (0)
+ # will return expectedly nothing (our ids always begin at 1).
+ # This means the union of those two results will give only some
+ # records, but not all present in database.
+ #
+ # When using domains and the ORM's search method, we think it is
+ # more intuitive that the union returns all the records, and that
+ # a domain like ('parent_id', 'not in', [0]) will return all
+ # the records. For instance, if you perform a search for the companies
+ # that don't have OpenERP has a parent company, you expect to find,
+ # among others, the companies that don't have parent company.
+ #
+
+ # existing values be treated similarly if we simply check that some
+ # existing value belongs to them.
+ res_0 = Partner.search([('parent_id', 'not like', 'probably_unexisting_name')]) # get all rows, included null parent_id
+ self.assertEqual(res_0, all_partners)
+ res_1 = Partner.search([('parent_id', 'not in', [non_partner_id])]) # get all rows, included null parent_id
+ self.assertEqual(res_1, all_partners)
+ res_2 = Partner.search([('parent_id', '!=', False)]) # get rows with not null parent_id, deprecated syntax
+ self.assertEqual(res_2, with_parent)
+ res_3 = Partner.search([('parent_id', 'not in', [])]) # get all rows, included null parent_id
+ self.assertEqual(res_3, all_partners)
+ res_4 = Partner.search([('parent_id', 'not in', [False])]) # get rows with not null parent_id
+ self.assertEqual(res_4, with_parent)
+ res_4b = Partner.search([('parent_id', 'not ilike', '')]) # get only rows without parent
+ self.assertEqual(res_4b, without_parent)
+
+ # The results of these queries, when combined with queries 0..4 must
+ # give the whole set of ids.
+ res_5 = Partner.search([('parent_id', 'like', 'probably_unexisting_name')])
+ self.assertFalse(res_5)
+ res_6 = Partner.search([('parent_id', 'in', [non_partner_id])])
+ self.assertFalse(res_6)
+ res_7 = Partner.search([('parent_id', '=', False)])
+ self.assertEqual(res_7, without_parent)
+ res_8 = Partner.search([('parent_id', 'in', [])])
+ self.assertFalse(res_8)
+ res_9 = Partner.search([('parent_id', 'in', [False])])
+ self.assertEqual(res_9, without_parent)
+ res_9b = Partner.search([('parent_id', 'ilike', '')]) # get those with a parent
+ self.assertEqual(res_9b, with_parent)
+
+ # These queries must return exactly the results than the queries 0..4,
+ # i.e. not ... in ... must be the same as ... not in ... .
+ res_10 = Partner.search(['!', ('parent_id', 'like', 'probably_unexisting_name')])
+ self.assertEqual(res_0, res_10)
+ res_11 = Partner.search(['!', ('parent_id', 'in', [non_partner_id])])
+ self.assertEqual(res_1, res_11)
+ res_12 = Partner.search(['!', ('parent_id', '=', False)])
+ self.assertEqual(res_2, res_12)
+ res_13 = Partner.search(['!', ('parent_id', 'in', [])])
+ self.assertEqual(res_3, res_13)
+ res_14 = Partner.search(['!', ('parent_id', 'in', [False])])
+ self.assertEqual(res_4, res_14)
+
+ # Testing many2one field is not enough, a regular char field is tested
+ res_15 = Partner.search([('website', 'in', [])])
+ self.assertFalse(res_15)
+ res_16 = Partner.search([('website', 'not in', [])])
+ self.assertEqual(res_16, all_partners)
+ res_17 = Partner.search([('website', '!=', False)])
+ self.assertEqual(res_17, with_website)
+
+ # check behavior for required many2one fields: currency_id is required
+ companies = self.env['res.company'].search([])
+ res_101 = companies.search([('currency_id', 'not ilike', '')]) # get no companies
+ self.assertFalse(res_101)
+ res_102 = companies.search([('currency_id', 'ilike', '')]) # get all companies
+ self.assertEqual(res_102, companies)
+
+ def test_in_operator(self):
+ """ check that we can use the 'in' operator for plain fields """
+ menus = self.env['ir.ui.menu'].search([('sequence', 'in', [1, 2, 10, 20])])
+ self.assertTrue(menus)
+
+ def test_15_o2m(self):
+ Partner = self.env['res.partner']
+
+ # test one2many operator with empty search list
+ partners = Partner.search([('child_ids', 'in', [])])
+ self.assertFalse(partners)
+
+ # test one2many operator with False
+ partners = Partner.search([('child_ids', '=', False)])
+ for partner in partners:
+ self.assertFalse(partner.child_ids)
+
+ # verify domain evaluation for one2many != False and one2many == False
+ categories = self.env['res.partner.category'].search([])
+ parents = categories.search([('child_ids', '!=', False)])
+ self.assertEqual(parents, categories.filtered(lambda c: c.child_ids))
+ leafs = categories.search([('child_ids', '=', False)])
+ self.assertEqual(leafs, categories.filtered(lambda c: not c.child_ids))
+
+ # test many2many operator with empty search list
+ partners = Partner.search([('category_id', 'in', [])])
+ self.assertFalse(partners)
+
+ # test many2many operator with False
+ partners = Partner.search([('category_id', '=', False)])
+ for partner in partners:
+ self.assertFalse(partner.category_id)
+
+ # filtering on nonexistent value across x2many should return nothing
+ partners = Partner.search([('child_ids.city', '=', 'foo')])
+ self.assertFalse(partners)
+
+ def test_15_equivalent_one2many_1(self):
+ Company = self.env['res.company']
+ company3 = Company.create({'name': 'Acme 3'})
+ company4 = Company.create({'name': 'Acme 4', 'parent_id': company3.id})
+
+ # one2many towards same model
+ res_1 = Company.search([('child_ids', 'in', company3.child_ids.ids)]) # any company having a child of company3 as child
+ self.assertEqual(res_1, company3)
+ res_2 = Company.search([('child_ids', 'in', company3.child_ids[0].ids)]) # any company having the first child of company3 as child
+ self.assertEqual(res_2, company3)
+
+ # child_of x returns x and its children (direct or not).
+ expected = company3 + company4
+ res_1 = Company.search([('id', 'child_of', [company3.id])])
+ self.assertEqual(res_1, expected)
+ res_2 = Company.search([('id', 'child_of', company3.id)])
+ self.assertEqual(res_2, expected)
+ res_3 = Company.search([('id', 'child_of', [company3.name])])
+ self.assertEqual(res_3, expected)
+ res_4 = Company.search([('id', 'child_of', company3.name)])
+ self.assertEqual(res_4, expected)
+
+ # parent_of x returns x and its parents (direct or not).
+ expected = company3 + company4
+ res_1 = Company.search([('id', 'parent_of', [company4.id])])
+ self.assertEqual(res_1, expected)
+ res_2 = Company.search([('id', 'parent_of', company4.id)])
+ self.assertEqual(res_2, expected)
+ res_3 = Company.search([('id', 'parent_of', [company4.name])])
+ self.assertEqual(res_3, expected)
+ res_4 = Company.search([('id', 'parent_of', company4.name)])
+ self.assertEqual(res_4, expected)
+
+ # try testing real subsets with IN/NOT IN
+ Partner = self.env['res.partner']
+ Users = self.env['res.users']
+ p1, _ = Partner.name_create("Dédé Boitaclou")
+ p2, _ = Partner.name_create("Raoulette Pizza O'poil")
+ u1a = Users.create({'login': 'dbo', 'partner_id': p1}).id
+ u1b = Users.create({'login': 'dbo2', 'partner_id': p1}).id
+ u2 = Users.create({'login': 'rpo', 'partner_id': p2}).id
+ self.assertEqual([p1], Partner.search([('user_ids', 'in', u1a)]).ids, "o2m IN accept single int on right side")
+ self.assertEqual([p1], Partner.search([('user_ids', '=', 'Dédé Boitaclou')]).ids, "o2m NOT IN matches none on the right side")
+ self.assertEqual([], Partner.search([('user_ids', 'in', [10000])]).ids, "o2m NOT IN matches none on the right side")
+ self.assertEqual([p1,p2], Partner.search([('user_ids', 'in', [u1a,u2])]).ids, "o2m IN matches any on the right side")
+ all_ids = Partner.search([]).ids
+ self.assertEqual(set(all_ids) - set([p1]), set(Partner.search([('user_ids', 'not in', u1a)]).ids), "o2m NOT IN matches none on the right side")
+ self.assertEqual(set(all_ids) - set([p1]), set(Partner.search([('user_ids', '!=', 'Dédé Boitaclou')]).ids), "o2m NOT IN matches none on the right side")
+ self.assertEqual(set(all_ids) - set([p1,p2]), set(Partner.search([('user_ids', 'not in', [u1b, u2])]).ids), "o2m NOT IN matches none on the right side")
+
+ def test_15_equivalent_one2many_2(self):
+ Currency = self.env['res.currency']
+ CurrencyRate = self.env['res.currency.rate']
+
+ # create a currency and a currency rate
+ currency = Currency.create({'name': 'ZZZ', 'symbol': 'ZZZ', 'rounding': 1.0})
+ currency_rate = CurrencyRate.create({'name': '2010-01-01', 'currency_id': currency.id, 'rate': 1.0})
+ non_currency_id = currency_rate.id + 1000
+ default_currency = Currency.browse(1)
+
+ # search the currency via its rates one2many (the one2many must point back at the currency)
+ currency_rate1 = CurrencyRate.search([('name', 'not like', 'probably_unexisting_name')])
+ currency_rate2 = CurrencyRate.search([('id', 'not in', [non_currency_id])])
+ self.assertEqual(currency_rate1, currency_rate2)
+ currency_rate3 = CurrencyRate.search([('id', 'not in', [])])
+ self.assertEqual(currency_rate1, currency_rate3)
+
+ # one2many towards another model
+ res_3 = Currency.search([('rate_ids', 'in', default_currency.rate_ids.ids)]) # currencies having a rate of main currency
+ self.assertEqual(res_3, default_currency)
+ res_4 = Currency.search([('rate_ids', 'in', default_currency.rate_ids[0].ids)]) # currencies having first rate of main currency
+ self.assertEqual(res_4, default_currency)
+ res_5 = Currency.search([('rate_ids', 'in', default_currency.rate_ids[0].id)]) # currencies having first rate of main currency
+ self.assertEqual(res_5, default_currency)
+ # res_6 = Currency.search([('rate_ids', 'in', [default_currency.rate_ids[0].name])])
+ # res_7 = Currency.search([('rate_ids', '=', default_currency.rate_ids[0].name)])
+ # res_8 = Currency.search([('rate_ids', 'like', default_currency.rate_ids[0].name)])
+
+ res_9 = Currency.search([('rate_ids', 'like', 'probably_unexisting_name')])
+ self.assertFalse(res_9)
+ # Currency.search([('rate_ids', 'unexisting_op', 'probably_unexisting_name')]) # TODO expected exception
+
+ # get the currencies referenced by some currency rates using a weird negative domain
+ res_10 = Currency.search([('rate_ids', 'not like', 'probably_unexisting_name')])
+ res_11 = Currency.search([('rate_ids', 'not in', [non_currency_id])])
+ self.assertEqual(res_10, res_11)
+ res_12 = Currency.search([('rate_ids', '!=', False)])
+ self.assertEqual(res_10, res_12)
+ res_13 = Currency.search([('rate_ids', 'not in', [])])
+ self.assertEqual(res_10, res_13)
+
+ def test_20_expression_parse(self):
# TDE note: those tests have been added when refactoring the expression.parse() method.
- # They come in addition to the already existing test_osv_expression.yml; maybe some tests
+ # They come in addition to the already existing tests; maybe some tests
# will be a bit redundant
- registry, cr, uid = self.registry, self.cr, self.uid
- users_obj = registry('res.users')
+ Users = self.env['res.users']
# Create users
- a = users_obj.create(cr, uid, {'name': 'test_A', 'login': 'test_A'})
- b1 = users_obj.create(cr, uid, {'name': 'test_B', 'login': 'test_B'})
- b1_user = users_obj.browse(cr, uid, [b1])[0]
- b2 = users_obj.create(cr, uid, {'name': 'test_B2', 'login': 'test_B2', 'parent_id': b1_user.partner_id.id})
+ a = Users.create({'name': 'test_A', 'login': 'test_A'})
+ b1 = Users.create({'name': 'test_B', 'login': 'test_B'})
+ b2 = Users.create({'name': 'test_B2', 'login': 'test_B2', 'parent_id': b1.partner_id.id})
# Test1: simple inheritance
- user_ids = users_obj.search(cr, uid, [('name', 'like', 'test')])
- self.assertEqual(set(user_ids), set([a, b1, b2]), 'searching through inheritance failed')
- user_ids = users_obj.search(cr, uid, [('name', '=', 'test_B')])
- self.assertEqual(set(user_ids), set([b1]), 'searching through inheritance failed')
+ users = Users.search([('name', 'like', 'test')])
+ self.assertEqual(users, a + b1 + b2, 'searching through inheritance failed')
+ users = Users.search([('name', '=', 'test_B')])
+ self.assertEqual(users, b1, 'searching through inheritance failed')
# Test2: inheritance + relational fields
- user_ids = users_obj.search(cr, uid, [('child_ids.name', 'like', 'test_B')])
- self.assertEqual(set(user_ids), set([b1]), 'searching through inheritance failed')
+ users = Users.search([('child_ids.name', 'like', 'test_B')])
+ self.assertEqual(users, b1, 'searching through inheritance failed')
# Special =? operator mean "is equal if right is set, otherwise always True"
- user_ids = users_obj.search(cr, uid, [('name', 'like', 'test'), ('parent_id', '=?', False)])
- self.assertEqual(set(user_ids), set([a, b1, b2]), '(x =? False) failed')
- user_ids = users_obj.search(cr, uid, [('name', 'like', 'test'), ('parent_id', '=?', b1_user.partner_id.id)])
- self.assertEqual(set(user_ids), set([b2]), '(x =? id) failed')
+ users = Users.search([('name', 'like', 'test'), ('parent_id', '=?', False)])
+ self.assertEqual(users, a + b1 + b2, '(x =? False) failed')
+ users = Users.search([('name', 'like', 'test'), ('parent_id', '=?', b1.partner_id.id)])
+ self.assertEqual(users, b2, '(x =? id) failed')
+
+ def test_30_normalize_domain(self):
+ norm_domain = domain = ['&', (1, '=', 1), ('a', '=', 'b')]
+ self.assertEqual(norm_domain, expression.normalize_domain(domain), "Normalized domains should be left untouched")
+ domain = [('x', 'in', ['y', 'z']), ('a.v', '=', 'e'), '|', '|', ('a', '=', 'b'), '!', ('c', '>', 'd'), ('e', '!=', 'f'), ('g', '=', 'h')]
+ norm_domain = ['&', '&', '&'] + domain
+ self.assertEqual(norm_domain, expression.normalize_domain(domain), "Non-normalized domains should be properly normalized")
+
+ def test_40_negating_long_expression(self):
+ source = ['!', '&', ('user_id', '=', 4), ('partner_id', 'in', [1, 2])]
+ expect = ['|', ('user_id', '!=', 4), ('partner_id', 'not in', [1, 2])]
+ self.assertEqual(expression.distribute_not(source), expect,
+ "distribute_not on expression applied wrongly")
+
+ pos_leaves = [[('a', 'in', [])], [('d', '!=', 3)]]
+ neg_leaves = [[('a', 'not in', [])], [('d', '=', 3)]]
+
+ source = expression.OR([expression.AND(pos_leaves)] * 1000)
+ expect = source
+ self.assertEqual(expression.distribute_not(source), expect,
+ "distribute_not on long expression without negation operator should not alter it")
+
+ source = ['!'] + source
+ expect = expression.AND([expression.OR(neg_leaves)] * 1000)
+ self.assertEqual(expression.distribute_not(source), expect,
+ "distribute_not on long expression applied wrongly")
+
+ def test_accent(self):
+ if not self.registry.has_unaccent:
+ return
+ Company = self.env['res.company']
+ helene = Company.create({'name': u'Hélène'})
+ self.assertEqual(helene, Company.search([('name','ilike','Helene')]))
+ self.assertEqual(helene, Company.search([('name','ilike','hélène')]))
+ self.assertNotIn(helene, Company.search([('name','not ilike','Helene')]))
+ self.assertNotIn(helene, Company.search([('name','not ilike','hélène')]))
+
+ def test_like_wildcards(self):
+ # check that =like/=ilike expressions are working on an untranslated field
+ Partner = self.env['res.partner']
+ partners = Partner.search([('name', '=like', 'A_U_TeK')])
+ self.assertTrue(len(partners) == 1, "Must match one partner (ASUSTeK)")
+ partners = Partner.search([('name', '=ilike', 'c%')])
+ self.assertTrue(len(partners) >= 1, "Must match one partner (China Export)")
+
+ # check that =like/=ilike expressions are working on translated field
+ Country = self.env['res.country']
+ countries = Country.search([('name', '=like', 'Ind__')])
+ self.assertTrue(len(countries) == 1, "Must match India only")
+ countries = Country.search([('name', '=ilike', 'z%')])
+ self.assertTrue(len(countries) == 3, "Must match only countries with names starting with Z (currently 3)")
+
+ def test_translate_search(self):
+ Country = self.env['res.country']
+ belgium = self.env.ref('base.be')
+ domains = [
+ [('name', '=', 'Belgium')],
+ [('name', 'ilike', 'Belgi')],
+ [('name', 'in', ['Belgium', 'Care Bears'])],
+ ]
+
+ for domain in domains:
+ countries = Country.search(domain)
+ self.assertEqual(countries, belgium)
+
+ def test_long_table_alias(self):
+ # To test the 64 characters limit for table aliases in PostgreSQL
+ self.patch_order('res.users', 'partner_id')
+ self.patch_order('res.partner', 'commercial_partner_id,company_id,name')
+ self.patch_order('res.company', 'parent_id')
+ self.env['res.users'].search([('name', '=', 'test')])
+
+ @mute_logger('openerp.sql_db')
+ def test_invalid(self):
+ """ verify that invalid expressions are refused, even for magic fields """
+ Country = self.env['res.country']
+
+ with self.assertRaises(ValueError):
+ Country.search([('does_not_exist', '=', 'foo')])
+
+ with self.assertRaises(ValueError):
+ Country.search([('create_date', '>>', 'foo')])
+
+ with self.assertRaises(psycopg2.DataError):
+ Country.search([('create_date', '=', "1970-01-01'); --")])
+
+ def test_active(self):
+ # testing for many2many field with category vendor and active=False
+ Partner = self.env['res.partner']
+ vals = {
+ 'name': 'OpenERP Test',
+ 'active': False,
+ 'category_id': [(6, 0, [self.ref("base.res_partner_category_1")])],
+ 'child_ids': [(0, 0, {'name': 'address of OpenERP Test', 'country_id': self.ref("base.be")})],
+ }
+ Partner.create(vals)
+ partner = Partner.search([('category_id', 'ilike', 'vendor'), ('active', '=', False)])
+ self.assertTrue(partner, "Record not Found with category vendor and active False.")
+
+ # testing for one2many field with country Belgium and active=False
+ partner = Partner.search([('child_ids.country_id','=','Belgium'),('active','=',False)])
+ self.assertTrue(partner, "Record not Found with country Belgium and active False.")
+
+ def test_lp1071710(self):
+ """ Check that we can exclude translated fields (bug lp:1071710) """
+ # first install french language
+ self.env['ir.translation'].load_module_terms(['base'], ['fr_FR'])
+
+ # actual test
+ Country = self.env['res.country']
+ be = self.env.ref('base.be')
+ not_be = Country.with_context(lang='fr_FR').search([('name', '!=', 'Belgique')])
+ self.assertNotIn(be, not_be)
+
+ # indirect search via m2o
+ Partner = self.env['res.partner']
+ agrolait = Partner.search([('name', '=', 'Agrolait')])
- def test_20_auto_join(self):
- registry, cr, uid = self.registry, self.cr, self.uid
- unaccent = get_unaccent_wrapper(cr)
+ not_be = Partner.search([('country_id', '!=', 'Belgium')])
+ self.assertNotIn(agrolait, not_be)
+
+ not_be = Partner.with_context(lang='fr_FR').search([('country_id', '!=', 'Belgique')])
+ self.assertNotIn(agrolait, not_be)
+
+
+class TestAutoJoin(TransactionCase):
+
+ def setUp(self):
+ super(TestAutoJoin, self).setUp()
+ # Mock BaseModel._where_calc(), to be able to proceed to some tests about generated expression
+ self._reinit_mock()
+ BaseModel_where_calc = BaseModel._where_calc
+
+ def _where_calc(model, *args, **kwargs):
+ """ Mock `_where_calc` to be able to test its results. Store them
+ into some internal variable for latter processing. """
+ query = BaseModel_where_calc(model, *args, **kwargs)
+ self.query_list.append(query)
+ return query
+
+ self.patch(BaseModel, '_where_calc', _where_calc)
+
+ def _reinit_mock(self):
+ self.query_list = []
+
+ def test_auto_join(self):
+ unaccent = expression.get_unaccent_wrapper(self.cr)
# Get models
- partner_obj = registry('res.partner')
- state_obj = registry('res.country.state')
- bank_obj = registry('res.partner.bank')
+ partner_obj = self.env['res.partner']
+ state_obj = self.env['res.country.state']
+ bank_obj = self.env['res.partner.bank']
# Get test columns
- partner_state_id_col = partner_obj._columns.get('state_id') # many2one on res.partner to res.country.state
- partner_parent_id_col = partner_obj._columns.get('parent_id') # many2one on res.partner to res.partner
- state_country_id_col = state_obj._columns.get('country_id') # many2one on res.country.state on res.country
- partner_child_ids_col = partner_obj._columns.get('child_ids') # one2many on res.partner to res.partner
- partner_bank_ids_col = partner_obj._columns.get('bank_ids') # one2many on res.partner to res.partner.bank
- category_id_col = partner_obj._columns.get('category_id') # many2many on res.partner to res.partner.category
+ def patch_auto_join(model, fname, value):
+ self.patch(model._fields[fname], 'auto_join', value)
+ self.patch(model._columns[fname], '_auto_join', value)
+
+ def patch_domain(model, fname, value):
+ self.patch(model._fields[fname], 'domain', value)
+ self.patch(model._columns[fname], '_domain', value)
# Get country/state data
- country_us_id = registry('res.country').search(cr, uid, [('code', 'like', 'US')])[0]
- state_ids = registry('res.country.state').search(cr, uid, [('country_id', '=', country_us_id)], limit=2)
+ country_us = self.env['res.country'].search([('code', 'like', 'US')], limit=1)
+ states = self.env['res.country.state'].search([('country_id', '=', country_us.id)], limit=2)
# Create demo data: partners and bank object
- p_a = partner_obj.create(cr, uid, {'name': 'test__A', 'state_id': state_ids[0]})
- p_b = partner_obj.create(cr, uid, {'name': 'test__B', 'state_id': state_ids[1]})
- p_aa = partner_obj.create(cr, uid, {'name': 'test__AA', 'parent_id': p_a, 'state_id': state_ids[0]})
- p_ab = partner_obj.create(cr, uid, {'name': 'test__AB', 'parent_id': p_a, 'state_id': state_ids[1]})
- p_ba = partner_obj.create(cr, uid, {'name': 'test__BA', 'parent_id': p_b, 'state_id': state_ids[0]})
- b_aa = bank_obj.create(cr, uid, {'acc_number': '123', 'acc_type': 'bank', 'partner_id': p_aa})
- b_ab = bank_obj.create(cr, uid, {'acc_number': '456', 'acc_type': 'bank', 'partner_id': p_ab})
- b_ba = bank_obj.create(cr, uid, {'acc_number': '789', 'acc_type': 'bank', 'partner_id': p_ba})
+ p_a = partner_obj.create({'name': 'test__A', 'state_id': states[0].id})
+ p_b = partner_obj.create({'name': 'test__B', 'state_id': states[1].id})
+ p_aa = partner_obj.create({'name': 'test__AA', 'parent_id': p_a.id, 'state_id': states[0].id})
+ p_ab = partner_obj.create({'name': 'test__AB', 'parent_id': p_a.id, 'state_id': states[1].id})
+ p_ba = partner_obj.create({'name': 'test__BA', 'parent_id': p_b.id, 'state_id': states[0].id})
+ b_aa = bank_obj.create({'acc_number': '123', 'acc_type': 'bank', 'partner_id': p_aa.id})
+ b_ab = bank_obj.create({'acc_number': '456', 'acc_type': 'bank', 'partner_id': p_ab.id})
+ b_ba = bank_obj.create({'acc_number': '789', 'acc_type': 'bank', 'partner_id': p_ba.id})
# --------------------------------------------------
# Test1: basics about the attribute
# --------------------------------------------------
- category_id_col._auto_join = True
- self.assertRaises(NotImplementedError, partner_obj.search, cr, uid, [('category_id.name', '=', 'foo')])
- category_id_col._auto_join = False
+ patch_auto_join(partner_obj, 'category_id', True)
+ with self.assertRaises(NotImplementedError):
+ partner_obj.search([('category_id.name', '=', 'foo')])
# --------------------------------------------------
# Test2: one2many
@@ -206,9 +677,9 @@ class test_expression(common.TransactionCase):
# Do: one2many without _auto_join
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('bank_ids.sanitized_acc_number', 'like', name_test)])
+ partners = partner_obj.search([('bank_ids.sanitized_acc_number', 'like', name_test)])
# Test result
- self.assertEqual(set(partner_ids), set([p_aa]),
+ self.assertEqual(partners, p_aa,
"_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..'): incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 3,
@@ -221,32 +692,32 @@ class test_expression(common.TransactionCase):
self.assertIn(expected, sql_query[1],
"_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect where condition")
- self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]),
+ self.assertEqual(['%' + name_test + '%'], sql_query[2],
"_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') first query incorrect parameter")
sql_query = self.query_list[2].get_sql()
self.assertIn('res_partner', sql_query[0],
"_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect main table")
self.assertIn('"res_partner"."id" in (%s)', sql_query[1],
"_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect where condition")
- self.assertEqual(set([p_aa]), set(sql_query[2]),
+ self.assertIn(p_aa.id, sql_query[2],
"_auto_join off: ('bank_ids.sanitized_acc_number', 'like', '..') third query incorrect parameter")
# Do: cascaded one2many without _auto_join
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
+ partners = partner_obj.search([('child_ids.bank_ids.id', 'in', [b_aa.id, b_ba.id])])
# Test result
- self.assertEqual(set(partner_ids), set([p_a, p_b]),
+ self.assertEqual(partners, p_a + p_b,
"_auto_join off: ('child_ids.bank_ids.id', 'in', [..]): incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 5,
"_auto_join off: ('child_ids.bank_ids.id', 'in', [..]) should produce 5 queries (1 in res_partner_bank, 4 on res_partner)")
# Do: one2many with _auto_join
- partner_bank_ids_col._auto_join = True
+ patch_auto_join(partner_obj, 'bank_ids', True)
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('bank_ids.sanitized_acc_number', 'like', '12')])
+ partners = partner_obj.search([('bank_ids.sanitized_acc_number', 'like', name_test)])
# Test result
- self.assertEqual(set(partner_ids), set([p_aa]),
+ self.assertEqual(partners, p_aa,
"_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 1,
@@ -263,14 +734,15 @@ class test_expression(common.TransactionCase):
self.assertIn('"res_partner"."id"="res_partner__bank_ids"."partner_id"', sql_query[1],
"_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect join condition")
- self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]),
+ self.assertIn('%' + name_test + '%', sql_query[2],
"_auto_join on: ('bank_ids.sanitized_acc_number', 'like', '..') query incorrect parameter")
# Do: one2many with _auto_join, test final leaf is an id
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('bank_ids.id', 'in', [b_aa, b_ab])])
+ bank_ids = [b_aa.id, b_ab.id]
+ partners = partner_obj.search([('bank_ids.id', 'in', bank_ids)])
# Test result
- self.assertEqual(set(partner_ids), set([p_aa, p_ab]),
+ self.assertEqual(partners, p_aa + p_ab,
"_auto_join on: ('bank_ids.id', 'in', [..]) incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 1,
@@ -280,15 +752,16 @@ class test_expression(common.TransactionCase):
"_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect main table")
self.assertIn('"res_partner__bank_ids"."id" in (%s,%s)', sql_query[1],
"_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect where condition")
- self.assertEqual(set([b_aa, b_ab]), set(sql_query[2]),
+ self.assertLessEqual(set(bank_ids), set(sql_query[2]),
"_auto_join on: ('bank_ids.id', 'in', [..]) query incorrect parameter")
# Do: 2 cascaded one2many with _auto_join, test final leaf is an id
- partner_child_ids_col._auto_join = True
+ patch_auto_join(partner_obj, 'child_ids', True)
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
+ bank_ids = [b_aa.id, b_ba.id]
+ partners = partner_obj.search([('child_ids.bank_ids.id', 'in', bank_ids)])
# Test result
- self.assertEqual(set(partner_ids), set([p_a, p_b]),
+ self.assertEqual(partners, p_a + p_b,
"_auto_join on: ('child_ids.bank_ids.id', 'not in', [..]): incorrect result")
# # Test produced queries
self.assertEqual(len(self.query_list), 1,
@@ -306,31 +779,30 @@ class test_expression(common.TransactionCase):
"_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition")
self.assertIn('"res_partner__child_ids"."id"="res_partner__child_ids__bank_ids"."partner_id"', sql_query[1],
"_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition")
- self.assertEqual(set([b_aa, b_ba]), set(sql_query[2][-2:]),
+ self.assertLessEqual(set(bank_ids), set(sql_query[2][-2:]),
"_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect parameter")
# --------------------------------------------------
# Test3: many2one
# --------------------------------------------------
-
name_test = 'US'
# Do: many2one without _auto_join
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
+ partners = partner_obj.search([('state_id.country_id.code', 'like', name_test)])
# Test result: at least our added data + demo data
- self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a + p_b + p_aa + p_ab + p_ba, partners,
"_auto_join off: ('state_id.country_id.code', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 3,
"_auto_join off: ('state_id.country_id.code', 'like', '..') should produce 3 queries (1 on res_country, 1 on res_country_state, 1 on res_partner)")
# Do: many2one with 1 _auto_join on the first many2one
- partner_state_id_col._auto_join = True
+ patch_auto_join(partner_obj, 'state_id', True)
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
+ partners = partner_obj.search([('state_id.country_id.code', 'like', name_test)])
# Test result: at least our added data + demo data
- self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a + p_b + p_aa + p_ab + p_ba, partners,
"_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 2,
@@ -356,12 +828,12 @@ class test_expression(common.TransactionCase):
"_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect join condition")
# Do: many2one with 1 _auto_join on the second many2one
- partner_state_id_col._auto_join = False
- state_country_id_col._auto_join = True
+ patch_auto_join(partner_obj, 'state_id', False)
+ patch_auto_join(state_obj, 'country_id', True)
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
+ partners = partner_obj.search([('state_id.country_id.code', 'like', name_test)])
# Test result: at least our added data + demo data
- self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a + p_b + p_aa + p_ab + p_ba, partners,
"_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 2,
@@ -389,12 +861,12 @@ class test_expression(common.TransactionCase):
"_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 2 incorrect where condition")
# Do: many2one with 2 _auto_join
- partner_state_id_col._auto_join = True
- state_country_id_col._auto_join = True
+ patch_auto_join(partner_obj, 'state_id', True)
+ patch_auto_join(state_obj, 'country_id', True)
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('state_id.country_id.code', 'like', name_test)])
+ partners = partner_obj.search([('state_id.country_id.code', 'like', name_test)])
# Test result: at least our added data + demo data
- self.assertTrue(set([p_a, p_b, p_aa, p_ab, p_ba]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a + p_b + p_aa + p_ab + p_ba, partners,
"_auto_join on: ('state_id.country_id.code', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 1,
@@ -415,28 +887,28 @@ class test_expression(common.TransactionCase):
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition")
self.assertIn('"res_partner__state_id"."country_id"="res_partner__state_id__country_id"."id"', sql_query[1],
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition")
- self.assertEqual(['%' + name_test + '%'], sql_query[2],
+ self.assertIn('%' + name_test + '%', sql_query[2],
"_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect parameter")
# --------------------------------------------------
# Test4: domain attribute on one2many fields
# --------------------------------------------------
- partner_child_ids_col._auto_join = True
- partner_bank_ids_col._auto_join = True
- partner_child_ids_col._domain = lambda self: ['!', ('name', '=', self._name)]
- partner_bank_ids_col._domain = [('sanitized_acc_number', 'like', '2')]
+ patch_auto_join(partner_obj, 'child_ids', True)
+ patch_auto_join(partner_obj, 'bank_ids', True)
+ patch_domain(partner_obj, 'child_ids', lambda self: ['!', ('name', '=', self._name)])
+ patch_domain(partner_obj, 'bank_ids', [('sanitized_acc_number', 'like', '2')])
# Do: 2 cascaded one2many with _auto_join, test final leaf is an id
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, ['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
+ partners = partner_obj.search(['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa.id, b_ba.id])])
# Test result: at least one of our added data
- self.assertTrue(set([p_a]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a, partners,
"_auto_join on one2many with domains incorrect result")
- self.assertTrue(set([p_ab, p_ba]) not in set(partner_ids),
+ self.assertFalse((p_ab + p_ba) & partners,
"_auto_join on one2many with domains incorrect result")
# Test produced queries that domains effectively present
sql_query = self.query_list[0].get_sql()
-
+
expected = "%s::text like %s" % (unaccent('"res_partner__child_ids__bank_ids"."sanitized_acc_number"'), unaccent('%s'))
self.assertIn(expected, sql_query[1],
"_auto_join on one2many with domains incorrect result")
@@ -444,101 +916,44 @@ class test_expression(common.TransactionCase):
self.assertIn('"res_partner__child_ids"."name" = %s', sql_query[1],
"_auto_join on one2many with domains incorrect result")
- partner_child_ids_col._domain = lambda self: [('name', '=', '__%s' % self._name)]
+ patch_domain(partner_obj, 'child_ids', lambda self: [('name', '=', '__%s' % self._name)])
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, ['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa, b_ba])])
+ partners = partner_obj.search(['&', (1, '=', 1), ('child_ids.bank_ids.id', 'in', [b_aa.id, b_ba.id])])
# Test result: no one
- self.assertFalse(partner_ids,
+ self.assertFalse(partners,
"_auto_join on one2many with domains incorrect result")
# ----------------------------------------
# Test5: result-based tests
# ----------------------------------------
- partner_bank_ids_col._auto_join = False
- partner_child_ids_col._auto_join = False
- partner_state_id_col._auto_join = False
- partner_parent_id_col._auto_join = False
- state_country_id_col._auto_join = False
- partner_child_ids_col._domain = []
- partner_bank_ids_col._domain = []
+ patch_auto_join(partner_obj, 'bank_ids', False)
+ patch_auto_join(partner_obj, 'child_ids', False)
+ patch_auto_join(partner_obj, 'state_id', False)
+ patch_auto_join(partner_obj, 'parent_id', False)
+ patch_auto_join(state_obj, 'country_id', False)
+ patch_domain(partner_obj, 'child_ids', [])
+ patch_domain(partner_obj, 'bank_ids', [])
# Do: ('child_ids.state_id.country_id.code', 'like', '..') without _auto_join
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('child_ids.state_id.country_id.code', 'like', name_test)])
+ partners = partner_obj.search([('child_ids.state_id.country_id.code', 'like', name_test)])
# Test result: at least our added data + demo data
- self.assertTrue(set([p_a, p_b]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a + p_b, partners,
"_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 5,
"_auto_join off: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect")
# Do: ('child_ids.state_id.country_id.code', 'like', '..') with _auto_join
- partner_child_ids_col._auto_join = True
- partner_state_id_col._auto_join = True
- state_country_id_col._auto_join = True
+ patch_auto_join(partner_obj, 'child_ids', True)
+ patch_auto_join(partner_obj, 'state_id', True)
+ patch_auto_join(state_obj, 'country_id', True)
self._reinit_mock()
- partner_ids = partner_obj.search(cr, uid, [('child_ids.state_id.country_id.code', 'like', name_test)])
+ partners = partner_obj.search([('child_ids.state_id.country_id.code', 'like', name_test)])
# Test result: at least our added data + demo data
- self.assertTrue(set([p_a, p_b]).issubset(set(partner_ids)),
+ self.assertLessEqual(p_a + p_b, partners,
"_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') incorrect result")
# Test produced queries
self.assertEqual(len(self.query_list), 1,
"_auto_join on: ('child_ids.state_id.country_id.code', 'like', '..') number of queries incorrect")
-
- # Remove mocks and modifications
- partner_bank_ids_col._auto_join = False
- partner_child_ids_col._auto_join = False
- partner_state_id_col._auto_join = False
- partner_parent_id_col._auto_join = False
- state_country_id_col._auto_join = False
-
- def test_30_normalize_domain(self):
- expression = openerp.osv.expression
- norm_domain = domain = ['&', (1, '=', 1), ('a', '=', 'b')]
- assert norm_domain == expression.normalize_domain(domain), "Normalized domains should be left untouched"
- domain = [('x', 'in', ['y', 'z']), ('a.v', '=', 'e'), '|', '|', ('a', '=', 'b'), '!', ('c', '>', 'd'), ('e', '!=', 'f'), ('g', '=', 'h')]
- norm_domain = ['&', '&', '&'] + domain
- assert norm_domain == expression.normalize_domain(domain), "Non-normalized domains should be properly normalized"
-
- def test_40_negating_long_expression(self):
- source = ['!','&',('user_id','=',4),('partner_id','in',[1,2])]
- expect = ['|',('user_id','!=',4),('partner_id','not in',[1,2])]
- self.assertEqual(expression.distribute_not(source), expect,
- "distribute_not on expression applied wrongly")
-
- pos_leaves = [[('a', 'in', [])], [('d', '!=', 3)]]
- neg_leaves = [[('a', 'not in', [])], [('d', '=', 3)]]
-
- source = expression.OR([expression.AND(pos_leaves)] * 1000)
- expect = source
- self.assertEqual(expression.distribute_not(source), expect,
- "distribute_not on long expression without negation operator should not alter it")
-
- source = ['!'] + source
- expect = expression.AND([expression.OR(neg_leaves)] * 1000)
- self.assertEqual(expression.distribute_not(source), expect,
- "distribute_not on long expression applied wrongly")
-
- def test_translate_search(self):
- Country = self.registry('res.country')
- be = self.ref('base.be')
- domains = [
- [('name', '=', 'Belgium')],
- [('name', 'ilike', 'Belgi')],
- [('name', 'in', ['Belgium', 'Care Bears'])],
- ]
-
- for domain in domains:
- ids = Country.search(self.cr, self.uid, domain)
- self.assertListEqual([be], ids)
-
- def test_long_table_alias(self):
- # To test the 64 characters limit for table aliases in PostgreSQL
- self.patch_order('res.users', 'partner_id')
- self.patch_order('res.partner', 'commercial_partner_id,company_id,name')
- self.patch_order('res.company', 'parent_id')
- self.env['res.users'].search([('name', '=', 'test')])
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/openerp/addons/base/tests/test_float.py b/openerp/addons/base/tests/test_float.py
new file mode 100644
index 00000000000..6737cbc63df
--- /dev/null
+++ b/openerp/addons/base/tests/test_float.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from math import log10
+
+from odoo.tests.common import TransactionCase
+from odoo.tools import float_compare, float_is_zero, float_repr, float_round
+
+
+class TestFloatPrecision(TransactionCase):
+ """ Tests on float precision. """
+
+ def test_rounding_02(self):
+ """ Test rounding methods with 2 digits. """
+ currency = self.env.ref('base.EUR')
+
+ def try_round(amount, expected):
+ digits = max(0, -int(log10(currency.rounding)))
+ result = float_repr(currency.round(amount), precision_digits=digits)
+ self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
+
+ try_round(2.674,'2.67')
+ try_round(2.675,'2.68') # in Python 2.7.2, round(2.675,2) gives 2.67
+ try_round(-2.675,'-2.68') # in Python 2.7.2, round(2.675,2) gives 2.67
+ try_round(0.001,'0.00')
+ try_round(-0.001,'-0.00')
+ try_round(0.0049,'0.00') # 0.0049 is closer to 0 than to 0.01, so should round down
+ try_round(0.005,'0.01') # the rule is to round half away from zero
+ try_round(-0.005,'-0.01') # the rule is to round half away from zero
+
+ def try_zero(amount, expected):
+ self.assertEqual(currency.is_zero(amount), expected,
+ "Rounding error: %s should be zero!" % amount)
+
+ try_zero(0.01, False)
+ try_zero(-0.01, False)
+ try_zero(0.001, True)
+ try_zero(-0.001, True)
+ try_zero(0.0046, True)
+ try_zero(-0.0046, True)
+ try_zero(2.68-2.675, False) # 2.68 - 2.675 = 0.005 -> rounds to 0.01
+ try_zero(2.68-2.676, True) # 2.68 - 2.675 = 0.004 -> rounds to 0.0
+ try_zero(2.676-2.68, True) # 2.675 - 2.68 = -0.004 -> rounds to -0.0
+ try_zero(2.675-2.68, False) # 2.675 - 2.68 = -0.005 -> rounds to -0.01
+
+ def try_compare(amount1, amount2, expected):
+ self.assertEqual(currency.compare_amounts(amount1, amount2), expected,
+ "Rounding error, compare_amounts(%s,%s) should be %s" % (amount1, amount2, expected))
+
+ try_compare(0.001, 0.001, 0)
+ try_compare(-0.001, -0.001, 0)
+ try_compare(0.001, 0.002, 0)
+ try_compare(-0.001, -0.002, 0)
+ try_compare(2.675, 2.68, 0)
+ try_compare(2.676, 2.68, 0)
+ try_compare(-2.676, -2.68, 0)
+ try_compare(2.674, 2.68, -1)
+ try_compare(-2.674, -2.68, 1)
+ try_compare(3, 2.68, 1)
+ try_compare(-3, -2.68, -1)
+ try_compare(0.01, 0, 1)
+ try_compare(-0.01, 0, -1)
+
+ def test_rounding_03(self):
+ """ Test rounding methods with 3 digits. """
+
+ def try_round(amount, expected, digits=3, method='HALF-UP'):
+ value = float_round(amount, precision_digits=digits, rounding_method=method)
+ result = float_repr(value, precision_digits=digits)
+ self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
+
+ try_round(2.6745, '2.675')
+ try_round(-2.6745, '-2.675')
+ try_round(2.6744, '2.674')
+ try_round(-2.6744, '-2.674')
+ try_round(0.0004, '0.000')
+ try_round(-0.0004, '-0.000')
+ try_round(357.4555, '357.456')
+ try_round(-357.4555, '-357.456')
+ try_round(457.4554, '457.455')
+ try_round(-457.4554, '-457.455')
+
+ # Try some rounding value with rounding method UP instead of HALF-UP
+ # We use 8.175 because when normalizing 8.175 with precision_digits=3 it gives
+ # us 8175,0000000001234 as value, and if not handle correctly the rounding UP
+ # value will be incorrect (should be 8,175 and not 8,176)
+ try_round(8.175, '8.175', method='UP')
+ try_round(8.1751, '8.176', method='UP')
+ try_round(-8.175, '-8.175', method='UP')
+ try_round(-8.1751, '-8.176', method='UP')
+ try_round(-6.000, '-6.000', method='UP')
+ try_round(1.8, '2', 0, method='UP')
+ try_round(-1.8, '-2', 0, method='UP')
+
+ # Extended float range test, inspired by Cloves Almeida's test on bug #882036.
+ fractions = [.0, .015, .01499, .675, .67499, .4555, .4555, .45555]
+ expecteds = ['.00', '.02', '.01', '.68', '.67', '.46', '.456', '.4556']
+ precisions = [2, 2, 2, 2, 2, 2, 3, 4]
+ # Note: max precision for double floats is 53 bits of precision or
+ # 17 significant decimal digits
+ for magnitude in range(7):
+ for i in xrange(len(fractions)):
+ frac, exp, prec = fractions[i], expecteds[i], precisions[i]
+ for sign in [-1,1]:
+ for x in xrange(0,10000,97):
+ n = x * 10**magnitude
+ f = sign * (n + frac)
+ f_exp = ('-' if f != 0 and sign == -1 else '') + str(n) + exp
+ try_round(f, f_exp, digits=prec)
+
+ def try_zero(amount, expected):
+ self.assertEqual(float_is_zero(amount, precision_digits=3), expected,
+ "Rounding error: %s should be zero!" % amount)
+
+ try_zero(0.0002, True)
+ try_zero(-0.0002, True)
+ try_zero(0.00034, True)
+ try_zero(0.0005, False)
+ try_zero(-0.0005, False)
+ try_zero(0.0008, False)
+ try_zero(-0.0008, False)
+
+ def try_compare(amount1, amount2, expected):
+ self.assertEqual(float_compare(amount1, amount2, precision_digits=3), expected,
+ "Rounding error, compare_amounts(%s,%s) should be %s" % (amount1, amount2, expected))
+
+ try_compare(0.0003, 0.0004, 0)
+ try_compare(-0.0003, -0.0004, 0)
+ try_compare(0.0002, 0.0005, -1)
+ try_compare(-0.0002, -0.0005, 1)
+ try_compare(0.0009, 0.0004, 1)
+ try_compare(-0.0009, -0.0004, -1)
+ try_compare(557.4555, 557.4556, 0)
+ try_compare(-557.4555, -557.4556, 0)
+ try_compare(657.4444, 657.445, -1)
+ try_compare(-657.4444, -657.445, 1)
+
+ # Rounding to unusual rounding units (e.g. coin values)
+ def try_round(amount, expected, precision_rounding=None):
+ value = float_round(amount, precision_rounding=precision_rounding)
+ result = float_repr(value, precision_digits=2)
+ self.assertEqual(result, expected, 'Rounding error: got %s, expected %s' % (result, expected))
+
+ try_round(-457.4554, '-457.45', precision_rounding=0.05)
+ try_round(457.444, '457.50', precision_rounding=0.5)
+ try_round(457.3, '455.00', precision_rounding=5)
+ try_round(457.5, '460.00', precision_rounding=5)
+ try_round(457.1, '456.00', precision_rounding=3)
+
+ def test_rounding_04(self):
+ """ check that proper rounding is performed for float persistence """
+ currency = self.env.ref('base.EUR')
+ currency_rate = self.env['res.currency.rate']
+
+ def try_roundtrip(value, expected):
+ rate = currency_rate.create({'name':'2000-01-01',
+ 'rate': value,
+ 'currency_id': currency.id})
+ self.assertEqual(rate.rate, expected,
+ 'Roundtrip error: got %s back from db, expected %s' % (rate, expected))
+
+ # res.currency.rate uses 6 digits of precision by default
+ try_roundtrip(2.6748955, 2.674896)
+ try_roundtrip(-2.6748955, -2.674896)
+ try_roundtrip(10000.999999, 10000.999999)
+ try_roundtrip(-10000.999999, -10000.999999)
+
+ def test_rounding_invalid(self):
+ """ verify that invalid parameters are forbidden """
+ with self.assertRaises(AssertionError):
+ float_is_zero(0.01, precision_digits=3, precision_rounding=0.01)
+
+ with self.assertRaises(AssertionError):
+ float_compare(0.01, 0.02, precision_digits=3, precision_rounding=0.01)
+
+ with self.assertRaises(AssertionError):
+ float_round(0.01, precision_digits=3, precision_rounding=0.01)
diff --git a/openerp/addons/base/tests/test_func.py b/openerp/addons/base/tests/test_func.py
index 1be2469666a..ac394cb9b79 100644
--- a/openerp/addons/base/tests/test_func.py
+++ b/openerp/addons/base/tests/test_func.py
@@ -1,16 +1,17 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
import functools
import unittest
-from openerp.tools.func import compose
-from openerp.tools import frozendict
+from odoo.tools import frozendict
+from odoo.tools.func import compose
+
class TestCompose(unittest.TestCase):
def test_basic(self):
str_add = compose(str, lambda a, b: a + b)
- self.assertEqual(
- str_add(1, 2),
- "3")
+ self.assertEqual(str_add(1, 2), "3")
def test_decorator(self):
""" ensure compose() can be partially applied as a decorator
@@ -21,6 +22,7 @@ class TestCompose(unittest.TestCase):
self.assertEqual(mul(5, 42), u"210")
+
class TestFrozendict(unittest.TestCase):
def test_frozendict_immutable(self):
""" Ensure that a frozendict is immutable. """
diff --git a/openerp/addons/base/tests/test_ir_actions.py b/openerp/addons/base/tests/test_ir_actions.py
index ee494ad84a7..a03ef2e0d0b 100644
--- a/openerp/addons/base/tests/test_ir_actions.py
+++ b/openerp/addons/base/tests/test_ir_actions.py
@@ -1,58 +1,50 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp.exceptions import ValidationError
-import openerp.tests.common as common
-from openerp.tools import mute_logger
+from odoo.exceptions import ValidationError
+from odoo.tools import mute_logger
+import odoo.tests.common as common
+import odoo.workflow
class TestServerActionsBase(common.TransactionCase):
def setUp(self):
super(TestServerActionsBase, self).setUp()
- cr, uid = self.cr, self.uid
-
- # Models
- self.ir_actions_server = self.registry('ir.actions.server')
- self.ir_actions_client = self.registry('ir.actions.client')
- self.ir_values = self.registry('ir.values')
- self.ir_model = self.registry('ir.model')
- self.ir_model_fields = self.registry('ir.model.fields')
- self.res_partner = self.registry('res.partner')
- self.res_country = self.registry('res.country')
# Data on which we will run the server action
- self.test_country_id = self.res_country.create(cr, uid, {
+ self.test_country = self.env['res.country'].create({
'name': 'TestingCountry',
'code': 'TY',
'address_format': 'SuperFormat',
})
- self.test_country = self.res_country.browse(cr, uid, self.test_country_id)
- self.test_partner_id = self.res_partner.create(cr, uid, {
+ self.test_partner = self.env['res.partner'].create({
'name': 'TestingPartner',
'city': 'OrigCity',
- 'country_id': self.test_country_id,
+ 'country_id': self.test_country.id,
})
- self.test_partner = self.res_partner.browse(cr, uid, self.test_partner_id)
self.context = {
- 'active_id': self.test_partner_id,
'active_model': 'res.partner',
+ 'active_id': self.test_partner.id,
}
# Model data
- self.res_partner_model_id = self.ir_model.search(cr, uid, [('model', '=', 'res.partner')])[0]
- self.res_partner_name_field_id = self.ir_model_fields.search(cr, uid, [('model', '=', 'res.partner'), ('name', '=', 'name')])[0]
- self.res_partner_city_field_id = self.ir_model_fields.search(cr, uid, [('model', '=', 'res.partner'), ('name', '=', 'city')])[0]
- self.res_partner_country_field_id = self.ir_model_fields.search(cr, uid, [('model', '=', 'res.partner'), ('name', '=', 'country_id')])[0]
- self.res_partner_parent_field_id = self.ir_model_fields.search(cr, uid, [('model', '=', 'res.partner'), ('name', '=', 'parent_id')])[0]
- self.res_country_model_id = self.ir_model.search(cr, uid, [('model', '=', 'res.country')])[0]
- self.res_country_name_field_id = self.ir_model_fields.search(cr, uid, [('model', '=', 'res.country'), ('name', '=', 'name')])[0]
- self.res_country_code_field_id = self.ir_model_fields.search(cr, uid, [('model', '=', 'res.country'), ('name', '=', 'code')])[0]
+ Model = self.env['ir.model']
+ Fields = self.env['ir.model.fields']
+ self.res_partner_model = Model.search([('model', '=', 'res.partner')])
+ self.res_partner_name_field = Fields.search([('model', '=', 'res.partner'), ('name', '=', 'name')])
+ self.res_partner_city_field = Fields.search([('model', '=', 'res.partner'), ('name', '=', 'city')])
+ self.res_partner_country_field = Fields.search([('model', '=', 'res.partner'), ('name', '=', 'country_id')])
+ self.res_partner_parent_field = Fields.search([('model', '=', 'res.partner'), ('name', '=', 'parent_id')])
+ self.res_country_model = Model.search([('model', '=', 'res.country')])
+ self.res_country_name_field = Fields.search([('model', '=', 'res.country'), ('name', '=', 'name')])
+ self.res_country_code_field = Fields.search([('model', '=', 'res.country'), ('name', '=', 'code')])
# create server action to
- self.act_id = self.ir_actions_server.create(cr, uid, {
+ self.action = self.env['ir.actions.server'].create({
'name': 'TestAction',
'condition': 'True',
- 'model_id': self.res_partner_model_id,
+ 'model_id': self.res_partner_model.id,
'state': 'code',
'code': 'obj.write({"comment": "MyComment"})',
})
@@ -61,346 +53,318 @@ class TestServerActionsBase(common.TransactionCase):
class TestServerActions(TestServerActionsBase):
def test_00_action(self):
- cr, uid = self.cr, self.uid
-
# Do: eval 'True' condition
- self.ir_actions_server.run(cr, uid, [self.act_id], self.context)
- self.test_partner.refresh()
+ self.action.with_context(self.context).run()
self.assertEqual(self.test_partner.comment, 'MyComment', 'ir_actions_server: invalid condition check')
self.test_partner.write({'comment': False})
# Do: eval False condition, that should be considered as True (void = True)
- self.ir_actions_server.write(cr, uid, [self.act_id], {'condition': False})
- self.ir_actions_server.run(cr, uid, [self.act_id], self.context)
- self.test_partner.refresh()
+ self.action.write({'condition': False})
+ self.action.with_context(self.context).run()
self.assertEqual(self.test_partner.comment, 'MyComment', 'ir_actions_server: invalid condition check')
# Do: create contextual action
- self.ir_actions_server.create_action(cr, uid, [self.act_id])
+ self.action.create_action()
# Test: ir_values created
- ir_values_ids = self.ir_values.search(cr, uid, [('name', '=', 'Run TestAction')])
- self.assertEqual(len(ir_values_ids), 1, 'ir_actions_server: create_action should have created an entry in ir_values')
- ir_value = self.ir_values.browse(cr, uid, ir_values_ids[0])
- self.assertEqual(ir_value.value, 'ir.actions.server,%s' % self.act_id, 'ir_actions_server: created ir_values should reference the server action')
- self.assertEqual(ir_value.model, 'res.partner', 'ir_actions_server: created ir_values should be linked to the action base model')
+ ir_values = self.env['ir.values'].search([('name', '=', 'Run TestAction')])
+ self.assertEqual(len(ir_values), 1, 'ir_actions_server: create_action should have created an entry in ir_values')
+ self.assertEqual(ir_values.value, 'ir.actions.server,%s' % self.action.id, 'ir_actions_server: created ir_values should reference the server action')
+ self.assertEqual(ir_values.model, 'res.partner', 'ir_actions_server: created ir_values should be linked to the action base model')
# Do: remove contextual action
- self.ir_actions_server.unlink_action(cr, uid, [self.act_id])
+ self.action.unlink_action()
# Test: ir_values removed
- ir_values_ids = self.ir_values.search(cr, uid, [('name', '=', 'Run TestAction')])
- self.assertEqual(len(ir_values_ids), 0, 'ir_actions_server: unlink_action should remove the ir_values record')
+ ir_values = self.env['ir.values'].search([('name', '=', 'Run TestAction')])
+ self.assertEqual(len(ir_values), 0, 'ir_actions_server: unlink_action should remove the ir_values record')
def test_10_code(self):
- cr, uid = self.cr, self.uid
- self.ir_actions_server.write(cr, uid, self.act_id, {
+ self.action.write({
'state': 'code',
- 'code': """partner_name = obj.name + '_code'
-self.pool["res.partner"].create(cr, uid, {"name": partner_name}, context=context)
-workflow"""
+ 'code': ("partner_name = obj.name + '_code'\n"
+ "obj.env['res.partner'].create({'name': partner_name})\n"
+ "workflow"),
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: code server action correctly finished should return False')
- pids = self.res_partner.search(cr, uid, [('name', 'ilike', 'TestingPartner_code')])
- self.assertEqual(len(pids), 1, 'ir_actions_server: 1 new partner should have been created')
+ partners = self.test_partner.search([('name', 'ilike', 'TestingPartner_code')])
+ self.assertEqual(len(partners), 1, 'ir_actions_server: 1 new partner should have been created')
def test_20_trigger(self):
- cr, uid = self.cr, self.uid
+ Workflow = self.env['workflow']
+ WorkflowActivity = self.env['workflow.activity']
+ WorkflowTransition = self.env['workflow.transition']
# Data: code server action (at this point code-based actions should work)
- act_id2 = self.ir_actions_server.create(cr, uid, {
+ action2 = self.action.create({
'name': 'TestAction2',
'type': 'ir.actions.server',
'condition': 'True',
- 'model_id': self.res_partner_model_id,
+ 'model_id': self.res_partner_model.id,
'state': 'code',
'code': 'obj.write({"comment": "MyComment"})',
})
- act_id3 = self.ir_actions_server.create(cr, uid, {
+ action3 = self.action.create({
'name': 'TestAction3',
'type': 'ir.actions.server',
'condition': 'True',
- 'model_id': self.res_country_model_id,
+ 'model_id': self.res_country_model.id,
'state': 'code',
'code': 'obj.write({"code": "ZZ"})',
})
# Data: create workflows
- partner_wf_id = self.registry('workflow').create(cr, uid, {
+ partner_workflow = Workflow.create({
'name': 'TestWorkflow',
'osv': 'res.partner',
'on_create': True,
})
- partner_act1_id = self.registry('workflow.activity').create(cr, uid, {
+ partner_activity1 = WorkflowActivity.create({
'name': 'PartnerStart',
- 'wkf_id': partner_wf_id,
- 'flow_start': True
+ 'wkf_id': partner_workflow.id,
+ 'flow_start': True,
})
- partner_act2_id = self.registry('workflow.activity').create(cr, uid, {
+ partner_activity2 = WorkflowActivity.create({
'name': 'PartnerTwo',
- 'wkf_id': partner_wf_id,
+ 'wkf_id': partner_workflow.id,
'kind': 'function',
'action': 'True',
- 'action_id': act_id2,
+ 'action_id': action2.id,
})
- partner_trs1_id = self.registry('workflow.transition').create(cr, uid, {
+ partner_transition1 = WorkflowTransition.create({
'signal': 'partner_trans',
- 'act_from': partner_act1_id,
- 'act_to': partner_act2_id
+ 'act_from': partner_activity1.id,
+ 'act_to': partner_activity2.id,
})
- country_wf_id = self.registry('workflow').create(cr, uid, {
+ country_workflow = Workflow.create({
'name': 'TestWorkflow',
'osv': 'res.country',
'on_create': True,
})
- country_act1_id = self.registry('workflow.activity').create(cr, uid, {
+ country_activity1 = WorkflowActivity.create({
'name': 'CountryStart',
- 'wkf_id': country_wf_id,
- 'flow_start': True
+ 'wkf_id': country_workflow.id,
+ 'flow_start': True,
})
- country_act2_id = self.registry('workflow.activity').create(cr, uid, {
+ country_activity2 = WorkflowActivity.create({
'name': 'CountryTwo',
- 'wkf_id': country_wf_id,
+ 'wkf_id': country_workflow.id,
'kind': 'function',
'action': 'True',
- 'action_id': act_id3,
+ 'action_id': action3.id,
})
- country_trs1_id = self.registry('workflow.transition').create(cr, uid, {
+ country_transition1 = WorkflowTransition.create({
'signal': 'country_trans',
- 'act_from': country_act1_id,
- 'act_to': country_act2_id
+ 'act_from': country_activity1.id,
+ 'act_to': country_activity2.id,
})
# Data: re-create country and partner to benefit from the workflows
- self.test_country_id = self.res_country.create(cr, uid, {
+ country = self.test_country.create({
'name': 'TestingCountry2',
'code': 'T2',
})
- self.test_country = self.res_country.browse(cr, uid, self.test_country_id)
- self.test_partner_id = self.res_partner.create(cr, uid, {
+ partner = self.test_partner.create({
'name': 'TestingPartner2',
- 'country_id': self.test_country_id,
+ 'country_id': country.id,
})
- self.test_partner = self.res_partner.browse(cr, uid, self.test_partner_id)
- self.context = {
- 'active_id': self.test_partner_id,
- 'active_model': 'res.partner',
- }
+ context = dict(self.context, active_id=partner.id)
# Run the action on partner object itself ('base')
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'trigger',
'use_relational_model': 'base',
- 'wkf_model_id': self.res_partner_model_id,
- 'wkf_transition_id': partner_trs1_id,
+ 'wkf_model_id': self.res_partner_model.id,
+ 'wkf_transition_id': partner_transition1.id,
})
- self.ir_actions_server.run(cr, uid, [self.act_id], self.context)
- self.test_partner.refresh()
- self.assertEqual(self.test_partner.comment, 'MyComment', 'ir_actions_server: incorrect signal trigger')
+ self.action.with_context(context).run()
+ self.assertEqual(partner.comment, 'MyComment', 'ir_actions_server: incorrect signal trigger')
# Run the action on related country object ('relational')
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'use_relational_model': 'relational',
- 'wkf_model_id': self.res_country_model_id,
- 'wkf_field_id': self.res_partner_country_field_id,
- 'wkf_transition_id': country_trs1_id,
+ 'wkf_model_id': self.res_country_model.id,
+ 'wkf_field_id': self.res_partner_country_field.id,
+ 'wkf_transition_id': country_transition1.id,
})
- self.ir_actions_server.run(cr, uid, [self.act_id], self.context)
- self.test_country.refresh()
- self.assertEqual(self.test_country.code, 'ZZ', 'ir_actions_server: incorrect signal trigger')
+ self.action.with_context(context).run()
+ self.assertEqual(country.code, 'ZZ', 'ir_actions_server: incorrect signal trigger')
- # Clear workflow cache, otherwise openerp will try to create workflows even if it has been deleted
- from openerp.workflow import clear_cache
- clear_cache(cr, uid)
+ # Clear workflow cache, otherwise odoo will try to create workflows even if it has been deleted
+ odoo.workflow.clear_cache(self.cr, self.uid)
def test_30_client(self):
- cr, uid = self.cr, self.uid
- client_action_id = self.registry('ir.actions.client').create(cr, uid, {
+ client_action = self.env['ir.actions.client'].create({
'name': 'TestAction2',
'tag': 'Test',
})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'client_action',
- 'action_id': client_action_id,
+ 'action_id': client_action.id,
})
- res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ res = self.action.with_context(self.context).run()
self.assertEqual(res['name'], 'TestAction2', 'ir_actions_server: incorrect return result for a client action')
def test_40_crud_create(self):
- cr, uid = self.cr, self.uid
_city = 'TestCity'
_name = 'TestNew'
# Do: create a new record in the same model and link it
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'object_create',
'use_create': 'new',
'link_new_record': True,
- 'link_field_id': self.res_partner_parent_field_id,
- 'fields_lines': [(0, 0, {'col1': self.res_partner_name_field_id, 'value': _name}),
- (0, 0, {'col1': self.res_partner_city_field_id, 'value': _city})],
+ 'link_field_id': self.res_partner_parent_field.id,
+ 'fields_lines': [(0, 0, {'col1': self.res_partner_name_field.id, 'value': _name}),
+ (0, 0, {'col1': self.res_partner_city_field.id, 'value': _city})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new partner created
- pids = self.res_partner.search(cr, uid, [('name', 'ilike', _name)])
- self.assertEqual(len(pids), 1, 'ir_actions_server: TODO')
- partner = self.res_partner.browse(cr, uid, pids[0])
+ partner = self.test_partner.search([('name', 'ilike', _name)])
+ self.assertEqual(len(partner), 1, 'ir_actions_server: TODO')
self.assertEqual(partner.city, _city, 'ir_actions_server: TODO')
# Test: new partner linked
- self.test_partner.refresh()
- self.assertEqual(self.test_partner.parent_id.id, pids[0], 'ir_actions_server: TODO')
+ self.assertEqual(self.test_partner.parent_id, partner, 'ir_actions_server: TODO')
# Do: copy current record
- self.ir_actions_server.write(cr, uid, [self.act_id], {'fields_lines': [[5]]})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'object_create',
'use_create': 'copy_current',
'link_new_record': False,
- 'fields_lines': [(0, 0, {'col1': self.res_partner_name_field_id, 'value': 'TestCopyCurrent'}),
- (0, 0, {'col1': self.res_partner_city_field_id, 'value': 'TestCity'})],
+ 'fields_lines': [(5,),
+ (0, 0, {'col1': self.res_partner_name_field.id, 'value': 'TestCopyCurrent'}),
+ (0, 0, {'col1': self.res_partner_city_field.id, 'value': 'TestCity'})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new partner created
- pids = self.res_partner.search(cr, uid, [('name', 'ilike', 'TestingPartner (copy)')]) # currently res_partner overrides default['name'] whatever its value
- self.assertEqual(len(pids), 1, 'ir_actions_server: TODO')
- partner = self.res_partner.browse(cr, uid, pids[0])
+ partner = self.test_partner.search([('name', 'ilike', 'TestingPartner (copy)')]) # currently res_partner overrides default['name'] whatever its value
+ self.assertEqual(len(partner), 1, 'ir_actions_server: TODO')
self.assertEqual(partner.city, 'TestCity', 'ir_actions_server: TODO')
- self.assertEqual(partner.country_id.id, self.test_partner.country_id.id, 'ir_actions_server: TODO')
+ self.assertEqual(partner.country_id, self.test_partner.country_id, 'ir_actions_server: TODO')
# Do: create a new record in another model
- self.ir_actions_server.write(cr, uid, [self.act_id], {'fields_lines': [[5]]})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'object_create',
'use_create': 'new_other',
- 'crud_model_id': self.res_country_model_id,
+ 'crud_model_id': self.res_country_model.id,
'link_new_record': False,
- 'fields_lines': [(0, 0, {'col1': self.res_country_name_field_id, 'value': 'obj.name', 'type': 'equation'}),
- (0, 0, {'col1': self.res_country_code_field_id, 'value': 'obj.name[0:2]', 'type': 'equation'})],
+ 'fields_lines': [(5,),
+ (0, 0, {'col1': self.res_country_name_field.id, 'value': 'obj.name', 'type': 'equation'}),
+ (0, 0, {'col1': self.res_country_code_field.id, 'value': 'obj.name[0:2]', 'type': 'equation'})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new country created
- cids = self.res_country.search(cr, uid, [('name', 'ilike', 'TestingPartner')])
- self.assertEqual(len(cids), 1, 'ir_actions_server: TODO')
- country = self.res_country.browse(cr, uid, cids[0])
+ country = self.test_country.search([('name', 'ilike', 'TestingPartner')])
+ self.assertEqual(len(country), 1, 'ir_actions_server: TODO')
self.assertEqual(country.code, 'TE', 'ir_actions_server: TODO')
# Do: copy a record in another model
- self.ir_actions_server.write(cr, uid, [self.act_id], {'fields_lines': [[5]]})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'object_create',
'use_create': 'copy_other',
- 'crud_model_id': self.res_country_model_id,
+ 'crud_model_id': self.res_country_model.id,
'link_new_record': False,
- 'ref_object': 'res.country,%s' % self.test_country_id,
- 'fields_lines': [(0, 0, {'col1': self.res_country_name_field_id, 'value': 'NewCountry', 'type': 'value'}),
- (0, 0, {'col1': self.res_country_code_field_id, 'value': 'NY', 'type': 'value'})],
+ 'ref_object': 'res.country,%s' % self.test_country.id,
+ 'fields_lines': [(5,),
+ (0, 0, {'col1': self.res_country_name_field.id, 'value': 'NewCountry', 'type': 'value'}),
+ (0, 0, {'col1': self.res_country_code_field.id, 'value': 'NY', 'type': 'value'})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new country created
- cids = self.res_country.search(cr, uid, [('name', 'ilike', 'NewCountry')])
- self.assertEqual(len(cids), 1, 'ir_actions_server: TODO')
- country = self.res_country.browse(cr, uid, cids[0])
+ country = self.test_country.search([('name', 'ilike', 'NewCountry')])
+ self.assertEqual(len(country), 1, 'ir_actions_server: TODO')
self.assertEqual(country.code, 'NY', 'ir_actions_server: TODO')
self.assertEqual(country.address_format, 'SuperFormat', 'ir_actions_server: TODO')
def test_50_crud_write(self):
- cr, uid = self.cr, self.uid
_name = 'TestNew'
# Do: create a new record in the same model and link it
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'object_write',
'use_write': 'current',
- 'fields_lines': [(0, 0, {'col1': self.res_partner_name_field_id, 'value': _name})],
+ 'fields_lines': [(0, 0, {'col1': self.res_partner_name_field.id, 'value': _name})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new partner created
- pids = self.res_partner.search(cr, uid, [('name', 'ilike', _name)])
- self.assertEqual(len(pids), 1, 'ir_actions_server: TODO')
- partner = self.res_partner.browse(cr, uid, pids[0])
+ partner = self.test_partner.search([('name', 'ilike', _name)])
+ self.assertEqual(len(partner), 1, 'ir_actions_server: TODO')
self.assertEqual(partner.city, 'OrigCity', 'ir_actions_server: TODO')
# Do: copy current record
- self.ir_actions_server.write(cr, uid, [self.act_id], {'fields_lines': [[5]]})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'use_write': 'other',
- 'crud_model_id': self.res_country_model_id,
- 'ref_object': 'res.country,%s' % self.test_country_id,
- 'fields_lines': [(0, 0, {'col1': self.res_country_name_field_id, 'value': 'obj.name', 'type': 'equation'})],
+ 'crud_model_id': self.res_country_model.id,
+ 'ref_object': 'res.country,%s' % self.test_country.id,
+ 'fields_lines': [(5,), (0, 0, {'col1': self.res_country_name_field.id, 'value': 'obj.name', 'type': 'equation'})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new country created
- cids = self.res_country.search(cr, uid, [('name', 'ilike', 'TestNew')])
- self.assertEqual(len(cids), 1, 'ir_actions_server: TODO')
+ country = self.test_country.search([('name', 'ilike', 'TestNew')])
+ self.assertEqual(len(country), 1, 'ir_actions_server: TODO')
# Do: copy a record in another model
- self.ir_actions_server.write(cr, uid, [self.act_id], {'fields_lines': [[5]]})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'use_write': 'expression',
- 'crud_model_id': self.res_country_model_id,
+ 'crud_model_id': self.res_country_model.id,
'write_expression': 'object.country_id',
- 'fields_lines': [(0, 0, {'col1': self.res_country_name_field_id, 'value': 'NewCountry', 'type': 'value'})],
+ 'fields_lines': [(5,), (0, 0, {'col1': self.res_country_name_field.id, 'value': 'NewCountry', 'type': 'value'})],
})
- run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ run_res = self.action.with_context(self.context).run()
self.assertFalse(run_res, 'ir_actions_server: create record action correctly finished should return False')
# Test: new country created
- cids = self.res_country.search(cr, uid, [('name', 'ilike', 'NewCountry')])
- self.assertEqual(len(cids), 1, 'ir_actions_server: TODO')
+ country = self.test_country.search([('name', 'ilike', 'NewCountry')])
+ self.assertEqual(len(country), 1, 'ir_actions_server: TODO')
@mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
def test_60_multi(self):
- cr, uid = self.cr, self.uid
-
# Data: 2 server actions that will be nested
- act1_id = self.ir_actions_server.create(cr, uid, {
+ action1 = self.action.create({
'name': 'Subaction1',
'sequence': 1,
- 'model_id': self.res_partner_model_id,
+ 'model_id': self.res_partner_model.id,
'state': 'code',
'code': 'action = {"type": "ir.actions.act_window"}',
})
- act2_id = self.ir_actions_server.create(cr, uid, {
+ action2 = self.action.create({
'name': 'Subaction2',
'sequence': 2,
- 'model_id': self.res_partner_model_id,
+ 'model_id': self.res_partner_model.id,
'state': 'object_create',
'use_create': 'copy_current',
})
- act3_id = self.ir_actions_server.create(cr, uid, {
+ action3 = self.action.create({
'name': 'Subaction3',
'sequence': 3,
- 'model_id': self.res_partner_model_id,
+ 'model_id': self.res_partner_model.id,
'state': 'code',
'code': 'action = {"type": "ir.actions.act_url"}',
})
- self.ir_actions_server.write(cr, uid, [self.act_id], {
+ self.action.write({
'state': 'multi',
- 'child_ids': [(6, 0, [act1_id, act2_id, act3_id])],
+ 'child_ids': [(6, 0, [action1.id, action2.id, action3.id])],
})
# Do: run the action
- res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
+ res = self.action.with_context(self.context).run()
# Test: new partner created
- pids = self.res_partner.search(cr, uid, [('name', 'ilike', 'TestingPartner (copy)')]) # currently res_partner overrides default['name'] whatever its value
- self.assertEqual(len(pids), 1, 'ir_actions_server: TODO')
+ # currently res_partner overrides default['name'] whatever its value
+ partner = self.test_partner.search([('name', 'ilike', 'TestingPartner (copy)')])
+ self.assertEqual(len(partner), 1, 'ir_actions_server: TODO')
# Test: action returned
self.assertEqual(res.get('type'), 'ir.actions.act_url')
# Test loops
with self.assertRaises(ValidationError):
- self.ir_actions_server.write(cr, uid, [self.act_id], {
- 'child_ids': [(6, 0, [self.act_id])]
+ self.action.write({
+ 'child_ids': [(6, 0, [self.action.id])]
})
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/openerp/addons/base/tests/test_ir_attachment.py b/openerp/addons/base/tests/test_ir_attachment.py
index 891b38b7dc3..d515cfc354d 100644
--- a/openerp/addons/base/tests/test_ir_attachment.py
+++ b/openerp/addons/base/tests/test_ir_attachment.py
@@ -1,17 +1,20 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
import hashlib
import os
-import openerp
-import openerp.tests.common
+from odoo.tests.common import TransactionCase
HASH_SPLIT = 2 # FIXME: testing implementations detail is not a good idea
-class test_ir_attachment(openerp.tests.common.TransactionCase):
+
+class TestIrAttachment(TransactionCase):
def setUp(self):
- super(test_ir_attachment, self).setUp()
- registry, cr, uid = self.registry, self.cr, self.uid
- self.ira = registry('ir.attachment')
- self.filestore = self.ira._filestore(cr, uid)
+ super(TestIrAttachment, self).setUp()
+ self.Attachment = self.env['ir.attachment']
+ self.ira = self.Attachment._model
+ self.filestore = self.Attachment._filestore()
# Blob1
self.blob1 = 'blob1'
@@ -20,73 +23,55 @@ class test_ir_attachment(openerp.tests.common.TransactionCase):
self.blob1_fname = blob1_hash[:HASH_SPLIT] + '/' + blob1_hash
# Blob2
- blob2 = 'blob2'
- self.blob2_b64 = blob2.encode('base64')
+ self.blob2 = 'blob2'
+ self.blob2_b64 = self.blob2.encode('base64')
def test_01_store_in_db(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
# force storing in database
- registry('ir.config_parameter').set_param(cr, uid, 'ir_attachment.location', 'db')
+ self.env['ir.config_parameter'].set_param('ir_attachment.location', 'db')
# 'ir_attachment.location' is undefined test database storage
- a1 = self.ira.create(cr, uid, {'name': 'a1', 'datas': self.blob1_b64})
- a1_read = self.ira.read(cr, uid, [a1], ['datas'])
- self.assertEqual(a1_read[0]['datas'], self.blob1_b64)
+ a1 = self.Attachment.create({'name': 'a1', 'datas': self.blob1_b64})
+ self.assertEqual(a1.datas, self.blob1_b64)
- a1_db_datas = self.ira.browse(cr, uid, a1).db_datas
+ a1_db_datas = a1.db_datas
self.assertEqual(a1_db_datas, self.blob1_b64)
def test_02_store_on_disk(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
-
- self.assertEqual(a2_store_fname, self.blob1_fname)
- self.assertTrue(os.path.isfile(os.path.join(self.filestore, a2_store_fname)))
+ a2 = self.Attachment.create({'name': 'a2', 'datas': self.blob1_b64})
+ self.assertEqual(a2.store_fname, self.blob1_fname)
+ self.assertTrue(os.path.isfile(os.path.join(self.filestore, a2.store_fname)))
def test_03_no_duplication(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
-
- a3 = self.ira.create(cr, uid, {'name': 'a3', 'datas': self.blob1_b64})
- a3_store_fname = self.ira.browse(cr, uid, a3).store_fname
-
- self.assertEqual(a3_store_fname, a2_store_fname)
+ a2 = self.Attachment.create({'name': 'a2', 'datas': self.blob1_b64})
+ a3 = self.Attachment.create({'name': 'a3', 'datas': self.blob1_b64})
+ self.assertEqual(a3.store_fname, a2.store_fname)
def test_04_keep_file(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a3 = self.ira.create(cr, uid, {'name': 'a3', 'datas': self.blob1_b64})
+ a2 = self.Attachment.create({'name': 'a2', 'datas': self.blob1_b64})
+ a3 = self.Attachment.create({'name': 'a3', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
- a2_fn = os.path.join(self.filestore, a2_store_fname)
+ a2_fn = os.path.join(self.filestore, a2.store_fname)
- self.ira.unlink(cr, uid, [a3])
+ a3.unlink()
self.assertTrue(os.path.isfile(a2_fn))
# delete a2 it is unlinked
- self.ira.unlink(cr, uid, [a2])
+ a2.unlink()
self.assertFalse(os.path.isfile(a2_fn))
def test_05_change_data_change_file(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
- a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
- a2_fn = os.path.join(self.filestore, a2_store_fname)
+ a2 = self.Attachment.create({'name': 'a2', 'datas': self.blob1_b64})
+ a2_store_fname1 = a2.store_fname
+ a2_fn = os.path.join(self.filestore, a2_store_fname1)
self.assertTrue(os.path.isfile(a2_fn))
- self.ira.write(cr, uid, [a2], {'datas': self.blob2_b64})
+ a2.write({'datas': self.blob2_b64})
self.assertFalse(os.path.isfile(a2_fn))
- new_a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
- self.assertNotEqual(a2_store_fname, new_a2_store_fname)
+ a2_store_fname2 = a2.store_fname
+ self.assertNotEqual(a2_store_fname1, a2_store_fname2)
- new_a2_fn = os.path.join(self.filestore, new_a2_store_fname)
- self.assertTrue(os.path.isfile(new_a2_fn))
+ a2_fn = os.path.join(self.filestore, a2_store_fname2)
+ self.assertTrue(os.path.isfile(a2_fn))
diff --git a/openerp/addons/base/tests/test_ir_filters.py b/openerp/addons/base/tests/test_ir_filters.py
index 2132fdb946b..d932f16be11 100644
--- a/openerp/addons/base/tests/test_ir_filters.py
+++ b/openerp/addons/base/tests/test_ir_filters.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
-import functools
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp import exceptions
-from openerp.tests import common
+from odoo import exceptions
+from odoo.tests.common import TransactionCase, ADMIN_USER_ID
def noid(d):
""" Removes values that are not relevant for the test comparisons """
@@ -10,17 +10,19 @@ def noid(d):
d.pop('action_id', None)
return d
-class FiltersCase(common.TransactionCase):
+
+class FiltersCase(TransactionCase):
def build(self, model, *args):
- Model = self.registry(model)
- for vars in args:
- Model.create(self.cr, common.ADMIN_USER_ID, vars, {})
+ Model = self.env[model].sudo(ADMIN_USER_ID)
+ for vals in args:
+ Model.create(vals)
+
class TestGetFilters(FiltersCase):
def setUp(self):
super(TestGetFilters, self).setUp()
- self.USER = self.registry('res.users').name_search(self.cr, self.uid, 'demo')[0]
- self.USER_ID = self.USER[0]
+ self.USER_NG = self.env['res.users'].name_search('demo')[0]
+ self.USER_ID = self.USER_NG[0]
def test_own_filters(self):
self.build(
@@ -30,14 +32,13 @@ class TestGetFilters(FiltersCase):
dict(name='c', user_id=self.USER_ID, model_id='ir.filters'),
dict(name='d', user_id=self.USER_ID, model_id='ir.filters'))
- filters = self.registry('ir.filters').get_filters(
- self.cr, self.USER_ID, 'ir.filters')
+ filters = self.env['ir.filters'].sudo(self.USER_ID).get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
- dict(name='a', is_default=False, user_id=self.USER, domain='[]', context='{}', sort='[]'),
- dict(name='b', is_default=False, user_id=self.USER, domain='[]', context='{}', sort='[]'),
- dict(name='c', is_default=False, user_id=self.USER, domain='[]', context='{}', sort='[]'),
- dict(name='d', is_default=False, user_id=self.USER, domain='[]', context='{}', sort='[]'),
+ dict(name='a', is_default=False, user_id=self.USER_NG, domain='[]', context='{}', sort='[]'),
+ dict(name='b', is_default=False, user_id=self.USER_NG, domain='[]', context='{}', sort='[]'),
+ dict(name='c', is_default=False, user_id=self.USER_NG, domain='[]', context='{}', sort='[]'),
+ dict(name='d', is_default=False, user_id=self.USER_NG, domain='[]', context='{}', sort='[]'),
])
def test_global_filters(self):
@@ -49,8 +50,7 @@ class TestGetFilters(FiltersCase):
dict(name='d', user_id=False, model_id='ir.filters'),
)
- filters = self.registry('ir.filters').get_filters(
- self.cr, self.USER_ID, 'ir.filters')
+ filters = self.env['ir.filters'].sudo(self.USER_ID).get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
dict(name='a', is_default=False, user_id=False, domain='[]', context='{}', sort='[]'),
@@ -63,40 +63,40 @@ class TestGetFilters(FiltersCase):
self.build(
'ir.filters',
dict(name='a', user_id=False, model_id='ir.filters'),
- dict(name='b', user_id=common.ADMIN_USER_ID, model_id='ir.filters'),
+ dict(name='b', user_id=ADMIN_USER_ID, model_id='ir.filters'),
dict(name='c', user_id=self.USER_ID, model_id='ir.filters'),
- dict(name='d', user_id=common.ADMIN_USER_ID, model_id='ir.filters') )
+ dict(name='d', user_id=ADMIN_USER_ID, model_id='ir.filters') )
- filters = self.registry('ir.filters').get_filters(
- self.cr, self.USER_ID, 'ir.filters')
+ filters = self.env['ir.filters'].sudo(self.USER_ID).get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
dict(name='a', is_default=False, user_id=False, domain='[]', context='{}', sort='[]'),
- dict(name='c', is_default=False, user_id=self.USER, domain='[]', context='{}', sort='[]'),
+ dict(name='c', is_default=False, user_id=self.USER_NG, domain='[]', context='{}', sort='[]'),
])
+
class TestOwnDefaults(FiltersCase):
def setUp(self):
super(TestOwnDefaults, self).setUp()
- self.USER = self.registry('res.users').name_search(self.cr, self.uid, 'demo')[0]
- self.USER_ID = self.USER[0]
+ self.USER_NG = self.env['res.users'].name_search('demo')[0]
+ self.USER_ID = self.USER_NG[0]
def test_new_no_filter(self):
"""
When creating a @is_default filter with no existing filter, that new
filter gets the default flag
"""
- Filters = self.registry('ir.filters')
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
+ Filters.create_or_replace({
'name': 'a',
'model_id': 'ir.filters',
'user_id': self.USER_ID,
'is_default': True,
})
- filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters')
+ filters = Filters.get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
- dict(name='a', user_id=self.USER, is_default=True,
+ dict(name='a', user_id=self.USER_NG, is_default=True,
domain='[]', context='{}', sort='[]')
])
@@ -111,19 +111,19 @@ class TestOwnDefaults(FiltersCase):
dict(name='b', user_id=self.USER_ID, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
+ Filters.create_or_replace({
'name': 'c',
'model_id': 'ir.filters',
'user_id': self.USER_ID,
'is_default': True,
})
- filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters')
+ filters = Filters.get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
- dict(name='a', user_id=self.USER, is_default=False, domain='[]', context='{}', sort='[]'),
- dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}', sort='[]'),
- dict(name='c', user_id=self.USER, is_default=True, domain='[]', context='{}', sort='[]'),
+ dict(name='a', user_id=self.USER_NG, is_default=False, domain='[]', context='{}', sort='[]'),
+ dict(name='b', user_id=self.USER_NG, is_default=False, domain='[]', context='{}', sort='[]'),
+ dict(name='c', user_id=self.USER_NG, is_default=True, domain='[]', context='{}', sort='[]'),
])
def test_new_filter_existing_default(self):
@@ -137,19 +137,19 @@ class TestOwnDefaults(FiltersCase):
dict(name='b', is_default=True, user_id=self.USER_ID, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
+ Filters.create_or_replace({
'name': 'c',
'model_id': 'ir.filters',
'user_id': self.USER_ID,
'is_default': True,
})
- filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters')
+ filters = Filters.get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
- dict(name='a', user_id=self.USER, is_default=False, domain='[]', context='{}', sort='[]'),
- dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}', sort='[]'),
- dict(name='c', user_id=self.USER, is_default=True, domain='[]', context='{}', sort='[]'),
+ dict(name='a', user_id=self.USER_NG, is_default=False, domain='[]', context='{}', sort='[]'),
+ dict(name='b', user_id=self.USER_NG, is_default=False, domain='[]', context='{}', sort='[]'),
+ dict(name='c', user_id=self.USER_NG, is_default=True, domain='[]', context='{}', sort='[]'),
])
def test_update_filter_set_default(self):
@@ -163,25 +163,26 @@ class TestOwnDefaults(FiltersCase):
dict(name='b', is_default=True, user_id=self.USER_ID, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
+ Filters.create_or_replace({
'name': 'a',
'model_id': 'ir.filters',
'user_id': self.USER_ID,
'is_default': True,
})
- filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters')
+ filters = Filters.get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
- dict(name='a', user_id=self.USER, is_default=True, domain='[]', context='{}', sort='[]'),
- dict(name='b', user_id=self.USER, is_default=False, domain='[]', context='{}', sort='[]'),
+ dict(name='a', user_id=self.USER_NG, is_default=True, domain='[]', context='{}', sort='[]'),
+ dict(name='b', user_id=self.USER_NG, is_default=False, domain='[]', context='{}', sort='[]'),
])
+
class TestGlobalDefaults(FiltersCase):
def setUp(self):
super(TestGlobalDefaults, self).setUp()
- self.USER = self.registry('res.users').name_search(self.cr, self.uid, 'demo')[0]
- self.USER_ID = self.USER[0]
+ self.USER_NG = self.env['res.users'].name_search('demo')[0]
+ self.USER_ID = self.USER_NG[0]
def test_new_filter_not_default(self):
"""
@@ -194,14 +195,14 @@ class TestGlobalDefaults(FiltersCase):
dict(name='b', user_id=False, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
+ Filters.create_or_replace({
'name': 'c',
'model_id': 'ir.filters',
'user_id': False,
'is_default': True,
})
- filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters')
+ filters = Filters.get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
dict(name='a', user_id=False, is_default=False, domain='[]', context='{}', sort='[]'),
@@ -220,9 +221,9 @@ class TestGlobalDefaults(FiltersCase):
dict(name='b', is_default=True, user_id=False, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
with self.assertRaises(exceptions.Warning):
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters.create_or_replace({
'name': 'c',
'model_id': 'ir.filters',
'user_id': False,
@@ -240,10 +241,9 @@ class TestGlobalDefaults(FiltersCase):
dict(name='b', is_default=True, user_id=False, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
-
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
with self.assertRaises(exceptions.Warning):
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters.create_or_replace({
'name': 'a',
'model_id': 'ir.filters',
'user_id': False,
@@ -260,42 +260,37 @@ class TestGlobalDefaults(FiltersCase):
dict(name='b', is_default=True, user_id=False, model_id='ir.filters'),
)
- Filters = self.registry('ir.filters')
+ Filters = self.env['ir.filters'].sudo(self.USER_ID)
context_value = "{'some_key': True}"
- Filters.create_or_replace(self.cr, self.USER_ID, {
+ Filters.create_or_replace({
'name': 'b',
'model_id': 'ir.filters',
'user_id': False,
'context': context_value,
'is_default': True,
})
- filters = Filters.get_filters(self.cr, self.USER_ID, 'ir.filters')
+ filters = Filters.get_filters('ir.filters')
self.assertItemsEqual(map(noid, filters), [
dict(name='a', user_id=False, is_default=False, domain='[]', context='{}', sort='[]'),
dict(name='b', user_id=False, is_default=True, domain='[]', context=context_value, sort='[]'),
])
-from openerp.tests.common import TransactionCase
class TestReadGroup(TransactionCase):
"""Test function read_group with groupby on a many2one field to a model
(in test, "user_id" to "res.users") which is ordered by an inherited not stored field (in
test, "name" inherited from "res.partners").
"""
-
- def setUp(self):
- super(TestReadGroup, self).setUp()
- self.ir_filters_model = self.env['ir.filters']
- self.res_partner_model = self.env['res.partner']
- self.res_users_model = self.env['res.users']
-
def test_read_group_1(self):
- self.assertEqual(self.res_users_model._order, "name, login", "Model res.users must be ordered by name, login")
- self.assertFalse(self.res_users_model._fields['name'].store, "Field name is not stored in res.users")
+ Users = self.env['res.users']
+ self.assertEqual(Users._order, "name, login", "Model res.users must be ordered by name, login")
+ self.assertFalse(Users._fields['name'].store, "Field name is not stored in res.users")
- filter_a = self.ir_filters_model.create(dict(name="Filter_A", model_id="ir.filters"))
- filter_b = self.ir_filters_model.create(dict(name="Filter_B", model_id="ir.filters"))
+ Filters = self.env['ir.filters']
+ filter_a = Filters.create(dict(name="Filter_A", model_id="ir.filters"))
+ filter_b = Filters.create(dict(name="Filter_B", model_id="ir.filters"))
filter_b.write(dict(user_id=False))
- res = self.ir_filters_model.read_group([], ['name', 'user_id'], ['user_id'])
+
+ res = Filters.read_group([], ['name', 'user_id'], ['user_id'])
self.assertTrue(any(val['user_id'] == False for val in res), "At least one group must contain val['user_id'] == False.")
diff --git a/openerp/addons/base/tests/test_ir_rule.yml b/openerp/addons/base/tests/test_ir_rule.yml
deleted file mode 100644
index 02fc2e3d3b4..00000000000
--- a/openerp/addons/base/tests/test_ir_rule.yml
+++ /dev/null
@@ -1,189 +0,0 @@
--
- Exercise ir_rule.py code (and indirectly expression.py).
--
- Create an ir_rule for the Employee group (called base.group_user)
- with an blank domain.
--
- !record {model: ir.rule, id: test_rule}:
- model_id: base.model_res_partner
- domain_force: False
- name: test_rule
- groups:
- - base.group_user
- perm_unlink: 1
- perm_write: 1
- perm_read: 1
- perm_create: 1
--
- Read as demo user the partners (one blank domain).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Domain is not empty.
--
- !record {model: ir.rule, id: test_rule}:
- model_id: base.model_res_partner
- domain_force: "[(1,'=',1)]"
--
- Read as demo user the partners (one 1=1 domain).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Domain is an empty list.
--
- !record {model: ir.rule, id: test_rule}:
- model_id: base.model_res_partner
- domain_force: "[]"
--
- Read as demo user the partners (one [] domain).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Create another ir_rule for the Employee group (to test rules from
- multiple groups).
--
- !record {model: ir.rule, id: test_rule2}:
- model_id: base.model_res_partner
- domain_force: False
- name: test_rule2
- groups:
- - base.group_user
- perm_unlink: 1
- perm_write: 1
- perm_read: 1
- perm_create: 1
--
- Read as demo user the partners (blank and [] domains).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Domain is not empty.
--
- !record {model: ir.rule, id: test_rule}:
- model_id: base.model_res_partner
- domain_force: "[(1,'=',1)]"
--
- Read as demo user the partners (1=1 and blank domain).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Domain is not empty.
--
- !record {model: ir.rule, id: test_rule2}:
- model_id: base.model_res_partner
- domain_force: "[(1,'=',1)]"
--
- Read as demo user the partners (two 1=1 domains).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Create another ir_rule for the Employee group (to test rules from
- multiple groups).
--
- !record {model: ir.rule, id: test_rule3}:
- model_id: base.model_res_partner
- domain_force: False
- name: test_rule3
- groups:
- - base.group_user
- perm_unlink: 1
- perm_write: 1
- perm_read: 1
- perm_create: 1
--
- Read as demo user the partners.
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Domain is not empty.
--
- !record {model: ir.rule, id: test_rule3}:
- model_id: base.model_res_partner
- domain_force: "[(1,'=',1)]"
--
- Read as demo user the partners (three 1=1 domains).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Modify the global rule on res_company which triggers a recursive check
- of the rules on company.
--
- !record {model: ir.rule, id: res_company_rule_employee}:
- domain_force: "[('id','child_of',[user.company_id.id])]"
--
- Read as demo user the partners (exercising the global company rule).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Modify the ir_rule for employee to have a rule that fordids
- seeing any record.
- We use a domain with implicit AND operator for later tests
- on normalization.
--
- !record {model: ir.rule, id: test_rule2}:
- domain_force: "[('id','=',False),('name','=',False)]"
--
- Check that demo user still sees partners, because group-rules are OR'ed.
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
--
- Create a new group with demo user in it, and a complex rule.
- Demo should still see partners.
--
- !record {model: res.groups, id: test_group}:
- name: Test Group
- users:
- - base.user_demo
--
- Add the rule to the new group, with a domain containing an implicit AND operator,
- which is more tricky because it will have to be normalized before combining it.
--
- !record {model: ir.rule, id: test_rule3}:
- model_id: base.model_res_partner
- domain_force: "[('name', '!=', False),('id', '!=', False)]"
- name: test_rule4
- groups:
- - test_group
- perm_unlink: 1
- perm_write: 1
- perm_read: 1
- perm_create: 1
--
- Read the partners again as demo user, which should give results.
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see partners even with the combined rules."
--
- Delete global domains (to combine only group domains).
--
- !python {model: ir.rule}: |
- ids = self.search(cr, uid, [('groups','=',False)])
- assert ids, "Demo user should see some partner."
- self.unlink(cr, uid, ids)
--
- Read as demo user the partners (several group domains, no global domain).
--
- !python {model: res.partner }: |
- ids = self.search(cr, ref('base.user_demo'), [])
- assert ids, "Demo user should see some partner."
diff --git a/openerp/addons/base/tests/test_ir_sequence.py b/openerp/addons/base/tests/test_ir_sequence.py
index 3d2f891c63e..76db66d7008 100644
--- a/openerp/addons/base/tests/test_ir_sequence.py
+++ b/openerp/addons/base/tests/test_ir_sequence.py
@@ -1,193 +1,177 @@
# -*- coding: utf-8 -*-
-# Run with one of these commands:
-# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \
-# OPENERP_DATABASE=yy PYTHONPATH=. python tests/test_ir_sequence.py
-# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \
-# OPENERP_DATABASE=yy nosetests tests/test_ir_sequence.py
-# > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \
-# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence
-# This assume an existing database.
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from contextlib import contextmanager
+import unittest
+
import psycopg2
import psycopg2.errorcodes
-import unittest
-import openerp
-from openerp.tests import common
+import odoo
+from odoo.tests import common
ADMIN_USER_ID = common.ADMIN_USER_ID
-def registry(model):
- return openerp.modules.registry.RegistryManager.get(common.get_db_name())[model]
-
-def cursor():
- return openerp.modules.registry.RegistryManager.get(common.get_db_name()).cursor()
+@contextmanager
+def environment():
+ """ Return an environment with a new cursor for the current database; the
+ cursor is committed and closed after the context block.
+ """
+ registry = odoo.registry(common.get_db_name())
+ with registry.cursor() as cr:
+ yield odoo.api.Environment(cr, ADMIN_USER_ID, {})
+ cr.commit()
def drop_sequence(code):
- cr = cursor()
- s = registry('ir.sequence')
- ids = s.search(cr, ADMIN_USER_ID, [('code', '=', code)])
- s.unlink(cr, ADMIN_USER_ID, ids)
- cr.commit()
- cr.close()
-
-class test_ir_sequence_standard(unittest.TestCase):
+ with environment() as env:
+ seq = env['ir.sequence'].search([('code', '=', code)])
+ seq.unlink()
+
+
+class TestIrSequenceStandard(unittest.TestCase):
""" A few tests for a 'Standard' (i.e. PostgreSQL) sequence. """
def test_ir_sequence_create(self):
""" Try to create a sequence object. """
- cr = cursor()
- d = dict(code='test_sequence_type', name='Test sequence')
- c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {})
- assert c
- cr.commit()
- cr.close()
+ with environment() as env:
+ seq = env['ir.sequence'].create({
+ 'code': 'test_sequence_type',
+ 'name': 'Test sequence',
+ })
+ self.assertTrue(seq)
def test_ir_sequence_search(self):
""" Try a search. """
- cr = cursor()
- ids = registry('ir.sequence').search(cr, ADMIN_USER_ID, [], {})
- assert ids
- cr.commit()
- cr.close()
+ with environment() as env:
+ seqs = env['ir.sequence'].search([])
+ self.assertTrue(seqs)
def test_ir_sequence_draw(self):
""" Try to draw a number. """
- cr = cursor()
- n = registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type', {})
- assert n
- cr.commit()
- cr.close()
+ with environment() as env:
+ n = env['ir.sequence'].next_by_code('test_sequence_type')
+ self.assertTrue(n)
def test_ir_sequence_draw_twice(self):
""" Try to draw a number from two transactions. """
- cr0 = cursor()
- cr1 = cursor()
- n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type', {})
- assert n0
- n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type', {})
- assert n1
- cr0.commit()
- cr1.commit()
- cr0.close()
- cr1.close()
+ with environment() as env0:
+ with environment() as env1:
+ n0 = env0['ir.sequence'].next_by_code('test_sequence_type')
+ self.assertTrue(n0)
+ n1 = env1['ir.sequence'].next_by_code('test_sequence_type')
+ self.assertTrue(n1)
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type')
-class test_ir_sequence_no_gap(unittest.TestCase):
+
+class TestIrSequenceNoGap(unittest.TestCase):
""" Copy of the previous tests for a 'No gap' sequence. """
def test_ir_sequence_create_no_gap(self):
""" Try to create a sequence object. """
- cr = cursor()
- d = dict(code='test_sequence_type_2', name='Test sequence',
- implementation='no_gap')
- c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {})
- assert c
- cr.commit()
- cr.close()
+ with environment() as env:
+ seq = env['ir.sequence'].create({
+ 'code': 'test_sequence_type_2',
+ 'name': 'Test sequence',
+ 'implementation': 'no_gap',
+ })
+ self.assertTrue(seq)
def test_ir_sequence_draw_no_gap(self):
""" Try to draw a number. """
- cr = cursor()
- n = registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type_2', {})
- assert n
- cr.commit()
- cr.close()
+ with environment() as env:
+ n = env['ir.sequence'].next_by_code('test_sequence_type_2')
+ self.assertTrue(n)
def test_ir_sequence_draw_twice_no_gap(self):
""" Try to draw a number from two transactions.
This is expected to not work.
"""
- cr0 = cursor()
- cr1 = cursor()
- cr1._default_log_exceptions = False # Prevent logging a traceback
- with self.assertRaises(psycopg2.OperationalError) as e:
- n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {})
- assert n0
- n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {})
- self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode")
- cr0.close()
- cr1.close()
+ with environment() as env0:
+ with environment() as env1:
+ env1.cr._default_log_exceptions = False # Prevent logging a traceback
+ with self.assertRaises(psycopg2.OperationalError) as e:
+ n0 = env0['ir.sequence'].next_by_code('test_sequence_type_2')
+ self.assertTrue(n0)
+ n1 = env1['ir.sequence'].next_by_code('test_sequence_type_2')
+ self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode")
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type_2')
-class test_ir_sequence_change_implementation(unittest.TestCase):
+
+class TestIrSequenceChangeImplementation(unittest.TestCase):
""" Create sequence objects and change their ``implementation`` field. """
def test_ir_sequence_1_create(self):
""" Try to create a sequence object. """
- cr = cursor()
- d = dict(code='test_sequence_type_3', name='Test sequence')
- c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {})
- assert c
- d = dict(code='test_sequence_type_4', name='Test sequence',
- implementation='no_gap')
- c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {})
- assert c
- cr.commit()
- cr.close()
+ with environment() as env:
+ seq = env['ir.sequence'].create({
+ 'code': 'test_sequence_type_3',
+ 'name': 'Test sequence',
+ })
+ self.assertTrue(seq)
+ seq = env['ir.sequence'].create({
+ 'code': 'test_sequence_type_4',
+ 'name': 'Test sequence',
+ 'implementation': 'no_gap',
+ })
+ self.assertTrue(seq)
def test_ir_sequence_2_write(self):
- cr = cursor()
- ids = registry('ir.sequence').search(cr, ADMIN_USER_ID,
- [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])], {})
- registry('ir.sequence').write(cr, ADMIN_USER_ID, ids,
- {'implementation': 'standard'}, {})
- registry('ir.sequence').write(cr, ADMIN_USER_ID, ids,
- {'implementation': 'no_gap'}, {})
- cr.commit()
- cr.close()
+ with environment() as env:
+ domain = [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])]
+ seqs = env['ir.sequence'].search(domain)
+ seqs.write({'implementation': 'standard'})
+ seqs.write({'implementation': 'no_gap'})
def test_ir_sequence_3_unlink(self):
- cr = cursor()
- ids = registry('ir.sequence').search(cr, ADMIN_USER_ID,
- [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])], {})
- registry('ir.sequence').unlink(cr, ADMIN_USER_ID, ids, {})
- cr.commit()
- cr.close()
+ with environment() as env:
+ domain = [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])]
+ seqs = env['ir.sequence'].search(domain)
+ seqs.unlink()
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type_3')
drop_sequence('test_sequence_type_4')
-class test_ir_sequence_generate(unittest.TestCase):
+
+class TestIrSequenceGenerate(unittest.TestCase):
""" Create sequence objects and generate some values. """
def test_ir_sequence_create(self):
""" Try to create a sequence object. """
- cr = cursor()
- d = dict(code='test_sequence_type_5', name='Test sequence')
- c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {})
- assert c
- cr.commit()
- cr.close()
-
- cr = cursor()
- f = lambda *a: registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type_5', {})
- assert all(str(x) == f() for x in xrange(1,10))
- cr.commit()
- cr.close()
+ with environment() as env:
+ seq = env['ir.sequence'].create({
+ 'code': 'test_sequence_type_5',
+ 'name': 'Test sequence',
+ })
+ self.assertTrue(seq)
+
+ with environment() as env:
+ for i in xrange(1, 10):
+ n = env['ir.sequence'].next_by_code('test_sequence_type_5')
+ self.assertEqual(n, str(i))
def test_ir_sequence_create_no_gap(self):
""" Try to create a sequence object. """
- cr = cursor()
- d = dict(code='test_sequence_type_6', name='Test sequence', implementation='no_gap')
- c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {})
- assert c
- cr.commit()
- cr.close()
-
- cr = cursor()
- f = lambda *a: registry('ir.sequence').next_by_code(cr, ADMIN_USER_ID, 'test_sequence_type_6', {})
- assert all(str(x) == f() for x in xrange(1,10))
- cr.commit()
- cr.close()
+ with environment() as env:
+ seq = env['ir.sequence'].create({
+ 'code': 'test_sequence_type_6',
+ 'name': 'Test sequence',
+ 'implementation': 'no_gap',
+ })
+ self.assertTrue(seq)
+
+ with environment() as env:
+ for i in xrange(1, 10):
+ n = env['ir.sequence'].next_by_code('test_sequence_type_6')
+ self.assertEqual(n, str(i))
@classmethod
def tearDownClass(cls):
@@ -195,33 +179,29 @@ class test_ir_sequence_generate(unittest.TestCase):
drop_sequence('test_sequence_type_6')
-class Test_ir_sequence_init(common.TransactionCase):
+class TestIrSequenceInit(common.TransactionCase):
def test_00(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- # test if read statement return the good number_next value (from postgreSQL sequence and not ir_sequence value)
- sequence = registry('ir.sequence')
+ """ test whether the read method returns the right number_next value
+ (from postgreSQL sequence and not ir_sequence value)
+ """
# first creation of sequence (normal)
- values = {'number_next': 1,
- 'company_id': 1,
- 'padding': 4,
- 'number_increment': 1,
- 'implementation': 'standard',
- 'name': 'test-sequence-00'}
- seq_id = sequence.create(cr, uid, values)
- # Call get next 4 times
- sequence.next_by_id(cr, uid, seq_id)
- sequence.next_by_id(cr, uid, seq_id)
- sequence.next_by_id(cr, uid, seq_id)
- read_sequence = sequence.next_by_id(cr, uid, seq_id)
- # Read the value of the current sequence
- assert read_sequence == "0004", 'The actual sequence value must be 4. reading : %s' % read_sequence
- # reset sequence to 1 by write method calling
- sequence.write(cr, uid, [seq_id], {'number_next': 1})
+ seq = self.env['ir.sequence'].create({
+ 'number_next': 1,
+ 'company_id': 1,
+ 'padding': 4,
+ 'number_increment': 1,
+ 'implementation': 'standard',
+ 'name': 'test-sequence-00',
+ })
+ # Call next() 4 times, and check the last returned value
+ seq.next_by_id()
+ seq.next_by_id()
+ seq.next_by_id()
+ n = seq.next_by_id()
+ self.assertEqual(n, "0004", 'The actual sequence value must be 4. reading : %s' % n)
+ # reset sequence to 1 by write()
+ seq.write({'number_next': 1})
# Read the value of the current sequence
- read_sequence = sequence.next_by_id(cr, uid, seq_id)
- assert read_sequence == "0001", 'The actual sequence value must be 1. reading : %s' % read_sequence
-
-if __name__ == "__main__":
- unittest.main()
+ n = seq.next_by_id()
+ self.assertEqual(n, "0001", 'The actual sequence value must be 1. reading : %s' % n)
diff --git a/openerp/addons/base/tests/test_ir_sequence_date_range.py b/openerp/addons/base/tests/test_ir_sequence_date_range.py
index c2ddc4e4f0f..147b0f26050 100644
--- a/openerp/addons/base/tests/test_ir_sequence_date_range.py
+++ b/openerp/addons/base/tests/test_ir_sequence_date_range.py
@@ -1,122 +1,142 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp.tests import common
from datetime import date
+from odoo.tests.common import SingleTransactionCase
+from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
-class test_ir_sequence_date_range_standard(common.SingleTransactionCase):
+
+class TestIrSequenceDateRangeStandard(SingleTransactionCase):
""" A few tests for a 'Standard' (i.e. PostgreSQL) sequence. """
def test_ir_sequence_date_range_1_create(self):
""" Try to create a sequence object with date ranges enabled. """
- d = dict(code='test_sequence_date_range', name='Test sequence', use_date_range=True)
- c = self.registry('ir.sequence').create(self.cr, self.uid, d, {})
- assert c
+ seq = self.env['ir.sequence'].create({
+ 'code': 'test_sequence_date_range',
+ 'name': 'Test sequence',
+ 'use_date_range': True,
+ })
+ self.assertTrue(seq)
def test_ir_sequence_date_range_2_change_dates(self):
""" Draw numbers to create a first subsequence then change its date range. Then, try to draw a new number adn check a new subsequence was correctly created. """
- year = str(int(date.today().strftime("%Y")) - 1)
- dt = "{}-01-16".format(year)
- n = self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range', {'ir_sequence_date': dt})
+ year = date.today().year - 1
+ january = lambda d: date(year, 1, d).strftime(DATE_FORMAT)
+
+ seq16 = self.env['ir.sequence'].with_context({'ir_sequence_date': january(16)})
+ n = seq16.next_by_code('test_sequence_date_range')
self.assertEqual(n, '1')
- n = self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range', {'ir_sequence_date': dt})
+ n = seq16.next_by_code('test_sequence_date_range')
self.assertEqual(n, '2')
+
# modify the range of date created
- domain = [('sequence_id.code', '=', 'test_sequence_date_range'), ('date_from', '=', '{}-01-01'.format(year))]
- seq_date_range_id = self.registry('ir.sequence.date_range').search(self.cr, self.uid, domain, {})
- self.registry('ir.sequence.date_range').write(self.cr, self.uid, seq_date_range_id, {'date_from': '{}-01-18'.format(year)}, {})
- n = self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range', {'ir_sequence_date': dt})
+ domain = [('sequence_id.code', '=', 'test_sequence_date_range'), ('date_from', '=', january(1))]
+ seq_date_range = self.env['ir.sequence.date_range'].search(domain)
+ seq_date_range.write({'date_from': january(18)})
+ n = seq16.next_by_code('test_sequence_date_range')
self.assertEqual(n, '1')
+
# check the newly created sequence stops at the 17th of January
- domain = [('sequence_id.code', '=', 'test_sequence_date_range'), ('date_from', '=', '{}-01-01'.format(year))]
- seq_date_range_id = self.registry('ir.sequence.date_range').search(self.cr, self.uid, domain, {})
- seq_date_range = self.registry('ir.sequence.date_range').browse(self.cr, self.uid, seq_date_range_id[0])
- self.assertEqual(seq_date_range.date_to, '{}-01-17'.format(year))
+ domain = [('sequence_id.code', '=', 'test_sequence_date_range'), ('date_from', '=', january(1))]
+ seq_date_range = self.env['ir.sequence.date_range'].search(domain)
+ self.assertEqual(seq_date_range.date_to, january(17))
def test_ir_sequence_date_range_3_unlink(self):
- ids = self.registry('ir.sequence').search(self.cr, self.uid, [('code', '=', 'test_sequence_date_range')])
- self.registry('ir.sequence').unlink(self.cr, self.uid, ids)
+ seq = self.env['ir.sequence'].search([('code', '=', 'test_sequence_date_range')])
+ seq.unlink()
-class test_ir_sequence_date_range_no_gap(common.SingleTransactionCase):
+class TestIrSequenceDateRangeNoGap(SingleTransactionCase):
""" Copy of the previous tests for a 'No gap' sequence. """
def test_ir_sequence_date_range_1_create_no_gap(self):
""" Try to create a sequence object. """
- d = dict(code='test_sequence_date_range_2', name='Test sequence',
- implementation='no_gap', use_date_range=True)
- c = self.registry('ir.sequence').create(self.cr, self.uid, d, {})
- assert c
+ seq = self.env['ir.sequence'].create({
+ 'code': 'test_sequence_date_range_2',
+ 'name': 'Test sequence',
+ 'use_date_range': True,
+ 'implementation': 'no_gap',
+ })
+ self.assertTrue(seq)
def test_ir_sequence_date_range_2_change_dates(self):
""" Draw numbers to create a first subsequence then change its date range. Then, try to draw a new number adn check a new subsequence was correctly created. """
- year = str(int(date.today().strftime("%Y")) - 1)
- dt = "{}-01-16".format(year)
- n = self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_2', {'ir_sequence_date': dt})
+ year = date.today().year - 1
+ january = lambda d: date(year, 1, d).strftime(DATE_FORMAT)
+
+ seq16 = self.env['ir.sequence'].with_context({'ir_sequence_date': january(16)})
+ n = seq16.next_by_code('test_sequence_date_range_2')
self.assertEqual(n, '1')
- n = self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_2', {'ir_sequence_date': dt})
+ n = seq16.next_by_code('test_sequence_date_range_2')
self.assertEqual(n, '2')
+
# modify the range of date created
- domain = [('sequence_id.code', '=', 'test_sequence_date_range_2'), ('date_from', '=', '{}-01-01'.format(year))]
- seq_date_range_id = self.registry('ir.sequence.date_range').search(self.cr, self.uid, domain, {})
- self.registry('ir.sequence.date_range').write(self.cr, self.uid, seq_date_range_id, {'date_from': '{}-01-18'.format(year)}, {})
- n = self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_2', {'ir_sequence_date': dt})
+ domain = [('sequence_id.code', '=', 'test_sequence_date_range_2'), ('date_from', '=', january(1))]
+ seq_date_range = self.env['ir.sequence.date_range'].search(domain)
+ seq_date_range.write({'date_from': january(18)})
+ n = seq16.next_by_code('test_sequence_date_range_2')
self.assertEqual(n, '1')
+
# check the newly created sequence stops at the 17th of January
- domain = [('sequence_id.code', '=', 'test_sequence_date_range_2'), ('date_from', '=', '{}-01-01'.format(year))]
- seq_date_range_id = self.registry('ir.sequence.date_range').search(self.cr, self.uid, domain, {})
- seq_date_range = self.registry('ir.sequence.date_range').browse(self.cr, self.uid, seq_date_range_id[0])
- self.assertEqual(seq_date_range.date_to, '{}-01-17'.format(year))
+ domain = [('sequence_id.code', '=', 'test_sequence_date_range_2'), ('date_from', '=', january(1))]
+ seq_date_range = self.env['ir.sequence.date_range'].search(domain)
+ self.assertEqual(seq_date_range.date_to, january(17))
def test_ir_sequence_date_range_3_unlink(self):
- ids = self.registry('ir.sequence').search(self.cr, self.uid, [('code', '=', 'test_sequence_date_range_2')])
- self.registry('ir.sequence').unlink(self.cr, self.uid, ids)
+ seq = self.env['ir.sequence'].search([('code', '=', 'test_sequence_date_range_2')])
+ seq.unlink()
-class test_ir_sequence_date_range_change_implementation(common.SingleTransactionCase):
+class TestIrSequenceDateRangeChangeImplementation(SingleTransactionCase):
""" Create sequence objects and change their ``implementation`` field. """
def test_ir_sequence_date_range_1_create(self):
""" Try to create a sequence object. """
- d = dict(code='test_sequence_date_range_3', name='Test sequence', use_date_range=True)
- c = self.registry('ir.sequence').create(self.cr, self.uid, d, {})
- assert c
- d = {
+ seq = self.env['ir.sequence'].create({
+ 'code': 'test_sequence_date_range_3',
+ 'name': 'Test sequence',
+ 'use_date_range': True,
+ })
+ self.assertTrue(seq)
+
+ seq = self.env['ir.sequence'].create({
'code': 'test_sequence_date_range_4',
'name': 'Test sequence',
+ 'use_date_range': True,
'implementation': 'no_gap',
- 'use_date_range': True
- }
- c = self.registry('ir.sequence').create(self.cr, self.uid, d, {})
- assert c
+ })
+ self.assertTrue(seq)
def test_ir_sequence_date_range_2_use(self):
""" Make some use of the sequences to create some subsequences """
- year = str(int(date.today().strftime("%Y")) - 1)
- dt = "{}-01-16".format(year)
- f = lambda *a: self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_3', {})
- assert all(str(x) == f() for x in xrange(1, 5))
- f = lambda *a: self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_3', {'ir_sequence_date': dt})
- assert all(str(x) == f() for x in xrange(1, 5))
- f = lambda *a: self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_4', {})
- assert all(str(x) == f() for x in xrange(1, 5))
- f = lambda *a: self.registry('ir.sequence').next_by_code(self.cr, self.uid, 'test_sequence_date_range_4', {'ir_sequence_date': dt})
- assert all(str(x) == f() for x in xrange(1, 5))
+ year = date.today().year - 1
+ january = lambda d: date(year, 1, d).strftime(DATE_FORMAT)
+
+ seq = self.env['ir.sequence']
+ seq16 = self.env['ir.sequence'].with_context({'ir_sequence_date': january(16)})
+
+ for i in xrange(1, 5):
+ n = seq.next_by_code('test_sequence_date_range_3')
+ self.assertEqual(n, str(i))
+ for i in xrange(1, 5):
+ n = seq16.next_by_code('test_sequence_date_range_3')
+ self.assertEqual(n, str(i))
+ for i in xrange(1, 5):
+ n = seq.next_by_code('test_sequence_date_range_4')
+ self.assertEqual(n, str(i))
+ for i in xrange(1, 5):
+ n = seq16.next_by_code('test_sequence_date_range_4')
+ self.assertEqual(n, str(i))
def test_ir_sequence_date_range_3_write(self):
"""swap the implementation method on both"""
- ids = self.registry('ir.sequence').search(self.cr, self.uid, [
- ('code', 'in', ['test_sequence_date_range_3', 'test_sequence_date_range_4'])
- ], {})
- self.registry('ir.sequence').write(self.cr, self.uid, ids, {'implementation': 'standard'})
- self.registry('ir.sequence').write(self.cr, self.uid, ids, {'implementation': 'no_gap'})
+ domain = [('code', 'in', ['test_sequence_date_range_3', 'test_sequence_date_range_4'])]
+ seqs = self.env['ir.sequence'].search(domain)
+ seqs.write({'implementation': 'standard'})
+ seqs.write({'implementation': 'no_gap'})
def test_ir_sequence_date_range_4_unlink(self):
- ids = self.registry('ir.sequence').search(self.cr, self.uid, [
- ('code', 'in', ['test_sequence_date_range_3', 'test_sequence_date_range_4'])
- ], {})
- self.registry('ir.sequence').unlink(self.cr, self.uid, ids, {})
-
-
-if __name__ == '__main__':
- unittest.main()
+ domain = [('code', 'in', ['test_sequence_date_range_3', 'test_sequence_date_range_4'])]
+ seqs = self.env['ir.sequence'].search(domain)
+ seqs.unlink()
diff --git a/openerp/addons/base/tests/test_ir_values.py b/openerp/addons/base/tests/test_ir_values.py
index 435421ea845..8cdf35e4d40 100644
--- a/openerp/addons/base/tests/test_ir_values.py
+++ b/openerp/addons/base/tests/test_ir_values.py
@@ -1,98 +1,99 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import openerp.tests.common as common
+from odoo.tests.common import TransactionCase
-class test_ir_values(common.TransactionCase):
+
+class TestIrValues(TransactionCase):
def test_00(self):
# Create some default value for some (non-existing) model, for all users.
- ir_values = self.registry('ir.values')
+ ir_values = self.env['ir.values']
# use the old API
- ir_values.set(self.cr, self.uid, 'default', False, 'my_test_field',
- ['unexisting_model'], 'global value')
+ ir_values.set('default', False, 'my_test_field', ['unexisting_model'],
+ 'global value')
# use the new API
- ir_values.set_default(self.cr, self.uid, 'other_unexisting_model',
- 'my_other_test_field', 'conditional value', condition='foo=bar')
-
+ ir_values.set_default('other_unexisting_model', 'my_other_test_field',
+ 'conditional value', condition='foo=bar')
# Retrieve them.
- ir_values = self.registry('ir.values')
# d is a list of triplets (id, name, value)
# Old API
- d = ir_values.get(self.cr, self.uid, 'default', False, ['unexisting_model'])
- assert len(d) == 1, "Only one single value should be retrieved for this model"
- assert d[0][1] == 'my_test_field', "Can't retrieve the created default value. (1)"
- assert d[0][2] == 'global value', "Can't retrieve the created default value. (2)"
+ d = ir_values.get('default', False, ['unexisting_model'])
+ self.assertEqual(len(d), 1, "Only one single value should be retrieved for this model")
+ self.assertEqual(d[0][1], 'my_test_field', "Can't retrieve the created default value. (1)")
+ self.assertEqual(d[0][2], 'global value', "Can't retrieve the created default value. (2)")
# New API, Conditional version
- d = ir_values.get_defaults(self.cr, self.uid, 'other_unexisting_model')
- assert len(d) == 0, "No value should be retrieved, the condition is not met"
- d = ir_values.get_defaults(self.cr, self.uid, 'other_unexisting_model', condition="foo=eggs")
- assert len(d) == 0, 'Condition is not met either, no defaults should be returned'
- d = ir_values.get_defaults(self.cr, self.uid, 'other_unexisting_model', condition="foo=bar")
- assert len(d) == 1, "Only one single value should be retrieved"
- assert d[0][1] == 'my_other_test_field', "Can't retrieve the created default value. (5)"
- assert d[0][2] == 'conditional value', "Can't retrieve the created default value. (6)"
+ d = ir_values.get_defaults('other_unexisting_model')
+ self.assertEqual(len(d), 0, "No value should be retrieved, the condition is not met")
+ d = ir_values.get_defaults('other_unexisting_model', condition="foo=eggs")
+ self.assertEqual(len(d), 0, 'Condition is not met either, no defaults should be returned')
+ d = ir_values.get_defaults('other_unexisting_model', condition="foo=bar")
+ self.assertEqual(len(d), 1, "Only one single value should be retrieved")
+ self.assertEqual(d[0][1], 'my_other_test_field', "Can't retrieve the created default value. (5)")
+ self.assertEqual(d[0][2], 'conditional value', "Can't retrieve the created default value. (6)")
# Do it again but for a specific user.
- ir_values = self.registry('ir.values')
- ir_values.set(self.cr, self.uid, 'default', False, 'my_test_field',['unexisting_model'], 'specific value', preserve_user=True)
+ ir_values.set('default', False, 'my_test_field',['unexisting_model'],
+ 'specific value', preserve_user=True)
# Retrieve it and check it is the one for the current user.
- ir_values = self.registry('ir.values')
- d = ir_values.get(self.cr, self.uid, 'default', False, ['unexisting_model'])
- assert len(d) == 1, "Only one default must be returned per field"
- assert d[0][1] == 'my_test_field', "Can't retrieve the created default value."
- assert d[0][2] == 'specific value', "Can't retrieve the created default value."
+
+ d = ir_values.get('default', False, ['unexisting_model'])
+ self.assertEqual(len(d), 1, "Only one default must be returned per field")
+ self.assertEqual(d[0][1], 'my_test_field', "Can't retrieve the created default value.")
+ self.assertEqual(d[0][2], 'specific value', "Can't retrieve the created default value.")
# Create some action bindings for a non-existing model.
act_id_1 = self.ref('base.act_values_form_action')
act_id_2 = self.ref('base.act_values_form_defaults')
act_id_3 = self.ref('base.action_res_company_form')
-
- ir_values = self.registry('ir.values')
- ir_values.set(self.cr, self.uid, 'action', 'tree_but_open', 'OnDblClick Action', ['unexisting_model'], 'ir.actions.act_window,%d' % act_id_1, isobject=True)
- ir_values.set(self.cr, self.uid, 'action', 'tree_but_open', 'OnDblClick Action 2', ['unexisting_model'], 'ir.actions.act_window,%d' % act_id_2, isobject=True)
- ir_values.set(self.cr, self.uid, 'action', 'client_action_multi', 'Side Wizard', ['unexisting_model'], 'ir.actions.act_window,%d' % act_id_3, isobject=True)
- report_ids = self.registry('ir.actions.report.xml').search(self.cr, self.uid, [], {})
- reports = self.registry('ir.actions.report.xml').browse(self.cr, self.uid, report_ids, {})
- report_id = [report.id for report in reports if not report.groups_id][0] # assume at least one
- ir_values.set(self.cr, self.uid, 'action', 'client_print_multi', 'Nice Report', ['unexisting_model'], 'ir.actions.report.xml,%d' % report_id, isobject=True)
+ ir_values.set('action', 'tree_but_open', 'OnDblClick Action', ['unexisting_model'],
+ 'ir.actions.act_window,%d' % act_id_1, isobject=True)
+ ir_values.set('action', 'tree_but_open', 'OnDblClick Action 2', ['unexisting_model'],
+ 'ir.actions.act_window,%d' % act_id_2, isobject=True)
+ ir_values.set('action', 'client_action_multi', 'Side Wizard', ['unexisting_model'],
+ 'ir.actions.act_window,%d' % act_id_3, isobject=True)
+ reports = self.env['ir.actions.report.xml'].search([])
+ report_id = next(report.id for report in reports if not report.groups_id)
+ ir_values.set('action', 'client_print_multi', 'Nice Report', ['unexisting_model'],
+ 'ir.actions.report.xml,%d' % report_id, isobject=True)
# Replace one action binding to set a new name.
- ir_values = self.registry('ir.values')
- ir_values.set(self.cr, self.uid, 'action', 'tree_but_open', 'OnDblClick Action New', ['unexisting_model'], 'ir.actions.act_window,%d' % act_id_1, isobject=True)
+ ir_values.set('action', 'tree_but_open', 'OnDblClick Action New', ['unexisting_model'],
+ 'ir.actions.act_window,%d' % act_id_1, isobject=True)
# Retrieve the action bindings and check they're correct
- ir_values = self.registry('ir.values')
- actions = ir_values.get(self.cr, self.uid, 'action', 'tree_but_open', ['unexisting_model'])
- assert len(actions) == 2, "Mismatching number of bound actions"
+ actions = ir_values.get('action', 'tree_but_open', ['unexisting_model'])
+ self.assertEqual(len(actions), 2, "Mismatching number of bound actions")
#first action
- assert len(actions[0]) == 3, "Malformed action definition"
- assert actions[0][1] == 'OnDblClick Action 2', 'Bound action does not match definition'
- assert isinstance(actions[0][2], dict) and actions[0][2]['id'] == act_id_2, 'Bound action does not match definition'
+ self.assertEqual(len(actions[0]), 3, "Malformed action definition")
+ self.assertEqual(actions[0][1], 'OnDblClick Action 2', 'Bound action does not match definition')
+ self.assertTrue(isinstance(actions[0][2], dict) and actions[0][2]['id'] == act_id_2,
+ 'Bound action does not match definition')
#second action - this ones comes last because it was re-created with a different name
- assert len(actions[1]) == 3, "Malformed action definition"
- assert actions[1][1] == 'OnDblClick Action New', 'Re-Registering an action should replace it'
- assert isinstance(actions[1][2], dict) and actions[1][2]['id'] == act_id_1, 'Bound action does not match definition'
-
- actions = ir_values.get(self.cr, self.uid, 'action', 'client_action_multi', ['unexisting_model'])
- assert len(actions) == 1, "Mismatching number of bound actions"
- assert len(actions[0]) == 3, "Malformed action definition"
- assert actions[0][1] == 'Side Wizard', 'Bound action does not match definition'
- assert isinstance(actions[0][2], dict) and actions[0][2]['id'] == act_id_3, 'Bound action does not match definition'
-
- actions = ir_values.get(self.cr, self.uid, 'action', 'client_print_multi', ['unexisting_model'])
- assert len(actions) == 1, "Mismatching number of bound actions"
- assert len(actions[0]) == 3, "Malformed action definition"
- assert actions[0][1] == 'Nice Report', 'Bound action does not match definition'
- assert isinstance(actions[0][2], dict) and actions[0][2]['id'] == report_id, 'Bound action does not match definition'
-
-if __name__ == '__main__':
- unittest.main()
+ self.assertEqual(len(actions[1]), 3, "Malformed action definition")
+ self.assertEqual(actions[1][1], 'OnDblClick Action New', 'Re-Registering an action should replace it')
+ self.assertTrue(isinstance(actions[1][2], dict) and actions[1][2]['id'] == act_id_1,
+ 'Bound action does not match definition')
+
+ actions = ir_values.get('action', 'client_action_multi', ['unexisting_model'])
+ self.assertEqual(len(actions), 1, "Mismatching number of bound actions")
+ self.assertEqual(len(actions[0]), 3, "Malformed action definition")
+ self.assertEqual(actions[0][1], 'Side Wizard', 'Bound action does not match definition')
+ self.assertTrue(isinstance(actions[0][2], dict) and actions[0][2]['id'] == act_id_3,
+ 'Bound action does not match definition')
+
+ actions = ir_values.get('action', 'client_print_multi', ['unexisting_model'])
+ self.assertEqual(len(actions), 1, "Mismatching number of bound actions")
+ self.assertEqual(len(actions[0]), 3, "Malformed action definition")
+ self.assertEqual(actions[0][1], 'Nice Report', 'Bound action does not match definition')
+ self.assertTrue(isinstance(actions[0][2], dict) and actions[0][2]['id'] == report_id,
+ 'Bound action does not match definition')
diff --git a/openerp/addons/base/tests/test_mail.py b/openerp/addons/base/tests/test_mail.py
index 96e1973ed49..a751b7a76e3 100644
--- a/openerp/addons/base/tests/test_mail.py
+++ b/openerp/addons/base/tests/test_mail.py
@@ -1,14 +1,11 @@
-#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# This test can be run stand-alone with something like:
-# > PYTHONPATH=. python2 openerp/tests/test_misc.py
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import cgi
import unittest
-from openerp.tools import html_sanitize, append_content_to_html, plaintext2html, email_split
-import test_mail_examples
+from odoo.tools import html_sanitize, append_content_to_html, plaintext2html, email_split
+from . import test_mail_examples
class TestSanitizer(unittest.TestCase):
@@ -325,7 +322,3 @@ class TestEmailTools(unittest.TestCase):
]
for text, expected in cases:
self.assertEqual(email_split(text), expected, 'email_split is broken')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/openerp/addons/base/tests/test_mail_examples.py b/openerp/addons/base/tests/test_mail_examples.py
index 19cadd6f156..a83e668d940 100644
--- a/openerp/addons/base/tests/test_mail_examples.py
+++ b/openerp/addons/base/tests/test_mail_examples.py
@@ -1,5 +1,5 @@
-#!/usr/bin/env python
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
MISC_HTML_SOURCE = """
<font size="2" style="color: rgb(31, 31, 31); font-family: monospace; font-variant: normal; line-height: normal; ">test1</font>
@@ -515,4 +515,4 @@ REMOVE_CLASS_IN = [
REMOVE_CLASS_OUT = [
'<div class="modal-backdrop in">',
'<div class="modal-content openerp">',
- '<div class="modal-header">'] \ No newline at end of file
+ '<div class="modal-header">']
diff --git a/openerp/addons/base/tests/test_menu.py b/openerp/addons/base/tests/test_menu.py
index a4b5315dc82..451b63d5f17 100644
--- a/openerp/addons/base/tests/test_menu.py
+++ b/openerp/addons/base/tests/test_menu.py
@@ -1,32 +1,30 @@
-import openerp.tests.common as common
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-class test_menu(common.TransactionCase):
+from odoo.tests.common import TransactionCase
- def setUp(self):
- super(test_menu,self).setUp()
- self.Menus = self.registry('ir.ui.menu')
+
+class TestMenu(TransactionCase):
def test_00_menu_deletion(self):
"""Verify that menu deletion works properly when there are child menus, and those
are indeed made orphans"""
- cr, uid, Menus = self.cr, self.uid, self.Menus
-
- # Generic trick necessary for search() calls to avoid hidden menus
- ctx = {'ir.ui.menu.full_list': True}
-
- root_id = Menus.create(cr, uid, {'name': 'Test root'})
- child1_id = Menus.create(cr, uid, {'name': 'Test child 1', 'parent_id': root_id})
- child2_id = Menus.create(cr, uid, {'name': 'Test child 2', 'parent_id': root_id})
- child21_id = Menus.create(cr, uid, {'name': 'Test child 2-1', 'parent_id': child2_id})
-
- all_ids = [root_id, child1_id, child2_id, child21_id]
+ Menu = self.env['ir.ui.menu']
+ root = Menu.create({'name': 'Test root'})
+ child1 = Menu.create({'name': 'Test child 1', 'parent_id': root.id})
+ child2 = Menu.create({'name': 'Test child 2', 'parent_id': root.id})
+ child21 = Menu.create({'name': 'Test child 2-1', 'parent_id': child2.id})
+ all_ids = [root.id, child1.id, child2.id, child21.id]
# delete and check that direct children are promoted to top-level
# cfr. explanation in menu.unlink()
- Menus.unlink(cr, uid, [root_id])
+ root.unlink()
+
+ # Generic trick necessary for search() calls to avoid hidden menus
+ Menu = self.env['ir.ui.menu'].with_context({'ir.ui.menu.full_list': True})
- remaining_ids = Menus.search(cr, uid, [('id', 'in', all_ids)], order="id", context=ctx)
- self.assertEqual([child1_id, child2_id, child21_id], remaining_ids)
+ remaining = Menu.search([('id', 'in', all_ids)], order="id")
+ self.assertEqual([child1.id, child2.id, child21.id], remaining.ids)
- orphan_ids = Menus.search(cr, uid, [('id', 'in', all_ids), ('parent_id', '=', False)], order="id", context=ctx)
- self.assertEqual([child1_id, child2_id], orphan_ids)
+ orphans = Menu.search([('id', 'in', all_ids), ('parent_id', '=', False)], order="id")
+ self.assertEqual([child1.id, child2.id], orphans.ids)
diff --git a/openerp/addons/base/tests/test_misc.py b/openerp/addons/base/tests/test_misc.py
index d20a17403ff..0dc48a0f29b 100644
--- a/openerp/addons/base/tests/test_misc.py
+++ b/openerp/addons/base/tests/test_misc.py
@@ -1,9 +1,12 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
import unittest
-from openerp.tools import misc
+from odoo.tools import misc
-class test_countingstream(unittest.TestCase):
+class TestCountingStream(unittest.TestCase):
def test_empty_stream(self):
s = misc.CountingStream(iter([]))
self.assertEqual(s.index, -1)
@@ -32,6 +35,3 @@ class test_countingstream(unittest.TestCase):
self.assertEqual(s.index, 0)
self.assertIsNone(next(s, None))
self.assertEqual(s.index, 0)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/openerp/addons/base/tests/test_orm.py b/openerp/addons/base/tests/test_orm.py
index bfc6e52c470..0fdfb05636c 100644
--- a/openerp/addons/base/tests/test_orm.py
+++ b/openerp/addons/base/tests/test_orm.py
@@ -1,117 +1,125 @@
-from collections import defaultdict
-from openerp.tools import mute_logger
-from openerp.tests import common
-
-UID = common.ADMIN_USER_ID
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from collections import defaultdict
-class TestORM(common.TransactionCase):
- """ test special behaviors of ORM CRUD functions
-
- TODO: use real Exceptions types instead of Exception """
+from odoo.exceptions import AccessError, MissingError
+from odoo.tests.common import TransactionCase
+from odoo.tools import mute_logger
- def setUp(self):
- super(TestORM, self).setUp()
- cr, uid = self.cr, self.uid
- self.partner = self.registry('res.partner')
- self.users = self.registry('res.users')
- self.p1 = self.partner.name_create(cr, uid, 'W')[0]
- self.p2 = self.partner.name_create(cr, uid, 'Y')[0]
- self.ir_rule = self.registry('ir.rule')
- # sample unprivileged user
- employee_gid = self.ref('base.group_user')
- self.uid2 = self.users.create(cr, uid, {'name': 'test user', 'login': 'test', 'groups_id': [4,employee_gid]})
+class TestORM(TransactionCase):
+ """ test special behaviors of ORM CRUD functions """
@mute_logger('openerp.models')
- def testAccessDeletedRecords(self):
+ def test_access_deleted_records(self):
""" Verify that accessing deleted records works as expected """
- cr, uid, uid2, p1, p2 = self.cr, self.uid, self.uid2, self.p1, self.p2
- self.partner.unlink(cr, uid, [p1])
+ p1 = self.env['res.partner'].create({'name': 'W'})
+ p2 = self.env['res.partner'].create({'name': 'Y'})
+ p1.unlink()
# read() is expected to skip deleted records because our API is not
# transactional for a sequence of search()->read() performed from the
# client-side... a concurrent deletion could therefore cause spurious
# exceptions even when simply opening a list view!
# /!\ Using unprileged user to detect former side effects of ir.rules!
- self.assertEqual([{'id': p2, 'name': 'Y'}], self.partner.read(cr, uid2, [p1,p2], ['name']), "read() should skip deleted records")
- self.assertEqual([], self.partner.read(cr, uid2, [p1], ['name']), "read() should skip deleted records")
+ user = self.env['res.users'].create({
+ 'name': 'test user',
+ 'login': 'test2',
+ 'groups_id': [4, self.ref('base.group_user')],
+ })
+ ps = (p1 + p2).sudo(user)
+ self.assertEqual([{'id': p2.id, 'name': 'Y'}], ps.read(['name']), "read() should skip deleted records")
+ self.assertEqual([], ps[0].read(['name']), "read() should skip deleted records")
# Deleting an already deleted record should be simply ignored
- self.assertTrue(self.partner.unlink(cr, uid, [p1]), "Re-deleting should be a no-op")
+ self.assertTrue(p1.unlink(), "Re-deleting should be a no-op")
# Updating an already deleted record should raise, even as admin
- with self.assertRaises(Exception):
- self.partner.write(cr, uid, [p1], {'name': 'foo'})
+ with self.assertRaises(MissingError):
+ p1.write({'name': 'foo'})
@mute_logger('openerp.models')
- def testAccessFilteredRecords(self):
+ def test_access_filtered_records(self):
""" Verify that accessing filtered records works as expected for non-admin user """
- cr, uid, uid2, p1, p2 = self.cr, self.uid, self.uid2, self.p1, self.p2
- partner_model = self.registry('ir.model').search(cr, uid, [('model','=','res.partner')])[0]
- self.ir_rule.create(cr, uid, {'name': 'Y is invisible',
- 'domain_force': [('id', '!=', p1)],
- 'model_id': partner_model})
+ p1 = self.env['res.partner'].create({'name': 'W'})
+ p2 = self.env['res.partner'].create({'name': 'Y'})
+ user = self.env['res.users'].create({
+ 'name': 'test user',
+ 'login': 'test2',
+ 'groups_id': [4, self.ref('base.group_user')],
+ })
+
+ partner_model = self.env['ir.model'].search([('model','=','res.partner')])
+ self.env['ir.rule'].create({
+ 'name': 'Y is invisible',
+ 'domain_force': [('id', '!=', p1.id)],
+ 'model_id': partner_model.id,
+ })
+
# search as unprivileged user
- partners = self.partner.search(cr, uid2, [])
- self.assertFalse(p1 in partners, "W should not be visible...")
- self.assertTrue(p2 in partners, "... but Y should be visible")
+ partners = self.env['res.partner'].sudo(user).search([])
+ self.assertNotIn(p1, partners, "W should not be visible...")
+ self.assertIn(p2, partners, "... but Y should be visible")
# read as unprivileged user
- with self.assertRaises(Exception):
- self.partner.read(cr, uid2, [p1], ['name'])
+ with self.assertRaises(AccessError):
+ p1.sudo(user).read(['name'])
# write as unprivileged user
- with self.assertRaises(Exception):
- self.partner.write(cr, uid2, [p1], {'name': 'foo'})
+ with self.assertRaises(AccessError):
+ p1.sudo(user).write({'name': 'foo'})
# unlink as unprivileged user
- with self.assertRaises(Exception):
- self.partner.unlink(cr, uid2, [p1])
+ with self.assertRaises(AccessError):
+ p1.sudo(user).unlink()
# Prepare mixed case
- self.partner.unlink(cr, uid, [p2])
+ p2.unlink()
# read mixed records: some deleted and some filtered
- with self.assertRaises(Exception):
- self.partner.read(cr, uid2, [p1,p2], ['name'])
+ with self.assertRaises(AccessError):
+ (p1 + p2).sudo(user).read(['name'])
# delete mixed records: some deleted and some filtered
- with self.assertRaises(Exception):
- self.partner.unlink(cr, uid2, [p1,p2])
+ with self.assertRaises(AccessError):
+ (p1 + p2).sudo(user).unlink()
- def test_multi_read(self):
- record_id = self.partner.create(self.cr, UID, {'name': 'MyPartner1'})
- records = self.partner.read(self.cr, UID, [record_id])
- self.assertIsInstance(records, list)
+ def test_read(self):
+ partner = self.env['res.partner'].create({'name': 'MyPartner1'})
+ result = partner.read()
+ self.assertIsInstance(result, list)
- def test_one_read(self):
- record_id = self.partner.create(self.cr, UID, {'name': 'MyPartner1'})
- record = self.partner.read(self.cr, UID, record_id)
- self.assertIsInstance(record, dict)
+ # special cases for the old API only
+ result = self.registry('res.partner').read(self.cr, self.uid, [partner.id])
+ self.assertIsInstance(result, list)
+ result = self.registry('res.partner').read(self.cr, self.uid, partner.id)
+ self.assertIsInstance(result, dict)
@mute_logger('openerp.models')
def test_search_read(self):
+ partner = self.env['res.partner']
+
# simple search_read
- self.partner.create(self.cr, UID, {'name': 'MyPartner1'})
- found = self.partner.search_read(self.cr, UID, [['name', '=', 'MyPartner1']], ['name'])
+ partner.create({'name': 'MyPartner1'})
+ found = partner.search_read([('name', '=', 'MyPartner1')], ['name'])
self.assertEqual(len(found), 1)
self.assertEqual(found[0]['name'], 'MyPartner1')
- self.assertTrue('id' in found[0])
+ self.assertIn('id', found[0])
# search_read correct order
- self.partner.create(self.cr, UID, {'name': 'MyPartner2'})
- found = self.partner.search_read(self.cr, UID, [['name', 'like', 'MyPartner']], ['name'], order="name")
+ partner.create({'name': 'MyPartner2'})
+ found = partner.search_read([('name', 'like', 'MyPartner')], ['name'], order="name")
self.assertEqual(len(found), 2)
self.assertEqual(found[0]['name'], 'MyPartner1')
self.assertEqual(found[1]['name'], 'MyPartner2')
- found = self.partner.search_read(self.cr, UID, [['name', 'like', 'MyPartner']], ['name'], order="name desc")
+ found = partner.search_read([('name', 'like', 'MyPartner')], ['name'], order="name desc")
self.assertEqual(len(found), 2)
self.assertEqual(found[0]['name'], 'MyPartner2')
self.assertEqual(found[1]['name'], 'MyPartner1')
# search_read that finds nothing
- found = self.partner.search_read(self.cr, UID, [['name', '=', 'Does not exists']], ['name'])
+ found = partner.search_read([('name', '=', 'Does not exists')], ['name'])
self.assertEqual(len(found), 0)
def test_exists(self):
- partner = self.partner.browse(self.cr, UID, [])
+ partner = self.env['res.partner']
# check that records obtained from search exist
recs = partner.search([])
@@ -123,7 +131,7 @@ class TestORM(common.TransactionCase):
self.assertFalse(recs.exists())
def test_groupby_date(self):
- partners = dict(
+ partners_data = dict(
A='2012-11-19',
B='2012-12-17',
C='2012-12-31',
@@ -133,42 +141,37 @@ class TestORM(common.TransactionCase):
G='2013-02-11',
)
- all_partners = []
- partners_by_day = defaultdict(set)
- partners_by_month = defaultdict(set)
- partners_by_year = defaultdict(set)
-
- for name, date in partners.items():
- p = self.partner.create(self.cr, UID, dict(name=name, date=date))
- all_partners.append(p)
- partners_by_day[date].add(p)
- partners_by_month[date.rsplit('-', 1)[0]].add(p)
- partners_by_year[date.split('-', 1)[0]].add(p)
-
- def read_group(interval, domain=None):
- main_domain = [('id', 'in', all_partners)]
- if domain:
- domain = ['&'] + main_domain + domain
- else:
- domain = main_domain
-
- rg = self.partner.read_group(self.cr, self.uid, domain, ['date'], 'date' + ':' + interval)
+ partner_ids = []
+ partner_ids_by_day = defaultdict(list)
+ partner_ids_by_month = defaultdict(list)
+ partner_ids_by_year = defaultdict(list)
+
+ partners = self.env['res.partner']
+ for name, date in partners_data.items():
+ p = partners.create(dict(name=name, date=date))
+ partner_ids.append(p.id)
+ partner_ids_by_day[date].append(p.id)
+ partner_ids_by_month[date.rsplit('-', 1)[0]].append(p.id)
+ partner_ids_by_year[date.split('-', 1)[0]].append(p.id)
+
+ def read_group(interval):
+ domain = [('id', 'in', partner_ids)]
result = {}
- for r in rg:
- result[r['date:' + interval]] = set(self.partner.search(self.cr, self.uid, r['__domain']))
+ for grp in partners.read_group(domain, ['date'], ['date:' + interval]):
+ result[grp['date:' + interval]] = partners.search(grp['__domain'])
return result
- self.assertEqual(len(read_group('day')), len(partners_by_day))
- self.assertEqual(len(read_group('month')), len(partners_by_month))
- self.assertEqual(len(read_group('year')), len(partners_by_year))
+ self.assertEqual(len(read_group('day')), len(partner_ids_by_day))
+ self.assertEqual(len(read_group('month')), len(partner_ids_by_month))
+ self.assertEqual(len(read_group('year')), len(partner_ids_by_year))
- rg = self.partner.read_group(self.cr, self.uid, [('id', 'in', all_partners)],
- ['date'], ['date:month', 'date:day'], lazy=False)
- self.assertEqual(len(rg), len(all_partners))
+ res = partners.read_group([('id', 'in', partner_ids)], ['date'],
+ ['date:month', 'date:day'], lazy=False)
+ self.assertEqual(len(res), len(partner_ids))
def test_write_duplicate(self):
- cr, uid, p1 = self.cr, self.uid, self.p1
- self.partner.write(cr, uid, [p1, p1], {'name': 'X'})
+ p1 = self.env['res.partner'].create({'name': 'W'})
+ (p1 + p1).write({'name': 'X'})
def test_m2m_store_trigger(self):
group_user = self.env.ref('base.group_user')
@@ -187,110 +190,93 @@ class TestORM(common.TransactionCase):
self.assertTrue(user.share)
-class TestInherits(common.TransactionCase):
+class TestInherits(TransactionCase):
""" test the behavior of the orm for models that use _inherits;
specifically: res.users, that inherits from res.partner
"""
- def setUp(self):
- super(TestInherits, self).setUp()
- self.partner = self.registry('res.partner')
- self.user = self.registry('res.users')
-
def test_default(self):
""" `default_get` cannot return a dictionary or a new id """
- defaults = self.user.default_get(self.cr, UID, ['partner_id'])
+ defaults = self.env['res.users'].default_get(['partner_id'])
if 'partner_id' in defaults:
self.assertIsInstance(defaults['partner_id'], (bool, int, long))
def test_create(self):
""" creating a user should automatically create a new partner """
- partners_before = self.partner.search(self.cr, UID, [])
- foo_id = self.user.create(self.cr, UID, {'name': 'Foo', 'login': 'foo', 'password': 'foo'})
- foo = self.user.browse(self.cr, UID, foo_id)
+ partners_before = self.env['res.partner'].search([])
+ user_foo = self.env['res.users'].create({'name': 'Foo', 'login': 'foo'})
- self.assertNotIn(foo.partner_id.id, partners_before)
+ self.assertNotIn(user_foo.partner_id, partners_before)
def test_create_with_ancestor(self):
""" creating a user with a specific 'partner_id' should not create a new partner """
- par_id = self.partner.create(self.cr, UID, {'name': 'Foo'})
- partners_before = self.partner.search(self.cr, UID, [])
- foo_id = self.user.create(self.cr, UID, {'partner_id': par_id, 'login': 'foo', 'password': 'foo'})
- partners_after = self.partner.search(self.cr, UID, [])
+ partner_foo = self.env['res.partner'].create({'name': 'Foo'})
+ partners_before = self.env['res.partner'].search([])
+ user_foo = self.env['res.users'].create({'partner_id': partner_foo.id, 'login': 'foo'})
+ partners_after = self.env['res.partner'].search([])
- self.assertEqual(set(partners_before), set(partners_after))
-
- foo = self.user.browse(self.cr, UID, foo_id)
- self.assertEqual(foo.name, 'Foo')
- self.assertEqual(foo.partner_id.id, par_id)
+ self.assertEqual(partners_before, partners_after)
+ self.assertEqual(user_foo.name, 'Foo')
+ self.assertEqual(user_foo.partner_id, partner_foo)
@mute_logger('openerp.models')
def test_read(self):
""" inherited fields should be read without any indirection """
- foo_id = self.user.create(self.cr, UID, {'name': 'Foo', 'login': 'foo', 'password': 'foo'})
- foo_values, = self.user.read(self.cr, UID, [foo_id])
- partner_id = foo_values['partner_id'][0]
- partner_values, = self.partner.read(self.cr, UID, [partner_id])
- self.assertEqual(foo_values['name'], partner_values['name'])
+ user_foo = self.env['res.users'].create({'name': 'Foo', 'login': 'foo'})
+ user_values, = user_foo.read()
+ partner_values, = user_foo.partner_id.read()
- foo = self.user.browse(self.cr, UID, foo_id)
- self.assertEqual(foo.name, foo.partner_id.name)
+ self.assertEqual(user_values['name'], partner_values['name'])
+ self.assertEqual(user_foo.name, user_foo.partner_id.name)
@mute_logger('openerp.models')
def test_copy(self):
""" copying a user should automatically copy its partner, too """
- foo_id = self.user.create(self.cr, UID, {
+ user_foo = self.env['res.users'].create({
'name': 'Foo',
'login': 'foo',
- 'password': 'foo',
'supplier': True,
})
- foo_before, = self.user.read(self.cr, UID, [foo_id])
+ foo_before, = user_foo.read()
del foo_before['__last_update']
- bar_id = self.user.copy(self.cr, UID, foo_id, {
- 'login': 'bar',
- 'password': 'bar',
- })
- foo_after, = self.user.read(self.cr, UID, [foo_id])
+ user_bar = user_foo.copy({'login': 'bar'})
+ foo_after, = user_foo.read()
del foo_after['__last_update']
self.assertEqual(foo_before, foo_after)
- foo, bar = self.user.browse(self.cr, UID, [foo_id, bar_id])
- self.assertEqual(bar.name, 'Foo (copy)')
- self.assertEqual(bar.login, 'bar')
- self.assertEqual(foo.supplier, bar.supplier)
- self.assertNotEqual(foo.id, bar.id)
- self.assertNotEqual(foo.partner_id.id, bar.partner_id.id)
+ self.assertEqual(user_bar.name, 'Foo (copy)')
+ self.assertEqual(user_bar.login, 'bar')
+ self.assertEqual(user_foo.supplier, user_bar.supplier)
+ self.assertNotEqual(user_foo.id, user_bar.id)
+ self.assertNotEqual(user_foo.partner_id.id, user_bar.partner_id.id)
@mute_logger('openerp.models')
def test_copy_with_ancestor(self):
""" copying a user with 'parent_id' in defaults should not duplicate the partner """
- foo_id = self.user.create(self.cr, UID, {'name': 'Foo', 'login': 'foo', 'password': 'foo',
+ user_foo = self.env['res.users'].create({'name': 'Foo', 'login': 'foo', 'password': 'foo',
'login_date': '2016-01-01', 'signature': 'XXX'})
- par_id = self.partner.create(self.cr, UID, {'name': 'Bar'})
+ partner_bar = self.env['res.partner'].create({'name': 'Bar'})
- foo_before, = self.user.read(self.cr, UID, [foo_id])
+ foo_before, = user_foo.read()
del foo_before['__last_update']
del foo_before['login_date']
- partners_before = self.partner.search(self.cr, UID, [])
- bar_id = self.user.copy(self.cr, UID, foo_id, {'partner_id': par_id, 'login': 'bar'})
- foo_after, = self.user.read(self.cr, UID, [foo_id])
+ partners_before = self.env['res.partner'].search([])
+ user_bar = user_foo.copy({'partner_id': partner_bar.id, 'login': 'bar'})
+ foo_after, = user_foo.read()
del foo_after['__last_update']
del foo_after['login_date']
- partners_after = self.partner.search(self.cr, UID, [])
+ partners_after = self.env['res.partner'].search([])
self.assertEqual(foo_before, foo_after)
- self.assertEqual(set(partners_before), set(partners_after))
-
- foo, bar = self.user.browse(self.cr, UID, [foo_id, bar_id])
- self.assertNotEqual(foo.id, bar.id)
- self.assertEqual(bar.partner_id.id, par_id)
- self.assertEqual(bar.login, 'bar', "login is given from copy parameters")
- self.assertFalse(bar.password, "password should not be copied from original record")
- self.assertEqual(bar.name, 'Bar', "name is given from specific partner")
- self.assertEqual(bar.signature, foo.signature, "signature should be copied")
+ self.assertEqual(partners_before, partners_after)
+ self.assertNotEqual(user_foo.id, user_bar.id)
+ self.assertEqual(user_bar.partner_id.id, partner_bar.id)
+ self.assertEqual(user_bar.login, 'bar', "login is given from copy parameters")
+ self.assertFalse(user_bar.password, "password should not be copied from original record")
+ self.assertEqual(user_bar.name, 'Bar', "name is given from specific partner")
+ self.assertEqual(user_bar.signature, user_foo.signature, "signature should be copied")
CREATE = lambda values: (0, False, values)
@@ -301,11 +287,8 @@ LINK_TO = lambda id: (4, id, False)
DELETE_ALL = lambda: (5, False, False)
REPLACE_WITH = lambda ids: (6, False, ids)
-def sorted_by_id(list_of_dicts):
- "sort dictionaries by their 'id' field; useful for comparisons"
- return sorted(list_of_dicts, key=lambda d: d.get('id'))
-class TestO2MSerialization(common.TransactionCase):
+class TestO2MSerialization(TransactionCase):
""" test the orm method 'write' on one2many fields """
def setUp(self):
@@ -314,136 +297,121 @@ class TestO2MSerialization(common.TransactionCase):
def test_no_command(self):
" empty list of commands yields an empty list of records "
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', [])
-
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', [])
self.assertEqual(results, [])
def test_CREATE_commands(self):
" returns the VALUES dict as-is "
values = [{'foo': 'bar'}, {'foo': 'baz'}, {'foo': 'baq'}]
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', map(CREATE, values))
-
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', map(CREATE, values))
self.assertEqual(results, values)
def test_LINK_TO_command(self):
" reads the records from the database, records are returned with their ids. "
ids = [
- self.partner.create(self.cr, UID, {'name': 'foo'}),
- self.partner.create(self.cr, UID, {'name': 'bar'}),
- self.partner.create(self.cr, UID, {'name': 'baz'})
+ self.env['res.partner'].create({'name': 'foo'}).id,
+ self.env['res.partner'].create({'name': 'bar'}).id,
+ self.env['res.partner'].create({'name': 'baz'}).id,
]
commands = map(LINK_TO, ids)
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', commands, ['name'])
-
- self.assertEqual(sorted_by_id(results), sorted_by_id([
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', commands, ['name'])
+ self.assertItemsEqual(results, [
{'id': ids[0], 'name': 'foo'},
{'id': ids[1], 'name': 'bar'},
- {'id': ids[2], 'name': 'baz'}
- ]))
+ {'id': ids[2], 'name': 'baz'},
+ ])
def test_bare_ids_command(self):
" same as the equivalent LINK_TO commands "
ids = [
- self.partner.create(self.cr, UID, {'name': 'foo'}),
- self.partner.create(self.cr, UID, {'name': 'bar'}),
- self.partner.create(self.cr, UID, {'name': 'baz'})
+ self.env['res.partner'].create({'name': 'foo'}).id,
+ self.env['res.partner'].create({'name': 'bar'}).id,
+ self.env['res.partner'].create({'name': 'baz'}).id,
]
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', ids, ['name'])
-
- self.assertEqual(sorted_by_id(results), sorted_by_id([
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', ids, ['name'])
+ self.assertItemsEqual(results, [
{'id': ids[0], 'name': 'foo'},
{'id': ids[1], 'name': 'bar'},
- {'id': ids[2], 'name': 'baz'}
- ]))
+ {'id': ids[2], 'name': 'baz'},
+ ])
def test_UPDATE_command(self):
" take the in-db records and merge the provided information in "
- id_foo = self.partner.create(self.cr, UID, {'name': 'foo'})
- id_bar = self.partner.create(self.cr, UID, {'name': 'bar'})
- id_baz = self.partner.create(self.cr, UID, {'name': 'baz', 'city': 'tag'})
-
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', [
- LINK_TO(id_foo),
- UPDATE(id_bar, {'name': 'qux', 'city': 'tagtag'}),
- UPDATE(id_baz, {'name': 'quux'})
- ], ['name', 'city'])
-
- self.assertEqual(sorted_by_id(results), sorted_by_id([
- {'id': id_foo, 'name': 'foo', 'city': False},
- {'id': id_bar, 'name': 'qux', 'city': 'tagtag'},
- {'id': id_baz, 'name': 'quux', 'city': 'tag'}
- ]))
+ foo = self.env['res.partner'].create({'name': 'foo'})
+ bar = self.env['res.partner'].create({'name': 'bar'})
+ baz = self.env['res.partner'].create({'name': 'baz', 'city': 'tag'})
+ commands = [
+ LINK_TO(foo.id),
+ UPDATE(bar.id, {'name': 'qux', 'city': 'tagtag'}),
+ UPDATE(baz.id, {'name': 'quux'}),
+ ]
+
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', commands, ['name', 'city'])
+ self.assertItemsEqual(results, [
+ {'id': foo.id, 'name': 'foo', 'city': False},
+ {'id': bar.id, 'name': 'qux', 'city': 'tagtag'},
+ {'id': baz.id, 'name': 'quux', 'city': 'tag'},
+ ])
def test_DELETE_command(self):
" deleted records are not returned at all. "
ids = [
- self.partner.create(self.cr, UID, {'name': 'foo'}),
- self.partner.create(self.cr, UID, {'name': 'bar'}),
- self.partner.create(self.cr, UID, {'name': 'baz'})
+ self.env['res.partner'].create({'name': 'foo'}).id,
+ self.env['res.partner'].create({'name': 'bar'}).id,
+ self.env['res.partner'].create({'name': 'baz'}).id,
]
- commands = [DELETE(ids[0]), DELETE(ids[1]), DELETE(ids[2])]
-
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', commands, ['name'])
+ commands = map(DELETE, ids)
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', commands, ['name'])
self.assertEqual(results, [])
def test_mixed_commands(self):
ids = [
- self.partner.create(self.cr, UID, {'name': name})
+ self.env['res.partner'].create({'name': name}).id
for name in ['NObar', 'baz', 'qux', 'NOquux', 'NOcorge', 'garply']
]
+ commands = [
+ CREATE({'name': 'foo'}),
+ UPDATE(ids[0], {'name': 'bar'}),
+ LINK_TO(ids[1]),
+ DELETE(ids[2]),
+ UPDATE(ids[3], {'name': 'quux',}),
+ UPDATE(ids[4], {'name': 'corge'}),
+ CREATE({'name': 'grault'}),
+ LINK_TO(ids[5]),
+ ]
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', [
- CREATE({'name': 'foo'}),
- UPDATE(ids[0], {'name': 'bar'}),
- LINK_TO(ids[1]),
- DELETE(ids[2]),
- UPDATE(ids[3], {'name': 'quux',}),
- UPDATE(ids[4], {'name': 'corge'}),
- CREATE({'name': 'grault'}),
- LINK_TO(ids[5])
- ], ['name'])
-
- self.assertEqual(sorted_by_id(results), sorted_by_id([
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', commands, ['name'])
+ self.assertItemsEqual(results, [
{'name': 'foo'},
{'id': ids[0], 'name': 'bar'},
{'id': ids[1], 'name': 'baz'},
{'id': ids[3], 'name': 'quux'},
{'id': ids[4], 'name': 'corge'},
{'name': 'grault'},
- {'id': ids[5], 'name': 'garply'}
- ]))
+ {'id': ids[5], 'name': 'garply'},
+ ])
def test_LINK_TO_pairs(self):
"LINK_TO commands can be written as pairs, instead of triplets"
ids = [
- self.partner.create(self.cr, UID, {'name': 'foo'}),
- self.partner.create(self.cr, UID, {'name': 'bar'}),
- self.partner.create(self.cr, UID, {'name': 'baz'})
+ self.env['res.partner'].create({'name': 'foo'}).id,
+ self.env['res.partner'].create({'name': 'bar'}).id,
+ self.env['res.partner'].create({'name': 'baz'}).id,
]
- commands = map(lambda id: (4, id), ids)
-
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', commands, ['name'])
+ commands = [(4, id) for id in ids]
- self.assertEqual(sorted_by_id(results), sorted_by_id([
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', commands, ['name'])
+ self.assertItemsEqual(results, [
{'id': ids[0], 'name': 'foo'},
{'id': ids[1], 'name': 'bar'},
- {'id': ids[2], 'name': 'baz'}
- ]))
+ {'id': ids[2], 'name': 'baz'},
+ ])
def test_singleton_commands(self):
"DELETE_ALL can appear as a singleton"
- results = self.partner.resolve_2many_commands(
- self.cr, UID, 'child_ids', [DELETE_ALL()], ['name'])
-
+ commands = [DELETE_ALL()]
+ results = self.env['res.partner'].resolve_2many_commands('child_ids', commands, ['name'])
self.assertEqual(results, [])
diff --git a/openerp/addons/base/tests/test_ormcache.py b/openerp/addons/base/tests/test_ormcache.py
index c6f27aa39db..3f281cb5582 100644
--- a/openerp/addons/base/tests/test_ormcache.py
+++ b/openerp/addons/base/tests/test_ormcache.py
@@ -1,8 +1,11 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp.tests import common
-from openerp.tools import get_cache_key_counter
+from odoo.tests.common import TransactionCase
+from odoo.tools import get_cache_key_counter
-class TestOrmcache(common.TransactionCase):
+
+class TestOrmcache(TransactionCase):
def test_ormcache(self):
""" Test the effectiveness of the ormcache() decorator. """
IMD = self.env['ir.model.data']
diff --git a/openerp/addons/base/tests/test_osv.py b/openerp/addons/base/tests/test_osv.py
index 22b5572d543..65bf315f67c 100644
--- a/openerp/addons/base/tests/test_osv.py
+++ b/openerp/addons/base/tests/test_osv.py
@@ -2,7 +2,8 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import unittest
-from openerp.osv.query import Query
+
+from odoo.osv.query import Query
class QueryTestCase(unittest.TestCase):
diff --git a/openerp/addons/base/tests/test_osv_expression.yml b/openerp/addons/base/tests/test_osv_expression.yml
deleted file mode 100644
index 9e0a003cf3a..00000000000
--- a/openerp/addons/base/tests/test_osv_expression.yml
+++ /dev/null
@@ -1,632 +0,0 @@
--
- Testing for hierarchical search in M2M
--
- !python {model: res.partner }: |
- ids = self.search(cr, uid, [('category_id', 'child_of',ref('res_partner_category_0'))])
- assert len(ids) >= 1, ids
--
- "1.0 Setup test partner categories: parent root"
--
- !record {model: res.partner.category, id: categ_root}:
- name: Root category
--
- "1.1 Setup test partner categories: parent category"
--
- !record {model: res.partner.category, id: categ_0}:
- name: Parent category
- parent_id: categ_root
--
- "1.2 Setup test partner categories: child 1"
--
- !record {model: res.partner.category, id: categ_1}:
- name: Child 1
- parent_id: categ_0
--
- Test hierarchical search in M2M with child ID (list of ids)
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_root')])])
- assert len(ids) == 3, ids
--
- Test hierarchical search in M2M with child ID (single id)
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'child_of',ref('categ_root'))])
- assert len(ids) == 3, ids
--
- Test hierarchical search in M2M with child IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_1'), ref('categ_0')])])
- assert len(ids) == 2, ids
--
- Test hierarchical search in M2M with child IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_0')])])
- assert len(ids) == 2, ids
--
- Test hierarchical search in M2M with child IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_1')])])
- assert len(ids) == 1, ids
--
- Test hierarchical search in M2M with parent ID (list of ids)
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'parent_of',[ref('categ_1')])])
- assert len(ids) == 3, ids
--
- Test hierarchical search in M2M with parent ID (single id)
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'parent_of',ref('categ_1'))])
- assert len(ids) == 3, ids
--
- Test hierarchical search in M2M with parent IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'parent_of',[ref('categ_root'), ref('categ_0')])])
- assert len(ids) == 2, ids
--
- Test hierarchical search in M2M with parent IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'parent_of',[ref('categ_0')])])
- assert len(ids) == 2, ids
--
- Test hierarchical search in M2M with parent IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'parent_of',[ref('categ_1')])])
- assert len(ids) == 3, ids
--
- Test hierarchical search in M2M with parent IDs
--
- !python {model: res.partner.category }: |
- ids = self.search(cr, uid, [('id', 'parent_of',[ref('categ_root')])])
- assert len(ids) == 1, ids
--
- Testing that some domain expressions work
--
- !python {model: res.partner }: |
- ids = self.search(cr, uid, [('parent_id','=','Agrolait')])
- assert len(ids) >= 1, ids
--
- Trying the "in" operator, for scalar value
--
- !python {model: res.partner }: |
- ids = self.search(cr, uid, [('parent_id','in','Agrolait')])
- assert len(ids) >= 1, ids
--
- Trying the "in" operator for list value
--
- !python {model: res.partner }: |
- ids = self.search(cr, uid, [('parent_id','in',['Agrolait','ASUStek'])])
- assert len(ids) >= 1, ids
--
- Check we can use "in" operator for plain fields.
--
- !python {model: ir.ui.menu }: |
- ids = self.search(cr, uid, [('sequence','in',[1, 2, 10, 20])])
- assert len(ids) >= 1, ids
--
- Test one2many operator with empty search list
--
- !assert {model: res.partner, search: "[('child_ids', 'in', [])]", count: 0, string: "Ids should be empty"}
--
- Test one2many operator with False
--
- !assert {model: res.partner, search: "[('child_ids', '=', False)]"}:
- - list(child_ids) == []
--
- Test many2many operator with empty search list
--
- !assert {model: res.partner, search: "[('category_id', 'in', [])]", count: 0, string: "Ids should be empty"}
--
- Test many2many operator with False
--
- !assert {model: res.partner, search: "[('category_id', '=', False)]"}:
- - list(category_id) == []
--
- Filtering on invalid value across x2many relationship should return an empty set
--
- !assert {model: res.partner, search: "[('child_ids.city','=','foo')]", count: 0, string: "Searching for address.city = foo should give empty results"}
--
- Check if many2one works with empty search list
--
- !assert {model: res.partner, search: "[('company_id','in', [])]", count: 0, string: "Searching for company_id in [] should be empty!" }
--
- For the sake of the following tests, I will create a second company
--
- !record {model: res.company, id: ymltest_company2}:
- name: Acme 2
--
- And create a few partners with that company or no company
--
- !python {model: res.partner }: |
- for r in range(4):
- self.create(cr, uid, { 'name': 'P of Acme %d' % r,
- 'company_id': ref('ymltest_company2') })
- for r in range(4):
- self.create(cr, uid, { 'name': 'P of All %d' % r,
- 'company_id': False })
--
- Check if many2one works with negative empty list
--
- !python {model: res.partner }: |
- all_ids = self.search(cr, uid, [])
- all_ids.sort()
- res_ids = self.search(cr, uid,['|',('company_id','not in', []), ('company_id','=',False)])
- res_ids.sort()
- assert all_ids == res_ids, "not in [] fails"
--
- Check that many2one will pick the correct records with a list
--
- !python {model: res.partner }: |
- res_ids = self.search(cr, uid, [('company_id', 'in', [False,])])
- assert len(res_ids) >= 4, "We created 4 partners w/company, why find %d? %r" % \
- (len(res_ids), res_ids)
--
- Check that many2one will exclude the correct records with a list
--
- !python {model: res.partner }: |
- # assuming that the default company is #1
- res_ids = self.search(cr, uid, [('company_id', 'not in', [1])])
- assert len(res_ids) >= 4, "We should have found 4 records at least, only have %d! %r" % \
- (len(res_ids), res_ids)
--
- Check that we exclude the correct records, + False
--
- !python {model: res.partner }: |
- # assuming that the default company is #1
- res_ids = self.search(cr, uid, ['|', ('company_id', 'not in', [1]), ('company_id', '=', False)])
- assert len(res_ids) >= 8, "We should have found 8 records at least, only have %d! %r" % \
- (len(res_ids), res_ids)
--
- Check that multi-level expressions also work
--
- !python {model: res.partner }: |
- res_ids = self.search(cr, uid, [('company_id.partner_id', 'in', [])])
- assert res_ids == [], "Searching an empty set should return empty result, not %r" % res_ids
--
- Check that multi-level expressions with negative op work
--
- !python {model: res.partner }: |
- all_ids = self.search(cr, uid, [('company_id', '!=', False)])
- all_ids.sort()
- res_ids = self.search(cr, uid, [('company_id.partner_id', 'not in', [])])
- res_ids.sort()
- assert res_ids == all_ids, "Searching against empty set failed, returns %r" % res_ids
--
- Test the '(not) like/in' behavior. res.partner and its parent_id column are used because
- parent_id is a many2one, allowing to test the Null value, and there are actually some
- null and non-null values in the demo data.
--
- !python {model: res.partner }: |
- partner_ids = self.search(cr, uid, [])
- partner_ids.sort()
- max_partner_id = max(partner_ids)
-
- # Grab test sample data without using a normal
- # search domain, because we want to test these later,
- # so we can't rely on them!
- partners = self.browse(cr, uid, partner_ids)
- with_parent = []
- without_parent = []
- with_website = []
- for x in partners:
- if x.parent_id:
- with_parent.append(x.id)
- else:
- without_parent.append(x.id)
- if x.website:
- with_website.append(x.id)
- with_parent.sort()
- without_parent.sort()
- with_website.sort()
-
- # We treat null values differently than in SQL. For instance in SQL:
- # SELECT id FROM res_partner WHERE parent_id NOT IN (0)
- # will return only the records with non-null parent_id.
- # SELECT id FROM res_partner WHERE parent_id IN (0)
- # will return expectedly nothing (our ids always begin at 1).
- # This means the union of those two results will give only some
- # records, but not all present in database.
- #
- # When using domains and the ORM's search method, we think it is
- # more intuitive that the union returns all the records, and that
- # a domain like ('parent_id', 'not in', [0]) will return all
- # the records. For instance, if you perform a search for the companies
- # that don't have OpenERP has a parent company, you expect to find,
- # among others, the companies that don't have parent company.
- #
-
- # existing values be treated similarly if we simply check that some
- # existing value belongs to them.
-
- res_0 = self.search(cr, uid, [('parent_id', 'not like', 'probably_unexisting_name')]) # get all rows, included null parent_id
- res_0.sort()
- res_1 = self.search(cr, uid, [('parent_id', 'not in', [max_partner_id + 1])]) # get all rows, included null parent_id
- res_1.sort()
- res_2 = self.search(cr, uid, [('parent_id', '!=', False)]) # get rows with not null parent_id, deprecated syntax
- res_2.sort()
- res_3 = self.search(cr, uid, [('parent_id', 'not in', [])]) # get all rows, included null parent_id
- res_3.sort()
- res_4 = self.search(cr, uid, [('parent_id', 'not in', [False])]) # get rows with not null parent_id
- res_4.sort()
- res_4b = self.search(cr, uid, [('parent_id', 'not ilike', '')]) # get only rows without parent
- res_4b.sort()
- assert res_0 == partner_ids, 'res0: expected %r, got %r' % (partner_ids, res_0)
- assert res_1 == partner_ids, 'res1: expected %r, got %r' % (partner_ids, res_1)
- assert res_2 == with_parent, 'res2: expected %r, got %r' % (with_parent, res_2)
- assert res_3 == partner_ids, 'res3: expected %r, got %r' % (partner_ids, res_3)
- assert res_4 == with_parent, 'res4: expected %r, got %r' % (with_parent, res_4)
- assert res_4b == without_parent, 'res4b: expected %r, got %r' % (without_parent, res_4b)
- # The results of these queries, when combined with queries 0..4 must
- # give the whole set of ids.
- res_5 = self.search(cr, uid, [('parent_id', 'like', 'probably_unexisting_name')])
- res_5.sort()
- res_6 = self.search(cr, uid, [('parent_id', 'in', [max_partner_id + 1])])
- res_6.sort()
- res_7 = self.search(cr, uid, [('parent_id', '=', False)])
- res_7.sort()
- res_8 = self.search(cr, uid, [('parent_id', 'in', [])])
- res_8.sort()
- res_9 = self.search(cr, uid, [('parent_id', 'in', [False])])
- res_9.sort()
- res_9b = self.search(cr, uid, [('parent_id', 'ilike', '')]) # get those with a parent
- res_9b.sort()
-
- assert res_5 == [], 'res5: expected %r, got %r' % ([], res_5)
- assert res_6 == [], 'res6: expected %r, got %r' % ([], res_6)
- assert res_7 == without_parent, 'res7: expected %r, got %r' % (without_parent, res_7)
- assert res_8 == [], 'res8: expected %r, got %r' % ([], res_8)
- assert res_9 == without_parent, 'res9: expected %r, got %r' % (without_parent, res_9)
- assert res_9b == with_parent, 'res9b: expected %r, got %r' % (with_parent, res_9b)
- # These queries must return exactly the results than the queries 0..4,
- # i.e. not ... in ... must be the same as ... not in ... .
- res_10 = self.search(cr, uid, ['!', ('parent_id', 'like', 'probably_unexisting_name')])
- res_10.sort()
- res_11 = self.search(cr, uid, ['!', ('parent_id', 'in', [max_partner_id + 1])])
- res_11.sort()
- res_12 = self.search(cr, uid, ['!', ('parent_id', '=', False)])
- res_12.sort()
- res_13 = self.search(cr, uid, ['!', ('parent_id', 'in', [])])
- res_13.sort()
- res_14 = self.search(cr, uid, ['!', ('parent_id', 'in', [False])])
- res_14.sort()
- assert res_0 == res_10
- assert res_1 == res_11
- assert res_2 == res_12
- assert res_3 == res_13
- assert res_4 == res_14
-
- # Testing many2one field is not enough, a regular char field is tested
- # with in [] and must not return any result.
- res_15 = self.search(cr, uid, [('website', 'in', [])])
- assert res_15 == []
- # not in [] must return everything.
- res_16 = self.search(cr, uid, [('website', 'not in', [])])
- res_16.sort()
- assert res_16 == partner_ids
-
- res_17 = self.search(cr, uid, [('website', '!=', False)])
- res_17.sort()
- assert res_17 == with_website
-
--
- Check behavior for required many2one fields
--
- !python {model: res.company }: |
- company_ids = sorted(self.search(cr, uid, []))
- # currency_id is required
- res_101 = sorted(self.search(cr, uid, [('currency_id', 'not ilike', '')])) # get no companies
- res_102 = sorted(self.search(cr, uid, [('currency_id', 'ilike', '')])) # get all companies
- assert res_101 == [], 'res_101: expected %r, got %r' % ([], res_101)
- assert res_102 == company_ids, 'res_102: expected %r, got %r' % (company_ids, res_102)
--
- Verify domain evaluation for `one2many != False`
--
- !python {model: res.partner.category }: |
- all_ids = self.search(cr, uid, [])
- parent_categs = set([c.parent_id.id for c in self.browse(cr, uid, all_ids) if c.parent_id])
- result = set(self.search(cr, uid, [('child_ids', '!=', False)]))
- assert result and result == parent_categs, "Got %r, expected %r" % (result, parent_categs)
--
- Verify domain evaluation for `one2many == False`
--
- !python {model: res.partner.category }: |
- all_ids = self.search(cr, uid, [])
- parent_categs = set([c.parent_id.id for c in self.browse(cr, uid, all_ids) if c.parent_id])
- leaf_categs = set(all_ids) - parent_categs
- result = set(self.search(cr, uid, [('child_ids', '=', False)]))
- assert result and result == leaf_categs, "Got %r, expected %r" % (result, leaf_categs)
--
- Equivalent queries.
--
- !python {model: res.currency }: |
- max_currency_id = max(self.search(cr, uid, []))
- res_0 = self.search(cr, uid, [])
- res_1 = self.search(cr, uid, [('name', 'not like', 'probably_unexisting_name')])
- res_2 = self.search(cr, uid, [('id', 'not in', [max_currency_id + 1003])])
- res_3 = self.search(cr, uid, [('id', 'not in', [])])
- res_4 = self.search(cr, uid, [('id', '!=', False)])
- res_0.sort()
- res_1.sort()
- res_2.sort()
- res_3.sort()
- res_4.sort()
- assert res_0 == res_1
- assert res_0 == res_2
- assert res_0 == res_3
- assert res_0 == res_4
--
- Equivalent queries, integer and string.
--
- !python {model: res.partner }: |
- all_ids = self.search(cr, uid, [])
- if len(all_ids) > 1:
- one = all_ids[0]
- record = self.browse(cr, uid, one)
- others = all_ids[1:]
- res_1 = self.search(cr, uid, [('id', '=', one)])
- # self.search(cr, uid, [('id', '!=', others)]) # not permitted
- res_2 = self.search(cr, uid, [('id', 'not in', others)])
- res_3 = self.search(cr, uid, ['!', ('id', '!=', one)])
- res_4 = self.search(cr, uid, ['!', ('id', 'in', others)])
- # res_5 = self.search(cr, uid, [('id', 'in', one)]) # TODO make it permitted, just like for child_of
- res_6 = self.search(cr, uid, [('id', 'in', [one])])
- res_7 = self.search(cr, uid, [('name', '=', record.name)])
- res_8 = self.search(cr, uid, [('name', 'in', [record.name])])
- # res_9 = self.search(cr, uid, [('name', 'in', record.name)]) # TODO
- assert [one] == res_1
- assert [one] == res_2
- assert [one] == res_3
- assert [one] == res_4
- #assert [one] == res_5
- assert [one] == res_6
- assert [one] == res_7
--
- Need a company with a parent_id.
--
- !record {model: res.company, id: ymltest_company3}:
- name: Acme 3
--
- Need a company with a parent_id.
--
- !record {model: res.company, id: ymltest_company4}:
- name: Acme 4
- parent_id: ymltest_company3
--
- Equivalent queries, one2many.
--
- !python {model: res.company }: |
- company = self.browse(cr, uid, ref('ymltest_company3'))
-
- # one2many towards same model
- res_1 = self.search(cr, uid, [('child_ids', 'in', [x.id for x in company.child_ids])]) # any company having a child of company3 as child
- res_2 = self.search(cr, uid, [('child_ids', 'in', [company.child_ids[0].id])]) # any company having the first child of company3 as child
- assert res_1 == [ref('ymltest_company3')], "res_1"
- assert res_2 == [ref('ymltest_company3')], "res_2"
-
- # try testing real subsets with IN/NOT IN
- res_partner = self.pool.get('res.partner')
- res_users = self.pool.get('res.users')
- p1, _ = res_partner.name_create(cr, uid, "Dédé Boitaclou")
- p2, _ = res_partner.name_create(cr, uid, "Raoulette Pizza O'poil")
- u1a = res_users.create(cr, uid, {'login': 'dbo', 'partner_id': p1})
- u1b = res_users.create(cr, uid, {'login': 'dbo2', 'partner_id': p1})
- u2 = res_users.create(cr, uid, {'login': 'rpo', 'partner_id': p2})
- assert [p1] == res_partner.search(cr, uid, [('user_ids', 'in', u1a)]), "o2m IN accept single int on right side"
- assert [p1] == res_partner.search(cr, uid, [('user_ids', '=', 'Dédé Boitaclou')]), "o2m NOT IN matches none on the right side"
- assert [] == res_partner.search(cr, uid, [('user_ids', 'in', [10000])]), "o2m NOT IN matches none on the right side"
- assert [p1,p2] == res_partner.search(cr, uid, [('user_ids', 'in', [u1a,u2])]), "o2m IN matches any on the right side"
- all_partners = res_partner.search(cr, uid, [])
- assert (set(all_partners) - set([p1])) == set(res_partner.search(cr, uid, [('user_ids', 'not in', u1a)])), "o2m NOT IN matches none on the right side"
- assert (set(all_partners) - set([p1])) == set(res_partner.search(cr, uid, [('user_ids', '!=', 'Dédé Boitaclou')])), "o2m NOT IN matches none on the right side"
- assert (set(all_partners) - set([p1,p2])) == set(res_partner.search(cr, uid, [('user_ids', 'not in', [u1b, u2])])), "o2m NOT IN matches none on the right side"
-
-
-
-
-
-
- # child_of x returns x and its children (direct or not).
- company = self.browse(cr, uid, ref('ymltest_company3'))
- expected = [ref('ymltest_company3'), ref('ymltest_company4')]
- expected.sort()
- res_1 = self.search(cr, uid, [('id', 'child_of', [ref('ymltest_company3')])])
- res_1.sort()
- res_2 = self.search(cr, uid, [('id', 'child_of', ref('ymltest_company3'))])
- res_2.sort()
- res_3 = self.search(cr, uid, [('id', 'child_of', [company.name])])
- res_3.sort()
- res_4 = self.search(cr, uid, [('id', 'child_of', company.name)])
- res_4.sort()
- assert res_1 == expected
- assert res_2 == expected
- assert res_3 == expected
- assert res_4 == expected
-
- # parent_of x returns x and its parents (direct or not).
- company = self.browse(cr, uid, ref('ymltest_company4'))
- expected = [ref('ymltest_company4'), ref('ymltest_company3')]
- expected.sort()
- res_1 = self.search(cr, uid, [('id', 'parent_of', [ref('ymltest_company4')])])
- res_1.sort()
- res_2 = self.search(cr, uid, [('id', 'parent_of', ref('ymltest_company4'))])
- res_2.sort()
- res_3 = self.search(cr, uid, [('id', 'parent_of', [company.name])])
- res_3.sort()
- res_4 = self.search(cr, uid, [('id', 'parent_of', company.name)])
- res_4.sort()
- assert res_1 == expected
- assert res_2 == expected
- assert res_3 == expected
- assert res_4 == expected
--
- Equivalent queries, one2many.
--
- !python {model: res.currency }: |
- # Create a currency and a currency rate
- res_currency = self.pool['res.currency']
- res_currency_rate = self.pool['res.currency.rate']
- currency = res_currency.create(cr, uid, {'name': 'ZZZ', 'symbol': 'ZZZ', 'rounding': 1.0})
- currency_rate = self.pool['res.currency.rate'].create(cr, uid, {'name': '2010-01-01', 'currency_id': currency, 'rate': 1.0})
-
- # Search the currency via its rates one2many (the one2many must point back at the currency).
- max_currency_rate_id = max(res_currency_rate.search(cr, uid, []))
- currency_rate1 = res_currency_rate.search(cr, uid, [('name', 'not like', 'probably_unexisting_name')])
- currency_rate2 = res_currency_rate.search(cr, uid, [('id', 'not in', [max_currency_rate_id + 1003])])
- currency_rate3 = res_currency_rate.search(cr, uid, [('id', 'not in', [])])
- assert currency_rate1 == currency_rate2 == currency_rate3, 'All 3 results should be the same : empty'
- default_currency = self.browse(cr, uid, 1)
-
- # one2many towards another model
- res_3 = self.search(cr, uid, [('rate_ids', 'in', [x.id for x in default_currency.rate_ids])]) # currencies having a rate of main currency
- res_4 = self.search(cr, uid, [('rate_ids', 'in', [default_currency.rate_ids[0].id])]) # currencies having first rate of main currency
- res_5 = self.search(cr, uid, [('rate_ids', 'in', default_currency.rate_ids[0].id)]) # currencies having first rate of main currency
- # res_6 = self.search(cr, uid, [('rate_ids', 'in', [default_currency.rate_ids[0].name])])
- # res_7 = self.search(cr, uid, [('rate_ids', '=', default_currency.rate_ids[0].name)])
- # res_8 = self.search(cr, uid, [('rate_ids', 'like', default_currency.rate_ids[0].name)])
-
- res_9 = self.search(cr, uid, [('rate_ids', 'like', 'probably_unexisting_name')])
- # self.search(cr, uid, [('rate_ids', 'unexisting_op', 'probably_unexisting_name')]) # TODO expected exception
- assert res_3 == [1], "res_3"
- assert res_4 == [1], "res_4"
- assert res_5 == [1], "res_5"
- # assert res_7 == [1], "res_7"
- # assert res_8 == [1], "res_8"
- assert res_9 == [], "res_9"
-
- # get the currencies referenced by some currency rates using a weird negative domain
- res_10 = self.search(cr, uid, [('rate_ids', 'not like', 'probably_unexisting_name')])
- res_11 = self.search(cr, uid, [('rate_ids', 'not in', [max_currency_rate_id + 1])])
- res_12 = self.search(cr, uid, [('rate_ids', '!=', False)])
- res_13 = self.search(cr, uid, [('rate_ids', 'not in', [])])
- res_10.sort()
- res_11.sort()
- res_12.sort()
- res_13.sort()
- assert res_10 == res_11, 'res_11'
- assert res_10 == res_12, 'res_12'
- assert res_10 == res_13, 'res_13'
--
- Unaccent. Create a company with an accent in its name.
--
- !record {model: res.company, id: ymltest_unaccent_company}:
- name: Hélène
--
- Test the unaccent-enabled 'ilike'.
--
- !python {model: res.company}: |
- if self.pool.has_unaccent:
- ids = self.search(cr, uid, [('name','ilike','Helene')], {})
- assert ids == [ref('ymltest_unaccent_company')]
- ids = self.search(cr, uid, [('name','ilike','hélène')], {})
- assert ids == [ref('ymltest_unaccent_company')]
- ids = self.search(cr, uid, [('name','not ilike','Helene')], {})
- assert ref('ymltest_unaccent_company') not in ids
- ids = self.search(cr, uid, [('name','not ilike','hélène')], {})
- assert ref('ymltest_unaccent_company') not in ids
--
- Check that =like/=ilike expressions (no wildcard variants of like/ilike) are working on an untranslated field.
--
- !python {model: res.partner }: |
- all_ids = self.search(cr, uid, [('name', '=like', 'A_U_TeK')])
- assert len(all_ids) == 1, "Must match one partner (ASUSTeK), got %r"%all_ids
- all_ids = self.search(cr, uid, [('name', '=ilike', 'c%')])
- assert len(all_ids) >= 1, "Must match one partner (China Export), got %r"%all_ids
--
- Check that =like/=ilike expressions (no wildcard variants of like/ilike) are working on translated field.
--
- !python {model: res.country }: |
- all_ids = self.search(cr, uid, [('name', '=like', 'Ind__')])
- assert len(all_ids) == 1, "Must match India only, got %r"%all_ids
- all_ids = self.search(cr, uid, [('name', '=ilike', 'z%')])
- assert len(all_ids) == 3, "Must match only countries with names starting with Z (currently 3), got %r"%all_ids
--
- Use the create_date column on res.country (which doesn't declare it in _columns).
--
- !python {model: res.country }: |
- ids = self.search(cr, uid, [('create_date', '<', '2001-01-01 12:00:00')])
-
-
--
- Verify that invalid expressions are refused, even for magic fields
--
- !python {model: res.country }: |
- try:
- self.search(cr, uid, [('does_not_exist', '=', 'foo')])
- raise AssertionError('Invalid fields should not be accepted')
- except ValueError:
- pass
-
- try:
- self.search(cr, uid, [('create_date', '>>', 'foo')])
- raise AssertionError('Invalid operators should not be accepted')
- except ValueError:
- pass
-
- import psycopg2
- try:
- cr._default_log_exceptions = False
- cr.execute('SAVEPOINT expression_failure_test')
- self.search(cr, uid, [('create_date', '=', "1970-01-01'); --")])
- # if the above search gives no error, the operand was not escaped!
- cr.execute('RELEASE SAVEPOINT expression_failure_test')
- raise AssertionError('Operands should always be SQL escaped')
- except psycopg2.DataError:
- # Should give: 'DataError: invalid input syntax for type timestamp' or similar
- cr.execute('ROLLBACK TO SAVEPOINT expression_failure_test')
--
- Testing for Many2Many field with category vendor and active=False
--
- !python {model: res.partner }: |
- vals = {'category_id': [(6, 0, [ref("base.res_partner_category_1")])],
- 'name': 'OpenERP Test',
- 'active': False,
- 'child_ids': [(0, 0, {'name': 'address of OpenERP Test', 'country_id': ref("base.be")})]
- }
- self.create(cr, uid, vals, context=context)
- res_ids = self.search(cr, uid, [('category_id', 'ilike', 'vendor'), ('active', '=', False)])
- assert len(res_ids) != 0, "Record not Found with category vendor and active False."
--
- Testing for One2Many field with country Belgium and active=False
--
- !python {model: res.partner }: |
- res_ids = self.search(cr, uid, [('child_ids.country_id','=','Belgium'),('active','=',False)])
- assert len(res_ids) != 0, "Record not Found with country Belgium and active False."
--
- Check that we can exclude translated fields (bug lp:1071710)
--
- !python {model: res.country}: |
- # first install french language
- Modules = self.pool.get('ir.module.module')
- base = Modules.browse(cr, uid, Modules.search(cr, uid, [('name', '=', 'base')])[0])
-
- # hack: mark module as installed to allow install of the translation
- base_state = base.state
- base.write({'state': 'installed'})
- base.update_translations('fr_FR')
- base.write({'state': base_state})
-
- # tests
- be_id = self.search(cr, uid, [('name', '=', 'Belgium')])[0]
-
- ctx = {'lang': 'fr_FR'}
- not_be = self.search(cr, uid, [('name', '!=', 'Belgique')], context=ctx)
-
- assert be_id not in not_be, "Search match failed"
-
- # indirect search via m2o
- Partners = self.pool.get('res.partner')
- agrolait = Partners.search(cr, uid, [('name', '=', 'Agrolait')])[0]
-
- not_be = Partners.search(cr, uid, [('country_id', '!=', 'Belgium')])
- assert agrolait not in not_be, "Search match failed (m2o)"
-
- not_be = Partners.search(cr, uid, [('country_id', '!=', 'Belgique')], context=ctx)
- assert agrolait not in not_be, "Search match failed (m2o)"
diff --git a/openerp/addons/base/tests/test_phase.py b/openerp/addons/base/tests/test_phase.py
new file mode 100644
index 00000000000..09f6e1e64e5
--- /dev/null
+++ b/openerp/addons/base/tests/test_phase.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import unittest
+
+from odoo.tests import common
+
+
+#: Stores state information across multiple test classes
+test_state = None
+
+def setUpModule():
+ global test_state
+ test_state = {}
+
+def tearDownModule():
+ global test_state
+ test_state = None
+
+
+class TestPhaseInstall00(unittest.TestCase):
+ """
+ WARNING: Relies on tests being run in alphabetical order
+ """
+ @classmethod
+ def setUpClass(cls):
+ cls.state = None
+
+ def test_00_setup(self):
+ type(self).state = 'init'
+
+ @common.at_install(False)
+ def test_01_no_install(self):
+ type(self).state = 'error'
+
+ def test_02_check(self):
+ self.assertEqual(self.state, 'init',
+ "Testcase state should not have been transitioned from 00")
+
+
+class TestPhaseInstall01(unittest.TestCase):
+ at_install = False
+
+ def test_default_norun(self):
+ self.fail("An unmarket test in a non-at-install case should not run")
+
+ @common.at_install(True)
+ def test_set_run(self):
+ test_state['set_at_install'] = True
+
+
+class TestPhaseInstall02(unittest.TestCase):
+ """
+ Can't put the check for test_set_run in the same class: if
+ @common.at_install does not work for test_set_run, it won't work for
+ the other one either. Thus move checking of whether test_set_run has
+ correctly run indeed to a separate class.
+
+ Warning: relies on *classes* being run in alphabetical order in test
+ modules
+ """
+ def test_check_state(self):
+ self.assertTrue(test_state.get('set_at_install'),
+ "The flag should be set if local overriding of runstate")
diff --git a/openerp/addons/base/tests/test_qweb.py b/openerp/addons/base/tests/test_qweb.py
index 01e6626c10b..e7de2c3c3b3 100644
--- a/openerp/addons/base/tests/test_qweb.py
+++ b/openerp/addons/base/tests/test_qweb.py
@@ -1,92 +1,78 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
import cgi
+import collections
import json
import os.path
-import glob
import re
-import collections
from lxml import etree
-import openerp.modules
-from openerp.addons.base.ir.ir_qweb import QWebContext, FileSystemLoader
-from openerp.tests import common
+from odoo.addons.base.ir.ir_qweb import QWebContext, FileSystemLoader
+from odoo.modules import get_module_resource
+from odoo.tests.common import TransactionCase
-class TestQWebTField(common.TransactionCase):
+
+class TestQWebTField(TransactionCase):
def setUp(self):
super(TestQWebTField, self).setUp()
- self.env = self.env(context={'inherit_branding': True})
- self.engine = self.env['ir.qweb']
+ self.env_branding = self.env(context={'inherit_branding': True})
+ self.engine = self.env_branding['ir.qweb']
def context(self, values):
- return QWebContext(self.env, values)
+ return QWebContext(self.env_branding, values)
def test_trivial(self):
field = etree.Element('span', {'t-field': u'company.name'})
+ company = self.env['res.company'].create({'name': "My Test Company"})
- Companies = self.registry('res.company')
- company_id = Companies.create(self.cr, self.uid, {
- 'name': "My Test Company"
- })
- result = self.engine.render_node(field, self.context({
- 'company': Companies.browse(self.cr, self.uid, company_id),
- }))
-
+ result = self.engine.render_node(field, self.context({'company': company}))
self.assertEqual(
result,
'<span data-oe-model="res.company" data-oe-id="%d" '
'data-oe-field="name" data-oe-type="char" '
'data-oe-expression="company.name">%s</span>' % (
- company_id,
- "My Test Company",))
+ company.id,
+ "My Test Company",
+ ),
+ )
def test_i18n(self):
field = etree.Element('span', {'t-field': u'company.name'})
-
- Companies = self.registry('res.company')
s = u"Testing «ταБЬℓσ»: 1<2 & 4+1>3, now 20% off!"
- company_id = Companies.create(self.cr, self.uid, {
- 'name': s,
- })
- result = self.engine.render_node(field, self.context({
- 'company': Companies.browse(self.cr, self.uid, company_id),
- }))
+ company = self.env['res.company'].create({'name': s})
+ result = self.engine.render_node(field, self.context({'company': company}))
self.assertEqual(
result,
'<span data-oe-model="res.company" data-oe-id="%d" '
'data-oe-field="name" data-oe-type="char" '
'data-oe-expression="company.name">%s</span>' % (
- company_id,
- cgi.escape(s.encode('utf-8')),))
+ company.id,
+ cgi.escape(s.encode('utf-8')),
+ ),
+ )
def test_reject_crummy_tags(self):
field = etree.Element('td', {'t-field': u'company.name'})
- with self.assertRaisesRegexp(
- AssertionError,
- r'^RTE widgets do not work correctly'):
- self.engine.render_node(field, self.context({
- 'company': None
- }))
+ with self.assertRaisesRegexp(AssertionError, r'^RTE widgets do not work correctly'):
+ self.engine.render_node(field, self.context({'company': None}))
def test_reject_t_tag(self):
field = etree.Element('t', {'t-field': u'company.name'})
- with self.assertRaisesRegexp(
- AssertionError,
- r'^t-field can not be used on a t element'):
- self.engine.render_node(field, self.context({
- 'company': None
- }))
+ with self.assertRaisesRegexp(AssertionError, r'^t-field can not be used on a t element'):
+ self.engine.render_node(field, self.context({'company': None}))
+
-class TestQWeb(common.TransactionCase):
- matcher = re.compile('^qweb-test-(.*)\.xml$')
+class TestQWeb(TransactionCase):
+ matcher = re.compile(r'^qweb-test-(.*)\.xml$')
@classmethod
def get_cases(cls):
path = cls.qweb_test_file_path()
-
return (
cls("test_qweb_{}".format(cls.matcher.match(f).group(1)))
for f in os.listdir(path)
@@ -94,12 +80,10 @@ class TestQWeb(common.TransactionCase):
if f != 'qweb-test-extend.xml'
if cls.matcher.match(f)
)
+
@classmethod
def qweb_test_file_path(cls):
- path = os.path.dirname(
- openerp.modules.get_module_resource(
- 'web', 'static', 'lib', 'qweb', 'qweb2.js'))
- return path
+ return os.path.dirname(get_module_resource('web', 'static', 'lib', 'qweb', 'qweb2.js'))
def __getattr__(self, item):
if not item.startswith('test_qweb_'):
@@ -129,9 +113,10 @@ class TestQWeb(common.TransactionCase):
self.assertEqual(
qweb.render(template, qwebcontext=ctx).strip(),
(result or u'').strip().encode('utf-8'),
- template
+ template,
)
+
def load_tests(loader, suite, _):
# can't override TestQWeb.__dir__ because dir() called on *class* not
# instance
diff --git a/openerp/addons/base/tests/test_res_config.py b/openerp/addons/base/tests/test_res_config.py
index 0a6a49efdeb..af919ce4b66 100644
--- a/openerp/addons/base/tests/test_res_config.py
+++ b/openerp/addons/base/tests/test_res_config.py
@@ -1,13 +1,15 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import openerp
-import openerp.tests.common as common
+from odoo import exceptions
+from odoo.tests.common import TransactionCase
-class test_res_config(common.TransactionCase):
+
+class TestResConfig(TransactionCase):
def setUp(self):
- super(test_res_config, self).setUp()
- self.res_config = self.registry('res.config.settings')
+ super(TestResConfig, self).setUp()
+ self.ResConfig = self.env['res.config.settings']
# Define the test values
self.menu_xml_id = 'base.menu_action_res_users'
@@ -17,15 +19,13 @@ class test_res_config(common.TransactionCase):
# Note: see the get_config_warning() doc for a better example
# Fetch the expected values
- module_name, menu_xml_id = self.menu_xml_id.split('.')
- dummy, menu_id = self.registry('ir.model.data').get_object_reference(self.cr, self.uid, module_name, menu_xml_id)
- ir_ui_menu = self.registry('ir.ui.menu').browse(self.cr, self.uid, menu_id, context=None)
+ menu = self.env.ref(self.menu_xml_id)
model_name, field_name = self.full_field_name.rsplit('.', 1)
- self.expected_path = ir_ui_menu.complete_name
- self.expected_action_id = ir_ui_menu.action.id
- self.expected_name = self.registry(model_name).fields_get(self.cr, self.uid, allfields=[field_name], context=None)[field_name]['string']
+ self.expected_path = menu.complete_name
+ self.expected_action_id = menu.action.id
+ self.expected_name = self.env[model_name].fields_get([field_name])[field_name]['string']
self.expected_final_error_msg = self.error_msg % {
'field:res.partner.lang': self.expected_name,
'menu:base.menu_action_res_users': self.expected_path
@@ -36,7 +36,7 @@ class test_res_config(common.TransactionCase):
def test_00_get_option_path(self):
""" The get_option_path() method should return a tuple containing a string and an integer """
- res = self.res_config.get_option_path(self.cr, self.uid, self.menu_xml_id, context=None)
+ res = self.ResConfig.get_option_path(self.menu_xml_id)
# Check types
self.assertIsInstance(res, tuple)
@@ -50,7 +50,7 @@ class test_res_config(common.TransactionCase):
def test_10_get_option_name(self):
""" The get_option_name() method should return a string """
- res = self.res_config.get_option_name(self.cr, self.uid, self.full_field_name, context=None)
+ res = self.ResConfig.get_option_name(self.full_field_name)
# Check type
self.assertIsInstance(res, basestring)
@@ -60,10 +60,10 @@ class test_res_config(common.TransactionCase):
def test_20_get_config_warning(self):
""" The get_config_warning() method should return a RedirectWarning """
- res = self.res_config.get_config_warning(self.cr, self.error_msg, context=None)
+ res = self.ResConfig.get_config_warning(self.error_msg)
# Check type
- self.assertIsInstance(res, openerp.exceptions.RedirectWarning)
+ self.assertIsInstance(res, exceptions.RedirectWarning)
# Check returned value
self.assertEqual(res.args[0], self.expected_final_error_msg)
@@ -71,10 +71,10 @@ class test_res_config(common.TransactionCase):
def test_30_get_config_warning_wo_menu(self):
""" The get_config_warning() method should return a Warning exception """
- res = self.res_config.get_config_warning(self.cr, self.error_msg_wo_menu, context=None)
+ res = self.ResConfig.get_config_warning(self.error_msg_wo_menu)
# Check type
- self.assertIsInstance(res, openerp.exceptions.Warning)
+ self.assertIsInstance(res, exceptions.Warning)
# Check returned value
self.assertEqual(res.args[0], self.expected_final_error_msg_wo_menu)
diff --git a/openerp/addons/base/tests/test_res_lang.py b/openerp/addons/base/tests/test_res_lang.py
index c7e591472c5..c6eab4ded78 100644
--- a/openerp/addons/base/tests/test_res_lang.py
+++ b/openerp/addons/base/tests/test_res_lang.py
@@ -1,11 +1,12 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import openerp.tests.common as common
+from odoo.tests.common import TransactionCase
-class test_res_lang(common.TransactionCase):
+class test_res_lang(TransactionCase):
def test_00_intersperse(self):
- from openerp.addons.base.res.res_lang import intersperse
+ from odoo.addons.base.res.res_lang import intersperse
assert intersperse("", []) == ("", 0)
assert intersperse("0", []) == ("0", 0)
diff --git a/openerp/addons/base/tests/test_res_partner_bank.py b/openerp/addons/base/tests/test_res_partner_bank.py
index e9ed9172588..cbf533802a1 100644
--- a/openerp/addons/base/tests/test_res_partner_bank.py
+++ b/openerp/addons/base/tests/test_res_partner_bank.py
@@ -3,7 +3,8 @@
# Copyright (c) 2015 ACSONE SA/NV (<http://acsone.eu>)
-from openerp.tests.common import TransactionCase
+from odoo.tests.common import TransactionCase
+
class TestResPartnerBank(TransactionCase):
"""Tests acc_number
diff --git a/openerp/addons/base/tests/test_search.py b/openerp/addons/base/tests/test_search.py
index 000f05a33d8..8fba34ca025 100644
--- a/openerp/addons/base/tests/test_search.py
+++ b/openerp/addons/base/tests/test_search.py
@@ -1,26 +1,24 @@
-import unittest
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import openerp.tests.common as common
+from odoo.tests.common import TransactionCase
-class test_search(common.TransactionCase):
+class test_search(TransactionCase):
def test_00_search_order(self):
-
- registry, cr, uid = self.registry, self.cr, self.uid
-
# Create 6 partners with a given name, and a given creation order to
- # ensure the order of their ID. Some are set as unactive to verify they
+ # ensure the order of their ID. Some are set as inactive to verify they
# are by default excluded from the searches and to provide a second
# `order` argument.
- partners = registry('res.partner')
- c = partners.create(cr, uid, {'name': 'test_search_order_C'})
- d = partners.create(cr, uid, {'name': 'test_search_order_D', 'active': False})
- a = partners.create(cr, uid, {'name': 'test_search_order_A'})
- b = partners.create(cr, uid, {'name': 'test_search_order_B'})
- ab = partners.create(cr, uid, {'name': 'test_search_order_AB'})
- e = partners.create(cr, uid, {'name': 'test_search_order_E', 'active': False})
+ Partner = self.env['res.partner']
+ c = Partner.create({'name': 'test_search_order_C'})
+ d = Partner.create({'name': 'test_search_order_D', 'active': False})
+ a = Partner.create({'name': 'test_search_order_A'})
+ b = Partner.create({'name': 'test_search_order_B'})
+ ab = Partner.create({'name': 'test_search_order_AB'})
+ e = Partner.create({'name': 'test_search_order_E', 'active': False})
# The tests.
@@ -28,116 +26,109 @@ class test_search(common.TransactionCase):
# The order of the returned ids should be given by the `order`
# parameter of search().
- name_asc = partners.search(cr, uid, [('name', 'like', 'test_search_order%')], order="name asc")
- self.assertEqual([a, ab, b, c], name_asc, "Search with 'NAME ASC' order failed.")
- name_desc = partners.search(cr, uid, [('name', 'like', 'test_search_order%')], order="name desc")
- self.assertEqual([c, b, ab, a], name_desc, "Search with 'NAME DESC' order failed.")
- id_asc = partners.search(cr, uid, [('name', 'like', 'test_search_order%')], order="id asc")
- self.assertEqual([c, a, b, ab], id_asc, "Search with 'ID ASC' order failed.")
- id_desc = partners.search(cr, uid, [('name', 'like', 'test_search_order%')], order="id desc")
- self.assertEqual([ab, b, a, c], id_desc, "Search with 'ID DESC' order failed.")
+ name_asc = Partner.search([('name', 'like', 'test_search_order%')], order="name asc")
+ self.assertEqual([a, ab, b, c], list(name_asc), "Search with 'NAME ASC' order failed.")
+ name_desc = Partner.search([('name', 'like', 'test_search_order%')], order="name desc")
+ self.assertEqual([c, b, ab, a], list(name_desc), "Search with 'NAME DESC' order failed.")
+ id_asc = Partner.search([('name', 'like', 'test_search_order%')], order="id asc")
+ self.assertEqual([c, a, b, ab], list(id_asc), "Search with 'ID ASC' order failed.")
+ id_desc = Partner.search([('name', 'like', 'test_search_order%')], order="id desc")
+ self.assertEqual([ab, b, a, c], list(id_desc), "Search with 'ID DESC' order failed.")
# The inactive records shouldn't be excluded as soon as a condition on
# that field is present in the domain. The `order` parameter of
# search() should support any legal coma-separated values.
- active_asc_id_asc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active asc, id asc")
- self.assertEqual([d, e, c, a, b, ab], active_asc_id_asc, "Search with 'ACTIVE ASC, ID ASC' order failed.")
- active_desc_id_asc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active desc, id asc")
- self.assertEqual([c, a, b, ab, d, e], active_desc_id_asc, "Search with 'ACTIVE DESC, ID ASC' order failed.")
- active_asc_id_desc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active asc, id desc")
- self.assertEqual([e, d, ab, b, a, c], active_asc_id_desc, "Search with 'ACTIVE ASC, ID DESC' order failed.")
- active_desc_id_desc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active desc, id desc")
- self.assertEqual([ab, b, a, c, e, d], active_desc_id_desc, "Search with 'ACTIVE DESC, ID DESC' order failed.")
- id_asc_active_asc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id asc, active asc")
- self.assertEqual([c, d, a, b, ab, e], id_asc_active_asc, "Search with 'ID ASC, ACTIVE ASC' order failed.")
- id_asc_active_desc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id asc, active desc")
- self.assertEqual([c, d, a, b, ab, e], id_asc_active_desc, "Search with 'ID ASC, ACTIVE DESC' order failed.")
- id_desc_active_asc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id desc, active asc")
- self.assertEqual([e, ab, b, a, d, c], id_desc_active_asc, "Search with 'ID DESC, ACTIVE ASC' order failed.")
- id_desc_active_desc = partners.search(cr, uid, [('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id desc, active desc")
- self.assertEqual([e, ab, b, a, d, c], id_desc_active_desc, "Search with 'ID DESC, ACTIVE DESC' order failed.")
+ active_asc_id_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active asc, id asc")
+ self.assertEqual([d, e, c, a, b, ab], list(active_asc_id_asc), "Search with 'ACTIVE ASC, ID ASC' order failed.")
+ active_desc_id_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active desc, id asc")
+ self.assertEqual([c, a, b, ab, d, e], list(active_desc_id_asc), "Search with 'ACTIVE DESC, ID ASC' order failed.")
+ active_asc_id_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active asc, id desc")
+ self.assertEqual([e, d, ab, b, a, c], list(active_asc_id_desc), "Search with 'ACTIVE ASC, ID DESC' order failed.")
+ active_desc_id_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="active desc, id desc")
+ self.assertEqual([ab, b, a, c, e, d], list(active_desc_id_desc), "Search with 'ACTIVE DESC, ID DESC' order failed.")
+ id_asc_active_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id asc, active asc")
+ self.assertEqual([c, d, a, b, ab, e], list(id_asc_active_asc), "Search with 'ID ASC, ACTIVE ASC' order failed.")
+ id_asc_active_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id asc, active desc")
+ self.assertEqual([c, d, a, b, ab, e], list(id_asc_active_desc), "Search with 'ID ASC, ACTIVE DESC' order failed.")
+ id_desc_active_asc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id desc, active asc")
+ self.assertEqual([e, ab, b, a, d, c], list(id_desc_active_asc), "Search with 'ID DESC, ACTIVE ASC' order failed.")
+ id_desc_active_desc = Partner.search([('name', 'like', 'test_search_order%'), '|', ('active', '=', True), ('active', '=', False)], order="id desc, active desc")
+ self.assertEqual([e, ab, b, a, d, c], list(id_desc_active_desc), "Search with 'ID DESC, ACTIVE DESC' order failed.")
def test_10_inherits_m2order(self):
- registry, cr, uid = self.registry, self.cr, self.uid
- users_obj = registry('res.users')
+ Users = self.env['res.users']
# Find Employee group
- group_employee_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user')
- group_employee_id = group_employee_ref and group_employee_ref[1] or False
+ group_employee = self.env.ref('base.group_user')
# Get country/state data
- country_us_id = registry('res.country').search(cr, uid, [('code', 'like', 'US')])[0]
- state_ids = registry('res.country.state').search(cr, uid, [('country_id', '=', country_us_id)], limit=2)
- country_be_id = registry('res.country').search(cr, uid, [('code', 'like', 'BE')])[0]
+ country_be = self.env.ref('base.be')
+ country_us = self.env.ref('base.us')
+ states_us = country_us.state_ids[:2]
# Create test users
- search_user = users_obj.create(cr, uid, {'name': '__search', 'login': '__search', 'groups_id': [(6, 0, [group_employee_id])]})
- a = users_obj.create(cr, uid, {'name': '__test_A', 'login': '__test_A', 'country_id': country_be_id, 'state_id': country_be_id})
- b = users_obj.create(cr, uid, {'name': '__test_B', 'login': '__a_test_B', 'country_id': country_us_id, 'state_id': state_ids[1]})
- c = users_obj.create(cr, uid, {'name': '__test_B', 'login': '__z_test_B', 'country_id': country_us_id, 'state_id': state_ids[0]})
+ u = Users.create({'name': '__search', 'login': '__search', 'groups_id': [(6, 0, [group_employee.id])]})
+ a = Users.create({'name': '__test_A', 'login': '__test_A', 'country_id': country_be.id, 'state_id': country_be.id})
+ b = Users.create({'name': '__test_B', 'login': '__a_test_B', 'country_id': country_us.id, 'state_id': states_us[1].id})
+ c = Users.create({'name': '__test_B', 'login': '__z_test_B', 'country_id': country_us.id, 'state_id': states_us[0].id})
+
+ # Search as search user
+ Users = Users.sudo(u)
# Do: search on res.users, order on a field on res.partner to try inherits'd fields, then res.users
- user_ids = users_obj.search(cr, search_user, [], order='name asc, login desc')
- expected_ids = [search_user, a, c, b]
- test_user_ids = filter(lambda x: x in expected_ids, user_ids)
- self.assertEqual(test_user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
+ expected_ids = [u.id, a.id, c.id, b.id]
+ user_ids = Users.search([('id', 'in', expected_ids)], order='name asc, login desc').ids
+ self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
# Do: order on many2one and inherits'd fields
- user_ids = users_obj.search(cr, search_user, [], order='state_id asc, country_id desc, name asc, login desc')
- expected_ids = [c, b, a, search_user]
- test_user_ids = filter(lambda x: x in expected_ids, user_ids)
- self.assertEqual(test_user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
+ expected_ids = [c.id, b.id, a.id, u.id]
+ user_ids = Users.search([('id', 'in', expected_ids)], order='state_id asc, country_id desc, name asc, login desc').ids
+ self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
# Do: order on many2one and inherits'd fields
- user_ids = users_obj.search(cr, search_user, [], order='country_id desc, state_id desc, name asc, login desc')
- expected_ids = [search_user, b, c, a]
- test_user_ids = filter(lambda x: x in expected_ids, user_ids)
- self.assertEqual(test_user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
+ expected_ids = [u.id, b.id, c.id, a.id]
+ user_ids = Users.search([('id', 'in', expected_ids)], order='country_id desc, state_id desc, name asc, login desc').ids
+ self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
# Do: order on many2one, but not by specifying in order parameter of search, but by overriding _order of res_users
self.patch_order('res.users', 'country_id desc, name asc, login desc')
- user_ids = users_obj.search(cr, search_user, [])
- expected_ids = [search_user, c, b, a]
- test_user_ids = filter(lambda x: x in expected_ids, user_ids)
- self.assertEqual(test_user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
+ expected_ids = [u.id, c.id, b.id, a.id]
+ user_ids = Users.search([('id', 'in', expected_ids)]).ids
+ self.assertEqual(user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
def test_11_indirect_inherits_m2o_order(self):
- registry, cr, uid = self.registry, self.cr, self.uid
- Cron = registry('ir.cron')
- Users = registry('res.users')
+ Cron = self.env['ir.cron']
+ Users = self.env['res.users']
user_ids = {}
cron_ids = {}
for u in 'BAC':
- user_ids[u] = Users.create(cr, uid, {'name': u, 'login': u})
- cron_ids[u] = Cron.create(cr, uid, {'name': u, 'user_id': user_ids[u]})
+ user_ids[u] = Users.create({'name': u, 'login': u}).id
+ cron_ids[u] = Cron.create({'name': u, 'user_id': user_ids[u]}).id
- ids = Cron.search(cr, uid, [('id', 'in', cron_ids.values())], order='user_id')
+ ids = Cron.search([('id', 'in', cron_ids.values())], order='user_id').ids
expected_ids = [cron_ids[l] for l in 'ABC']
self.assertEqual(ids, expected_ids)
def test_12_m2o_order_loop_self(self):
- registry, cr, uid = self.registry, self.cr, self.uid
-
- Cats = registry('ir.module.category')
- ids = {}
+ Cats = self.env['ir.module.category']
+ cat_ids = {}
def create(name, **kw):
- ids[name] = Cats.create(cr, uid, dict(kw, name=name))
+ cat_ids[name] = Cats.create(dict(kw, name=name)).id
self.patch_order('ir.module.category', 'parent_id desc, name')
create('A')
- create('B', parent_id=ids['A'])
- create('C', parent_id=ids['A'])
+ create('B', parent_id=cat_ids['A'])
+ create('C', parent_id=cat_ids['A'])
create('D')
- create('E', parent_id=ids['D'])
- create('F', parent_id=ids['D'])
+ create('E', parent_id=cat_ids['D'])
+ create('F', parent_id=cat_ids['D'])
- expected_order = [ids[x] for x in 'ADEFBC']
- domain = [('id', 'in', ids.values())]
- search_result = Cats.search(cr, uid, domain)
- self.assertEqual(search_result, expected_order)
+ expected_ids = [cat_ids[x] for x in 'ADEFBC']
+ found_ids = Cats.search([('id', 'in', cat_ids.values())]).ids
+ self.assertEqual(found_ids, expected_ids)
def test_13_m2o_order_loop_multi(self):
Users = self.env['res.users']
@@ -154,11 +145,6 @@ class test_search(common.TransactionCase):
u3 = Users.create(dict(name='C', login='c', **kw)).id
u4 = Users.sudo(user=u2).create(dict(name='D', login='z', **kw)).id
- expected_order = [u2, u4, u3, u1]
-
- domain = [('id', 'in', [u1, u2, u3, u4])]
- search_result = list(Users.search(domain)._ids)
- self.assertEqual(search_result, expected_order)
-
-if __name__ == '__main__':
- unittest.main()
+ expected_ids = [u2, u4, u3, u1]
+ found_ids = Users.search([('id', 'in', expected_ids)]).ids
+ self.assertEqual(found_ids, expected_ids)
diff --git a/openerp/addons/base/tests/test_translate.py b/openerp/addons/base/tests/test_translate.py
index d6944cd24dd..fac2ec78284 100644
--- a/openerp/addons/base/tests/test_translate.py
+++ b/openerp/addons/base/tests/test_translate.py
@@ -1,9 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from lxml.etree import XMLSyntaxError
import unittest
-from openerp.tools.translate import quote, unquote, xml_translate, html_translate
+
+from odoo.tools.translate import quote, unquote, xml_translate, html_translate
+from odoo.tests.common import TransactionCase
+
class TranslationToolsTestCase(unittest.TestCase):
@@ -167,3 +169,56 @@ class TranslationToolsTestCase(unittest.TestCase):
self.assertEquals(result, """<i class="fa-check"/>""")
result = html_translate(lambda term: term, source)
self.assertEquals(result, source)
+
+
+class TestTranslation(TransactionCase):
+
+ def setUp(self):
+ super(TestTranslation, self).setUp()
+ self.env['ir.translation'].load_module_terms(['base'], ['fr_FR'])
+ self.customers = self.env['res.partner.category'].create({'name': 'Customers'})
+ self.env['ir.translation'].create({
+ 'type': 'model',
+ 'name': 'res.partner.category,name',
+ 'module':'base',
+ 'lang': 'fr_FR',
+ 'res_id': self.customers.id,
+ 'value': 'Clients',
+ 'state': 'translated',
+ })
+
+ def test_101_create_translated_record(self):
+ category = self.customers.with_context({})
+ self.assertEqual(category.name, 'Customers', "Error in basic name_get")
+
+ category_fr = category.with_context({'lang': 'fr_FR'})
+ self.assertEqual(category_fr.name, 'Clients', "Translation not found")
+
+ def test_102_duplicate_record(self):
+ category = self.customers.with_context({'lang': 'fr_FR'}).copy()
+
+ category_no = category.with_context({})
+ self.assertEqual(category_no.name, 'Customers', "Duplication did not set untranslated value")
+
+ category_fr = category.with_context({'lang': 'fr_FR'})
+ self.assertEqual(category_fr.name, 'Clients', "Did not found translation for initial value")
+
+ def test_103_duplicate_record_fr(self):
+ category = self.customers.with_context({'lang': 'fr_FR'}).copy({'name': 'Clients (copie)'})
+
+ category_no = category.with_context({})
+ self.assertEqual(category_no.name, 'Customers', "Duplication erased original untranslated value")
+
+ category_fr = category.with_context({'lang': 'fr_FR'})
+ self.assertEqual(category_fr.name, 'Clients (copie)', "Did not used default value for translated value")
+
+ def test_104_orderby_translated_field(self):
+ """ Test search ordered by a translated field. """
+ # create a category with a French translation
+ padawans = self.env['res.partner.category'].create({'name': 'Padawans'})
+ padawans_fr = padawans.with_context(lang='fr_FR')
+ padawans_fr.write({'name': 'Apprentis'})
+ # search for categories, and sort them by (translated) name
+ categories = padawans_fr.search([('id', 'in', [self.customers.id, padawans.id])], order='name')
+ self.assertEqual(categories.ids, [padawans.id, self.customers.id],
+ "Search ordered by translated name should return Padawans (Apprentis) before Customers (Clients)")
diff --git a/openerp/addons/base/tests/test_uninstall.py b/openerp/addons/base/tests/test_uninstall.py
index 8bb658d61ba..f1d9aef9d8a 100644
--- a/openerp/addons/base/tests/test_uninstall.py
+++ b/openerp/addons/base/tests/test_uninstall.py
@@ -1,57 +1,31 @@
# -*- coding: utf-8 -*-
-# This assumes an existing but uninitialized database.
-import unittest
-
-import openerp
-from openerp import SUPERUSER_ID
-import common
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-ADMIN_USER_ID = common.ADMIN_USER_ID
-
-def registry(model):
- return openerp.modules.registry.RegistryManager.get(common.get_db_name())[model]
+# This assumes an existing but uninitialized database.
-def cursor():
- return openerp.modules.registry.RegistryManager.get(common.get_db_name()).cursor()
+from contextlib import contextmanager
+import unittest
-def get_module(module_name):
- registry = openerp.modules.registry.RegistryManager.get(common.get_db_name())
- return registry.get(module_name)
+from openerp import api, registry, SUPERUSER_ID
+from openerp.tests import common
+from openerp.modules.registry import RegistryManager
-def reload_registry():
- openerp.modules.registry.RegistryManager.new(
- common.get_db_name(), update_module=True)
-def search_registry(model_name, domain):
- cr = cursor()
- model = registry(model_name)
- record_ids = model.search(cr, SUPERUSER_ID, domain, {})
- cr.close()
- return record_ids
+@contextmanager
+def environment():
+ """ Return an environment with a new cursor for the current database; the
+ cursor is committed and closed after the context block.
+ """
+ reg = registry(common.get_db_name())
+ with reg.cursor() as cr:
+ yield api.Environment(cr, SUPERUSER_ID, {})
+ cr.commit()
-def install_module(module_name):
- ir_module_module = registry('ir.module.module')
- cr = cursor()
- module_ids = ir_module_module.search(cr, SUPERUSER_ID,
- [('name', '=', module_name)], {})
- assert len(module_ids) == 1
- ir_module_module.button_install(cr, SUPERUSER_ID, module_ids, {})
- cr.commit()
- cr.close()
- reload_registry()
-def uninstall_module(module_name):
- ir_module_module = registry('ir.module.module')
- cr = cursor()
- module_ids = ir_module_module.search(cr, SUPERUSER_ID,
- [('name', '=', module_name)], {})
- assert len(module_ids) == 1
- ir_module_module.button_uninstall(cr, SUPERUSER_ID, module_ids, {})
- cr.commit()
- cr.close()
- reload_registry()
+MODULE = 'test_uninstall'
+MODEL = 'test_uninstall.model'
-class test_uninstall(unittest.TestCase):
+class TestUninstall(unittest.TestCase):
"""
Test the install/uninstall of a test module. The module is available in
`openerp.tests` which should be present in the addons-path.
@@ -59,26 +33,29 @@ class test_uninstall(unittest.TestCase):
def test_01_install(self):
""" Check a few things showing the module is installed. """
- install_module('test_uninstall')
- assert get_module('test_uninstall.model')
-
- assert search_registry('ir.model.data',
- [('module', '=', 'test_uninstall')])
+ with environment() as env:
+ module = env['ir.module.module'].search([('name', '=', MODULE)])
+ assert len(module) == 1
+ module.button_install()
+ RegistryManager.new(common.get_db_name(), update_module=True)
- assert search_registry('ir.model.fields',
- [('model', '=', 'test_uninstall.model')])
+ with environment() as env:
+ self.assertIn('test_uninstall.model', env.registry)
+ self.assertTrue(env['ir.model.data'].search([('module', '=', MODULE)]))
+ self.assertTrue(env['ir.model.fields'].search([('model', '=', MODEL)]))
def test_02_uninstall(self):
""" Check a few things showing the module is uninstalled. """
- uninstall_module('test_uninstall')
- assert not get_module('test_uninstall.model')
-
- assert not search_registry('ir.model.data',
- [('module', '=', 'test_uninstall')])
-
- assert not search_registry('ir.model.fields',
- [('model', '=', 'test_uninstall.model')])
-
+ with environment() as env:
+ module = env['ir.module.module'].search([('name', '=', MODULE)])
+ assert len(module) == 1
+ module.button_uninstall()
+ RegistryManager.new(common.get_db_name(), update_module=True)
+
+ with environment() as env:
+ self.assertNotIn('test_uninstall.model', env.registry)
+ self.assertFalse(env['ir.model.data'].search([('module', '=', MODULE)]))
+ self.assertFalse(env['ir.model.fields'].search([('model', '=', MODEL)]))
if __name__ == '__main__':
diff --git a/openerp/addons/base/tests/test_user_has_group.py b/openerp/addons/base/tests/test_user_has_group.py
index e13d04f5f6f..be326976d8d 100644
--- a/openerp/addons/base/tests/test_user_has_group.py
+++ b/openerp/addons/base/tests/test_user_has_group.py
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
-import openerp.tests
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-class TestHasGroup(openerp.tests.TransactionCase):
+from odoo.tests.common import TransactionCase
+
+
+class TestHasGroup(TransactionCase):
def setUp(self):
super(TestHasGroup, self).setUp()
diff --git a/openerp/addons/base/tests/test_view_validation.py b/openerp/addons/base/tests/test_view_validation.py
index 68d35e38d1c..963f737ae4d 100644
--- a/openerp/addons/base/tests/test_view_validation.py
+++ b/openerp/addons/base/tests/test_view_validation.py
@@ -1,13 +1,15 @@
-# This test can be run stand-alone with something like:
-# > PYTHONPATH=. python2 openerp/tests/test_view_validation.py
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
from lxml import etree
from StringIO import StringIO
import unittest
-from openerp.tools.view_validation import (valid_page_in_book, valid_att_in_form, valid_type_in_colspan,
- valid_type_in_col, valid_att_in_field, valid_att_in_label,
- valid_field_in_graph, valid_field_in_tree
- )
+from odoo.tools.view_validation import (
+ valid_page_in_book, valid_att_in_form, valid_type_in_colspan,
+ valid_type_in_col, valid_att_in_field, valid_att_in_label,
+ valid_field_in_graph, valid_field_in_tree,
+)
invalid_form = etree.parse(StringIO('''\
<form>
@@ -92,7 +94,7 @@ valid_tree = etree.parse(StringIO('''\
''')).getroot()
-class test_view_validation(unittest.TestCase):
+class TestViewValidation(unittest.TestCase):
""" Test the view validation code (but not the views themselves). """
def test_page_validation(self):
@@ -125,7 +127,3 @@ class test_view_validation(unittest.TestCase):
def test_col_datatype_validation(self):
assert not valid_type_in_col(invalid_form)
assert valid_type_in_col(valid_form)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/openerp/addons/base/tests/test_views.py b/openerp/addons/base/tests/test_views.py
index a4ef571f59a..1a3488d96c9 100644
--- a/openerp/addons/base/tests/test_views.py
+++ b/openerp/addons/base/tests/test_views.py
@@ -1,36 +1,22 @@
-# -*- encoding: utf-8 -*-
-from functools import partial
-import itertools
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import unittest
+from functools import partial
+from itertools import izip_longest
-from lxml import etree as ET
+from lxml import etree
from lxml.builder import E
-
from psycopg2 import IntegrityError
-from openerp.tests import common
-import openerp.tools
+from odoo.tests import common
+from odoo.tools import mute_logger
-Field = E.field
class ViewCase(common.TransactionCase):
def setUp(self):
super(ViewCase, self).setUp()
- self.addTypeEqualityFunc(ET._Element, self.assertTreesEqual)
- self.Views = self.registry('ir.ui.view')
-
- def browse(self, id, context=None):
- return self.Views.browse(self.cr, self.uid, id, context=context)
- def create(self, value, context=None):
- return self.Views.create(self.cr, self.uid, value, context=context)
-
- def read_combined(self, id):
- return self.Views.read_combined(
- self.cr, self.uid,
- id, ['arch'],
- context={'check_view_ids': self.Views.search(self.cr, self.uid, [])}
- )
+ self.addTypeEqualityFunc(etree._Element, self.assertTreesEqual)
+ self.View = self.env['ir.ui.view']
def assertTreesEqual(self, n1, n2, msg=None):
self.assertEqual(n1.tag, n2.tag, msg)
@@ -41,7 +27,7 @@ class ViewCase(common.TransactionCase):
# equality (!?!?!?!)
self.assertEqual(dict(n1.attrib), dict(n2.attrib), msg)
- for c1, c2 in itertools.izip_longest(n1, n2):
+ for c1, c2 in izip_longest(n1, n2):
self.assertEqual(c1, c2, msg)
@@ -50,63 +36,65 @@ class TestNodeLocator(common.TransactionCase):
The node locator returns None when it can not find a node, and the first
match when it finds something (no jquery-style node sets)
"""
- def setUp(self):
- super(TestNodeLocator, self).setUp()
- self.Views = self.registry('ir.ui.view')
def test_no_match_xpath(self):
"""
xpath simply uses the provided @expr pattern to find a node
"""
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(), E.bar(), E.baz()),
- E.xpath(expr="//qux"))
+ E.xpath(expr="//qux"),
+ )
self.assertIsNone(node)
def test_match_xpath(self):
bar = E.bar()
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(), bar, E.baz()),
- E.xpath(expr="//bar"))
+ E.xpath(expr="//bar"),
+ )
self.assertIs(node, bar)
-
def test_no_match_field(self):
"""
A field spec will match by @name against all fields of the view
"""
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(), E.bar(), E.baz()),
- Field(name="qux"))
+ E.field(name="qux"),
+ )
self.assertIsNone(node)
- node = self.Views.locate_node(
- E.root(Field(name="foo"), Field(name="bar"), Field(name="baz")),
- Field(name="qux"))
+ node = self.env['ir.ui.view'].locate_node(
+ E.root(E.field(name="foo"), E.field(name="bar"), E.field(name="baz")),
+ E.field(name="qux"),
+ )
self.assertIsNone(node)
def test_match_field(self):
- bar = Field(name="bar")
- node = self.Views.locate_node(
- E.root(Field(name="foo"), bar, Field(name="baz")),
- Field(name="bar"))
+ bar = E.field(name="bar")
+ node = self.env['ir.ui.view'].locate_node(
+ E.root(E.field(name="foo"), bar, E.field(name="baz")),
+ E.field(name="bar"),
+ )
self.assertIs(node, bar)
-
def test_no_match_other(self):
"""
Non-xpath non-fields are matched by node name first
"""
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(), E.bar(), E.baz()),
- E.qux())
+ E.qux(),
+ )
self.assertIsNone(node)
def test_match_other(self):
bar = E.bar()
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(), bar, E.baz()),
- E.bar())
+ E.bar(),
+ )
self.assertIs(bar, node)
def test_attribute_mismatch(self):
@@ -114,27 +102,31 @@ class TestNodeLocator(common.TransactionCase):
Non-xpath non-field are filtered by matching attributes on spec and
matched nodes
"""
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(attr='1'), E.bar(attr='2'), E.baz(attr='3')),
- E.bar(attr='5'))
+ E.bar(attr='5'),
+ )
self.assertIsNone(node)
def test_attribute_filter(self):
match = E.bar(attr='2')
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.bar(attr='1'), match, E.root(E.bar(attr='3'))),
- E.bar(attr='2'))
+ E.bar(attr='2'),
+ )
self.assertIs(node, match)
def test_version_mismatch(self):
"""
A @version on the spec will be matched against the view's version
"""
- node = self.Views.locate_node(
+ node = self.env['ir.ui.view'].locate_node(
E.root(E.foo(attr='1'), version='4'),
- E.foo(attr='1', version='3'))
+ E.foo(attr='1', version='3'),
+ )
self.assertIsNone(node)
+
class TestViewInheritance(ViewCase):
def arch_for(self, name, view_type='form', parent=None):
""" Generates a trivial view of the specified ``view_type``.
@@ -157,7 +149,7 @@ class TestViewInheritance(ViewCase):
E.attribute(name, name='string'),
position='attributes'
)
- return ET.tostring(element)
+ return etree.tostring(element)
def makeView(self, name, parent=None, arch=None):
""" Generates a basic ir.ui.view with the provided name, parent and arch.
@@ -172,76 +164,65 @@ class TestViewInheritance(ViewCase):
:returns: the created view's id.
:rtype: int
"""
- view_id = self.View.create(self.cr, self.uid, {
+ view = self.View.create({
'model': self.model,
'name': name,
'arch': arch or self.arch_for(name, parent=parent),
'inherit_id': parent,
'priority': 5, # higher than default views
})
- self.ids[name] = view_id
- return view_id
+ self.view_ids[name] = view.id
+ return view
def setUp(self):
super(TestViewInheritance, self).setUp()
+ self.patch(self.registry, '_init', False)
+
self.model = 'ir.ui.view.custom'
- self.View = self.registry('ir.ui.view')
- self._init = self.View.pool._init
- self.View.pool._init = False
- self.ids = {}
+ self.view_ids = {}
a = self.makeView("A")
- a1 = self.makeView("A1", a)
- a11 = self.makeView("A11", a1)
- self.makeView("A111", a11)
- self.makeView("A12", a1)
- a2 = self.makeView("A2", a)
- self.makeView("A21", a2)
- a22 = self.makeView("A22", a2)
- self.makeView("A221", a22)
+ a1 = self.makeView("A1", a.id)
+ a11 = self.makeView("A11", a1.id)
+ self.makeView("A111", a11.id)
+ self.makeView("A12", a1.id)
+ a2 = self.makeView("A2", a.id)
+ self.makeView("A21", a2.id)
+ a22 = self.makeView("A22", a2.id)
+ self.makeView("A221", a22.id)
b = self.makeView('B', arch=self.arch_for("B", 'tree'))
- self.makeView('B1', b, arch=self.arch_for("B1", 'tree', parent=b))
+ self.makeView('B1', b.id, arch=self.arch_for("B1", 'tree', parent=b))
c = self.makeView('C', arch=self.arch_for("C", 'tree'))
- self.View.write(self.cr, self.uid, c, {'priority': 1})
-
- def tearDown(self):
- self.View.pool._init = self._init
- super(TestViewInheritance, self).tearDown()
+ c.write({'priority': 1})
def test_get_inheriting_views_arch(self):
- self.assertEqual(self.View.get_inheriting_views_arch(
- self.cr, self.uid, self.ids['A'], self.model), [
- (self.arch_for('A1', parent=True), self.ids['A1']),
- (self.arch_for('A2', parent=True), self.ids['A2']),
+ self.assertEqual(
+ self.View.get_inheriting_views_arch(self.view_ids['A'], self.model), [
+ (self.arch_for('A1', parent=True), self.view_ids['A1']),
+ (self.arch_for('A2', parent=True), self.view_ids['A2']),
])
- self.assertEqual(self.View.get_inheriting_views_arch(
- self.cr, self.uid, self.ids['A21'], self.model),
+ self.assertEqual(
+ self.View.get_inheriting_views_arch(self.view_ids['A21'], self.model),
[])
- self.assertEqual(self.View.get_inheriting_views_arch(
- self.cr, self.uid, self.ids['A11'], self.model),
- [(self.arch_for('A111', parent=True), self.ids['A111'])])
+ self.assertEqual(
+ self.View.get_inheriting_views_arch(self.view_ids['A11'], self.model),
+ [(self.arch_for('A111', parent=True), self.view_ids['A111'])])
def test_default_view(self):
- default = self.View.default_view(
- self.cr, self.uid, model=self.model, view_type='form')
- self.assertEqual(default, self.ids['A'])
+ default = self.View.default_view(model=self.model, view_type='form')
+ self.assertEqual(default, self.view_ids['A'])
- default_tree = self.View.default_view(
- self.cr, self.uid, model=self.model, view_type='tree')
- self.assertEqual(default_tree, self.ids['C'])
+ default_tree = self.View.default_view(model=self.model, view_type='tree')
+ self.assertEqual(default_tree, self.view_ids['C'])
def test_no_default_view(self):
- self.assertFalse(
- self.View.default_view(
- self.cr, self.uid, model='does.not.exist', view_type='form'))
+ self.assertFalse(self.View.default_view(model='does.not.exist', view_type='form'))
+ self.assertFalse(self.View.default_view(model=self.model, view_type='graph'))
- self.assertFalse(
- self.View.default_view(
- self.cr, self.uid, model=self.model, view_type='graph'))
class TestApplyInheritanceSpecs(ViewCase):
""" Applies a sequence of inheritance specification nodes to a base
@@ -252,143 +233,123 @@ class TestApplyInheritanceSpecs(ViewCase):
"""
def setUp(self):
super(TestApplyInheritanceSpecs, self).setUp()
- self.View = self.registry('ir.ui.view')
self.base_arch = E.form(
- Field(name="target"),
+ E.field(name="target"),
string="Title")
def test_replace(self):
- spec = Field(
- Field(name="replacement"),
+ spec = E.field(
+ E.field(name="replacement"),
name="target", position="replace")
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
self.assertEqual(
self.base_arch,
- E.form(Field(name="replacement"), string="Title"))
+ E.form(E.field(name="replacement"), string="Title"))
def test_delete(self):
- spec = Field(name="target", position="replace")
+ spec = E.field(name="target", position="replace")
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
self.assertEqual(
self.base_arch,
E.form(string="Title"))
def test_insert_after(self):
- spec = Field(
- Field(name="inserted"),
+ spec = E.field(
+ E.field(name="inserted"),
name="target", position="after")
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
self.assertEqual(
self.base_arch,
E.form(
- Field(name="target"),
- Field(name="inserted"),
+ E.field(name="target"),
+ E.field(name="inserted"),
string="Title"
))
def test_insert_before(self):
- spec = Field(
- Field(name="inserted"),
+ spec = E.field(
+ E.field(name="inserted"),
name="target", position="before")
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
self.assertEqual(
self.base_arch,
E.form(
- Field(name="inserted"),
- Field(name="target"),
+ E.field(name="inserted"),
+ E.field(name="target"),
string="Title"))
def test_insert_inside(self):
- default = Field(Field(name="inserted"), name="target")
- spec = Field(Field(name="inserted 2"), name="target", position='inside')
+ default = E.field(E.field(name="inserted"), name="target")
+ spec = E.field(E.field(name="inserted 2"), name="target", position='inside')
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- default, None)
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, default, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
self.assertEqual(
self.base_arch,
E.form(
- Field(
- Field(name="inserted"),
- Field(name="inserted 2"),
+ E.field(
+ E.field(name="inserted"),
+ E.field(name="inserted 2"),
name="target"),
string="Title"))
def test_unpack_data(self):
spec = E.data(
- Field(Field(name="inserted 0"), name="target"),
- Field(Field(name="inserted 1"), name="target"),
- Field(Field(name="inserted 2"), name="target"),
- Field(Field(name="inserted 3"), name="target"),
+ E.field(E.field(name="inserted 0"), name="target"),
+ E.field(E.field(name="inserted 1"), name="target"),
+ E.field(E.field(name="inserted 2"), name="target"),
+ E.field(E.field(name="inserted 3"), name="target"),
)
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
self.assertEqual(
self.base_arch,
E.form(
- Field(
- Field(name="inserted 0"),
- Field(name="inserted 1"),
- Field(name="inserted 2"),
- Field(name="inserted 3"),
+ E.field(
+ E.field(name="inserted 0"),
+ E.field(name="inserted 1"),
+ E.field(name="inserted 2"),
+ E.field(name="inserted 3"),
name="target"),
string="Title"))
- @openerp.tools.mute_logger('openerp.addons.base.ir.ir_ui_view')
+ @mute_logger('openerp.addons.base.ir.ir_ui_view')
def test_invalid_position(self):
- spec = Field(
- Field(name="whoops"),
+ spec = E.field(
+ E.field(name="whoops"),
name="target", position="serious_series")
with self.assertRaises(ValueError):
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
- @openerp.tools.mute_logger('openerp.addons.base.ir.ir_ui_view')
+ @mute_logger('openerp.addons.base.ir.ir_ui_view')
def test_incorrect_version(self):
# Version ignored on //field elements, so use something else
arch = E.form(E.element(foo="42"))
spec = E.element(
- Field(name="placeholder"),
+ E.field(name="placeholder"),
foo="42", version="7.0")
with self.assertRaises(ValueError):
- self.View.apply_inheritance_specs(self.cr, self.uid,
- arch,
- spec, None)
+ self.View.apply_inheritance_specs(arch, spec, None)
- @openerp.tools.mute_logger('openerp.addons.base.ir.ir_ui_view')
+ @mute_logger('openerp.addons.base.ir.ir_ui_view')
def test_target_not_found(self):
- spec = Field(name="targut")
+ spec = E.field(name="targut")
with self.assertRaises(ValueError):
- self.View.apply_inheritance_specs(self.cr, self.uid,
- self.base_arch,
- spec, None)
+ self.View.apply_inheritance_specs(self.base_arch, spec, None)
+
class TestApplyInheritanceWrapSpecs(ViewCase):
def setUp(self):
@@ -418,19 +379,19 @@ class TestApplyInheritedArchs(ViewCase):
""" Applies a sequence of modificator archs to a base view
"""
+
class TestNoModel(ViewCase):
def test_create_view_nomodel(self):
- View = self.registry('ir.ui.view')
- view_id = View.create(self.cr, self.uid, {
+ view = self.View.create({
'name': 'dummy',
'arch': '<template name="foo"/>',
'inherit_id': False,
'type': 'qweb',
})
fields = ['name', 'arch', 'type', 'priority', 'inherit_id', 'model']
- [view] = View.read(self.cr, self.uid, [view_id], fields)
- self.assertEqual(view, {
- 'id': view_id,
+ [data] = view.read(fields)
+ self.assertEqual(data, {
+ 'id': view.id,
'name': 'dummy',
'arch': '<template name="foo"/>',
'type': 'qweb',
@@ -459,7 +420,7 @@ class TestNoModel(ViewCase):
ARCH = '<template name="foo">%s</template>'
TEXT_EN = "Copyright copyrighter"
TEXT_FR = u"Copyrighter, tous droits réservés"
- view = self.env['ir.ui.view'].create({
+ view = self.View.create({
'name': 'dummy',
'arch': ARCH % TEXT_EN,
'inherit_id': False,
@@ -476,22 +437,14 @@ class TestNoModel(ViewCase):
view = view.with_context(lang='fr_FR')
self.assertEqual(view.arch, ARCH % TEXT_FR)
+
class TestTemplating(ViewCase):
def setUp(self):
- import openerp.modules
super(TestTemplating, self).setUp()
- self._pool = openerp.modules.registry.RegistryManager.get(common.get_db_name())
- self._init = self._pool._init
- # fuck off
- self._pool._init = False
-
- def tearDown(self):
- self._pool._init = self._init
- super(TestTemplating, self).tearDown()
+ self.patch(self.registry, '_init', False)
def test_branding_inherit(self):
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
+ view1 = self.View.create({
'name': "Base view",
'type': 'qweb',
'arch': """<root>
@@ -499,26 +452,24 @@ class TestTemplating(ViewCase):
</root>
"""
})
- id2 = Views.create(self.cr, self.uid, {
+ view2 = self.View.create({
'name': "Extension",
'type': 'qweb',
- 'inherit_id': id,
+ 'inherit_id': view1.id,
'arch': """<xpath expr="//item" position="before">
<item order="2"/>
</xpath>
"""
})
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
+ arch_string = view1.with_context(inherit_branding=True).read_combined(['arch'])['arch']
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
+ arch = etree.fromstring(arch_string)
+ self.View.distribute_branding(arch)
[initial] = arch.xpath('//item[@order=1]')
self.assertEqual(
- str(id),
+ str(view1.id),
initial.get('data-oe-id'),
"initial should come from the root view")
self.assertEqual(
@@ -528,7 +479,7 @@ class TestTemplating(ViewCase):
[second] = arch.xpath('//item[@order=2]')
self.assertEqual(
- str(id2),
+ str(view2.id),
second.get('data-oe-id'),
"second should come from the extension view")
@@ -536,18 +487,17 @@ class TestTemplating(ViewCase):
""" Checks that the branding is correctly distributed within a view
extension
"""
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
+ view1 = self.View.create({
'name': "Base view",
'type': 'qweb',
'arch': """<root>
<item order="1"/>
</root>"""
})
- id2 = Views.create(self.cr, self.uid, {
+ view2 = self.View.create({
'name': "Extension",
'type': 'qweb',
- 'inherit_id': id,
+ 'inherit_id': view1.id,
'arch': """<xpath expr="//item" position="before">
<item order="2">
<content t-att-href="foo">bar</content>
@@ -555,12 +505,10 @@ class TestTemplating(ViewCase):
</xpath>"""
})
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
+ arch_string = view1.with_context(inherit_branding=True).read_combined(['arch'])['arch']
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
+ arch = etree.fromstring(arch_string)
+ self.View.distribute_branding(arch)
self.assertEqual(
arch,
@@ -569,7 +517,7 @@ class TestTemplating(ViewCase):
E.content("bar", {
't-att-href': "foo",
'data-oe-model': 'ir.ui.view',
- 'data-oe-id': str(id2),
+ 'data-oe-id': str(view2.id),
'data-oe-field': 'arch',
'data-oe-xpath': '/xpath/item/content[1]',
}), {
@@ -578,7 +526,7 @@ class TestTemplating(ViewCase):
E.item({
'order': '1',
'data-oe-model': 'ir.ui.view',
- 'data-oe-id': str(id),
+ 'data-oe-id': str(view1.id),
'data-oe-field': 'arch',
'data-oe-xpath': '/root[1]/item[1]',
})
@@ -586,8 +534,7 @@ class TestTemplating(ViewCase):
)
def test_esc_no_branding(self):
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
+ view = self.View.create({
'name': "Base View",
'type': 'qweb',
'arch': """<root>
@@ -595,17 +542,14 @@ class TestTemplating(ViewCase):
</root>""",
})
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
+ arch_string = view.with_context(inherit_branding=True).read_combined(['arch'])['arch']
+ arch = etree.fromstring(arch_string)
+ self.View.distribute_branding(arch)
self.assertEqual(arch, E.root(E.item(E.span({'t-esc': "foo"}))))
def test_ignore_unbrand(self):
- Views = self.registry('ir.ui.view')
- id = Views.create(self.cr, self.uid, {
+ view1 = self.View.create({
'name': "Base view",
'type': 'qweb',
'arch': """<root>
@@ -614,10 +558,10 @@ class TestTemplating(ViewCase):
</item>
</root>"""
})
- id2 = Views.create(self.cr, self.uid, {
+ view2 = self.View.create({
'name': "Extension",
'type': 'qweb',
- 'inherit_id': id,
+ 'inherit_id': view1.id,
'arch': """<xpath expr="//item[@order='1']" position="inside">
<item order="2">
<content t-att-href="foo">bar</content>
@@ -625,12 +569,10 @@ class TestTemplating(ViewCase):
</xpath>"""
})
- arch_string = Views.read_combined(
- self.cr, self.uid, id, fields=['arch'],
- context={'inherit_branding': True})['arch']
+ arch_string = view1.with_context(inherit_branding=True).read_combined(['arch'])['arch']
- arch = ET.fromstring(arch_string)
- Views.distribute_branding(arch)
+ arch = etree.fromstring(arch_string)
+ self.View.distribute_branding(arch)
self.assertEqual(
arch,
@@ -650,14 +592,14 @@ class TestTemplating(ViewCase):
" the main view's"
)
-class test_views(ViewCase):
+
+class TestViews(ViewCase):
def test_nonexistent_attribute_removal(self):
- Views = self.registry('ir.ui.view')
- Views.create(self.cr, self.uid, {
+ self.View.create({
'name': 'Test View',
'model': 'ir.ui.view',
- 'inherit_id': self.browse_ref('base.view_view_tree').id,
+ 'inherit_id': self.ref('base.view_view_tree'),
'arch': """<?xml version="1.0"?>
<xpath expr="//field[@name='name']" position="attributes">
<attribute name="non_existing_attribute"></attribute>
@@ -680,10 +622,8 @@ class test_views(ViewCase):
return self.cr.fetchone()[0]
def test_custom_view_validation(self):
- Views = self.registry('ir.ui.view')
model = 'ir.actions.act_url'
-
- validate = partial(Views._validate_custom_views, self.cr, self.uid, model)
+ validate = partial(self.View._validate_custom_views, model)
# validation of a single view
vid = self._insert_view(
@@ -727,9 +667,7 @@ class test_views(ViewCase):
self.assertTrue(validate()) # inherited view
def test_view_inheritance(self):
- Views = self.registry('ir.ui.view')
-
- v1 = Views.create(self.cr, self.uid, {
+ view1 = self.View.create({
'name': "bob",
'model': 'ir.ui.view',
'arch': """
@@ -742,10 +680,10 @@ class test_views(ViewCase):
</form>
"""
})
- v2 = Views.create(self.cr, self.uid, {
+ view2 = self.View.create({
'name': "edmund",
'model': 'ir.ui.view',
- 'inherit_id': v1,
+ 'inherit_id': view1.id,
'arch': """
<data>
<form position="attributes" version="7.0">
@@ -762,10 +700,10 @@ class test_views(ViewCase):
</data>
"""
})
- v3 = Views.create(self.cr, self.uid, {
+ view3 = self.View.create({
'name': 'jake',
'model': 'ir.ui.view',
- 'inherit_id': v1,
+ 'inherit_id': view1.id,
'priority': 17,
'arch': """
<footer position="attributes">
@@ -777,16 +715,13 @@ class test_views(ViewCase):
"""
})
- view = self.registry('ir.ui.view').fields_view_get(
- self.cr, self.uid, v2, view_type='form', context={
- # fucking what?
- 'check_view_ids': [v2, v3]
- })
+ view = self.View.with_context(check_view_ids=[view2.id, view3.id]) \
+ .fields_view_get(view2.id, view_type='form')
self.assertEqual(view['type'], 'form')
self.assertEqual(
- ET.fromstring(
+ etree.fromstring(
view['arch'],
- parser=ET.XMLParser(remove_blank_text=True)
+ parser=etree.XMLParser(remove_blank_text=True)
),
E.form(
E.p("Replacement data"),
@@ -797,9 +732,7 @@ class test_views(ViewCase):
string="Replacement title", version="7.0"))
def test_view_inheritance_divergent_models(self):
- Views = self.registry('ir.ui.view')
-
- v1 = Views.create(self.cr, self.uid, {
+ view1 = self.View.create({
'name': "bob",
'model': 'ir.ui.view.custom',
'arch': """
@@ -812,10 +745,10 @@ class test_views(ViewCase):
</form>
"""
})
- v2 = Views.create(self.cr, self.uid, {
+ view2 = self.View.create({
'name': "edmund",
'model': 'ir.ui.view',
- 'inherit_id': v1,
+ 'inherit_id': view1.id,
'arch': """
<data>
<form position="attributes" version="7.0">
@@ -832,10 +765,10 @@ class test_views(ViewCase):
</data>
"""
})
- v3 = Views.create(self.cr, self.uid, {
+ view3 = self.View.create({
'name': 'jake',
'model': 'ir.ui.menu',
- 'inherit_id': v1,
+ 'inherit_id': view1.id,
'priority': 17,
'arch': """
<footer position="attributes">
@@ -844,16 +777,13 @@ class test_views(ViewCase):
"""
})
- view = self.registry('ir.ui.view').fields_view_get(
- self.cr, self.uid, v2, view_type='form', context={
- # fucking what?
- 'check_view_ids': [v2, v3]
- })
+ view = self.View.with_context(check_view_ids=[view2.id, view3.id]) \
+ .fields_view_get(view2.id, view_type='form')
self.assertEqual(view['type'], 'form')
self.assertEqual(
- ET.fromstring(
+ etree.fromstring(
view['arch'],
- parser=ET.XMLParser(remove_blank_text=True)
+ parser=etree.XMLParser(remove_blank_text=True)
),
E.form(
E.p("Replacement data"),
@@ -862,6 +792,7 @@ class test_views(ViewCase):
string="Replacement title", version="7.0"
))
+
class ViewModeField(ViewCase):
"""
This should probably, eventually, be folded back into other test case
@@ -873,47 +804,47 @@ class ViewModeField(ViewCase):
* inherit_id -> mode=extension
* not inherit_id -> mode=primary
"""
- view = self.browse(self.create({
+ view = self.View.create({
'inherit_id': None,
'arch': '<qweb/>'
- }))
+ })
self.assertEqual(view.mode, 'primary')
- view2 = self.browse(self.create({
+ view2 = self.View.create({
'inherit_id': view.id,
'arch': '<qweb/>'
- }))
+ })
self.assertEqual(view2.mode, 'extension')
- @openerp.tools.mute_logger('openerp.sql_db')
+ @mute_logger('openerp.sql_db')
def testModeExplicit(self):
- view = self.browse(self.create({
+ view = self.View.create({
'inherit_id': None,
'arch': '<qweb/>'
- }))
- view2 = self.browse(self.create({
+ })
+ view2 = self.View.create({
'inherit_id': view.id,
'mode': 'primary',
'arch': '<qweb/>'
- }))
+ })
self.assertEqual(view.mode, 'primary')
with self.assertRaises(IntegrityError):
- self.create({
+ self.View.create({
'inherit_id': None,
'mode': 'extension',
'arch': '<qweb/>'
})
- @openerp.tools.mute_logger('openerp.sql_db')
+ @mute_logger('openerp.sql_db')
def testPurePrimaryToExtension(self):
"""
A primary view with inherit_id=None can't be converted to extension
"""
- view_pure_primary = self.browse(self.create({
+ view_pure_primary = self.View.create({
'inherit_id': None,
'arch': '<qweb/>'
- }))
+ })
with self.assertRaises(IntegrityError):
view_pure_primary.write({'mode': 'extension'})
@@ -921,12 +852,15 @@ class ViewModeField(ViewCase):
"""
A primary view with an inherit_id can be converted to extension
"""
- base = self.create({'inherit_id': None, 'arch': '<qweb/>'})
- view = self.browse(self.create({
- 'inherit_id': base,
+ base = self.View.create({
+ 'inherit_id': None,
+ 'arch': '<qweb/>',
+ })
+ view = self.View.create({
+ 'inherit_id': base.id,
'mode': 'primary',
'arch': '<qweb/>'
- }))
+ })
view.write({'mode': 'extension'})
@@ -934,63 +868,68 @@ class ViewModeField(ViewCase):
"""
An extension view can be converted to primary
"""
- base = self.create({'inherit_id': None, 'arch': '<qweb/>'})
- view = self.browse(self.create({
- 'inherit_id': base,
+ base = self.View.create({
+ 'inherit_id': None,
+ 'arch': '<qweb/>',
+ })
+ view = self.View.create({
+ 'inherit_id': base.id,
'arch': '<qweb/>'
- }))
+ })
view.write({'mode': 'primary'})
+
class TestDefaultView(ViewCase):
def testDefaultViewBase(self):
- self.create({
+ self.View.create({
'inherit_id': False,
'priority': 10,
'mode': 'primary',
'arch': '<qweb/>',
})
- v2 = self.create({
+ view2 = self.View.create({
'inherit_id': False,
'priority': 1,
'mode': 'primary',
'arch': '<qweb/>',
})
- default = self.Views.default_view(self.cr, self.uid, False, 'qweb')
+ default = self.View.default_view(False, 'qweb')
self.assertEqual(
- default, v2,
+ default, view2.id,
"default_view should get the view with the lowest priority for "
"a (model, view_type) pair"
)
def testDefaultViewPrimary(self):
- v1 = self.create({
+ view1 = self.View.create({
'inherit_id': False,
'priority': 10,
'mode': 'primary',
'arch': '<qweb/>',
})
- self.create({
+ self.View.create({
'inherit_id': False,
'priority': 5,
'mode': 'primary',
'arch': '<qweb/>',
})
- v3 = self.create({
- 'inherit_id': v1,
+ view3 = self.View.create({
+ 'inherit_id': view1.id,
'priority': 1,
'mode': 'primary',
'arch': '<qweb/>',
})
- default = self.Views.default_view(self.cr, self.uid, False, 'qweb')
+ default = self.View.default_view(False, 'qweb')
self.assertEqual(
- default, v3,
+ default, view3.id,
"default_view should get the view with the lowest priority for "
"a (model, view_type) pair in all the primary tables"
)
+
class TestViewCombined(ViewCase):
"""
* When asked for a view, instead of looking for the closest parent with
@@ -1003,72 +942,73 @@ class TestViewCombined(ViewCase):
def setUp(self):
super(TestViewCombined, self).setUp()
- self.a1 = self.create({
+ self.a1 = self.View.create({
'model': 'a',
'arch': '<qweb><a1/></qweb>'
})
- self.a2 = self.create({
+ self.a2 = self.View.create({
'model': 'a',
- 'inherit_id': self.a1,
+ 'inherit_id': self.a1.id,
'priority': 5,
'arch': '<xpath expr="//a1" position="after"><a2/></xpath>'
})
- self.a3 = self.create({
+ self.a3 = self.View.create({
'model': 'a',
- 'inherit_id': self.a1,
+ 'inherit_id': self.a1.id,
'arch': '<xpath expr="//a1" position="after"><a3/></xpath>'
})
# mode=primary should be an inheritance boundary in both direction,
# even within a model it should not extend the parent
- self.a4 = self.create({
+ self.a4 = self.View.create({
'model': 'a',
- 'inherit_id': self.a1,
+ 'inherit_id': self.a1.id,
'mode': 'primary',
'arch': '<xpath expr="//a1" position="after"><a4/></xpath>',
})
- self.b1 = self.create({
+ self.b1 = self.View.create({
'model': 'b',
- 'inherit_id': self.a3,
+ 'inherit_id': self.a3.id,
'mode': 'primary',
'arch': '<xpath expr="//a1" position="after"><b1/></xpath>'
})
- self.b2 = self.create({
+ self.b2 = self.View.create({
'model': 'b',
- 'inherit_id': self.b1,
+ 'inherit_id': self.b1.id,
'arch': '<xpath expr="//a1" position="after"><b2/></xpath>'
})
- self.c1 = self.create({
+ self.c1 = self.View.create({
'model': 'c',
- 'inherit_id': self.a1,
+ 'inherit_id': self.a1.id,
'mode': 'primary',
'arch': '<xpath expr="//a1" position="after"><c1/></xpath>'
})
- self.c2 = self.create({
+ self.c2 = self.View.create({
'model': 'c',
- 'inherit_id': self.c1,
+ 'inherit_id': self.c1.id,
'priority': 5,
'arch': '<xpath expr="//a1" position="after"><c2/></xpath>'
})
- self.c3 = self.create({
+ self.c3 = self.View.create({
'model': 'c',
- 'inherit_id': self.c2,
+ 'inherit_id': self.c2.id,
'priority': 10,
'arch': '<xpath expr="//a1" position="after"><c3/></xpath>'
})
- self.d1 = self.create({
+ self.d1 = self.View.create({
'model': 'd',
- 'inherit_id': self.b1,
+ 'inherit_id': self.b1.id,
'mode': 'primary',
'arch': '<xpath expr="//a1" position="after"><d1/></xpath>'
})
def test_basic_read(self):
- arch = self.read_combined(self.a1)['arch']
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.a1.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.a1(),
E.a3(),
@@ -1076,9 +1016,10 @@ class TestViewCombined(ViewCase):
), arch)
def test_read_from_child(self):
- arch = self.read_combined(self.a3)['arch']
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.a3.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.a1(),
E.a3(),
@@ -1086,9 +1027,10 @@ class TestViewCombined(ViewCase):
), arch)
def test_read_from_child_primary(self):
- arch = self.read_combined(self.a4)['arch']
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.a4.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.a1(),
E.a4(),
@@ -1097,9 +1039,10 @@ class TestViewCombined(ViewCase):
), arch)
def test_cross_model_simple(self):
- arch = self.read_combined(self.c2)['arch']
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.c2.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.a1(),
E.c3(),
@@ -1110,9 +1053,10 @@ class TestViewCombined(ViewCase):
), arch)
def test_cross_model_double(self):
- arch = self.read_combined(self.d1)['arch']
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.d1.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.a1(),
E.d1(),
@@ -1122,6 +1066,7 @@ class TestViewCombined(ViewCase):
E.a2(),
), arch)
+
class TestOptionalViews(ViewCase):
"""
Tests ability to enable/disable inherited views, formerly known as
@@ -1130,27 +1075,27 @@ class TestOptionalViews(ViewCase):
def setUp(self):
super(TestOptionalViews, self).setUp()
- self.v0 = self.create({
+ self.v0 = self.View.create({
'model': 'a',
'arch': '<qweb><base/></qweb>',
})
- self.v1 = self.create({
+ self.v1 = self.View.create({
'model': 'a',
- 'inherit_id': self.v0,
+ 'inherit_id': self.v0.id,
'active': True,
'priority': 10,
'arch': '<xpath expr="//base" position="after"><v1/></xpath>',
})
- self.v2 = self.create({
+ self.v2 = self.View.create({
'model': 'a',
- 'inherit_id': self.v0,
+ 'inherit_id': self.v0.id,
'active': True,
'priority': 9,
'arch': '<xpath expr="//base" position="after"><v2/></xpath>',
})
- self.v3 = self.create({
+ self.v3 = self.View.create({
'model': 'a',
- 'inherit_id': self.v0,
+ 'inherit_id': self.v0.id,
'active': False,
'priority': 8,
'arch': '<xpath expr="//base" position="after"><v3/></xpath>'
@@ -1159,9 +1104,10 @@ class TestOptionalViews(ViewCase):
def test_applied(self):
""" mandatory and enabled views should be applied
"""
- arch = self.read_combined(self.v0)['arch']
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.v0.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.base(),
E.v1(),
@@ -1173,20 +1119,22 @@ class TestOptionalViews(ViewCase):
""" Change active states of v2 and v3, check that the results
are as expected
"""
- self.browse(self.v2).toggle()
- arch = self.read_combined(self.v0)['arch']
+ self.v2.toggle()
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.v0.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.base(),
E.v1(),
)
)
- self.browse(self.v3).toggle()
- arch = self.read_combined(self.v0)['arch']
+ self.v3.toggle()
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.v0.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.base(),
E.v1(),
@@ -1194,10 +1142,11 @@ class TestOptionalViews(ViewCase):
)
)
- self.browse(self.v2).toggle()
- arch = self.read_combined(self.v0)['arch']
+ self.v2.toggle()
+ context = {'check_view_ids': self.View.search([]).ids}
+ arch = self.v0.with_context(context).read_combined(['arch'])['arch']
self.assertEqual(
- ET.fromstring(arch),
+ etree.fromstring(arch),
E.qweb(
E.base(),
E.v1(),
@@ -1206,6 +1155,7 @@ class TestOptionalViews(ViewCase):
)
)
+
class TestXPathExtentions(common.BaseCase):
def test_hasclass(self):
tree = E.node(
diff --git a/openerp/addons/base/tests/test_xmlrpc.py b/openerp/addons/base/tests/test_xmlrpc.py
index 0eca22faa58..c47b51acd93 100644
--- a/openerp/addons/base/tests/test_xmlrpc.py
+++ b/openerp/addons/base/tests/test_xmlrpc.py
@@ -1,21 +1,23 @@
# -*- coding: utf-8 -*-
-import openerp.tests.common
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo.tests import common
-class test_xmlrpc(openerp.tests.common.HttpCase):
+
+class TestXMLRPC(common.HttpCase):
at_install = False
post_install = True
def test_01_xmlrpc_login(self):
""" Try to login on the common service. """
- db_name = openerp.tests.common.get_db_name()
+ db_name = common.get_db_name()
uid = self.xmlrpc_common.login(db_name, 'admin', 'admin')
self.assertEqual(uid, 1)
def test_xmlrpc_ir_model_search(self):
""" Try a search on the object service. """
o = self.xmlrpc_object
- db_name = openerp.tests.common.get_db_name()
+ db_name = common.get_db_name()
ids = o.execute(db_name, 1, 'admin', 'ir.model', 'search', [])
self.assertIsInstance(ids, list)
ids = o.execute(db_name, 1, 'admin', 'ir.model', 'search', [], {})
diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py
index 6e3d775bc54..97feff79551 100644
--- a/openerp/osv/expression.py
+++ b/openerp/osv/expression.py
@@ -5,7 +5,7 @@
The main duty of this module is to compile a domain expression into a
SQL query. A lot of things should be documented here, but as a first
-step in the right direction, some tests in test_osv_expression.yml
+step in the right direction, some tests in test_expression.py
might give you some additional information.
For legacy reasons, a domain uses an inconsistent two-levels abstract