import pytest from pydantic import ValidationError from schemas import AdminLogin, CodeItem, CouponUploadItem, CouponUpload class TestAdminLoginSchema: """Test cases for AdminLogin schema""" def test_valid_admin_login(self): """Test valid admin login data""" data = { "username": "testadmin", "password": "testpassword123" } admin_login = AdminLogin(**data) assert admin_login.username == "testadmin" assert admin_login.password == "testpassword123" def test_admin_login_missing_username(self): """Test admin login with missing username""" data = { "password": "testpassword123" } with pytest.raises(ValidationError) as exc_info: AdminLogin(**data) errors = exc_info.value.errors() assert len(errors) == 1 assert errors[0]["loc"] == ("username",) assert errors[0]["type"] == "missing" def test_admin_login_missing_password(self): """Test admin login with missing password""" data = { "username": "testadmin" } with pytest.raises(ValidationError) as exc_info: AdminLogin(**data) errors = exc_info.value.errors() assert len(errors) == 1 assert errors[0]["loc"] == ("password",) assert errors[0]["type"] == "missing" def test_admin_login_empty_username(self): """Test admin login with empty username""" data = { "username": "", "password": "testpassword123" } admin_login = AdminLogin(**data) assert admin_login.username == "" def test_admin_login_empty_password(self): """Test admin login with empty password""" data = { "username": "testadmin", "password": "" } admin_login = AdminLogin(**data) assert admin_login.password == "" def test_admin_login_whitespace_values(self): """Test admin login with whitespace values""" data = { "username": " ", "password": " " } admin_login = AdminLogin(**data) assert admin_login.username == " " assert admin_login.password == " " def test_admin_login_long_values(self): """Test admin login with long values""" long_username = "a" * 1000 long_password = "b" * 1000 data = { "username": long_username, "password": long_password } admin_login = AdminLogin(**data) assert admin_login.username == long_username assert admin_login.password == long_password def test_admin_login_special_characters(self): """Test admin login with special characters""" data = { "username": "admin@test.com", "password": "pass@word#123!" } admin_login = AdminLogin(**data) assert admin_login.username == "admin@test.com" assert admin_login.password == "pass@word#123!" def test_admin_login_unicode_characters(self): """Test admin login with unicode characters""" data = { "username": "admin_测试", "password": "password_测试" } admin_login = AdminLogin(**data) assert admin_login.username == "admin_测试" assert admin_login.password == "password_测试" def test_admin_login_model_dump(self): """Test admin login model serialization""" data = { "username": "testadmin", "password": "testpassword123" } admin_login = AdminLogin(**data) dumped = admin_login.model_dump() assert dumped == data def test_admin_login_model_json(self): """Test admin login model JSON serialization""" data = { "username": "testadmin", "password": "testpassword123" } admin_login = AdminLogin(**data) json_str = admin_login.model_dump_json() # Check for presence of fields in JSON (order may vary) assert "testadmin" in json_str assert "testpassword123" in json_str class TestCodeItemSchema: """Test cases for CodeItem schema""" def test_valid_code_item(self): """Test valid code item data""" data = { "code": "TEST123", "usage": 0 } code_item = CodeItem(**data) assert code_item.code == "TEST123" assert code_item.usage == 0 def test_code_item_missing_code(self): """Test code item with missing code""" data = { "usage": 0 } with pytest.raises(ValidationError) as exc_info: CodeItem(**data) errors = exc_info.value.errors() assert len(errors) == 1 assert errors[0]["loc"] == ("code",) assert errors[0]["type"] == "missing" def test_code_item_missing_usage(self): """Test code item with missing usage""" data = { "code": "TEST123" } with pytest.raises(ValidationError) as exc_info: CodeItem(**data) errors = exc_info.value.errors() assert len(errors) == 1 assert errors[0]["loc"] == ("usage",) assert errors[0]["type"] == "missing" def test_code_item_negative_usage(self): """Test code item with negative usage""" data = { "code": "TEST123", "usage": -5 } code_item = CodeItem(**data) assert code_item.usage == -5 def test_code_item_large_usage(self): """Test code item with large usage value""" data = { "code": "TEST123", "usage": 999999 } code_item = CodeItem(**data) assert code_item.usage == 999999 def test_code_item_zero_usage(self): """Test code item with zero usage""" data = { "code": "TEST123", "usage": 0 } code_item = CodeItem(**data) assert code_item.usage == 0 def test_code_item_empty_code(self): """Test code item with empty code""" data = { "code": "", "usage": 0 } code_item = CodeItem(**data) assert code_item.code == "" def test_code_item_whitespace_code(self): """Test code item with whitespace code""" data = { "code": " TEST123 ", "usage": 0 } code_item = CodeItem(**data) assert code_item.code == " TEST123 " def test_code_item_special_characters(self): """Test code item with special characters""" data = { "code": "TEST-123_ABC@456", "usage": 0 } code_item = CodeItem(**data) assert code_item.code == "TEST-123_ABC@456" def test_code_item_unicode_characters(self): """Test code item with unicode characters""" data = { "code": "TEST测试123", "usage": 0 } code_item = CodeItem(**data) assert code_item.code == "TEST测试123" def test_code_item_model_dump(self): """Test code item model serialization""" data = { "code": "TEST123", "usage": 5 } code_item = CodeItem(**data) dumped = code_item.model_dump() assert dumped == data class TestCouponUploadItemSchema: """Test cases for CouponUploadItem schema""" def test_valid_coupon_upload_item(self): """Test valid coupon upload item data""" data = { "code": "TEST123", "usage": 0 } upload_item = CouponUploadItem(**data) assert upload_item.code == "TEST123" assert upload_item.usage == 0 def test_coupon_upload_item_default_usage(self): """Test coupon upload item with default usage""" data = { "code": "TEST123" # usage not specified, should default to 0 } upload_item = CouponUploadItem(**data) assert upload_item.code == "TEST123" assert upload_item.usage == 0 def test_coupon_upload_item_missing_code(self): """Test coupon upload item with missing code""" data = { "usage": 0 } with pytest.raises(ValidationError) as exc_info: CouponUploadItem(**data) errors = exc_info.value.errors() assert len(errors) == 1 assert errors[0]["loc"] == ("code",) assert errors[0]["type"] == "missing" def test_coupon_upload_item_negative_usage(self): """Test coupon upload item with negative usage""" data = { "code": "TEST123", "usage": -10 } upload_item = CouponUploadItem(**data) assert upload_item.usage == -10 def test_coupon_upload_item_large_usage(self): """Test coupon upload item with large usage value""" data = { "code": "TEST123", "usage": 999999 } upload_item = CouponUploadItem(**data) assert upload_item.usage == 999999 def test_coupon_upload_item_empty_code(self): """Test coupon upload item with empty code""" data = { "code": "", "usage": 0 } upload_item = CouponUploadItem(**data) assert upload_item.code == "" def test_coupon_upload_item_whitespace_code(self): """Test coupon upload item with whitespace code""" data = { "code": " TEST123 ", "usage": 0 } upload_item = CouponUploadItem(**data) assert upload_item.code == " TEST123 " def test_coupon_upload_item_special_characters(self): """Test coupon upload item with special characters""" data = { "code": "TEST-123_ABC@456", "usage": 0 } upload_item = CouponUploadItem(**data) assert upload_item.code == "TEST-123_ABC@456" def test_coupon_upload_item_model_dump(self): """Test coupon upload item model serialization""" data = { "code": "TEST123", "usage": 5 } upload_item = CouponUploadItem(**data) dumped = upload_item.model_dump() assert dumped == data class TestCouponUploadSchema: """Test cases for CouponUpload schema""" def test_valid_coupon_upload(self): """Test valid coupon upload data""" data = { "codes": [ {"code": "TEST123", "usage": 0}, {"code": "TEST456", "usage": 1} ] } upload = CouponUpload(**data) assert len(upload.codes) == 2 assert upload.codes[0].code == "TEST123" assert upload.codes[0].usage == 0 assert upload.codes[1].code == "TEST456" assert upload.codes[1].usage == 1 def test_coupon_upload_empty_list(self): """Test coupon upload with empty codes list""" data = { "codes": [] } upload = CouponUpload(**data) assert len(upload.codes) == 0 def test_coupon_upload_missing_codes(self): """Test coupon upload with missing codes""" data = {} with pytest.raises(ValidationError) as exc_info: CouponUpload(**data) errors = exc_info.value.errors() assert len(errors) == 1 assert errors[0]["loc"] == ("codes",) assert errors[0]["type"] == "missing" def test_coupon_upload_single_code(self): """Test coupon upload with single code""" data = { "codes": [ {"code": "TEST123", "usage": 0} ] } upload = CouponUpload(**data) assert len(upload.codes) == 1 assert upload.codes[0].code == "TEST123" assert upload.codes[0].usage == 0 def test_coupon_upload_many_codes(self): """Test coupon upload with many codes""" codes_data = [] for i in range(100): codes_data.append({"code": f"TEST{i:03d}", "usage": i % 3}) data = { "codes": codes_data } upload = CouponUpload(**data) assert len(upload.codes) == 100 for i, code_item in enumerate(upload.codes): assert code_item.code == f"TEST{i:03d}" assert code_item.usage == i % 3 def test_coupon_upload_with_default_usage(self): """Test coupon upload with codes using default usage""" data = { "codes": [ {"code": "TEST123"}, # usage not specified {"code": "TEST456", "usage": 5} ] } upload = CouponUpload(**data) assert len(upload.codes) == 2 assert upload.codes[0].code == "TEST123" assert upload.codes[0].usage == 0 # Default value assert upload.codes[1].code == "TEST456" assert upload.codes[1].usage == 5 def test_coupon_upload_duplicate_codes(self): """Test coupon upload with duplicate codes (should be allowed in schema)""" data = { "codes": [ {"code": "TEST123", "usage": 0}, {"code": "TEST123", "usage": 1} # Duplicate code ] } upload = CouponUpload(**data) assert len(upload.codes) == 2 assert upload.codes[0].code == "TEST123" assert upload.codes[0].usage == 0 assert upload.codes[1].code == "TEST123" assert upload.codes[1].usage == 1 def test_coupon_upload_special_characters(self): """Test coupon upload with special characters in codes""" data = { "codes": [ {"code": "TEST-123", "usage": 0}, {"code": "TEST_456", "usage": 1}, {"code": "TEST@789", "usage": 2} ] } upload = CouponUpload(**data) assert len(upload.codes) == 3 assert upload.codes[0].code == "TEST-123" assert upload.codes[1].code == "TEST_456" assert upload.codes[2].code == "TEST@789" def test_coupon_upload_unicode_characters(self): """Test coupon upload with unicode characters""" data = { "codes": [ {"code": "TEST测试123", "usage": 0}, {"code": "TEST测试456", "usage": 1} ] } upload = CouponUpload(**data) assert len(upload.codes) == 2 assert upload.codes[0].code == "TEST测试123" assert upload.codes[1].code == "TEST测试456" def test_coupon_upload_model_dump(self): """Test coupon upload model serialization""" data = { "codes": [ {"code": "TEST123", "usage": 0}, {"code": "TEST456", "usage": 1} ] } upload = CouponUpload(**data) dumped = upload.model_dump() assert dumped == data def test_coupon_upload_model_json(self): """Test coupon upload model JSON serialization""" data = { "codes": [ {"code": "TEST123", "usage": 0}, {"code": "TEST456", "usage": 1} ] } upload = CouponUpload(**data) json_str = upload.model_dump_json() # Check for presence of fields in JSON (order may vary) assert "TEST123" in json_str assert "TEST456" in json_str assert "0" in json_str assert "1" in json_str def test_coupon_upload_invalid_code_item(self): """Test coupon upload with invalid code item""" data = { "codes": [ {"code": "TEST123", "usage": 0}, {"usage": 1} # Missing code field ] } with pytest.raises(ValidationError) as exc_info: CouponUpload(**data) errors = exc_info.value.errors() assert len(errors) >= 1 # Should have error for missing code field in second item