Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
"postalCode",
)

CANADIAN_POSTAL_CODE_REGEX = re.compile(
r"^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z] ?\d[ABCEGHJ-NPRSTV-Z]\d$",
re.IGNORECASE
)

PARTY_NAME_MAX_LENGTH = 30

# Share structure constants
Expand Down Expand Up @@ -789,7 +794,7 @@ def _validate_postal_code(
address: dict,
address_path: str
) -> dict:
"""Validate that postal code is optional for specified country."""
"""Validate postal code presence and format for the given country."""
country = address["addressCountry"]
postal_code = address.get("postalCode")
try:
Expand All @@ -798,6 +803,13 @@ def _validate_postal_code(
not postal_code:
return {"error": _("Postal code is required."),
"path": f"{address_path}/postalCode"}

# Canadian postal code format validation
if country == "CA" and postal_code and not CANADIAN_POSTAL_CODE_REGEX.match(postal_code):
return {
"error": _("Postal code must follow Canadian format 'A1A 1A1'."),
"path": f"{address_path}/postalCode"
}
except LookupError:
# Different ISO-2 country validations are done at filing level,
# this can be refactored into a common validator in the future
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ def test_validate_cod_basic(session, test_name, now,
{"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "postalCode": "V8W1C2"},
HTTPStatus.BAD_REQUEST, [
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'}
'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'},
]
),
(
Expand Down Expand Up @@ -248,6 +250,8 @@ def test_validate_cod_basic(session, test_name, now,
{"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "postalCode": " V8W1C2 "},
HTTPStatus.BAD_REQUEST, [
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'}
]
),
Expand All @@ -258,7 +262,11 @@ def test_validate_cod_basic(session, test_name, now,
HTTPStatus.BAD_REQUEST, [
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'},
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'}
]
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,81 @@ def test_validate_offices_addresses(session, filing_type, filing_data, office_ty
error_fields = {e['path'].split('/')[-1] for e in err4}
assert error_fields == set(WHITESPACE_VALIDATED_ADDRESS_FIELDS)



@pytest.mark.parametrize('filing_type, filing_data, office_type', [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, didn't know you could stack parameters like this!

('amaglamationApplication', AMALGAMATION_APPLICATION, 'registeredOffice'),
('changeOfAddress', CHANGE_OF_ADDRESS, 'registeredOffice'),
('changeOfLiquidators', CHANGE_OF_LIQUIDATORS, 'liquidationRecordsOffice'),
('changeOfRegistration', CHANGE_OF_REGISTRATION, 'businessOffice'),
('continuationIn', CONTINUATION_IN, 'registeredOffice'),
('conversion', FIRMS_CONVERSION, 'businessOffice'),
('correction', CORRECTION, 'registeredOffice'),
('incorporationApplication', INCORPORATION, 'registeredOffice'),
('registration', REGISTRATION, 'businessOffice'),
('restoration', RESTORATION, 'registeredOffice')
])
@pytest.mark.parametrize('postal_code, expected_valid', [
# Valid cases
('V6B 1A1', True), # with space
('V6B1A1', True), # without space
('v6b 1a1', True), # lowercase
('v6B1a1', True), # mixed case
('K1N 3H9', True), # different province

# Invalid cases
('V6B\t1A1', False), # tab
('V6B\n1A1', False), # newline
('12345', False), # US zip code
('V6B 1A1', False), # double space
('V6B', False), # too short
('V6B 1A1X', False), # too long
('VV6 1A1', False), # wrong character positions

# Invalid cases with disallowed first letters (D, F, I, O, Q, U, W)
('D6B 1A1', False),
('F6B 1A1', False),
('I6B 1A1', False),
('O6B 1A1', False),
('Q6B 1A1', False),
('U6B 1A1', False),
('W6B 1A1', False),

])
def test_validate_offices_addresses_canadian_postal_code(session, filing_type, filing_data, office_type, postal_code, expected_valid):
"""Test Canadian postal code format validation for office addresses."""
filing = copy.deepcopy(FILING_HEADER)
filing['filing'][filing_type] = copy.deepcopy(filing_data)

address = {
'streetAddress': '123 Main St',
'addressCity': 'Vancouver',
'addressCountry': 'CA',
'postalCode': postal_code,
'addressRegion': 'BC'
}
filing['filing'][filing_type]['offices'][office_type]['deliveryAddress'] = address

errs = validate_offices_addresses(filing, filing_type)

if expected_valid:
assert errs == []
else:
assert errs
assert errs[0]['error'] == "Postal code must follow Canadian format 'A1A 1A1'."
assert 'postalCode' in errs[0]['path']


def test_validate_offices_addresses_non_ca_postal_code_not_validated(session):
"""Test that non-Canadian addresses are not subject to Canadian postal code format validation."""
filing = copy.deepcopy(FILING_HEADER)
filing_type = 'incorporationApplication'
filing['filing'][filing_type] = copy.deepcopy(INCORPORATION)

# A US zip code on a US address should not trigger Canadian format validation
filing['filing'][filing_type]['offices']['registeredOffice']['deliveryAddress'] = VALID_ADDRESS_EX_CA
errs = validate_offices_addresses(filing, filing_type)
assert errs == []


@pytest.mark.parametrize('filing_type, filing_data, party_key', [
('amaglamationApplication', AMALGAMATION_APPLICATION, 'parties'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,9 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega
{"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "addressRegion": "BC", "postalCode": "V8W1C2"},
HTTPStatus.BAD_REQUEST, [
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/postalCode'}
'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/postalCode'},
]
),
(
Expand Down Expand Up @@ -369,7 +371,9 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega
{"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "addressRegion": "BC", "postalCode": " V8W1C2 "},
HTTPStatus.BAD_REQUEST, [
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'}
'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'},
]
),
(
Expand All @@ -379,7 +383,11 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega
HTTPStatus.BAD_REQUEST, [
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/postalCode'},
{'error': 'postalCode cannot start or end with whitespace.',
'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'},
{'error': "Postal code must follow Canadian format 'A1A 1A1'.",
'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'}
]
),
Expand Down