177 lines
9.9 KiB
Python
177 lines
9.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from typing import NamedTuple, Iterable
|
|
try:
|
|
import phonenumbers
|
|
except ImportError:
|
|
phonenumbers = None
|
|
|
|
from odoo.tests.common import BaseCase
|
|
|
|
class TestPhonenumbersPatch(BaseCase):
|
|
|
|
class PhoneInputOutputLine(NamedTuple):
|
|
""" Datastructure to store data for phone number parsing tests. Consist of single set of:
|
|
- input phone data to be parsed
|
|
- (optionally) ground-truths, i.e expected results
|
|
|
|
Input phone data can be one of the following:
|
|
- international phone number like: "+23057654321"
|
|
- national phone number + region code, like: "57654321" + "MU"
|
|
|
|
:param number: The input phone number to be parsed.
|
|
:param region: (optional) The two-letter ISO country code, used when parsing national number without country prefix eg. "SN"
|
|
:param gt_national_number: (optional) ground-truth to compare parsed national number with
|
|
:param gt_country_code: (optional) ground-truth to compare country calling code eg. 221
|
|
:param gt_italian_leading_zero: (optional) ground-truth for italian_leading_zero, True if expected to find 1 leading zero after parsing
|
|
:param gt_number_of_leading_zeros: (optional) ground-truth to compare number_of_leading_zeros to code, Set if expected more then one leading zero
|
|
|
|
┌────────┐
|
|
INPUT ─►│ PARSER ├─► OUTPUT (EXPECTED ground-truth)
|
|
└────────┘ compare
|
|
number number ◄───────► (number)
|
|
(region) code (code)
|
|
|
|
Placeholders in parenthesis () are optional, why are they optional? The idea is that in the most basic parse check
|
|
we would only parse number and check if it's valid (according to implicit phonenumbers implementation). However, we
|
|
might want to perform additional validation on the parsed number, then we'd use optional expected fields that should
|
|
trigger additional checks.
|
|
"""
|
|
number: str
|
|
region: str = ""
|
|
gt_national_number: int = None
|
|
gt_country_code: int = None
|
|
gt_italian_leading_zero: bool = None
|
|
gt_number_of_leading_zeros: int = None
|
|
|
|
def _assert_parsing_phonenumbers(self, parse_test_lines: Iterable[PhoneInputOutputLine]):
|
|
""" Iterates over test_lines, performs asserts according to what data each test_line contains.
|
|
Simple cases:
|
|
1. test_line contains only the international number -> check if phonenumbers can parse it
|
|
2. test_line contains national number and country code -> check if phonenumbers can parse it
|
|
Presence of expected data:
|
|
In case test line contains some ground-truth this function will compare parsed data against the ground truths.
|
|
|
|
:param parse_test_lines: An iterable consisting of PhoneInputOutputLine
|
|
"""
|
|
if not phonenumbers:
|
|
self.skipTest('Cannot test parsing without phonenumbers module installed.')
|
|
|
|
for parse_test_line in parse_test_lines:
|
|
with self.subTest(**parse_test_line._asdict()):
|
|
parsed_phone = phonenumbers.parse(parse_test_line.number, region=parse_test_line.region)
|
|
self.assertTrue(phonenumbers.is_valid_number(parsed_phone),
|
|
"Phone number does not match any patterns in the metadata.")
|
|
if parse_test_line.gt_national_number:
|
|
self.assertEqual(parsed_phone.national_number, parse_test_line.gt_national_number,
|
|
"Parsed national number differs from expected national number")
|
|
if parse_test_line.gt_country_code:
|
|
self.assertEqual(parsed_phone.country_code, parse_test_line.gt_country_code,
|
|
"Parsed country code number differs from expected country code")
|
|
if parse_test_line.gt_italian_leading_zero:
|
|
self.assertEqual(parsed_phone.italian_leading_zero, parse_test_line.gt_italian_leading_zero,
|
|
"Parsed country code number differs from expected country code")
|
|
if parse_test_line.gt_number_of_leading_zeros:
|
|
self.assertEqual(parsed_phone.number_of_leading_zeros, parse_test_line.gt_number_of_leading_zeros,
|
|
"Parsed country code number differs from expected country code")
|
|
|
|
def test_region_BR_monkey_patch(self):
|
|
""" Test Brazil phone numbers patch for added 9 in mobile numbers
|
|
It should not be added for fixed lines numbers"""
|
|
if not phonenumbers:
|
|
self.skipTest('Cannot test without phonenumbers module installed.')
|
|
|
|
# Mobile number => 9 should be added
|
|
parsed = phonenumbers.parse('11 6123 4567', region="BR")
|
|
formatted = phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
|
|
self.assertEqual(formatted, '+55 11 96123-4567')
|
|
|
|
# Fixed line => 9 should not be added
|
|
parsed = phonenumbers.parse('11 2345 6789', region="BR")
|
|
formatted = phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
|
|
self.assertEqual(formatted, '+55 11 2345-6789')
|
|
|
|
def test_region_CI_monkey_patch(self):
|
|
"""Makes sure that patch for Ivory Coast phone numbers work"""
|
|
parse_test_lines_CI = (
|
|
self.PhoneInputOutputLine("+2250506007995"),
|
|
self.PhoneInputOutputLine("0506007995", region='CI', gt_national_number=506007995, gt_country_code=225, gt_italian_leading_zero=True),
|
|
self.PhoneInputOutputLine("+225 05 20 963 777", gt_national_number=520963777, gt_country_code=225, gt_italian_leading_zero=True),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_CI)
|
|
|
|
def test_region_CO_monkey_patch(self):
|
|
"""Makes sure that patch for Colombian phone numbers work"""
|
|
parse_test_lines_CO = (
|
|
self.PhoneInputOutputLine("3241234567", "CO"),
|
|
self.PhoneInputOutputLine("+57 324 1234567"),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_CO)
|
|
|
|
def test_region_IL_monkey_patch(self):
|
|
""" Makes sure that patch for Israeli phone numbers work
|
|
Example of wrong phone number: +972 55 731 1234
|
|
"""
|
|
parse_test_lines_IL = (
|
|
self.PhoneInputOutputLine("055 294 1234", "IL"),
|
|
self.PhoneInputOutputLine("+972 55 295 1235"),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_IL)
|
|
|
|
def test_region_MA_monkey_patch(self):
|
|
"""Makes sure that patch for Morocco phone numbers work"""
|
|
parse_test_lines_MA = (
|
|
self.PhoneInputOutputLine("+212 6 23 24 56 28"),
|
|
self.PhoneInputOutputLine("+212603190852"),
|
|
self.PhoneInputOutputLine("+212780137429"),
|
|
self.PhoneInputOutputLine("+212546547649"),
|
|
self.PhoneInputOutputLine("+212690979618"),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_MA)
|
|
|
|
def test_region_MU_monkey_patch(self):
|
|
"""Makes sure that patch for Mauritius phone numbers work"""
|
|
gt_MU_number = 57654321 # what national number we expect after parsing
|
|
gt_MU_code = 230 # what country code we expect after parsing
|
|
parse_test_lines_MU = (
|
|
self.PhoneInputOutputLine("+23057654321", gt_national_number=gt_MU_number, gt_country_code=gt_MU_code),
|
|
self.PhoneInputOutputLine("+2305 76/54 3-21 ", gt_national_number=gt_MU_number, gt_country_code=gt_MU_code),
|
|
self.PhoneInputOutputLine("57654321", region="MU", gt_national_number=gt_MU_number, gt_country_code=gt_MU_code),
|
|
self.PhoneInputOutputLine("5 76/54 3-21 ", region="MU", gt_national_number=gt_MU_number, gt_country_code=gt_MU_code),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_MU)
|
|
|
|
def test_region_KE_monkey_patch(self):
|
|
"""Makes sure that patch for kenyan phone numbers work"""
|
|
gt_KE_number = 711123456 # what national number we expect after parsing
|
|
gt_KE_code = 254 # what country code we expect after parsing
|
|
|
|
parse_test_lines_KE = (
|
|
self.PhoneInputOutputLine("+254711123456", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("+254 711 123 456", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("+254-711-123-456", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("+254 711/123/456", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("0711123456", region="KE", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("0711 123 456", region="KE", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("0711-123-456", region="KE", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
self.PhoneInputOutputLine("0711/123/456", region="KE", gt_national_number=gt_KE_number, gt_country_code=gt_KE_code),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_KE)
|
|
|
|
def test_region_PA_monkey_patch(self):
|
|
"""Makes sure that patch for Panama's phone numbers work"""
|
|
parse_test_lines_PA = (
|
|
self.PhoneInputOutputLine("6198 5462", "PA", gt_country_code=507),
|
|
self.PhoneInputOutputLine("+507 833 8744", gt_national_number=8338744),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_PA)
|
|
|
|
def test_region_SN_monkey_patch(self):
|
|
"""Makes sure that patch for Senegalese phone numbers work"""
|
|
parse_test_lines_SN = (
|
|
self.PhoneInputOutputLine("+221750142092"),
|
|
self.PhoneInputOutputLine("+22176 707 0065"),
|
|
)
|
|
self._assert_parsing_phonenumbers(parse_test_lines_SN)
|