Files
notifications-api/tests/notifications_utils/test_postal_address.py
2024-05-17 17:14:46 -04:00

778 lines
17 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import pytest
from notifications_utils.countries import Country
from notifications_utils.countries.data import Postage
from notifications_utils.insensitive_dict import InsensitiveDict
from notifications_utils.postal_address import (
PostalAddress,
format_postcode_for_printing,
is_a_real_uk_postcode,
normalise_postcode,
)
def test_raw_address():
raw_address = "a\n\n\tb\r c "
assert PostalAddress(raw_address).raw_address == raw_address
@pytest.mark.parametrize(
("address", "expected_country"),
[
(
"""
123 Example Street
City of Town
SW1A 1AA
""",
Country("United Kingdom"),
),
(
"""
123 Example Street
City of Town
SW1A 1AA
United Kingdom
""",
Country("United Kingdom"),
),
(
"""
123 Example Street
City of Town
Wales
""",
Country("United Kingdom"),
),
(
"""
123 Example Straße
Deutschland
""",
Country("Germany"),
),
],
)
def test_country(address, expected_country):
assert PostalAddress(address).country == expected_country
@pytest.mark.parametrize(
("address", "enough_lines_expected"),
[
(
"",
False,
),
(
"""
123 Example Street
City of Town
SW1A 1AA
""",
True,
),
(
"""
123 Example Street
City of Town
United Kingdom
""",
False,
),
(
"""
123 Example Street
City of Town
""",
False,
),
(
"""
1
2
3
4
5
6
7
8
""",
True,
),
],
)
def test_has_enough_lines(address, enough_lines_expected):
assert PostalAddress(address).has_enough_lines is enough_lines_expected
@pytest.mark.parametrize(
("address", "too_many_lines_expected"),
[
(
"",
False,
),
(
"""
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
""",
False,
),
(
"""
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
""",
False,
),
(
"""
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Scotland
""",
False,
),
(
"""
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
""",
True,
),
],
)
def test_has_too_many_lines(address, too_many_lines_expected):
assert PostalAddress(address).has_too_many_lines is too_many_lines_expected
@pytest.mark.parametrize(
("address", "expected_postcode"),
[
(
"",
None,
),
(
"""
123 Example Street
City of Town
SW1A 1AA
""",
"SW1A 1AA",
),
(
"""
123 Example Street
City of Town
S W1 A 1 AA
""",
"SW1A 1AA",
),
(
"""
123 Example Straße
Deutschland
""",
None,
),
(
"""
123 Example Straße
SW1A 1AA
Deutschland
""",
None,
),
],
)
def test_postcode(address, expected_postcode):
assert PostalAddress(address).has_valid_postcode is bool(expected_postcode)
assert PostalAddress(address).postcode == expected_postcode
@pytest.mark.parametrize(
("address", "expected_result"),
[
(
"",
False,
),
(
"""
1[23 Example Street)
C@ity of Town
SW1A 1AA
""",
False,
),
(
"""
[123 Example Street
(ity of Town
]S W1 A 1 AA
""",
True,
),
(
r"""
123 Example Straße
SW1A 1AA
\Deutschland
""",
True,
),
(
r"""
>123 Example Straße
SW1A 1AA
Deutschland
""",
True,
),
(
"""
~123 Example Street
City of Town
SW1 A 1 AA
""",
True,
),
],
)
def test_has_invalid_characters(address, expected_result):
assert PostalAddress(address).has_invalid_characters is expected_result
@pytest.mark.parametrize(
("address", "expected_international"),
[
(
"",
False,
),
(
"""
123 Example Street
City of Town
SW1A 1AA
""",
False,
),
(
"""
123 Example Street
City of Town
United Kingdom
""",
False,
),
(
"""
123 Example Street
City of Town
Guernsey
""",
False,
),
(
"""
123 Example Straße
Deutschland
""",
True,
),
],
)
def test_international(address, expected_international):
assert PostalAddress(address).international is expected_international
@pytest.mark.parametrize(
("address", "expected_normalised", "expected_as_single_line"),
[
(
"",
"",
"",
),
(
"""
123 Example St .
City of Town
S W1 A 1 AA
""",
("123 Example St.\n" "City of Town\n" "SW1A 1AA"),
("123 Example St., City of Town, SW1A 1AA"),
),
(
(
"123 Example St. \t , \n"
", , , , , , ,\n"
"City of Town, Region,\n"
"SW1A 1AA,,\n"
),
("123 Example St.\n" "City of Town, Region\n" "SW1A 1AA"),
("123 Example St., City of Town, Region, SW1A 1AA"),
),
(
"""
123 Example Straße
Deutschland
""",
("123 Example Straße\n" "Germany"),
("123 Example Straße, Germany"),
),
],
)
def test_normalised(address, expected_normalised, expected_as_single_line):
assert PostalAddress(address).normalised == expected_normalised
assert PostalAddress(address).as_single_line == expected_as_single_line
@pytest.mark.parametrize(
("address", "expected_postage"),
[
(
"",
Postage.UK,
),
(
"""
123 Example Street
City of Town
SW1A 1AA
""",
Postage.UK,
),
(
"""
123 Example Street
City of Town
Scotland
""",
Postage.UK,
),
(
"""
123 Example Straße
Deutschland
""",
Postage.EUROPE,
),
(
"""
123 Rue Example
Côte d'Ivoire
""",
Postage.REST_OF_WORLD,
),
],
)
def test_postage(address, expected_postage):
assert PostalAddress(address).postage == expected_postage
@pytest.mark.parametrize(
"personalisation",
[
{
"address_line_1": "123 Example Street",
"address_line_3": "City of Town",
"address_line_4": "",
"postcode": "SW1A1AA",
"ignore me": "ignore me",
},
{
"address_line_1": "123 Example Street",
"address_line_3": "City of Town",
"address_line_4": "SW1A1AA",
},
{
"address_line_2": "123 Example Street",
"address_line_5": "City of Town",
"address_line_7": "SW1A1AA",
},
{
"address_line_1": "123 Example Street",
"address_line_3": "City of Town",
"address_line_7": "SW1A1AA",
"postcode": "ignored if address line 7 provided",
},
InsensitiveDict(
{
"address line 1": "123 Example Street",
"ADDRESS_LINE_2": "City of Town",
"Address-Line-7": "Sw1a 1aa",
}
),
],
)
def test_from_personalisation(personalisation):
assert PostalAddress.from_personalisation(personalisation).normalised == (
"123 Example Street\n" "City of Town\n" "SW1A 1AA"
)
def test_from_personalisation_handles_int():
personalisation = {
"address_line_1": 123,
"address_line_2": "Example Street",
"address_line_3": "City of Town",
"address_line_4": "SW1A1AA",
}
assert PostalAddress.from_personalisation(personalisation).normalised == (
"123\n" "Example Street\n" "City of Town\n" "SW1A 1AA"
)
@pytest.mark.parametrize(
("address", "expected_personalisation"),
[
(
"",
{
"address_line_1": "",
"address_line_2": "",
"address_line_3": "",
"address_line_4": "",
"address_line_5": "",
"address_line_6": "",
"address_line_7": "",
"postcode": "",
},
),
(
"""
123 Example Street
City of Town
SW1A1AA
""",
{
"address_line_1": "123 Example Street",
"address_line_2": "City of Town",
"address_line_3": "",
"address_line_4": "",
"address_line_5": "",
"address_line_6": "",
"address_line_7": "SW1A 1AA",
"postcode": "SW1A 1AA",
},
),
(
"""
One
Two
Three
Four
Five
Six
Seven
Eight
""",
{
"address_line_1": "One",
"address_line_2": "Two",
"address_line_3": "Three",
"address_line_4": "Four",
"address_line_5": "Five",
"address_line_6": "Six",
"address_line_7": "Eight",
"postcode": "Eight",
},
),
],
)
def test_as_personalisation(address, expected_personalisation):
assert PostalAddress(address).as_personalisation == expected_personalisation
@pytest.mark.parametrize(
("address", "expected_bool"),
[
("", False),
(" ", False),
("\n\n \n", False),
("a", True),
],
)
def test_bool(address, expected_bool):
assert bool(PostalAddress(address)) is expected_bool
@pytest.mark.parametrize(
("postcode", "normalised_postcode"),
[
("SW1 3EF", "SW13EF"),
("SW13EF", "SW13EF"),
("sw13ef", "SW13EF"),
("Sw13ef", "SW13EF"),
("sw1 3ef", "SW13EF"),
(" SW1 3EF ", "SW13EF"),
],
)
def test_normalise_postcode(postcode, normalised_postcode):
assert normalise_postcode(postcode) == normalised_postcode
@pytest.mark.parametrize(
("postcode", "result"),
[
# real standard UK poscodes
("SW1 3EF", True),
("SW13EF", True),
("SE1 63EF", True),
("N5 1AA", True),
("SO14 6WB", True),
("so14 6wb", True),
("so14\u00A06wb", True),
# invalida / incomplete postcodes
("N5", False),
("SO144 6WB", False),
("SO14 6WBA", False),
("", False),
("Bad postcode", False),
# valid British Forces postcodes
("BFPO1234", True),
("BFPO C/O 1234", True),
("BFPO 1234", True),
("BFPO1", True),
# invalid British Forces postcodes
("BFPO", False),
("BFPO12345", False),
# Giro Bank valid postcode and invalid postcode
("GIR0AA", True),
("GIR0AB", False),
],
)
def test_if_postcode_is_a_real_uk_postcode(postcode, result):
assert is_a_real_uk_postcode(postcode) is result
def test_if_postcode_is_a_real_uk_postcode_normalises_before_checking_postcode(mocker):
normalise_postcode_mock = mocker.patch(
"notifications_utils.postal_address.normalise_postcode"
)
normalise_postcode_mock.return_value = "SW11AA"
assert is_a_real_uk_postcode("sw1 1aa") is True
@pytest.mark.parametrize(
("postcode", "postcode_with_space"),
[
("SW13EF", "SW1 3EF"),
("SW1 3EF", "SW1 3EF"),
("N5 3EF", "N5 3EF"),
("N5 3EF", "N5 3EF"),
("N53EF ", "N5 3EF"),
("n53Ef", "N5 3EF"),
("n5 \u00A0 \t 3Ef", "N5 3EF"),
("SO146WB", "SO14 6WB"),
("BFPO2", "BFPO 2"),
("BFPO232", "BFPO 232"),
("BFPO 2432", "BFPO 2432"),
("BFPO C/O 2", "BFPO C/O 2"),
("BFPO c/o 232", "BFPO C/O 232"),
("GIR0AA", "GIR 0AA"),
],
)
def test_format_postcode_for_printing(postcode, postcode_with_space):
assert format_postcode_for_printing(postcode) == postcode_with_space
@pytest.mark.parametrize(
("address", "international", "expected_valid"),
[
(
"""
UK address
Service cant send internationally
SW1A 1AA
""",
False,
True,
),
(
"""
UK address
Service can send internationally
SW1A 1AA
""",
True,
True,
),
(
"""
Overseas address
Service cant send internationally
Guinea-Bissau
""",
False,
False,
),
(
"""
Overseas address
Service can send internationally
Guinea-Bissau
""",
True,
True,
),
(
"""
Overly long address
2
3
4
5
6
7
8
""",
True,
False,
),
(
"""
Address too short
2
""",
True,
False,
),
(
"""
No postcode or country
Service cant send internationally
3
""",
False,
False,
),
(
"""
No postcode or country
Service can send internationally
3
""",
True,
False,
),
(
"""
Postcode and country
Service cant send internationally
SW1 1AA
France
""",
False,
False,
),
],
)
def test_valid_with_international_parameter(address, international, expected_valid):
postal_address = PostalAddress(
address,
allow_international_letters=international,
)
assert postal_address.valid is expected_valid
assert postal_address.has_valid_last_line is expected_valid
@pytest.mark.parametrize(
"address",
[
"""
Too short, valid postcode
SW1A 1AA
""",
"""
Too short, valid country
Bhutan
""",
"""
Too long, valid postcode
2
3
4
5
6
7
SW1A 1AA
""",
"""
Too long, valid country
2
3
4
5
6
7
Bhutan
""",
],
)
def test_valid_last_line_too_short_too_long(address):
postal_address = PostalAddress(address, allow_international_letters=True)
assert postal_address.valid is False
assert postal_address.has_valid_last_line is True
def test_valid_with_invalid_characters():
address = "Valid\nExcept\n[For one character\nBhutan\n"
assert PostalAddress(address, allow_international_letters=True).valid is False
@pytest.mark.parametrize(
("international", "expected_valid"),
[
(False, False),
(True, True),
],
)
def test_valid_from_personalisation_with_international_parameter(
international, expected_valid
):
assert (
PostalAddress.from_personalisation(
{"address_line_1": "A", "address_line_2": "B", "address_line_3": "Chad"},
allow_international_letters=international,
).valid
is expected_valid
)