Renamed ebook_backend&admin_panel to ebook_backend_admin_panel The & character was being interpreted by shell as background process operator, causing 'Dockerfile not found' errors in Coolify.
557 lines
16 KiB
Python
557 lines
16 KiB
Python
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 |