[IMP] partner_phone_country_validation: add tests

This commit is contained in:
Stéphan Sainléger
2026-03-06 10:25:37 +01:00
parent 0c7120cd68
commit 6e776cbe64
2 changed files with 153 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
# Copyright 2024 Elabore (https://elabore.coop)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_partner_phone_country_validation

View File

@@ -0,0 +1,149 @@
# Copyright 2024 Elabore (https://elabore.coop)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.exceptions import ValidationError
from odoo.tests import Form, TransactionCase
class TestPartnerPhoneCountryValidation(TransactionCase):
"""Tests for partner phone country validation module.
Note on testing @api.onchange methods:
--------------------------------------
In Odoo, @api.onchange methods are only triggered by the web UI, not by
direct field assignment in Python code.
- `partner.phone = "xxx"` → triggers write() → validates constraints
BEFORE any onchange can run → fails if constraint not met
- `Form(partner)` → simulates web UI behavior → triggers onchange methods
when field values change → onchange can set country BEFORE save
We use Form() for tests that need onchange behavior (auto-detection of
country from phone prefix), and direct create/write for constraint tests.
"""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.country_fr = cls.env.ref("base.fr")
cls.country_be = cls.env.ref("base.be")
# Set company country to France for default formatting
cls.env.company.country_id = cls.country_fr
def test_normalize_00_to_plus(self):
"""Test conversion of 00xx format to +xx format."""
partner = self.env["res.partner"].create(
{"name": "Test Partner", "country_id": self.country_fr.id}
)
# 00 → + conversion
self.assertEqual(
partner._normalize_phone_number("0033612345678"), "+33612345678"
)
# + numbers unchanged
self.assertEqual(
partner._normalize_phone_number("+33612345678"), "+33612345678"
)
# National numbers unchanged
self.assertEqual(partner._normalize_phone_number("0612345678"), "0612345678")
# Edge cases
self.assertIsNone(partner._normalize_phone_number(None))
self.assertEqual(partner._normalize_phone_number(""), "")
def test_auto_country_detection(self):
"""Test automatic country detection from phone prefix."""
partner = self.env["res.partner"].create({"name": "Test Partner"})
self.assertFalse(partner.country_id)
partner._set_country_from_phone_number("+33612345678")
self.assertEqual(partner.country_id, self.country_fr)
def test_auto_country_detection_does_not_override(self):
"""Test that auto-detection does not override existing country."""
partner = self.env["res.partner"].create(
{"name": "Test Partner", "country_id": self.country_be.id}
)
partner._set_country_from_phone_number("+33612345678")
# Country should remain Belgium
self.assertEqual(partner.country_id, self.country_be)
def test_onchange_phone_full_flow(self):
"""Test complete onchange flow: 00→+ normalization, country detection, formatting.
Use Form to simulate UI behavior where onchange triggers before save.
"""
with Form(self.env["res.partner"]) as partner_form:
partner_form.name = "Test Partner"
partner_form.phone = "0033612345678"
# Onchange should have normalized and detected country
self.assertIn("+33", partner_form.phone)
self.assertEqual(partner_form.country_id, self.country_fr)
def test_onchange_mobile_full_flow(self):
"""Test complete onchange flow for mobile field."""
with Form(self.env["res.partner"]) as partner_form:
partner_form.name = "Test Partner"
partner_form.mobile = "0032475123456"
# Onchange should have normalized and detected country
self.assertIn("+32", partner_form.mobile)
self.assertEqual(partner_form.country_id, self.country_be)
def test_onchange_with_existing_country(self):
"""Test formatting with existing country uses that country."""
with Form(self.env["res.partner"]) as partner_form:
partner_form.name = "Test Partner"
partner_form.country_id = self.country_fr
partner_form.phone = "06 12 34 56 78"
# Should be formatted with French prefix
self.assertIn("+33", partner_form.phone)
def test_constraint_country_required_with_phone(self):
"""Test that country is required when phone/mobile is set."""
with self.assertRaises(ValidationError):
self.env["res.partner"].create(
{"name": "Test Partner", "phone": "0612345678"}
)
with self.assertRaises(ValidationError):
self.env["res.partner"].create(
{"name": "Test Partner", "mobile": "0612345678"}
)
def test_constraint_passes_without_phone(self):
"""Test that partner without phone doesn't require country."""
partner = self.env["res.partner"].create({"name": "Test Partner"})
self.assertTrue(partner.id)
self.assertFalse(partner.country_id)
class TestGetCountryFromPhoneNumber(TransactionCase):
"""Test the utility function for country detection."""
def test_valid_international_number(self):
"""Test detection from valid international number."""
from odoo.addons.partner_phone_country_validation.tools.get_country_from_phone_number import (
get_country_from_phone_number,
)
self.assertEqual(get_country_from_phone_number("+33612345678"), "FR")
def test_invalid_number_returns_false(self):
"""Test that invalid numbers return False."""
from odoo.addons.partner_phone_country_validation.tools.get_country_from_phone_number import (
get_country_from_phone_number,
)
self.assertFalse(get_country_from_phone_number("invalid"))
self.assertFalse(get_country_from_phone_number("0612345678"))
def test_national_number_without_prefix(self):
"""Test handling of national number without international prefix."""
from odoo.addons.partner_phone_country_validation.tools.get_country_from_phone_number import (
get_country_from_phone_number,
)
# National numbers without + cannot be reliably detected
result = get_country_from_phone_number("0612345678")
# phonenumbers cannot determine country without prefix
self.assertFalse(result)