Spaces:
Running
Running
File size: 2,661 Bytes
7cc81cb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | from pathlib import Path
import pytest
from pydantic import ValidationError
from app.copilot.actions import ACTION_DEFINITIONS
from app.social.schemas.posts import SocialPostCreate, SocialPostValidation
def test_canonical_copy_and_project_provenance_are_strict() -> None:
payload = SocialPostCreate.model_validate({
"project_id": "123e4567-e89b-12d3-a456-426614174000",
"caption": "Release update",
"hashtags": ["#release", "release", "media"],
"targets": [{
"social_account_id": "x-account",
"caption": {"text": "X override"},
"x": {"text": "X override"},
}],
})
assert payload.caption == "Release update"
assert payload.hashtags == ["release", "media"]
with pytest.raises(ValidationError):
SocialPostCreate.model_validate({
"targets": [{
"social_account_id": "x-account",
"caption": {},
"x": {"text": "valid"},
"unknown_provider_payload": {},
}],
})
def test_structured_validation_is_per_target() -> None:
result = SocialPostValidation.model_validate({
"post_id": "post-1",
"valid": False,
"targets": [{
"target_id": "target-1",
"provider": "youtube",
"account_id": "account-1",
"valid": False,
"errors": [{"code": "SOCIAL_MEDIA_INVALID", "message": "Invalid media."}],
"warnings": [],
}],
})
assert not result.valid
assert result.targets[0].errors[0].code == "SOCIAL_MEDIA_INVALID"
def test_copilot_external_publishing_actions_require_confirmation() -> None:
definitions = {
item.type: item for item in ACTION_DEFINITIONS
if item.type.startswith("publishing.")
}
assert set(definitions) == {
"publishing.validate",
"publishing.create_post",
"publishing.schedule",
"publishing.publish",
"publishing.cancel",
}
for name in ("publishing.schedule", "publishing.publish", "publishing.cancel"):
assert definitions[name].external_side_effect
assert definitions[name].requires_confirmation
def test_additive_migration_extends_existing_social_tables() -> None:
sql = Path("app/social/migrations/0008_unified_publishing.sql").read_text()
lowered = sql.lower()
assert "alter table social_posts" in lowered
assert "foreign key (project_id) references projects(id)" in lowered
assert "force row level security" in lowered
assert "create table social_posts" not in lowered
assert "create table social_jobs" not in lowered
|