Model/tests/domain/test_postcode.py
Jun-te Kim 23dfb3f899 Add UK-postcode format validity to the Postcode value object 🟩
A pure, offline regex check (no network) so a frozen value object stays pure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 15:24:18 +00:00

74 lines
2.1 KiB
Python

import dataclasses
import pytest
from domain.postcode import Postcode
def test_postcode_uppercases() -> None:
# act / assert
assert Postcode("sw1a1aa").value == "SW1A1AA"
def test_postcode_strips_internal_spaces() -> None:
# act / assert
assert Postcode("sw1a 1aa").value == "SW1A1AA"
def test_postcode_strips_leading_and_trailing_whitespace() -> None:
# act / assert
assert Postcode(" sw1a 1aa ").value == "SW1A1AA"
def test_postcode_strips_tabs_and_newlines() -> None:
# CSV ingestion occasionally introduces stray whitespace characters; the
# canonical form must absorb them just like literal spaces.
# act / assert
assert Postcode("sw1a\t1aa\n").value == "SW1A1AA"
def test_postcode_construction_is_idempotent() -> None:
# arrange
once = Postcode("sw1a 1aa")
# act / assert
assert Postcode(once.value).value == "SW1A1AA"
def test_postcode_empty_string() -> None:
# act / assert
assert Postcode("").value == ""
def test_postcode_str_returns_canonical_value() -> None:
# act / assert
assert str(Postcode("sw1a 1aa")) == "SW1A1AA"
def test_postcode_equality_ignores_surface_form() -> None:
# Differing case / whitespace sanitise to the same canonical value, so
# the value objects compare equal.
# act / assert
assert Postcode("sw1a 1aa") == Postcode("SW1A1AA")
def test_postcode_is_frozen() -> None:
# arrange
postcode = Postcode("SW1A1AA")
# act / assert
with pytest.raises(dataclasses.FrozenInstanceError):
postcode.value = "OTHER" # type: ignore[misc]
@pytest.mark.parametrize(
"raw",
["sw1a 1aa", "M1 1AA", "b33 8th", "cr2 6xh", "dn55 1pt", "ec1a 1bb", "w1a 0ax"],
)
def test_valid_uk_postcode_formats_are_valid(raw: str) -> None:
# act / assert — a pure format check on the canonical value, no network.
assert Postcode(raw).is_valid() is True
@pytest.mark.parametrize("raw", ["", " ", "NONSENSE", "12345", "SW1A 1A", "ZZ"])
def test_malformed_or_empty_postcodes_are_invalid(raw: str) -> None:
# act / assert
assert Postcode(raw).is_valid() is False