Skip to content

Commit 8679507

Browse files
committed
[MIG] serer_environment_data_encryption: improve coverage
1 parent 0717506 commit 8679507

1 file changed

Lines changed: 135 additions & 5 deletions

File tree

server_environment_data_encryption/tests/test_server_environment_data_encrypt.py

Lines changed: 135 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
22

33
from pathlib import Path
4+
from unittest.mock import patch
45

56
from lxml import etree
67
from odoo_test_helper import FakeModelLoader
78

9+
from odoo.exceptions import ValidationError
10+
from odoo.tools.config import config
11+
812
from odoo.addons.data_encryption.tests.common import CommonDataEncrypted
913

1014

@@ -14,18 +18,17 @@ def setUpClass(cls):
1418
super().setUpClass()
1519
cls.loader = FakeModelLoader(cls.env, cls.__module__)
1620
cls.loader.backup_registry()
17-
21+
cls.addClassCleanup(cls.loader.restore_registry)
1822
# The fake class is imported here !! After the backup_registry
1923
from .models import FakePartner
2024

2125
cls.loader.update_registry((FakePartner,))
2226
cls.set_new_key_env("prod")
2327
cls.set_new_key_env("preprod")
2428

25-
@classmethod
26-
def tearDownClass(cls):
27-
cls.loader.restore_registry()
28-
super().tearDownClass()
29+
cls.partner = cls.env["res.partner"].create(
30+
{"name": "Test Partner", "city": "Test City"}
31+
)
2932

3033
def test_env_dependent_value(self):
3134
partner = self.env["res.partner"].create(
@@ -110,3 +113,130 @@ def test_view_with_env_update(self):
110113
confirm_button.get("invisible"),
111114
"context.get(\"environment\", 'test') != 'test'",
112115
)
116+
117+
def test_missing_encryption_key(self):
118+
"""Test behavior when encryption key is missing for current env"""
119+
with patch.object(
120+
config,
121+
"get",
122+
side_effect=lambda key, default=None: "missing_env"
123+
if key == "running_env"
124+
else (None if key.startswith("encryption_key_") else default),
125+
):
126+
# This should trigger the warning in _current_env_encrypted_key_exists
127+
self.assertFalse(self.partner._current_env_encrypted_key_exists())
128+
129+
# Test fallbacks
130+
# Since we can't easily mock super(), we just verify it doesn't crash
131+
self.partner._compute_server_env_from_default("city", {})
132+
self.partner._inverse_server_env("city")
133+
134+
# Test warning div in view
135+
mixin_obj = self.env["server.env.mixin"]
136+
elem = mixin_obj._get_extra_environment_info_div("test", ["test", "prod"])
137+
self.assertIn(
138+
"The encryption key for current environement is not defined",
139+
etree.tostring(elem, encoding="unicode"),
140+
)
141+
142+
def test_action_change_env_data_encrypted_fields(self):
143+
"""Test action_change_env_data_encrypted_fields"""
144+
# Case 1: No action in context
145+
action = self.partner.action_change_env_data_encrypted_fields()
146+
self.assertEqual(action.get("res_id"), self.partner.id)
147+
148+
# Case 2: Action in context
149+
# We need a real action id to browse
150+
act_window = self.env["ir.actions.act_window"].search([], limit=1)
151+
if act_window:
152+
# Mock the read result to have multiple views including a non-form one
153+
with patch.object(
154+
type(self.env["ir.actions.act_window"]),
155+
"read",
156+
return_value=[
157+
{
158+
"views": [(1, "tree"), (2, "form")],
159+
"type": "ir.actions.act_window",
160+
}
161+
],
162+
):
163+
partner_with_ctx = self.partner.with_context(
164+
params={"action": act_window.id}
165+
)
166+
action = partner_with_ctx.action_change_env_data_encrypted_fields()
167+
self.assertEqual(action.get("res_id"), self.partner.id)
168+
self.assertEqual(action.get("view_mode"), "form")
169+
self.assertEqual(len(action["views"]), 1)
170+
self.assertEqual(action["views"][0][1], "form")
171+
172+
def test_view_processing_edge_cases(self):
173+
"""Test various edge cases in view processing"""
174+
mixin_obj = self.env["server.env.mixin"]
175+
arch = etree.XML("<form><sheet><field name='test'/></sheet></form>")
176+
177+
# 1. view_type != "form"
178+
res = mixin_obj._update_form_view_from_env(arch, "tree")
179+
self.assertEqual(res, arch)
180+
181+
# 2. missing running_env
182+
with patch.dict(config.options, {"running_env": ""}):
183+
with self.assertRaises(ValidationError):
184+
mixin_obj._update_form_view_from_env(arch, "form")
185+
186+
# 3. missing sheet
187+
bad_arch = etree.XML("<form><group><field name='test'/></group></form>")
188+
with self.assertLogs(
189+
"odoo.addons.server_environment_data_encryption.models.server_env_mixin",
190+
level="ERROR",
191+
) as cm:
192+
mixin_obj._update_form_view_from_env(bad_arch, "form")
193+
self.assertTrue(
194+
any("Missing sheet for form view" in output for output in cm.output)
195+
)
196+
197+
def test_set_readonly_form_view_skip_existing(self):
198+
"""Test that _set_readonly_form_view skips fields already
199+
in _server_env_fields"""
200+
mixin_obj = self.env["res.partner"] # This one has 'city' in _server_env_fields
201+
arch = etree.XML(
202+
"<form><sheet><field name='city'/><field name='name'/></sheet></form>"
203+
)
204+
mixin_obj._set_readonly_form_view(arch, "test", ["test"])
205+
206+
city_field = arch.find(".//field[@name='city']")
207+
name_field = arch.find(".//field[@name='name']")
208+
209+
# city should NOT have readonly added by
210+
# this method specifically (it's handled differently or skipped)
211+
self.assertNotIn(
212+
"context.get(\"environment\", 'test') != 'test'",
213+
city_field.get("readonly", ""),
214+
)
215+
# name SHOULD have it
216+
self.assertIn(
217+
"context.get(\"environment\", 'test') != 'test'",
218+
name_field.get("readonly", ""),
219+
)
220+
221+
def test_inverse_server_env_not_editable(self):
222+
"""Test _inverse_server_env when field is not editable"""
223+
with patch.object(
224+
type(self.partner),
225+
"_server_env_is_editable_fieldname",
226+
return_value="is_company",
227+
):
228+
self.partner.is_company = False
229+
# This should skip the loop body
230+
self.partner._inverse_server_env("city")
231+
232+
def test_get_view_integration(self):
233+
"""Test integration via _get_view"""
234+
arch_res, view = self.env["res.partner"]._get_view(view_type="form")
235+
# Check if our extra div was inserted
236+
self.assertTrue(
237+
any(
238+
"action_change_env_data_encrypted_fields"
239+
in etree.tostring(node, encoding="unicode")
240+
for node in arch_res.xpath("//button")
241+
)
242+
)

0 commit comments

Comments
 (0)