86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
# retoor <retoor@molodetz.nl>
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from devplacepy.services.sync.records import (
|
|
CommentRecord,
|
|
PostRecord,
|
|
SyncBatchForm,
|
|
UserRecord,
|
|
)
|
|
from devplacepy.services.sync.spec import LIMITS
|
|
|
|
BASE = {"origin_uid": "r1", "created_at": "2025-01-01T00:00:00Z"}
|
|
|
|
|
|
def test_updated_at_defaults_to_created_and_never_precedes_it():
|
|
record = PostRecord.model_validate(
|
|
{**BASE, "author_uid": "u", "content": "ten chars!!"}
|
|
)
|
|
assert record.updated_at == record.created_at
|
|
earlier = PostRecord.model_validate(
|
|
{**BASE, "author_uid": "u", "content": "ten chars!!", "updated_at": "2024-01-01"}
|
|
)
|
|
assert earlier.updated_at == earlier.created_at
|
|
|
|
|
|
def test_unknown_topic_becomes_random_and_known_is_kept():
|
|
base = {**BASE, "author_uid": "u", "content": "ten chars!!"}
|
|
assert PostRecord.model_validate({**base, "topic": "zzz"}).topic == "random"
|
|
assert PostRecord.model_validate({**base, "topic": "DevLog"}).topic == "devlog"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"payload",
|
|
[
|
|
{"author_uid": "u", "content": "short"},
|
|
{"author_uid": "u", "content": "x" * (LIMITS.max_post_length + 1)},
|
|
{"author_uid": "", "content": "ten chars!!"},
|
|
{"content": "ten chars!!"},
|
|
{"author_uid": "u", "content": "ten chars!!", "title": "t" * (LIMITS.max_title_length + 1)},
|
|
],
|
|
)
|
|
def test_invalid_posts_are_rejected(payload):
|
|
with pytest.raises(ValidationError):
|
|
PostRecord.model_validate({**BASE, **payload})
|
|
|
|
|
|
def test_comment_parent_is_optional_and_post_is_required():
|
|
base = {**BASE, "author_uid": "u", "content": "fine"}
|
|
assert CommentRecord.model_validate({**base, "post_uid": "p"}).parent_uid is None
|
|
assert CommentRecord.model_validate({**base, "post_uid": "p", "parent_uid": ""}).parent_uid is None
|
|
with pytest.raises(ValidationError):
|
|
CommentRecord.model_validate(base)
|
|
|
|
|
|
def test_user_urls_are_fixed_or_dropped():
|
|
record = UserRecord.model_validate(
|
|
{**BASE, "username": "bob", "website": "example.com", "git_link": "not a url"}
|
|
)
|
|
assert record.website == "https://example.com"
|
|
assert record.git_link == ""
|
|
|
|
|
|
def test_user_bio_over_limit_is_rejected():
|
|
with pytest.raises(ValidationError):
|
|
UserRecord.model_validate({**BASE, "username": "bob", "bio": "x" * (LIMITS.max_bio_length + 1)})
|
|
|
|
|
|
def test_user_counters_and_credentials_are_not_fields():
|
|
known = UserRecord.known_fields()
|
|
for name in ("email", "password_hash", "role", "xp", "level", "stars", "api_key"):
|
|
assert name not in known
|
|
assert "stars" not in PostRecord.known_fields()
|
|
|
|
|
|
def test_envelope_normalizes_origin_and_bounds_batch():
|
|
form = SyncBatchForm(origin="Other.ORG", records=[{}])
|
|
assert form.origin == "other.org"
|
|
with pytest.raises(ValidationError):
|
|
SyncBatchForm(origin="other.org", records=[])
|
|
with pytest.raises(ValidationError):
|
|
SyncBatchForm(origin="other.org", records=[{}] * (LIMITS.max_batch_records + 1))
|
|
with pytest.raises(ValidationError):
|
|
SyncBatchForm(origin="bad origin", records=[{}])
|