You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

366 lines
12 KiB

# -*- coding: utf-8 -*-
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import mock
from contextlib import contextmanager
import odoo.tests.common as common
class TestOnchangeHelper(common.TransactionCase):
def setUp(self):
super(TestOnchangeHelper, self).setUp()
self.Category = self.env["test_onchange_helper.category"]
self.Message = self.env["test_onchange_helper.message"]
self.Discussion = self.env["test_onchange_helper.discussion"]
self.maxDiff = None
@contextmanager
def assertNoOrmWrite(self, model):
with mock.patch.object(
model.__class__, "create"
) as mocked_create, mock.patch.object(
model.__class__, "write"
) as mocked_write:
yield
mocked_create.assert_not_called()
mocked_write.assert_not_called()
def test_play_onhanges_no_recompute(self):
# play_onchanges must not trigger recomputes except if an onchange
# method access a computed field.
# changing 'discussion' should recompute 'name'
values = {"name": "Cat Name"}
self.env.invalidate_all()
with self.assertNoOrmWrite(self.Category):
result = self.Category.play_onchanges(values, ["name"])
self.assertNotIn("computed_display_name", result)
def test_play_onchanges_many2one_new_record(self):
root = self.Category.create({"name": "root"})
values = {"name": "test", "parent": root.id}
self.env.invalidate_all()
with self.assertNoOrmWrite(self.Category):
result = self.Category.play_onchanges(values, "parent")
self.assertIn("root_categ", result)
self.assertEqual(result["root_categ"], root.id)
def test_play_onchanges_many2one_existing_record(self):
root = self.Category.create({"name": "root"})
values = {"name": "test", "parent": root.id}
self.env.invalidate_all()
with self.assertNoOrmWrite(self.Category):
result = self.Category.play_onchanges(values, "parent")
self.assertIn("root_categ", result)
self.assertEqual(result["root_categ"], root.id)
# create child catefory
values.update(result)
child = self.Category.create(values)
self.assertEqual(root.id, child.root_categ.id)
# since the parent is set to False and the root_categ
values = {"parent": False}
self.env.invalidate_all()
with self.assertNoOrmWrite(child):
result = child.play_onchanges(values, "parent")
self.assertIn("root_categ", result)
self.assertEqual(result["root_categ"], False)
def test_play_onchange_one2many_new_record(self):
""" test the effect of play_onchanges() on one2many fields on new
record"""
BODY = "What a beautiful day!"
USER = self.env.user
# create an independent message
message = self.Message.create({"body": BODY})
# modify discussion name
values = {
"name": "Foo",
"categories": [],
"moderator": False,
"participants": [],
"messages": [
(4, message.id),
(
0,
0,
{
"name": "[%s] %s" % ("", USER.name),
"body": BODY,
"author": USER.id,
"important": False,
},
),
],
}
self.env.invalidate_all()
with self.assertNoOrmWrite(self.Discussion):
result = self.Discussion.play_onchanges(values, "name")
self.assertIn("messages", result)
self.assertItemsEqual(
result["messages"],
[
(5,),
(
1,
message.id,
{
"name": "[%s] %s" % ("Foo", USER.name),
"body": "not last dummy message",
"author": message.author.id,
"important": message.important,
},
),
(
0,
0,
{
"name": "[%s] %s" % ("Foo", USER.name),
"body": "not last dummy message",
"author": USER.id,
"important": False,
},
),
(
0,
0,
{
"name": "[%s] %s" % ("Foo", USER.name),
"body": "dummy message",
"author": USER.id,
"important": True,
},
),
],
)
self.assertIn("important_messages", result)
self.assertItemsEqual(
result["important_messages"],
[
(5,),
(
0,
0,
{
"author": USER.id,
"body": "dummy message",
"important": True,
},
),
],
)
def test_play_onchange_one2many_existing_record(self):
""" test the effect of play_onchanges() on one2many fields on existing
record"""
BODY = "What a beautiful day!"
USER = self.env.user
# create an independent message
message = self.Message.create({"body": BODY})
# modify discussion name
values = {
"name": "Foo",
"categories": [],
"moderator": False,
"participants": [],
"messages": [
(4, message.id),
(
0,
0,
{
"name": "[%s] %s" % ("", USER.name),
"body": BODY,
"author": USER.id,
"important": False,
},
),
],
}
discussion = self.Discussion.create(values)
values = {"name": "New foo"}
with self.assertNoOrmWrite(discussion):
result = discussion.play_onchanges(values, "name")
self.assertIn("messages", result)
self.assertItemsEqual(
result["messages"],
[
(5,),
(
1,
discussion.messages[0].id,
{
"name": "[%s] %s" % ("New foo", USER.name),
"body": "not last dummy message",
"author": message.author.id,
"important": message.important,
"discussion": discussion.id,
},
),
(
1,
discussion.messages[1].id,
{
"name": "[%s] %s" % ("New foo", USER.name),
"body": "not last dummy message",
"author": USER.id,
"important": False,
"discussion": discussion.id,
},
),
(
0,
0,
{
"name": "[%s] %s" % ("New foo", USER.name),
"body": "dummy message",
"author": USER.id,
"important": True,
"discussion": discussion.id,
},
),
],
)
self.assertIn("important_messages", result)
self.assertItemsEqual(
result["important_messages"],
[
(5,),
(
0,
0,
{
"author": USER.id,
"body": "dummy message",
"important": True,
"discussion": discussion.id,
},
),
],
)
def test_onchange_specific(self):
"""test that only the id is added if a new item is added to an
existing relation"""
discussion = self.env.ref("test_onchange_helper.discussion_demo_0")
demo = self.env.ref("base.user_demo")
# first remove demo user from participants
discussion.participants -= demo
self.assertNotIn(demo, discussion.participants)
# check that demo_user is added to participants when set as moderator
values = {
"name": discussion.name,
"moderator": demo.id,
}
self.env.invalidate_all()
with self.assertNoOrmWrite(discussion):
result = discussion.play_onchanges(values, "moderator")
self.assertIn("participants", result)
self.assertTrue(discussion.participants)
self.assertItemsEqual(
result["participants"],
[(5,)] + [(4, user.id) for user in discussion.participants + demo],
)
def test_onchange_one2many_value(self):
""" test that the values provided for a one2many field inside are used
by the play_onchanges """
discussion = self.env.ref("test_onchange_helper.discussion_demo_0")
demo = self.env.ref("base.user_demo")
self.assertEqual(len(discussion.messages), 3)
messages = [(4, msg.id) for msg in discussion.messages]
messages[0] = (1, messages[0][1], {"body": "test onchange"})
values = {
"name": discussion.name,
"moderator": demo.id,
"categories": [(4, cat.id) for cat in discussion.categories],
"messages": messages,
"participants": [(4, usr.id) for usr in discussion.participants],
}
with self.assertNoOrmWrite(discussion):
result = discussion.play_onchanges(values, "messages")
self.assertIn("message_concat", result)
self.assertEqual(
result["message_concat"],
"\n".join(
["%s:%s" % (m.name, m.body) for m in discussion.messages]
),
)
def test_onchange_one2many_line(self):
""" test that changes on a field used as first position into the
related path of a related field will trigger the onchange also on the
related field """
partner = self.env.ref("base.res_partner_1")
multi = self.env["test_onchange_helper.multi"].create(
{"partner": partner.id}
)
line = multi.lines.create({"multi": multi.id})
values = multi._convert_to_write(
{key: multi[key] for key in ("partner", "lines")}
)
self.assertEqual(
values, {"partner": partner.id, "lines": [(6, 0, [line.id])]}
)
# modify 'partner'
# -> set 'partner' on all lines
# -> recompute 'name' (related on partner)
# -> set 'name' on all lines
partner = self.env.ref("base.res_partner_2")
values = {
"partner": partner.id,
"lines": [
(6, 0, [line.id]),
(0, 0, {"name": False, "partner": False}),
],
}
self.env.invalidate_all()
with self.assertNoOrmWrite(multi):
result = multi.play_onchanges(values, "partner")
self.assertEqual(
result,
{
"name": partner.name,
"lines": [
(5,),
(
1,
line.id,
{
"name": partner.name,
"partner": partner.id,
"multi": multi.id,
},
),
(
0,
0,
{
"name": partner.name,
"partner": partner.id,
"multi": multi.id,
},
),
],
},
)