mirror of
https://github.com/GSA/notifications-api.git
synced 2025-12-20 15:31:15 -05:00
778 lines
17 KiB
Python
778 lines
17 KiB
Python
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 can’t send internationally
|
||
SW1A 1AA
|
||
""",
|
||
False,
|
||
True,
|
||
),
|
||
(
|
||
"""
|
||
UK address
|
||
Service can send internationally
|
||
SW1A 1AA
|
||
""",
|
||
True,
|
||
True,
|
||
),
|
||
(
|
||
"""
|
||
Overseas address
|
||
Service can’t 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 can’t send internationally
|
||
3
|
||
""",
|
||
False,
|
||
False,
|
||
),
|
||
(
|
||
"""
|
||
No postcode or country
|
||
Service can send internationally
|
||
3
|
||
""",
|
||
True,
|
||
False,
|
||
),
|
||
(
|
||
"""
|
||
Postcode and country
|
||
Service can’t 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
|
||
)
|