diff --git a/core/src/zeit/content/audio/ctesting.zcml b/core/src/zeit/content/audio/ctesting.zcml new file mode 100644 index 0000000000..32cc9af076 --- /dev/null +++ b/core/src/zeit/content/audio/ctesting.zcml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/core/src/zeit/content/audio/mock-workflow.zcml b/core/src/zeit/content/audio/mock-workflow.zcml new file mode 100644 index 0000000000..6d87d0f82a --- /dev/null +++ b/core/src/zeit/content/audio/mock-workflow.zcml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/core/src/zeit/content/audio/testing.py b/core/src/zeit/content/audio/testing.py index b4aae8c3f6..426e2fdd9f 100644 --- a/core/src/zeit/content/audio/testing.py +++ b/core/src/zeit/content/audio/testing.py @@ -4,8 +4,9 @@ from zeit.cms.repository.interfaces import IRepository from zeit.content.audio.audio import Audio -from zeit.content.audio.interfaces import IPodcastEpisodeInfo, Podcast +from zeit.content.audio.interfaces import IPodcastEpisodeInfo, ISpeechInfo, Podcast import zeit.cms.testing +import zeit.workflow.testing T = TypeVar('T') # Can be anything @@ -17,7 +18,11 @@ """.format(here=importlib.resources.files(__package__)) CONFIG_LAYER = zeit.cms.testing.ProductConfigLayer( - product_config, bases=(zeit.cms.testing.CONFIG_LAYER,) + product_config, + bases=( + zeit.workflow.testing.CONFIG_LAYER, + zeit.cms.testing.CONFIG_LAYER, + ), ) ZCML_LAYER = zeit.cms.testing.ZCMLLayer('ftesting.zcml', bases=(CONFIG_LAYER,)) @@ -62,6 +67,11 @@ def __init__(self): 'cat-jokes-pawdcast', ), }, + 'tts': { + 'article_uuid': 'a89ce2e3-4887-466a-a52e-edc6b9802ef9', + 'preview_url': 'https://example-preview-url.bert', + 'checksum': '123foo', + }, } def with_attribute(self, attribute_name: str, value: T): @@ -73,11 +83,18 @@ def with_attribute(self, attribute_name: str, value: T): def build(self, repository: Optional[IRepository] = None) -> Audio: audio = Audio() - episode = IPodcastEpisodeInfo(audio) + audio_type = self.attributes['audio']['audio_type'] for attribute, value in self.attributes['audio'].items(): setattr(audio, attribute, value) - for attribute, value in self.attributes['podcast'].items(): - setattr(episode, attribute, value) + if audio_type == 'podcast': + episode = IPodcastEpisodeInfo(audio) + for attribute, value in self.attributes[audio_type].items(): + setattr(episode, attribute, value) + if audio_type == 'tts': + tts = ISpeechInfo(audio) + audio.external_id = '' + for attribute, value in self.attributes[audio_type].items(): + setattr(tts, attribute, value) if repository is not None: repository['audio'] = audio diff --git a/core/src/zeit/content/audio/tests/test_audio.py b/core/src/zeit/content/audio/tests/test_audio.py index 9ec7b5fba3..9e4a4df9f4 100644 --- a/core/src/zeit/content/audio/tests/test_audio.py +++ b/core/src/zeit/content/audio/tests/test_audio.py @@ -2,12 +2,15 @@ import zope.interface.verify +from zeit.cms.checkout.helper import checked_out +from zeit.cms.workflow.interfaces import CAN_PUBLISH_ERROR from zeit.content.audio.interfaces import Podcast, PodcastSource from zeit.content.audio.testing import AudioBuilder, FunctionalTestCase import zeit.cms.content.interfaces import zeit.cms.content.sources import zeit.cms.interfaces import zeit.cms.testing +import zeit.cms.workflow.interfaces import zeit.content.audio.audio import zeit.content.image.interfaces @@ -50,19 +53,50 @@ def test_get_podcast_image(self): ), 'Fill color should match color audio/tests/fixtures/podcasts.xml' +class WorkflowTest(FunctionalTestCase): + def test_podcast_not_published_if_requirements_not_met_url(self): + audio = AudioBuilder().with_url('').build(self.repository) + workflow = zeit.cms.workflow.interfaces.IPublishInfo(audio) + assert workflow.can_publish() == zeit.cms.workflow.interfaces.CAN_PUBLISH_ERROR + assert 'Audio URL is missing' in workflow.error_messages[0] + + def test_podcast_not_published_if_requirements_not_met_is_published(self): + audio = AudioBuilder().with_is_published(False).build(self.repository) + workflow = zeit.cms.workflow.interfaces.IPublishInfo(audio) + assert workflow.can_publish() == zeit.cms.workflow.interfaces.CAN_PUBLISH_ERROR + assert 'Podcast Episode is not published by Provider' in workflow.error_messages[0] + + def test_podcast_not_retracted_if_requirements_not_met_is_not_published(self): + audio = AudioBuilder().build(self.repository) + workflow = zeit.cms.workflow.interfaces.IPublishInfo(audio) + assert workflow.can_retract() == zeit.cms.workflow.interfaces.CAN_RETRACT_ERROR + assert 'Podcast Episode is published by Provider' in workflow.error_messages[0] + + class SpeechTest(FunctionalTestCase): + def setUp(self): + super().setUp() + article = zeit.cms.interfaces.ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') + uuid = zeit.cms.content.interfaces.IUUID(article).shortened + AudioBuilder().with_audio_type('tts').with_article_uuid(uuid).build(self.repository) + def test_create_tts_audio(self): article = zeit.cms.interfaces.ICMSContent('http://xml.zeit.de/online/2007/01/Somalia') uuid = zeit.cms.content.interfaces.IUUID(article) - audio = zeit.content.audio.audio.Audio() - audio.audio_type = 'tts' - tts = zeit.content.audio.interfaces.ISpeechInfo(audio) - tts.article_uuid = uuid.shortened - tts.preview_url = 'https://example-preview-url.bert' - tts.checksum = '123foo' - audio = self.repository['audio'] = audio + audio = self.repository['audio'] speechinfo = zeit.content.audio.interfaces.ISpeechInfo(audio) self.assertEqual(audio.audio_type, 'tts') self.assertEqual(speechinfo.article_uuid, uuid.shortened) self.assertEqual(speechinfo.preview_url, 'https://example-preview-url.bert') self.assertTrue(speechinfo.checksum, '123foo') + + def test_publish_tts_audio(self): + audio = self.repository['audio'] + zeit.cms.workflow.interfaces.IPublish(audio).publish(background=False) + assert zeit.cms.workflow.interfaces.IPublishInfo(audio).published + + def test_cannot_publish_tts_without_url(self): + audio = self.repository['audio'] + with checked_out(audio) as co: + co.url = '' + assert zeit.cms.workflow.interfaces.IPublishInfo(audio).can_publish() == CAN_PUBLISH_ERROR diff --git a/core/src/zeit/simplecast/ftesting.zcml b/core/src/zeit/simplecast/ftesting.zcml index 129742f2bb..b3232b6a46 100644 --- a/core/src/zeit/simplecast/ftesting.zcml +++ b/core/src/zeit/simplecast/ftesting.zcml @@ -4,7 +4,7 @@ - + diff --git a/core/src/zeit/simplecast/tests/test_connection.py b/core/src/zeit/simplecast/tests/test_connection.py index f155e5ae57..943226c10f 100644 --- a/core/src/zeit/simplecast/tests/test_connection.py +++ b/core/src/zeit/simplecast/tests/test_connection.py @@ -1,14 +1,12 @@ from unittest import mock import pendulum -import pytest import requests import requests_mock import zope.component from zeit.cms.content.interfaces import ISemanticChange from zeit.content.audio.interfaces import IPodcastEpisodeInfo -from zeit.content.audio.workflow import AudioWorkflow, PodcastWorkflow import zeit.cms.repository.folder import zeit.cms.workflow.interfaces import zeit.content.audio.audio @@ -181,7 +179,6 @@ def test_publish(self, m): content = self.repository['podcasts']['2023-08'][self.episode_info['id']] workflow = zeit.cms.workflow.interfaces.IPublishInfo(content) - assert isinstance(workflow, PodcastWorkflow) assert workflow.can_publish() == zeit.cms.workflow.interfaces.CAN_PUBLISH_SUCCESS assert workflow.published @@ -194,63 +191,6 @@ def test_publish(self, m): self.simplecast.synchronize_episode(self.episode_info['id']) assert workflow.published - def test_podcast_not_published_if_requirements_not_met_url(self): - simplecast_resp = self.episode_info.copy() - simplecast_resp['audio_file_url'] = None - self._check_publishing_error(simplecast_resp, 'Audio URL is missing') - - def test_podcast_not_published_if_requirements_not_met_is_published(self): - simplecast_resp = self.episode_info.copy() - simplecast_resp['is_published'] = False - self._check_publishing_error( - simplecast_resp, 'Podcast Episode is not published by Provider' - ) - - def test_podcast_not_retracted_if_requirements_not_met_is_not_published(self): - simplecast_resp = self.episode_info.copy() - simplecast_resp['is_published'] = True - self._check_retracting_error(simplecast_resp, 'Podcast Episode is published by Provider') - - def _check_publishing_error(self, simplecast_resp, message): - self.create_audio(simplecast_resp) - content = self.repository['podcasts']['2023-08'][self.episode_info['id']] - - workflow = zeit.cms.workflow.interfaces.IPublishInfo(content) - assert isinstance(workflow, PodcastWorkflow) - assert workflow.can_publish() == zeit.cms.workflow.interfaces.CAN_PUBLISH_ERROR - assert not workflow.published - assert message in workflow.error_messages[0] - - publish = zeit.cms.workflow.interfaces.IPublish(content) - with pytest.raises(zeit.cms.workflow.interfaces.PublishingError): - publish.publish(background=False) - assert not workflow.published - - def _check_retracting_error(self, simplecast_resp, message): - self.create_audio(simplecast_resp) - content = self.repository['podcasts']['2023-08'][self.episode_info['id']] - - workflow = zeit.cms.workflow.interfaces.IPublishInfo(content) - assert isinstance(workflow, PodcastWorkflow) - assert workflow.can_retract() == zeit.cms.workflow.interfaces.CAN_RETRACT_ERROR - assert workflow.published - assert message in workflow.error_messages[0] - - publish = zeit.cms.workflow.interfaces.IPublish(content) - with pytest.raises(zeit.cms.workflow.interfaces.RetractingError): - publish.retract(background=False) - assert workflow.published - - def test_missing_audio_type_uses_default_workflow(self): - default_audio = zeit.content.audio.audio.Audio() - default_audio.uniqueId = 'http://xml.zeit.de/default' - default_audio.url = 'https://example.com/default.mp3' - default_audio.external_id = '1234' - - workflow = zeit.cms.workflow.interfaces.IPublishInfo(default_audio) - assert isinstance(workflow, AudioWorkflow) - assert workflow.can_publish() == zeit.cms.workflow.interfaces.CAN_PUBLISH_SUCCESS - @requests_mock.Mocker() def test_retract(self, m): simplecast_resp = self.episode_info.copy() diff --git a/core/src/zeit/speech/ftesting.zcml b/core/src/zeit/speech/ftesting.zcml index dbc3ce2eb5..5afbdb29ea 100644 --- a/core/src/zeit/speech/ftesting.zcml +++ b/core/src/zeit/speech/ftesting.zcml @@ -7,7 +7,7 @@ - + diff --git a/core/src/zeit/speech/tests/test_connection.py b/core/src/zeit/speech/tests/test_connection.py index 7a78da6826..dc0fc3567e 100644 --- a/core/src/zeit/speech/tests/test_connection.py +++ b/core/src/zeit/speech/tests/test_connection.py @@ -47,13 +47,6 @@ def _setup_speech_message(self, field, value): tts_created['articlesAudio'][0][field] = value return tts_created - def test_cannot_publish_without_url(self): - tts_msg = self._setup_speech_message('audioEntry', {'url': None}) - self.create_audio(tts_msg) - assert not IPublishInfo( - ICMSContent(self.unique_id) - ).published, 'Do not publish incomplete audio!' - def test_update_existing_tts_audio(self): self.create_audio(TTS_CREATED) cms_tts = ICMSContent(self.unique_id)