Skip to content

Commit b9e4829

Browse files
committed
test(spp_branding_kit): add comprehensive test coverage
- Add tests for post_init_hook and uninstall_hook functions - Add tests for OpenSPPHome controller (debug mode restrictions) - Add tests for OpenSPPBrandingController routes (about, version, telemetry) - Add tests for IrHttp.session_info customization - Add tests for IrModuleModule helper methods (filter, count) - Add tests for ResUsers email signature and account URL - Add edge case tests for modules with no license - Add tests for various paid license format variations This improves test coverage from 68% to target coverage levels
1 parent 91ecfd3 commit b9e4829

File tree

5 files changed

+843
-0
lines changed

5 files changed

+843
-0
lines changed

spp_branding_kit/tests/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
# ABOUTME: Import test cases for spp_branding_kit module
33

44
from . import test_hide_paid_apps
5+
from . import test_init_hooks
6+
from . import test_controllers
7+
from . import test_models
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# ABOUTME: Unit tests for the controllers in spp_branding_kit
2+
# ABOUTME: Tests OpenSPPHome and OpenSPPBrandingController
3+
4+
import json
5+
from unittest.mock import MagicMock, patch
6+
7+
from odoo.tests import TransactionCase, tagged
8+
9+
10+
@tagged("post_install", "-at_install")
11+
class TestOpenSPPHome(TransactionCase):
12+
def setUp(self):
13+
super().setUp()
14+
self.IrConfigParam = self.env["ir.config_parameter"].sudo()
15+
16+
def test_web_client_removes_debug_for_non_admin(self):
17+
"""Test that debug mode is removed for non-admin users"""
18+
from ..controllers.main import OpenSPPHome
19+
20+
# Set debug_admin_only to True
21+
self.IrConfigParam.set_param("openspp.debug_admin_only", "True")
22+
23+
# Create a non-admin user
24+
non_admin_user = self.env["res.users"].create(
25+
{
26+
"name": "Test Non-Admin",
27+
"login": "test_non_admin",
28+
"email": "[email protected]",
29+
}
30+
)
31+
32+
# Mock request
33+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
34+
mock_request.env = self.env.sudo(non_admin_user)
35+
mock_request.session.uid = non_admin_user.id
36+
mock_request.env.user = non_admin_user
37+
mock_request.redirect = MagicMock(return_value="redirect_response")
38+
39+
controller = OpenSPPHome()
40+
41+
# Mock super().web_client
42+
with patch.object(OpenSPPHome.__bases__[0], "web_client", return_value="web_client_response"):
43+
# Test with debug=True for non-admin
44+
result = controller.web_client(debug=True)
45+
46+
# Should redirect without debug
47+
mock_request.redirect.assert_called_once_with("/web", 303)
48+
self.assertEqual(result, "redirect_response")
49+
50+
def test_web_client_allows_debug_for_admin(self):
51+
"""Test that debug mode is allowed for admin users"""
52+
from ..controllers.main import OpenSPPHome
53+
54+
# Set debug_admin_only to True
55+
self.IrConfigParam.set_param("openspp.debug_admin_only", "True")
56+
57+
# Use admin user
58+
admin_user = self.env.ref("base.user_admin")
59+
60+
# Mock request
61+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
62+
mock_request.env = self.env.sudo(admin_user)
63+
mock_request.session.uid = admin_user.id
64+
mock_request.env.user = admin_user
65+
66+
controller = OpenSPPHome()
67+
68+
# Mock super().web_client
69+
with patch.object(OpenSPPHome.__bases__[0], "web_client", return_value="web_client_response") as mock_super:
70+
# Test with debug=True for admin
71+
result = controller.web_client(debug=True)
72+
73+
# Should call super with debug parameter
74+
mock_super.assert_called_once_with(debug=True)
75+
self.assertEqual(result, "web_client_response")
76+
77+
def test_web_client_allows_debug_when_disabled(self):
78+
"""Test that debug mode is allowed for all when debug_admin_only is False"""
79+
from ..controllers.main import OpenSPPHome
80+
81+
# Set debug_admin_only to False
82+
self.IrConfigParam.set_param("openspp.debug_admin_only", "False")
83+
84+
# Create a non-admin user
85+
non_admin_user = self.env["res.users"].create(
86+
{
87+
"name": "Test User",
88+
"login": "test_user",
89+
"email": "[email protected]",
90+
}
91+
)
92+
93+
# Mock request
94+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
95+
mock_request.env = self.env.sudo(non_admin_user)
96+
mock_request.session.uid = non_admin_user.id
97+
mock_request.env.user = non_admin_user
98+
99+
controller = OpenSPPHome()
100+
101+
# Mock super().web_client
102+
with patch.object(OpenSPPHome.__bases__[0], "web_client", return_value="web_client_response") as mock_super:
103+
# Test with debug=True for non-admin
104+
result = controller.web_client(debug=True)
105+
106+
# Should call super with debug parameter
107+
mock_super.assert_called_once_with(debug=True)
108+
self.assertEqual(result, "web_client_response")
109+
110+
def test_web_client_without_debug(self):
111+
"""Test web_client without debug parameter"""
112+
from ..controllers.main import OpenSPPHome
113+
114+
controller = OpenSPPHome()
115+
116+
# Mock super().web_client
117+
with patch.object(OpenSPPHome.__bases__[0], "web_client", return_value="web_client_response") as mock_super:
118+
# Test without debug parameter
119+
result = controller.web_client()
120+
121+
# Should call super without modifications
122+
mock_super.assert_called_once_with()
123+
self.assertEqual(result, "web_client_response")
124+
125+
126+
@tagged("post_install", "-at_install")
127+
class TestOpenSPPBrandingController(TransactionCase):
128+
def setUp(self):
129+
super().setUp()
130+
self.IrConfigParam = self.env["ir.config_parameter"].sudo()
131+
132+
def test_openspp_about_route(self):
133+
"""Test the /openspp/about route"""
134+
from ..controllers.main import OpenSPPBrandingController
135+
136+
# Set custom configuration
137+
self.IrConfigParam.set_param("openspp.system_name", "Test System")
138+
self.IrConfigParam.set_param("openspp.documentation_url", "https://test-docs.org")
139+
self.IrConfigParam.set_param("openspp.support_url", "https://test-support.org")
140+
141+
# Mock request
142+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
143+
mock_request.env = self.env
144+
145+
controller = OpenSPPBrandingController()
146+
result = controller.openspp_about()
147+
148+
# Parse the JSON response
149+
data = json.loads(result)
150+
151+
self.assertEqual(data["title"], "About OpenSPP")
152+
self.assertEqual(data["version"], "1.0.0")
153+
self.assertEqual(data["system_name"], "Test System")
154+
self.assertEqual(data["documentation_url"], "https://test-docs.org")
155+
self.assertEqual(data["support_url"], "https://test-support.org")
156+
157+
def test_openspp_about_route_with_defaults(self):
158+
"""Test the /openspp/about route with default values"""
159+
from ..controllers.main import OpenSPPBrandingController
160+
161+
# Clear any existing parameters
162+
self.IrConfigParam.search([("key", "=like", "openspp.%")]).unlink()
163+
164+
# Mock request
165+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
166+
mock_request.env = self.env
167+
168+
controller = OpenSPPBrandingController()
169+
result = controller.openspp_about()
170+
171+
# Parse the JSON response
172+
data = json.loads(result)
173+
174+
self.assertEqual(data["title"], "About OpenSPP")
175+
self.assertEqual(data["version"], "1.0.0")
176+
self.assertEqual(data["system_name"], "OpenSPP Platform")
177+
self.assertEqual(data["documentation_url"], "https://docs.openspp.org")
178+
self.assertEqual(data["support_url"], "https://openspp.org")
179+
180+
def test_version_info_route(self):
181+
"""Test the /web/webclient/version_info route"""
182+
from ..controllers.main import OpenSPPBrandingController
183+
184+
# Set custom system name
185+
self.IrConfigParam.set_param("openspp.system_name", "Custom OpenSPP")
186+
187+
# Mock request
188+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
189+
mock_request.env = self.env
190+
191+
controller = OpenSPPBrandingController()
192+
result = controller.version_info()
193+
194+
self.assertEqual(result["server_version"], "Custom OpenSPP")
195+
self.assertEqual(result["server_serie"], "1.0")
196+
self.assertEqual(result["protocol_version"], 1)
197+
198+
def test_publisher_warranty_telemetry_enabled(self):
199+
"""Test publisher warranty route when telemetry is enabled"""
200+
from ..controllers.main import OpenSPPBrandingController
201+
202+
# Enable telemetry
203+
self.IrConfigParam.set_param("openspp.telemetry_enabled", "True")
204+
self.IrConfigParam.set_param("openspp.telemetry_endpoint", "https://custom-telemetry.org")
205+
206+
# Mock request
207+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
208+
mock_request.env = self.env
209+
210+
controller = OpenSPPBrandingController()
211+
result = controller.publisher_warranty()
212+
213+
# Parse the JSON response
214+
data = json.loads(result)
215+
216+
self.assertEqual(data["status"], "redirected")
217+
self.assertEqual(data["endpoint"], "https://custom-telemetry.org")
218+
self.assertEqual(data["message"], "Telemetry redirected to OpenSPP")
219+
220+
def test_publisher_warranty_telemetry_disabled(self):
221+
"""Test publisher warranty route when telemetry is disabled"""
222+
from ..controllers.main import OpenSPPBrandingController
223+
224+
# Disable telemetry
225+
self.IrConfigParam.set_param("openspp.telemetry_enabled", "False")
226+
227+
# Mock request
228+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
229+
mock_request.env = self.env
230+
231+
controller = OpenSPPBrandingController()
232+
result = controller.publisher_warranty()
233+
234+
# Parse the JSON response
235+
data = json.loads(result)
236+
237+
self.assertEqual(data["status"], "disabled")
238+
self.assertEqual(data["message"], "Telemetry disabled")
239+
240+
def test_publisher_warranty_with_default_endpoint(self):
241+
"""Test publisher warranty route with default telemetry endpoint"""
242+
from ..controllers.main import OpenSPPBrandingController
243+
244+
# Enable telemetry but don't set custom endpoint
245+
self.IrConfigParam.set_param("openspp.telemetry_enabled", "True")
246+
# Clear telemetry endpoint if exists
247+
param = self.IrConfigParam.search([("key", "=", "openspp.telemetry_endpoint")])
248+
if param:
249+
param.unlink()
250+
251+
# Mock request
252+
with patch("spp_branding_kit.controllers.main.request") as mock_request:
253+
mock_request.env = self.env
254+
255+
controller = OpenSPPBrandingController()
256+
result = controller.publisher_warranty()
257+
258+
# Parse the JSON response
259+
data = json.loads(result)
260+
261+
self.assertEqual(data["status"], "redirected")
262+
self.assertEqual(data["endpoint"], "https://telemetry.openspp.org")
263+
self.assertEqual(data["message"], "Telemetry redirected to OpenSPP")

