"""Unit tests for dataloader schema validation. This module contains tests for all dataloader schemas, including validation of vendor UUIDs, access control bypass functionality, and various error conditions.""" import uuid from typing import Any, Dict import pytest from account.validation.schemas.dataloader import ( SkipAccessCheck, VendorClosersRequestSchema, VendorCompanyBrandsDataloaderSchema, VendorFirstStatementPeriodRequestSchema, VendorRelationshipNotesRequestSchema, VendorsDataloader, VendorServiceTierDataloaderSchema, ) @pytest.mark.parametrize( ('payload', 'expected_errors', 'expected_data'), [ pytest.param( {'skip_access_check': True}, {}, {'skip_access_check': True}, id='valid_true_boolean', ), pytest.param( {'skip_access_check': False}, {}, {'skip_access_check': False}, id='valid_false_boolean', ), pytest.param( {'skip_access_check': 1}, {}, {'skip_access_check': True}, id='valid_truthy_integer', ), pytest.param( {'skip_access_check': 0}, {}, {'skip_access_check': False}, id='valid_falsy_integer', ), pytest.param( {}, {}, {'skip_access_check': False}, id='missing_field_uses_default', ), pytest.param( {'skip_access_check': 2}, {'skip_access_check': ['Not a valid boolean.']}, None, id='invalid_other_truthy_integer', ), pytest.param( {'skip_access_check': -1}, {'skip_access_check': ['Not a valid boolean.']}, None, id='invalid_negative_truthy_integer', ), pytest.param( {'skip_access_check': 'true'}, {'skip_access_check': ['Not a valid boolean.']}, None, id='invalid_string_true', ), pytest.param( {'skip_access_check': 'false'}, {'skip_access_check': ['Not a valid boolean.']}, None, id='invalid_string_false', ), pytest.param( {'skip_access_check': None}, {'skip_access_check': ['Field may not be null.']}, None, id='null_value', ), pytest.param( {'skip_access_check': []}, {'skip_access_check': ['Not a valid boolean.']}, None, id='invalid_list_value', ), pytest.param( {'skip_access_check': {}}, {'skip_access_check': ['Not a valid boolean.']}, None, id='invalid_dict_value', ), ], ) def test_skip_access_check_schema( payload: Dict[str, Any], expected_errors: Dict[str, Any], expected_data: Dict[str, Any] ) -> None: """Test SkipAccessCheck schema validation and loading. Tests validation and loading of the skip_access_check field including: - Valid boolean values (True/False) - Truthy/falsy integer values with proper type conversion - Invalid string, null, list, and dict values - Default behavior when field is missing """ schema = SkipAccessCheck() if expected_errors: errors = schema.validate(payload) assert errors == expected_errors else: result = schema.load(payload) assert result == expected_data @pytest.mark.parametrize( ('payload', 'expected_errors'), [ pytest.param( {'vendor_uuids': [str(uuid.uuid4()), str(uuid.uuid4())]}, {}, id='valid_payload', ), pytest.param( {'vendor_uuids': []}, {}, id='empty_list_valid', ), pytest.param( {}, {'vendor_uuids': ['Missing data for required field.']}, id='missing_vendor_uuids', ), pytest.param( {'vendor_uuids': ['invalid-uuid']}, {'vendor_uuids': {0: ['Not a valid UUID.']}}, id='invalid_uuid', ), pytest.param( {'vendor_uuids': None}, {'vendor_uuids': ['Field may not be null.']}, id='null_vendor_uuids', ), ], ) def test_vendors_dataloader_schema( payload: Dict[str, Any], expected_errors: Dict[str, Any] ) -> None: """Test VendorsDataloader base schema validation. Tests the base schema that accepts a list of vendor UUIDs without any additional validation constraints. """ schema = VendorsDataloader() if expected_errors: errors = schema.validate(payload) assert errors == expected_errors else: result = schema.load(payload) assert 'vendor_uuids' in result @pytest.mark.parametrize( ('payload', 'expected_errors'), [ pytest.param( {'skip_access_check': True}, {'vendor_uuids': ['Missing data for required field.']}, id='missing-vendor-uuids-field', ), pytest.param( {}, {'vendor_uuids': ['Missing data for required field.']}, id='missing-all-fields', ), pytest.param( {'vendor_uuids': ['invalid-uuid']}, {'vendor_uuids': {0: ['Not a valid UUID.']}}, id='invalid-uuid-format-single', ), pytest.param( {'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311', 'invalid']}, {'vendor_uuids': {1: ['Not a valid UUID.']}}, id='invalid-uuid-format-in-list', ), pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': 'true', }, {'skip_access_check': ['Not a valid boolean.']}, id='invalid-boolean-string-value', ), pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': 1, }, {}, id='valid-boolean-integer-value', ), pytest.param( {'vendor_uuids': 'not-a-list'}, {'vendor_uuids': ['Not a valid list.']}, id='invalid-vendor-uuids-not-list', ), pytest.param( {'vendor_uuids': None}, {'vendor_uuids': ['Field may not be null.']}, id='invalid-vendor-uuids-null', ), ], ) def test_vendor_company_brands_dataloader_errors( payload: Dict[str, Any], expected_errors: Dict[str, Any] ) -> None: """Test VendorCompanyBrandsDataloaderSchema validation. Tests validation for the /vendors/company_brands/dataloader endpoint, including vendor UUID validation and skip_access_check functionality. """ schema = VendorCompanyBrandsDataloaderSchema() errors = schema.validate(payload) assert errors == expected_errors @pytest.mark.parametrize( ('payload', 'expected_data'), [ pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': True, }, { 'vendor_uuids': [uuid.UUID('79a391d5-85d2-416a-9551-b26faaf09311')], 'skip_access_check': True, }, id='load-with-skip-access-true', ), pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': False, }, { 'vendor_uuids': [uuid.UUID('79a391d5-85d2-416a-9551-b26faaf09311')], 'skip_access_check': False, }, id='load-with-skip-access-false', ), pytest.param( {'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311']}, { 'vendor_uuids': [uuid.UUID('79a391d5-85d2-416a-9551-b26faaf09311')], 'skip_access_check': False, }, id='load-with-default-skip-access', ), pytest.param( {'vendor_uuids': []}, { 'vendor_uuids': [], 'skip_access_check': False, }, id='load-with-empty-uuid-list', ), ], ) def test_vendor_company_brands_dataloader_success( payload: Dict[str, Any], expected_data: Dict[str, Any] ) -> None: """Test VendorCompanyBrandsDataloaderSchema data loading with defaults. Tests that the schema correctly loads data and applies default values for skip_access_check when not provided. """ schema = VendorCompanyBrandsDataloaderSchema() data = schema.load(payload) assert data == expected_data @pytest.mark.parametrize( ('payload', 'expected_errors'), [ pytest.param( {'skip_access_check': True}, {'vendor_uuids': ['Missing data for required field.']}, id='missing-vendor-uuids-field', ), pytest.param( {}, {'vendor_uuids': ['Missing data for required field.']}, id='missing-all-fields', ), pytest.param( {'vendor_uuids': ['invalid-uuid']}, {'vendor_uuids': {0: ['Not a valid UUID.']}}, id='invalid-uuid-format-single', ), pytest.param( {'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311', 'invalid']}, {'vendor_uuids': {1: ['Not a valid UUID.']}}, id='invalid-uuid-format-in-list', ), pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': 'true', }, {'skip_access_check': ['Not a valid boolean.']}, id='invalid-boolean-string-value', ), pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': 1, }, {}, id='valid-boolean-integer-value', ), pytest.param( {'vendor_uuids': 'not-a-list'}, {'vendor_uuids': ['Not a valid list.']}, id='invalid-vendor-uuids-not-list', ), pytest.param( {'vendor_uuids': None}, {'vendor_uuids': ['Field may not be null.']}, id='invalid-vendor-uuids-null', ), ], ) def test_vendor_service_tier_dataloader_errors( payload: Dict[str, Any], expected_errors: Dict[str, Any] ) -> None: """Test VendorServiceTierDataloaderSchema validation. Tests validation for the /vendors/service_tier/dataloader endpoint, including vendor UUID validation and skip_access_check functionality. """ schema = VendorServiceTierDataloaderSchema() errors = schema.validate(payload) assert errors == expected_errors @pytest.mark.parametrize( ('payload', 'expected_data'), [ pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': True, }, { 'vendor_uuids': [uuid.UUID('79a391d5-85d2-416a-9551-b26faaf09311')], 'skip_access_check': True, }, id='load-with-skip-access-true', ), pytest.param( { 'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311'], 'skip_access_check': False, }, { 'vendor_uuids': [uuid.UUID('79a391d5-85d2-416a-9551-b26faaf09311')], 'skip_access_check': False, }, id='load-with-skip-access-false', ), pytest.param( {'vendor_uuids': ['79a391d5-85d2-416a-9551-b26faaf09311']}, { 'vendor_uuids': [uuid.UUID('79a391d5-85d2-416a-9551-b26faaf09311')], 'skip_access_check': False, }, id='load-with-default-skip-access', ), pytest.param( {'vendor_uuids': []}, { 'vendor_uuids': [], 'skip_access_check': False, }, id='load-with-empty-uuid-list', ), ], ) def test_vendor_service_tier_dataloader_success( payload: Dict[str, Any], expected_data: Dict[str, Any] ) -> None: """Test VendorServiceTierDataloaderSchema data loading with defaults. Tests that the schema correctly loads data and applies default values for skip_access_check when not provided. """ schema = VendorServiceTierDataloaderSchema() data = schema.load(payload) assert data == expected_data @pytest.mark.parametrize( ('payload', 'expected_errors'), [ pytest.param( {'vendor_uuids': [str(uuid.uuid4())]}, {}, id='valid_single_uuid', ), pytest.param( {'vendor_uuids': [str(uuid.uuid4()), str(uuid.uuid4())]}, {}, id='valid_multiple_uuids', ), pytest.param( {'vendor_uuids': []}, {'vendor_uuids': ['Shorter than minimum length 1.']}, id='empty_list_invalid', ), pytest.param( {}, {'vendor_uuids': ['Missing data for required field.']}, id='missing_vendor_uuids', ), pytest.param( {'vendor_uuids': ['invalid-uuid']}, {'vendor_uuids': {0: ['Not a valid UUID.']}}, id='invalid_uuid_format', ), pytest.param( {'vendor_uuids': None}, {'vendor_uuids': ['Field may not be null.']}, id='null_vendor_uuids', ), ], ) def test_vendor_closers_request_schema( payload: Dict[str, Any], expected_errors: Dict[str, Any] ) -> None: """Test VendorClosersRequestSchema validation. Tests validation for vendor closers requests, ensuring at least one vendor UUID is provided in the request. """ schema = VendorClosersRequestSchema() if expected_errors: errors = schema.validate(payload) assert errors == expected_errors else: result = schema.load(payload) assert 'vendor_uuids' in result @pytest.mark.parametrize( ('payload', 'expected_errors'), [ pytest.param( {'vendor_uuids': [str(uuid.uuid4())]}, {}, id='valid_single_uuid', ), pytest.param( {'vendor_uuids': [str(uuid.uuid4()), str(uuid.uuid4())]}, {}, id='valid_multiple_uuids', ), pytest.param( {'vendor_uuids': []}, {'vendor_uuids': ['Shorter than minimum length 1.']}, id='empty_list_invalid', ), pytest.param( {}, {'vendor_uuids': ['Missing data for required field.']}, id='missing_vendor_uuids', ), pytest.param( {'vendor_uuids': ['invalid-uuid']}, {'vendor_uuids': {0: ['Not a valid UUID.']}}, id='invalid_uuid_format', ), pytest.param( {'vendor_uuids': None}, {'vendor_uuids': ['Field may not be null.']}, id='null_vendor_uuids', ), ], ) def test_vendor_first_statement_period_request_schema( payload: Dict[str, Any], expected_errors: Dict[str, Any] ) -> None: """Test VendorFirstStatementPeriodRequestSchema validation. Tests validation for vendor first statement period requests, ensuring at least one vendor UUID is provided in the request. """ schema = VendorFirstStatementPeriodRequestSchema() if expected_errors: errors = schema.validate(payload) assert errors == expected_errors else: result = schema.load(payload) assert 'vendor_uuids' in result @pytest.mark.parametrize( 'payload, expected_errors', [ ({'vendor_uuids': ['87682992-bff2-40ff-aa75-18eb6214679e']}, {}), ({'vendor_uuids': []}, {'vendor_uuids': ['Shorter than minimum length 1.']}), ({'vendor_uuids': ['not-a-valid-uuid']}, {'vendor_uuids': {0: ['Not a valid UUID.']}}), ({}, {'vendor_uuids': ['Missing data for required field.']}), ({'vendor_uuids': 'not-a-list'}, {'vendor_uuids': ['Not a valid list.']}), ( {'vendor_uuids': ['87682992-bff2-40ff-aa75-18eb6214679e', 'bad_uuid']}, {'vendor_uuids': {1: ['Not a valid UUID.']}}, ), ], ) def test_vendor_relationship_notes_request_schema(payload, expected_errors): """Test VendorRelationshipNotesRequestSchema validation.""" schema = VendorRelationshipNotesRequestSchema() if expected_errors: errors = schema.validate(payload) assert errors == expected_errors else: result = schema.load(payload) assert 'vendor_uuids' in result