183 lines
6.4 KiB
Python
183 lines
6.4 KiB
Python
# #region Test.Schemas.Edge [C:3] [TYPE Module] [SEMANTICS test,schemas,auth,translate,edge]
|
|
# @BRIEF Edge-case coverage for schemas/auth.py and schemas/translate.py uncovered lines.
|
|
# @RELATION BINDS_TO -> [Schemas.Auth]
|
|
# @RELATION BINDS_TO -> [Schemas.Translate]
|
|
# @TEST_EDGE: missing_field -> Password missing digit/lowercase/uppercase
|
|
# @TEST_EDGE: invalid_type -> BCP-47 tag validation rejects malformed
|
|
# @TEST_EDGE: oversized_input -> Pattern exceeds 500 char limit
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
|
|
# ── auth.py: password validation ─────────────────────────────────
|
|
|
|
|
|
class TestUserCreatePasswordValidation:
|
|
"""Password strength validator edge cases (line 151)."""
|
|
|
|
def test_password_min_length_raises(self):
|
|
from src.schemas.auth import UserCreate
|
|
|
|
with pytest.raises(ValidationError) as exc:
|
|
UserCreate(
|
|
username="test",
|
|
email="test@x.com",
|
|
password="Ab1", # too short (3 chars, min 8)
|
|
)
|
|
errors = exc.value.errors()
|
|
assert any("at least 8" in str(e["msg"]) for e in errors)
|
|
|
|
def test_password_missing_uppercase_raises(self):
|
|
from src.schemas.auth import UserCreate
|
|
|
|
with pytest.raises(ValidationError) as exc:
|
|
UserCreate(
|
|
username="test",
|
|
email="test@x.com",
|
|
password="abcdefgh1", # no uppercase
|
|
)
|
|
errors = exc.value.errors()
|
|
assert any("uppercase" in str(e["msg"]) for e in errors)
|
|
|
|
def test_password_missing_lowercase_raises(self):
|
|
from src.schemas.auth import UserCreate
|
|
|
|
with pytest.raises(ValidationError) as exc:
|
|
UserCreate(
|
|
username="test",
|
|
email="test@x.com",
|
|
password="ABCDEFGH1", # no lowercase
|
|
)
|
|
errors = exc.value.errors()
|
|
assert any("lowercase" in str(e["msg"]) for e in errors)
|
|
|
|
def test_password_missing_digit_raises(self):
|
|
from src.schemas.auth import UserCreate
|
|
|
|
with pytest.raises(ValidationError) as exc:
|
|
UserCreate(
|
|
username="test",
|
|
email="test@x.com",
|
|
password="Abcdefgh", # no digit
|
|
)
|
|
errors = exc.value.errors()
|
|
assert any("digit" in str(e["msg"]) for e in errors)
|
|
|
|
def test_password_valid(self):
|
|
from src.schemas.auth import UserCreate
|
|
|
|
user = UserCreate(
|
|
username="test",
|
|
email="test@x.com",
|
|
password="ValidPassword1",
|
|
)
|
|
assert user.password == "ValidPassword1"
|
|
assert user.roles == []
|
|
|
|
|
|
# ── translate.py: BCP-47 validation and pattern length ────────────
|
|
|
|
|
|
class TestTranslateSchemasEdge:
|
|
"""BCP-47 validation and pattern length validation."""
|
|
|
|
def test_bcp47_empty_list(self):
|
|
from src.schemas.translate import _validate_bcp47_list
|
|
|
|
result = _validate_bcp47_list([])
|
|
assert result == []
|
|
|
|
def test_bcp47_none_list(self):
|
|
from src.schemas.translate import _validate_bcp47_list
|
|
|
|
result = _validate_bcp47_list(None)
|
|
assert result is None
|
|
|
|
def test_bcp47_valid_tags(self):
|
|
from src.schemas.translate import _validate_bcp47_list
|
|
|
|
result = _validate_bcp47_list(["en", "ru", "zh-CN", "pt-BR"])
|
|
assert result == ["en", "ru", "zh-CN", "pt-BR"]
|
|
|
|
def test_bcp47_invalid_tag_raises(self):
|
|
from src.schemas.translate import _validate_bcp47_list
|
|
|
|
with pytest.raises(ValueError) as exc:
|
|
_validate_bcp47_list(["en", "invalid tag with spaces"])
|
|
assert "BCP-47" in str(exc.value)
|
|
|
|
def test_bcp47_empty_tag_raises(self):
|
|
from src.schemas.translate import _validate_bcp47_list
|
|
|
|
with pytest.raises(ValueError) as exc:
|
|
_validate_bcp47_list(["en", ""])
|
|
assert "BCP-47" in str(exc.value)
|
|
|
|
def test_bulk_find_replace_pattern_too_long(self):
|
|
from src.schemas.translate import BulkFindReplaceRequest
|
|
|
|
with pytest.raises(ValidationError) as exc:
|
|
BulkFindReplaceRequest(
|
|
find_pattern="x" * 501,
|
|
replacement_text="test",
|
|
target_language="en",
|
|
)
|
|
errors = exc.value.errors()
|
|
assert any("500" in str(e["msg"]) for e in errors)
|
|
|
|
def test_bulk_find_replace_pattern_valid(self):
|
|
from src.schemas.translate import BulkFindReplaceRequest
|
|
|
|
req = BulkFindReplaceRequest(
|
|
find_pattern="old text",
|
|
replacement_text="new text",
|
|
target_language="en",
|
|
)
|
|
assert req.find_pattern == "old text"
|
|
assert req.replacement_text == "new text"
|
|
assert req.submit_to_dictionary_with_context is False
|
|
|
|
def test_translate_job_create_insert_method_direct_db_no_connection_raises(self):
|
|
"""Line 67-69: validate_insert_method model_validator."""
|
|
from src.schemas.translate import TranslateJobCreate
|
|
|
|
with pytest.raises(ValidationError) as exc:
|
|
TranslateJobCreate(
|
|
name="Test",
|
|
source_dialect="postgresql",
|
|
target_dialect="clickhouse",
|
|
insert_method="direct_db",
|
|
# no connection_id
|
|
)
|
|
errors = exc.value.errors()
|
|
assert any("connection_id" in str(e["msg"]) for e in errors)
|
|
|
|
def test_translate_job_create_insert_method_sqllab_needs_no_connection(self):
|
|
"""sqllab insert_method does not require connection_id."""
|
|
from src.schemas.translate import TranslateJobCreate
|
|
|
|
job = TranslateJobCreate(
|
|
name="Test",
|
|
source_dialect="postgresql",
|
|
target_dialect="clickhouse",
|
|
insert_method="sqllab",
|
|
)
|
|
assert job.insert_method == "sqllab"
|
|
assert job.connection_id is None
|
|
|
|
def test_translate_job_create_insert_method_direct_db_with_connection_ok(self):
|
|
"""direct_db insert_method with connection_id is valid."""
|
|
from src.schemas.translate import TranslateJobCreate
|
|
|
|
job = TranslateJobCreate(
|
|
name="Test",
|
|
source_dialect="postgresql",
|
|
target_dialect="clickhouse",
|
|
insert_method="direct_db",
|
|
connection_id="conn-1",
|
|
)
|
|
assert job.insert_method == "direct_db"
|
|
assert job.connection_id == "conn-1"
|
|
# #endregion Test.Schemas.Edge
|