spp_branding_kit/tests/test_hide_paid_apps.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,64 @@ def test_search_methods_respect_setting(self):
118118
if r.get("license") and (r["license"].startswith("OEEL") or r["license"].startswith("OPL"))
119119
]
120120
self.assertFalse(paid_in_web, "web_search_read should filter paid apps")
121+
122+
def test_edge_cases_with_none_license(self):
123+
"""Test handling of modules with None or empty license"""
124+
# Create module with no license
125+
no_license_module = self.Module.create(
126+
{
127+
"name": "test_no_license",
128+
"shortdesc": "Test No License",
129+
"state": "installed",
130+
"license": False, # No license
131+
"application": True,
132+
}
133+
)
134+
135+
# Enable hiding paid apps
136+
self.IrConfigParam.set_param("openspp.hide_paid_apps", True)
137+
138+
# Search for modules in Apps context
139+
modules = self.Module.with_context(apps_menu=True).search([])
140+
141+
# Module with no license should be visible
142+
self.assertIn(no_license_module, modules, "Modules with no license should be visible")
143+
144+
def test_paid_license_variations(self):
145+
"""Test that different variations of paid licenses are filtered"""
146+
# Create modules with various paid license formats
147+
oeel_variations = [
148+
self.Module.create(
149+
{
150+
"name": f"test_oeel_{i}",
151+
"shortdesc": f"Test OEEL {i}",
152+
"state": "installed",
153+
"license": license,
154+
"application": True,
155+
}
156+
)
157+
for i, license in enumerate(["OEEL-1", "OEEL-2", "OEEL", "OEEL-1.0"])
158+
]
159+
160+
opl_variations = [
161+
self.Module.create(
162+
{
163+
"name": f"test_opl_{i}",
164+
"shortdesc": f"Test OPL {i}",
165+
"state": "installed",
166+
"license": license,
167+
"application": True,
168+
}
169+
)
170+
for i, license in enumerate(["OPL-1", "OPL-2", "OPL", "OPL-1.0"])
171+
]
172+
173+
# Enable hiding paid apps
174+
self.IrConfigParam.set_param("openspp.hide_paid_apps", True)
175+
176+
# Search for modules in Apps context
177+
modules = self.Module.with_context(apps_menu=True).search([])
178+
179+
# All paid license variations should be hidden
180+
for module in oeel_variations + opl_variations:
181+
self.assertNotIn(module, modules, f"Module with license {module.license} should be hidden")

0 commit comments

Comments
 (0)