from __future__ import annotations import pytest from content_automation.adapters.storage.base import StorageAdapterBase from content_automation.controller import PublishController from content_automation.models import PublishedContentRecord from content_automation.settings import AppSettings class FakeStorage(StorageAdapterBase): def __init__( self, exists_result: bool, public_url: str = "file:///tmp/video.mp4" ) -> None: self._exists_result = exists_result self._public_url = public_url def exists(self, relative_path: str) -> bool: return self._exists_result def get_public_url(self, relative_path: str) -> str: return self._public_url class FakeAdapter: def __init__(self, adapter_name: str) -> None: self.name = adapter_name def post_media(self, media_url: str, caption: str) -> str: return f"{self.name}-post-id" class FakeAdapterWithResponsePayload: def __init__(self, payload: object) -> None: self.name = "adapter-with-payload" self._payload = payload def post_media(self, media_url: str, caption: str) -> object: return self._payload class FakePublishedContentStore: def __init__(self) -> None: self.records: list[PublishedContentRecord] = [] def save(self, record: PublishedContentRecord) -> None: self.records.append(record) def test_controller_publishes_to_all_configured_networks() -> None: settings = AppSettings.model_validate( {"target_social_networks": ["instagram", "youtube"]} ) controller = PublishController( settings=settings, storage=FakeStorage(exists_result=True), social_adapters={ "instagram": FakeAdapter("instagram"), "youtube": FakeAdapter("youtube"), }, ) result = controller.publish(relative_path="video.mp4", caption="hello") assert result == {"instagram": "instagram-post-id", "youtube": "youtube-post-id"} def test_controller_stores_published_content_with_youtube_id_only() -> None: settings = AppSettings.model_validate( {"target_social_networks": ["instagram", "youtube"]} ) published_content_store = FakePublishedContentStore() controller = PublishController( settings=settings, storage=FakeStorage(exists_result=True), social_adapters={ "instagram": FakeAdapterWithResponsePayload( {"id": "ig-123", "status": "ok"} ), "youtube": FakeAdapterWithResponsePayload( { "id": "yt-456", "kind": "youtube#video", "snippet": {"title": "hello"}, } ), }, published_content_store=published_content_store, ) result = controller.publish(relative_path="video.mp4", caption="hello") assert result["youtube"] == { "id": "yt-456", "kind": "youtube#video", "snippet": {"title": "hello"}, } assert len(published_content_store.records) == 1 saved_record = published_content_store.records[0] assert saved_record.relative_path == "video.mp4" assert saved_record.caption == "hello" assert saved_record.platform_responses["instagram"] == { "id": "ig-123", "status": "ok", } assert saved_record.platform_responses["youtube"] == "yt-456" def test_controller_raises_when_file_missing() -> None: settings = AppSettings.model_validate({"target_social_networks": ["youtube"]}) controller = PublishController( settings=settings, storage=FakeStorage(exists_result=False), social_adapters={"youtube": FakeAdapter("youtube")}, ) with pytest.raises(FileNotFoundError): controller.publish(relative_path="video.mp4", caption="hello")