Files
devplacepy/tests/unit/services/sync/records.py
T
retoor 6f80a820da
DevPlace CI / test (push) Failing after 3m13s
Zo doen wijdat in oost
2026-10-16 07:20:44 +02:00

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=[{}])