From 192b85fc566cd7160e6c9855461d72d4150b04c8 Mon Sep 17 00:00:00 2001 From: meawong Date: Tue, 10 Mar 2026 14:21:01 -0700 Subject: [PATCH 1/8] 31783 - Update common postal code validation and unit tests --- .../filings/validations/common_validations.py | 12 ++++++++++ .../validations/test_common_validations.py | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/legal-api/src/legal_api/services/filings/validations/common_validations.py b/legal-api/src/legal_api/services/filings/validations/common_validations.py index 69f86bf786..4a7886c6f5 100644 --- a/legal-api/src/legal_api/services/filings/validations/common_validations.py +++ b/legal-api/src/legal_api/services/filings/validations/common_validations.py @@ -52,6 +52,8 @@ "postalCode", ) +CANADIAN_POSTAL_CODE_REGEX = re.compile(r"^[A-Z]\d[A-Z]\s?\d[A-Z]\d$") + PARTY_NAME_MAX_LENGTH = 30 # Share structure constants @@ -798,6 +800,16 @@ 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: + normalized = postal_code.strip().upper() + + if not CANADIAN_POSTAL_CODE_REGEX.match(normalized): + 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 diff --git a/legal-api/tests/unit/services/filings/validations/test_common_validations.py b/legal-api/tests/unit/services/filings/validations/test_common_validations.py index abb05b1c3a..c24a49891a 100644 --- a/legal-api/tests/unit/services/filings/validations/test_common_validations.py +++ b/legal-api/tests/unit/services/filings/validations/test_common_validations.py @@ -84,6 +84,30 @@ 'addressRegion': '' } +VALID_CA_POSTAL_NO_SPACE = { + 'streetAddress': 'Valid street', + 'addressCity': 'Victoria', + 'addressRegion': 'BC', + 'postalCode': 'V8V2A4', + 'addressCountry': 'CA' +} + +INVALID_CA_POSTAL_FORMAT = { + 'streetAddress': 'Valid street', + 'addressCity': 'Victoria', + 'addressRegion': 'BC', + 'postalCode': '12345', + 'addressCountry': 'CA' +} + +INVALID_CA_POSTAL_SPECIAL = { + 'streetAddress': 'Valid street', + 'addressCity': 'Victoria', + 'addressRegion': 'BC', + 'postalCode': 'V8V-2A4', + 'addressCountry': 'CA' +} + INVALID_ADDRESS_WHITESPACE = { 'streetAddress': ' 123 Main St ', 'streetAddressAdditional': ' Suite 200 ', From 38c39cee2947a5d2f44a0bcce64e7a193209800a Mon Sep 17 00:00:00 2001 From: meawong Date: Tue, 10 Mar 2026 16:47:15 -0700 Subject: [PATCH 2/8] 31793 - Update regex pattern and unit tests --- .../filings/validations/common_validations.py | 20 ++-- .../test_validation_basic.py | 29 ------ .../validations/test_common_validations.py | 98 ++++++++++++++----- .../test_incorporation_application.py | 29 ------ 4 files changed, 83 insertions(+), 93 deletions(-) diff --git a/legal-api/src/legal_api/services/filings/validations/common_validations.py b/legal-api/src/legal_api/services/filings/validations/common_validations.py index 4a7886c6f5..fd58664e07 100644 --- a/legal-api/src/legal_api/services/filings/validations/common_validations.py +++ b/legal-api/src/legal_api/services/filings/validations/common_validations.py @@ -52,7 +52,10 @@ "postalCode", ) -CANADIAN_POSTAL_CODE_REGEX = re.compile(r"^[A-Z]\d[A-Z]\s?\d[A-Z]\d$") +CANADIAN_POSTAL_CODE_REGEX = re.compile( + r"^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z]\s?\d[ABCEGHJ-NPRSTV-Z]\d$", + re.IGNORECASE +) PARTY_NAME_MAX_LENGTH = 30 @@ -791,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: @@ -802,14 +805,11 @@ def _validate_postal_code( "path": f"{address_path}/postalCode"} # Canadian postal code format validation - if country == "CA" and postal_code: - normalized = postal_code.strip().upper() - - if not CANADIAN_POSTAL_CODE_REGEX.match(normalized): - return { - "error": _("Postal code must follow Canadian format A1A 1A1."), - "path": f"{address_path}/postalCode" - } + 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 diff --git a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py index e78fe2cbad..9b2763a9df 100644 --- a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py +++ b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py @@ -206,15 +206,6 @@ def test_validate_cod_basic(session, test_name, now, 'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/addressCountry'} ] ), - ( - 'FAIL - deliveryAddress postalCode with leading/trailing whitespace', - {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": " V8W1C2 "}, - {"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'} - ] - ), ( 'FAIL - mailingAddress streetAddress with leading/trailing whitespace', {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V8W1C2"}, @@ -242,26 +233,6 @@ def test_validate_cod_basic(session, test_name, now, 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/addressCountry'} ] ), - ( - 'FAIL - mailingAddress postalCode with leading/trailing whitespace', - {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V8W1C2"}, - {"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'} - ] - ), - ( - 'FAIL - multiple fields with leading/trailing whitespace', - {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": " V8W1C2 "}, - {"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'}, - {'error': 'postalCode cannot start or end with whitespace.', - 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'} - ] - ), ] ) def test_validate_whitespace_cod_address_fields(session, test_name, diff --git a/legal-api/tests/unit/services/filings/validations/test_common_validations.py b/legal-api/tests/unit/services/filings/validations/test_common_validations.py index c24a49891a..f14eb954ad 100644 --- a/legal-api/tests/unit/services/filings/validations/test_common_validations.py +++ b/legal-api/tests/unit/services/filings/validations/test_common_validations.py @@ -84,30 +84,6 @@ 'addressRegion': '' } -VALID_CA_POSTAL_NO_SPACE = { - 'streetAddress': 'Valid street', - 'addressCity': 'Victoria', - 'addressRegion': 'BC', - 'postalCode': 'V8V2A4', - 'addressCountry': 'CA' -} - -INVALID_CA_POSTAL_FORMAT = { - 'streetAddress': 'Valid street', - 'addressCity': 'Victoria', - 'addressRegion': 'BC', - 'postalCode': '12345', - 'addressCountry': 'CA' -} - -INVALID_CA_POSTAL_SPECIAL = { - 'streetAddress': 'Valid street', - 'addressCity': 'Victoria', - 'addressRegion': 'BC', - 'postalCode': 'V8V-2A4', - 'addressCountry': 'CA' -} - INVALID_ADDRESS_WHITESPACE = { 'streetAddress': ' 123 Main St ', 'streetAddressAdditional': ' Suite 200 ', @@ -280,7 +256,79 @@ 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', [ + ('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 + ('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'), diff --git a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py index ab2faab707..689e0a9a5b 100644 --- a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py @@ -327,15 +327,6 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega 'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/addressCountry'} ] ), - ( - 'FAIL - deliveryAddress postalCode with leading/trailing whitespace', - {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": " V8W1C2 "}, - {"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'} - ] - ), ( 'FAIL - mailingAddress streetAddress with leading/trailing whitespace', {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": "V8W1C2"}, @@ -363,26 +354,6 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega 'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/addressCountry'} ] ), - ( - 'FAIL - mailingAddress postalCode with leading/trailing whitespace', - {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": "V8W1C2"}, - {"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'} - ] - ), - ( - 'FAIL - multiple fields with leading/trailing whitespace', - {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": " V8W1C2 "}, - {"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'}, - {'error': 'postalCode cannot start or end with whitespace.', - 'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'} - ] - ), ] ) def test_validate_incorporation_addresses_whitespace(session, mocker, test_name, delivery_address, mailing_address, From 3f5b01945b18b322b5699fd30a8ff10a44aa2f31 Mon Sep 17 00:00:00 2001 From: meawong Date: Tue, 10 Mar 2026 17:33:57 -0700 Subject: [PATCH 3/8] 31783 - Update unit tests --- .../test_validation_basic.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py index 9b2763a9df..00c6c4de92 100644 --- a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py +++ b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py @@ -206,6 +206,15 @@ def test_validate_cod_basic(session, test_name, now, 'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/addressCountry'} ] ), + ( + 'FAIL - deliveryAddress postalCode with leading/trailing whitespace', + {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + {"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'} + ] + ), ( 'FAIL - mailingAddress streetAddress with leading/trailing whitespace', {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V8W1C2"}, @@ -233,6 +242,26 @@ def test_validate_cod_basic(session, test_name, now, 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/addressCountry'} ] ), + ( + 'FAIL - mailingAddress postalCode with leading/trailing whitespace', + {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V8W1C2"}, + {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + HTTPStatus.BAD_REQUEST, [ + {'error': 'postalCode cannot start or end with whitespace.', + 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'} + ] + ), + ( + 'FAIL - multiple fields with leading/trailing whitespace', + {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + HTTPStatus.BAD_REQUEST, [ + {'error': 'postalCode cannot start or end with whitespace.', + 'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'}, + {'error': 'postalCode cannot start or end with whitespace.', + 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'} + ] + ) ] ) def test_validate_whitespace_cod_address_fields(session, test_name, From 07900f87b55d97bade3093722b69412f0e7d03e4 Mon Sep 17 00:00:00 2001 From: meawong Date: Tue, 10 Mar 2026 17:40:43 -0700 Subject: [PATCH 4/8] 31783 - Update assert statements in test_validate_incorporation_address_whitespace --- .../test_incorporation_application.py | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py index 689e0a9a5b..ea9f62ac2f 100644 --- a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py @@ -327,6 +327,15 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega 'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/addressCountry'} ] ), + ( + 'FAIL - deliveryAddress postalCode with leading/trailing whitespace', + {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": " V8W1C2 "}, + {"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'} + ] + ), ( 'FAIL - mailingAddress streetAddress with leading/trailing whitespace', {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": "V8W1C2"}, @@ -354,6 +363,26 @@ def test_validate_incorporation_addresses_basic(session, mocker, test_name, lega 'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/addressCountry'} ] ), + ( + 'FAIL - mailingAddress postalCode with leading/trailing whitespace', + {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": "V8W1C2"}, + {"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'} + ] + ), + ( + 'FAIL - multiple fields with leading/trailing whitespace', + {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "addressRegion": "BC", "postalCode": " V8W1C2 "}, + {"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'}, + {'error': 'postalCode cannot start or end with whitespace.', + 'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'} + ] + ), ] ) def test_validate_incorporation_addresses_whitespace(session, mocker, test_name, delivery_address, mailing_address, @@ -388,7 +417,8 @@ def test_validate_incorporation_addresses_whitespace(session, mocker, test_name, # validate outcomes if expected_code: assert err.code == expected_code - assert lists_are_equal(err.msg, expected_msg) + actual_errors = [e['error'] for e in err.msg] + assert any(expected_error['error'] in actual_errors for expected_error in expected_msg) else: assert err is None From 87dba514364f54d46fb033563fd71fd5337abdc2 Mon Sep 17 00:00:00 2001 From: meawong Date: Tue, 10 Mar 2026 18:03:38 -0700 Subject: [PATCH 5/8] 31798 - Update COD tests --- .../change_of_director/test_validation_basic.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py index 00c6c4de92..68a8176f00 100644 --- a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py +++ b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py @@ -208,7 +208,7 @@ def test_validate_cod_basic(session, test_name, now, ), ( 'FAIL - deliveryAddress postalCode with leading/trailing whitespace', - {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + {"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "postalCode": " V8W1C2 "}, {"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "postalCode": "V8W1C2"}, HTTPStatus.BAD_REQUEST, [ {'error': 'postalCode cannot start or end with whitespace.', @@ -245,7 +245,7 @@ def test_validate_cod_basic(session, test_name, now, ( 'FAIL - mailingAddress postalCode with leading/trailing whitespace', {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V8W1C2"}, - {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + {"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'} @@ -253,15 +253,15 @@ def test_validate_cod_basic(session, test_name, now, ), ( 'FAIL - multiple fields with leading/trailing whitespace', - {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, - {"streetAddress": "350 Fifth Avenue", "addressCity": "New York", "addressCountry": "US", "postalCode": " 10118 "}, + {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": " V8W1C2 "}, + {"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'}, {'error': 'postalCode cannot start or end with whitespace.', 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'} ] - ) + ), ] ) def test_validate_whitespace_cod_address_fields(session, test_name, @@ -302,6 +302,7 @@ def test_validate_whitespace_cod_address_fields(session, test_name, # validate outcomes if expected_code: assert err.code == expected_code - assert lists_are_equal(err.msg, expected_msg) + actual_errors = [e['error'] for e in err.msg] + assert any(expected_error['error'] in actual_errors for expected_error in expected_msg) else: assert err is None From 2e6cf7d2262727ce9305631e669f2cf8b382ae3b Mon Sep 17 00:00:00 2001 From: meawong Date: Tue, 10 Mar 2026 18:05:04 -0700 Subject: [PATCH 6/8] 31798 - lint fix --- .../validations/change_of_director/test_validation_basic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py index 68a8176f00..fc9259d5ee 100644 --- a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py +++ b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py @@ -208,7 +208,7 @@ def test_validate_cod_basic(session, test_name, now, ), ( 'FAIL - deliveryAddress postalCode with leading/trailing whitespace', - {"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "postalCode": " V8W1C2 "}, + {"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": " V8W1C2 "}, {"streetAddress": "456 B St", "addressCity": "Victoria", "addressCountry": "CA", "postalCode": "V8W1C2"}, HTTPStatus.BAD_REQUEST, [ {'error': 'postalCode cannot start or end with whitespace.', From 1a432d93a3a0e26e207d909e51c45f21405c91c2 Mon Sep 17 00:00:00 2001 From: meawong Date: Thu, 12 Mar 2026 09:04:45 -0700 Subject: [PATCH 7/8] 31783 - Update regex patterns and tests --- .../filings/validations/common_validations.py | 2 +- .../change_of_director/test_validation_basic.py | 13 ++++++++++--- .../validations/test_common_validations.py | 2 ++ .../validations/test_incorporation_application.py | 15 +++++++++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/legal-api/src/legal_api/services/filings/validations/common_validations.py b/legal-api/src/legal_api/services/filings/validations/common_validations.py index fd58664e07..4dc22e28ef 100644 --- a/legal-api/src/legal_api/services/filings/validations/common_validations.py +++ b/legal-api/src/legal_api/services/filings/validations/common_validations.py @@ -53,7 +53,7 @@ ) CANADIAN_POSTAL_CODE_REGEX = re.compile( - r"^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z]\s?\d[ABCEGHJ-NPRSTV-Z]\d$", + r"^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z] ?\d[ABCEGHJ-NPRSTV-Z]\d$", re.IGNORECASE ) diff --git a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py index fc9259d5ee..92d0ab3d13 100644 --- a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py +++ b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py @@ -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'}, ] ), ( @@ -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'} ] ), @@ -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'} ] ), @@ -302,7 +310,6 @@ def test_validate_whitespace_cod_address_fields(session, test_name, # validate outcomes if expected_code: assert err.code == expected_code - actual_errors = [e['error'] for e in err.msg] - assert any(expected_error['error'] in actual_errors for expected_error in expected_msg) + assert lists_are_equal(err.msg, expected_msg) else: assert err is None diff --git a/legal-api/tests/unit/services/filings/validations/test_common_validations.py b/legal-api/tests/unit/services/filings/validations/test_common_validations.py index f14eb954ad..db914081d0 100644 --- a/legal-api/tests/unit/services/filings/validations/test_common_validations.py +++ b/legal-api/tests/unit/services/filings/validations/test_common_validations.py @@ -278,6 +278,8 @@ def test_validate_offices_addresses(session, filing_type, filing_data, office_ty ('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 diff --git a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py index ea9f62ac2f..04345a4176 100644 --- a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py @@ -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'}, ] ), ( @@ -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'}, ] ), ( @@ -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'} ] ), @@ -417,8 +425,7 @@ def test_validate_incorporation_addresses_whitespace(session, mocker, test_name, # validate outcomes if expected_code: assert err.code == expected_code - actual_errors = [e['error'] for e in err.msg] - assert any(expected_error['error'] in actual_errors for expected_error in expected_msg) + assert lists_are_equal(err.msg, expected_msg) else: assert err is None From a69da168dfcce97b0c2c6935c9a5c5364da2d7dc Mon Sep 17 00:00:00 2001 From: meawong Date: Thu, 12 Mar 2026 13:26:17 -0700 Subject: [PATCH 8/8] 31783 - Update validation error message + unit tests to reflect new message --- .../services/filings/validations/common_validations.py | 2 +- .../change_of_director/test_validation_basic.py | 8 ++++---- .../filings/validations/test_common_validations.py | 2 +- .../filings/validations/test_incorporation_application.py | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/legal-api/src/legal_api/services/filings/validations/common_validations.py b/legal-api/src/legal_api/services/filings/validations/common_validations.py index 4dc22e28ef..6d255dbc88 100644 --- a/legal-api/src/legal_api/services/filings/validations/common_validations.py +++ b/legal-api/src/legal_api/services/filings/validations/common_validations.py @@ -807,7 +807,7 @@ def _validate_postal_code( # 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'."), + "error": _("Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'."), "path": f"{address_path}/postalCode" } except LookupError: diff --git a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py index 92d0ab3d13..9f3274725c 100644 --- a/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py +++ b/legal-api/tests/unit/services/filings/validations/change_of_director/test_validation_basic.py @@ -213,7 +213,7 @@ 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'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", 'path': '/filing/changeOfDirectors/directors/0/deliveryAddress/postalCode'}, ] ), @@ -251,7 +251,7 @@ 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/mailingAddress/postalCode'}, - {'error': "Postal code must follow Canadian format 'A1A 1A1'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'} ] ), @@ -262,11 +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'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", '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'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", 'path': '/filing/changeOfDirectors/directors/0/mailingAddress/postalCode'} ] ), diff --git a/legal-api/tests/unit/services/filings/validations/test_common_validations.py b/legal-api/tests/unit/services/filings/validations/test_common_validations.py index db914081d0..7dd8538180 100644 --- a/legal-api/tests/unit/services/filings/validations/test_common_validations.py +++ b/legal-api/tests/unit/services/filings/validations/test_common_validations.py @@ -316,7 +316,7 @@ def test_validate_offices_addresses_canadian_postal_code(session, filing_type, f assert errs == [] else: assert errs - assert errs[0]['error'] == "Postal code must follow Canadian format 'A1A 1A1'." + assert errs[0]['error'] == "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'." assert 'postalCode' in errs[0]['path'] diff --git a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py index 04345a4176..7aaf4e71d7 100644 --- a/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_incorporation_application.py @@ -334,7 +334,7 @@ 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'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", 'path': '/filing/incorporationApplication/offices/registeredOffice/deliveryAddress/postalCode'}, ] ), @@ -372,7 +372,7 @@ 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/mailingAddress/postalCode'}, - {'error': "Postal code must follow Canadian format 'A1A 1A1'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", 'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'}, ] ), @@ -383,11 +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'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", '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'.", + {'error': "Postal code must follow Canadian format, e.g. 'A1A 1A1' or 'A1A1A1'.", 'path': '/filing/incorporationApplication/offices/registeredOffice/mailingAddress/postalCode'} ] ),