"""Test for Podcast logic tier.""" from unittest.mock import ANY from unittest.mock import MagicMock from unittest.mock import patch from oto import status import pytest from podcast import config from podcast.constants import asset_types as asset_types_consts from podcast.logic import megaphone from podcast.logic import podcast from podcast.logic import podcast_links from podcast.logic import user as user_logic from podcast.logic import user_v2 as user_v2_logic from podcast.models import category as category_model from podcast.models import episode as episode_model from podcast.models import ows_asset_transcoder as oat from podcast.models import podcast as podcast_model from podcast.models import podcast_season as season_model from podcast.models import s3 from podcast.models import show_family as show_family_model from podcast.models import user as user_model from podcast.models.api_podcast import ApiPodcast from podcast.utils import api_utils from podcast.utils import signed_urls from podcast.utils.exc import OwsError MEGAPHONE_ID = 'f64b0f8e-ea77-11e9-9831-df1b1d22b24b' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_create_podcast( mock_get_feature_flag, monkeypatch, mock_current_admin_user, participant_fixture, seasons_fixture): """Test create podcast.""" megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) monkeypatch.setattr(category_model, 'get_categories_by_ids', MagicMock( return_value={'items': ['Arts']} )) monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(season_model, 'create_seasons', MagicMock()) result = podcast.create_podcast({ 'artwork_filename': 'cowpoke', 'slug': 'slug', 'network_id': 1, 'title': 'title', 'show_type': 'serial', 'participants': [participant_fixture], 'seasons': seasons_fixture }) assert result['slug'] == 'slug' assert result['id'] == 5 assert result['megaphone_id'] == MEGAPHONE_ID assert result['participants'] == [ {'id': 2, 'name': 'Bill', 'podcast_id': 5, 'role': 'other', 'participant_id': 1}] link = '' assert podcast_links.get_podcast_links(result['id'])['items'][0]['link'] == link season_model.create_seasons.assert_called_once() @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_create_podcast_with_seasons_failure( mock_get_feature_flag, monkeypatch, mock_current_admin_user, seasons_fixture): """Test create podcast with seasons failure.""" monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(user_logic, 'current_user_owns_podcast_id_or_raise', MagicMock()) with pytest.raises(OwsError) as err: podcast.create_podcast({ 'slug': 'slug', 'network_id': 1, 'title': 'title', 'seasons': seasons_fixture }) err.value.status == 400 err.value.message == 'Invalid field seasons for show type: episodic' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_create_podcast_without_artwork( mock_get_feature_flag, monkeypatch, mock_current_admin_user, participant_fixture): """Test create podcast without artwork.""" megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) monkeypatch.setattr(category_model, 'get_categories_by_ids', MagicMock( return_value={'items': ['Arts']} )) monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock()) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) result = podcast.create_podcast({ 'slug': 'slug', 'network_id': 1, 'title': 'title', 'participants': [participant_fixture] }) assert result['slug'] == 'slug' assert result['id'] == 5 assert result['megaphone_id'] == MEGAPHONE_ID assert result['participants'] == [ {'id': 2, 'name': 'Bill', 'podcast_id': 5, 'role': 'other', 'participant_id': 1}] link = '' assert podcast_links.get_podcast_links(result['id'])['items'][0]['link'] == link oat.commit.assert_not_called() oat.get_podcast_assets.assert_not_called() def test_create_podcast_read_only(mock_current_read_only_user, participant_fixture): """Test create podcast fails if user is read only.""" with pytest.raises(OwsError) as err: podcast.create_podcast({ 'slug': 'slug', 'network_id': 1, 'title': 'title', 'participants': [participant_fixture] }) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', side_effect=[True, False]) def test_create_podcast_for_public_rss_feed_type(mock_feature_falg, mock_current_admin_user, monkeypatch, show_family_fixture, db_session): """Test create podcast for public rss feed type.""" megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) monkeypatch.setattr(category_model, 'get_categories_by_ids', MagicMock( return_value={'items': ['Arts']} )) monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(show_family_model, 'create_show_family', MagicMock(return_value=show_family_fixture)) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value={ 'id': 5, 'slug': 'slug', 'network_id': 1, 'feed_type': 'public-rss', 'megaphone_id': MEGAPHONE_ID, 'show_family_id': 1})) result = podcast.create_podcast({ 'slug': 'slug', 'network_id': 1, 'title': 'title', 'feed_type': 'public-rss', 'artwork_filename': 'test_artwork' }) link = '' show_family_model.create_show_family.assert_called_once_with( {'network_id': 1, 'title': 'title', 'created_by': 2, 'updated_by': 2}, db_session) assert ApiPodcast.create.called assert podcast.s3.check_s3_file_exists.called assert podcast_links.get_podcast_links(result['id'])['items'][0]['link'] == link assert podcast_model.update_podcast.called assert result['slug'] == 'slug' assert result['id'] == 5 assert result['megaphone_id'] == MEGAPHONE_ID assert result['show_family_id'] == 1 assert result['feed_type'] == 'public-rss' @patch('podcast.utils.feature_flag_utils.get_feature_flag', side_effect=[True, False]) def test_create_podcast_for_private_rss_feed_type(mock_feature_falg, mock_current_admin_user, monkeypatch, show_family_fixture, db_session): """Test create podcast for private rss feed type.""" megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) monkeypatch.setattr(category_model, 'get_categories_by_ids', MagicMock( return_value={'items': ['Arts']} )) monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(show_family_model, 'create_show_family', MagicMock(return_value=show_family_fixture)) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value={ 'id': 5, 'slug': 'slug', 'network_id': 1, 'feed_type': 'private-rss', 'megaphone_id': MEGAPHONE_ID, 'show_family_id': 1})) result = podcast.create_podcast({ 'slug': 'slug', 'network_id': 1, 'title': 'title', 'feed_type': 'private-rss', 'artwork_filename': 'test_artwork' }) link = '' show_family_model.create_show_family.assert_called_once_with( {'network_id': 1, 'title': 'title', 'created_by': 2, 'updated_by': 2}, db_session) assert podcast.s3.check_s3_file_exists.called assert ApiPodcast.create.called assert podcast_links.get_podcast_links(result['id'])['items'][0]['link'] == link assert podcast_model.update_podcast.called assert result['slug'] == 'slug' assert result['id'] == 5 assert result['megaphone_id'] == MEGAPHONE_ID assert result['show_family_id'] == 1 assert result['feed_type'] == 'private-rss' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_create_podcast_for_apple_subscription_feed_type(mock_feature_falg, mock_current_admin_user, monkeypatch, show_family_fixture, db_session): """Test create podcast for apple subscription feed type.""" monkeypatch.setattr(category_model, 'get_categories_by_ids', MagicMock( return_value={'items': ['Arts']} )) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(megaphone, 'create_or_update_podcast', MagicMock(return_value=None)) monkeypatch.setattr(show_family_model, 'create_show_family', MagicMock(return_value=show_family_fixture)) result = podcast.create_podcast({ 'channel_id': 'channel-id', 'network_id': 1, 'title': 'title', 'feed_type': 'apple-subscription' }) show_family_model.create_show_family.assert_called_once_with( {'network_id': 1, 'title': 'title', 'created_by': 2, 'updated_by': 2}, db_session) assert not megaphone.create_or_update_podcast.called assert not podcast.s3.check_s3_file_exists.called assert result['channel_id'] == 'channel-id' assert result['id'] == 5 assert result['show_family_id'] == 1 assert result['feed_type'] == 'apple-subscription' assert result['megaphone_id'] is None @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_create_podcast_for_youtube_feed_type(mock_feature_falg, mock_current_admin_user, monkeypatch, show_family_fixture, db_session): """Test create podcast for toutube feed type.""" monkeypatch.setattr(category_model, 'get_categories_by_ids', MagicMock( return_value={'items': ['Arts']} )) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(megaphone, 'create_or_update_podcast', MagicMock(return_value=None)) monkeypatch.setattr(show_family_model, 'create_show_family', MagicMock(return_value=show_family_fixture)) result = podcast.create_podcast({ 'channel_id': 'channel-id', 'network_id': 1, 'title': 'title', 'feed_type': 'youtube' }) show_family_model.create_show_family.assert_called_once_with( {'network_id': 1, 'title': 'title', 'created_by': 2, 'updated_by': 2}, db_session) assert not podcast.s3.check_s3_file_exists.called assert not megaphone.create_or_update_podcast.called assert result['channel_id'] == 'channel-id' assert result['id'] == 5 assert result['show_family_id'] == 1 assert result['feed_type'] == 'youtube' assert result['megaphone_id'] is None def test_get_podcasts(monkeypatch, podcast_fixture, mock_current_user): """Test get podcasts.""" monkeypatch.setattr( podcast_model, 'get_podcasts', MagicMock( return_value={'items': [podcast_fixture]})) monkeypatch.setattr( episode_model, 'get_num_episodes_for_podcast_ids', MagicMock( return_value={podcast_fixture['id']: 5})) result = podcast.get_podcasts() assert result['items'] == [podcast_fixture] assert result['items'][0]['num_episodes'] == 5 def test_get_podcasts_with_network_ids(monkeypatch, podcast_fixture, mock_current_user): """Test get podcasts with network ids.""" expected = {'items': [podcast_fixture]} monkeypatch.setattr(podcast_model, 'get_podcasts', MagicMock(return_value=expected)) result = podcast.get_podcasts(1, 1, network_ids=[1]) podcast_model.get_podcasts.assert_called_once_with(1, 1, [1]) assert expected == result def test_get_podcasts_with_invalid_network_ids(mock_current_user): """Test get podcasts with invalid network ids.""" with pytest.raises(OwsError) as err: podcast.get_podcasts(1, 1, [5]) assert err.value.status == 403 def test_get_podcasts_with_network_ids_and_ids( monkeypatch, podcast_fixture, podcast_fixture_2, mock_current_network_admin_user): """Test get podcasts with network ids and ids.""" expected = {'items': [podcast_fixture, podcast_fixture_2]} monkeypatch.setattr(podcast_model, 'get_podcasts', MagicMock(return_value=expected)) result = podcast.get_podcasts(1, 1, [1], [2]) podcast_model.get_podcasts.assert_called_once_with(1, 1, [2, 1]) assert expected == result def test_get_podcasts_with_ids(monkeypatch, podcast_fixture, mock_current_user): """Test get podcasts with ids.""" expected = {'items': [podcast_fixture]} monkeypatch.setattr(podcast_model, 'get_podcasts', MagicMock(return_value=expected)) result = podcast.get_podcasts(1, 1, ids=[1]) podcast_model.get_podcasts.assert_called_once_with(1, 1, [1]) assert expected == result def test_get_podcasts_with_invalid_ids(mock_current_user): """Test get podcasts with invalid ids.""" with pytest.raises(OwsError) as err: podcast.get_podcasts(1, 1, ids=[1, 2]) assert err.value.status == 403 def test_get_podcasts_with_network_ids_show_level(monkeypatch, podcast_fixture, mock_current_podcast_level_user): """Test get podcasts with network ids for show level user.""" expected = {'items': [podcast_fixture]} monkeypatch.setattr(podcast_model, 'get_podcasts', MagicMock(return_value=expected)) result = podcast.get_podcasts(1, 1, network_ids=[1]) podcast_model.get_podcasts.assert_called_once_with(1, 1, [1]) assert expected == result @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_update_podcast(mock_get_feature_flag, monkeypatch, mock_current_admin_user, participant_fixture): """Test update podcast.""" data = dict( title='title 2', participants=[participant_fixture], description='description 2') monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': 1})) result = podcast.update_podcast(1, data) assert ApiPodcast.update.call_args[0][1] == { 'itunesCategories': ['Active Category', 'Inactive Category'], 'summary': 'description 2', 'externalId': 1, 'title': 'title 2', 'slug': 'slug-123', 'author': 'Tom', 'ownerName': 'Bob', 'copyright': 'copyright', 'link': 'http://domain.dom', 'ownerEmail': 'email@domain.dom', 'explicit': False, 'language': 'en', 'podcastType': 'episodic', 'backgroundImageFileUrl': 'http://url/images/xlarge_cover/filename.jpg' } assert result['participants'] == [{'id': 1, 'name': 'Bill', 'podcast_id': 1, 'role': 'other', 'participant_id': 1}] def test_update_podcast_read_only(mock_current_read_only_user, participant_fixture): """Test update podcast fails if user is read only.""" data = dict( title='title 2', participants=[participant_fixture], description='description 2' ) with pytest.raises(OwsError) as err: podcast.update_podcast(1, data) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_update_podcast_and_update_megaphone_for_public_rss( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, seasons_fixture, db_session_fixture ): """Test update podcast invokes a megaphone create call when feed type is public-rss.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['seasons'] = seasons_fixture podcast_fixture['show_type'] = 'serial' podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_logic, 'current_user_owns_podcast_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(season_model, 'create_seasons', MagicMock()) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': MEGAPHONE_ID})) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(show_family_model, 'get_show_family_by_id', MagicMock()) monkeypatch.setattr(podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock()) monkeypatch.setattr(show_family_model, 'update_show_family', MagicMock()) result = podcast.update_podcast(podcast_id, podcast_fixture) podcast_model.get_podcast_by_id.assert_called_once_with(1) podcast_model.update_podcast.assert_any_call(podcast_id, podcast_fixture, db_session_fixture) season_model.create_seasons.assert_called_once_with(1, seasons_fixture, True, db_session_fixture) assert not show_family_model.get_show_family_by_id.called assert not podcast_model.get_earliest_feeds_by_show_family_ids.called assert not show_family_model.update_show_family.called assert podcast.s3.check_s3_file_exists.called assert ApiPodcast.update.called assert result['description'] == 'test description' @patch('podcast.logic.podcast.sentry.sentry_client') @patch('podcast.logic.podcast.sentry.send_to_sentry') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_and_update_megaphone_for_public_rss_and_log_silently_sentry_error( mock_get_feature_flag, mock_send_to_sentry, mock_sentry_client, monkeypatch, mock_current_network_admin_user, podcast_fixture, db_session_fixture, show_family_fixture ): """Test update podcast invokes a megaphone create call when feed type is public-rss. Also, log silently sentry error while show family update. """ podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_logic, 'current_user_owns_podcast_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': MEGAPHONE_ID})) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(show_family_model, 'get_show_family_by_id', MagicMock(return_value=show_family_fixture)) monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock(side_effect=OwsError.internal_server_error()) ) podcast.update_podcast(podcast_id, podcast_fixture) mock_send_to_sentry.assert_called_once_with(ANY, 500, {}, 'Internal server error.') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_and_update_megaphone_for_public_rss_and_no_show_family_update( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, db_session_fixture, podcast_fixture_2 ): """Test update podcast invokes a megaphone update call when feed type is public-rss and no show family update.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['feed_type'] = 'private-rss' podcast_fixture['artwork_filename'] = 'test-artwork' podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_v2_logic, 'current_user_owns_show_family_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'commit_or_delete_asset', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value='megaphone_data')) monkeypatch.setattr(show_family_model, 'get_show_family_by_id', MagicMock()) monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock(return_value={'items': [podcast_fixture_2]}) ) monkeypatch.setattr(show_family_model, 'update_show_family', MagicMock()) result = podcast.update_podcast(podcast_id, podcast_fixture) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_once_with([1]) assert not show_family_model.get_show_family_by_id.called assert not show_family_model.update_show_family.called assert result['description'] == 'test description' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_and_update_megaphone_for_private_rss( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, db_session_fixture, show_family_fixture ): """Test update podcast invokes a megaphone update call when feed type is private-rss.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['feed_type'] = 'private-rss' podcast_fixture['artwork_filename'] = 'test-artwork' podcast_fixture['title'] = 'test title' podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_v2_logic, 'current_user_owns_show_family_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'commit_or_delete_asset', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value='megaphone_data')) monkeypatch.setattr(show_family_model, 'get_show_family_by_id', MagicMock(return_value=show_family_fixture)) monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock(return_value={'items': [podcast_fixture]}) ) monkeypatch.setattr(show_family_model, 'update_show_family', MagicMock()) result = podcast.update_podcast(podcast_id, podcast_fixture) podcast_model.get_podcast_by_id.assert_called_once_with(1) podcast_model.update_podcast.assert_any_call(podcast_id, podcast_fixture, db_session_fixture) oat.commit_or_delete_asset.assert_called_with('test-artwork', 1, 'artwork', 'podcast') show_family_model.get_show_family_by_id.assert_called_once_with(1) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_once_with([1]) show_family_model.update_show_family.assert_called_once_with(1, {'title': 'test title'}, db_session_fixture) assert ApiPodcast.update.called assert podcast.s3.check_s3_file_exists.called assert result['title'] == 'test title' assert result['description'] == 'test description' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_and_update_megaphone_for_private_rss_and_no_show_family_update( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, db_session_fixture, show_family_fixture ): """Test update podcast invokes a megaphone update call when feed type is private-rss and no show family update.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['feed_type'] = 'private-rss' podcast_fixture['artwork_filename'] = 'test-artwork' podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_v2_logic, 'current_user_owns_show_family_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'commit_or_delete_asset', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value='megaphone_data')) monkeypatch.setattr(show_family_model, 'get_show_family_by_id', MagicMock(return_value=show_family_fixture)) monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock(return_value={'items': [podcast_fixture]}) ) monkeypatch.setattr(show_family_model, 'update_show_family', MagicMock()) result = podcast.update_podcast(podcast_id, podcast_fixture) show_family_model.get_show_family_by_id.assert_called_once_with(1) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_once_with([1]) assert not show_family_model.update_show_family.called assert result['description'] == 'test description' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_and_update_megaphone_for_apple_subscription( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, db_session_fixture ): """Test update podcast invokes a megaphone update call when feed type is apple-subscription.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['feed_type'] = 'apple-subscription' podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_v2_logic, 'current_user_owns_show_family_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'commit_or_delete_asset', MagicMock()) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value='megaphone_data')) result = podcast.update_podcast(podcast_id, podcast_fixture) podcast_model.get_podcast_by_id.assert_called_once_with(1) podcast_model.update_podcast.assert_any_call(podcast_id, podcast_fixture, db_session_fixture) assert not oat.commit_or_delete_asset.called assert not ApiPodcast.update.called assert not podcast.s3.check_s3_file_exists.called assert result['description'] == 'test description' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_update_podcast_and_update_megaphone_for_youtube( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, db_session_fixture ): """Test update podcast invokes a megaphone update call when feed type is youtube.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID podcast_fixture['feed_type'] = 'youtube' podcast_fixture['description'] = 'test description' podcast_id = podcast_fixture['id'] monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_logic, 'current_user_owns_podcast_or_raise', MagicMock()) monkeypatch.setattr(podcast_model, 'update_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'commit_or_delete_asset', MagicMock()) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value='megaphone_data')) result = podcast.update_podcast(podcast_id, podcast_fixture) podcast_model.get_podcast_by_id.assert_called_once_with(1) podcast_model.update_podcast.assert_any_call(podcast_id, podcast_fixture, db_session_fixture) assert not podcast.s3.check_s3_file_exists.called assert not ApiPodcast.update.called assert result['description'] == 'test description' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_update_podcast_with_seasons_failure( mock_get_feature_flag, monkeypatch, mock_current_admin_user, podcast_fixture, seasons_fixture): """Test update podcast with seasons failure.""" monkeypatch.setattr(user_logic, 'current_user_has_read_only_access_then_raise', MagicMock()) monkeypatch.setattr(user_logic, 'current_user_owns_podcast_id_or_raise', MagicMock()) podcast_fixture['seasons'] = seasons_fixture with pytest.raises(OwsError) as err: podcast.update_podcast(1, podcast_fixture) err.value.status == 400 err.value.message == 'Invalid field seasons for show type: episodic' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_update_podcast_commit(mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_admin_user): """Test update podcast and commits artwork.""" data = dict( title='title 2', artwork_filename='cowpoke' ) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(oat, 'commit', MagicMock()) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': 1})) podcast.update_podcast(podcast_fixture['id'], data) oat.commit.assert_called_with('cowpoke', podcast_fixture['id']) @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_update_podcast_delete(mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_admin_user): """Test update podcast and deletes artwork.""" data = dict( title='title 2', artwork_filename=None ) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(oat, 'delete_asset', MagicMock()) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': 1})) podcast.update_podcast(podcast_fixture['id'], data) oat.delete_asset.assert_called_with('artwork', podcast_fixture['id'], 'podcast') def test_delete_podcast(monkeypatch, podcast_fixture, mock_current_admin_user): """Test delete podcast.""" monkeypatch.setattr(podcast_model, 'delete_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_model, 'delete_favorite_podcast_by_podcast_id', MagicMock( return_value=None)) monkeypatch.setattr(megaphone, 'delete_podcast', MagicMock(return_value={'status': 'OK'})) result = podcast.delete_podcast(podcast_fixture['id']) podcast_model.delete_podcast.assert_called_once() user_model.delete_favorite_podcast_by_podcast_id.assert_called_once() assert result == podcast_fixture def test_delete_podcast_and_show_family( monkeypatch, podcast_fixture, mock_current_admin_user, db_session_fixture): """Test delete podcast and show family.""" monkeypatch.setattr(podcast_model, 'delete_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_model, 'delete_favorite_podcast_by_podcast_id', MagicMock( return_value=None)) monkeypatch.setattr(megaphone, 'delete_podcast', MagicMock(return_value={'status': 'OK'})) monkeypatch.setattr(podcast_model, 'get_feeds_by_show_family_id', MagicMock(return_value={'items': []})) monkeypatch.setattr(show_family_model, 'delete_show_family', MagicMock()) result = podcast.delete_podcast(podcast_fixture['id']) podcast_model.delete_podcast.assert_called_once_with(1, db_session_fixture) megaphone.delete_podcast.assert_called_once_with('megaphone_id_1', 1) user_model.delete_favorite_podcast_by_podcast_id.assert_called_once_with(1, db_session_fixture) podcast_model.get_feeds_by_show_family_id.assert_called_once_with(1, db_session_fixture) show_family_model.delete_show_family.assert_called_once_with(1, db_session_fixture) assert result == podcast_fixture def test_delete_podcast_but_not_show_family( monkeypatch, podcast_fixture, podcast_fixture_2, mock_current_admin_user, db_session_fixture ): """Test delete podcast but not show family.""" monkeypatch.setattr(podcast_model, 'delete_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(user_model, 'delete_favorite_podcast_by_podcast_id', MagicMock( return_value=None)) monkeypatch.setattr(megaphone, 'delete_podcast', MagicMock(return_value={'status': 'OK'})) monkeypatch.setattr( podcast_model, 'get_feeds_by_show_family_id', MagicMock(return_value={'items': [podcast_fixture_2]}) ) monkeypatch.setattr(show_family_model, 'delete_show_family', MagicMock()) result = podcast.delete_podcast(podcast_fixture['id']) podcast_model.delete_podcast.assert_called_once_with(1, db_session_fixture) megaphone.delete_podcast.assert_called_once_with('megaphone_id_1', 1) user_model.delete_favorite_podcast_by_podcast_id.assert_called_once_with(1, db_session_fixture) podcast_model.get_feeds_by_show_family_id.assert_called_once_with(1, db_session_fixture) assert not show_family_model.delete_show_family.called assert result == podcast_fixture def test_delete_podcast_not_admin(monkeypatch, podcast_fixture, mock_current_user): """Test delete podcast.""" monkeypatch.setattr(podcast_model, 'delete_podcast', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(megaphone, 'delete_podcast', MagicMock(return_value={'status': 'OK'})) monkeypatch.setattr(user_model, 'delete_favorite_podcast_by_podcast_id', MagicMock( return_value=None)) with pytest.raises(OwsError) as err: podcast.delete_podcast(podcast_fixture['id']) user_model.delete_favorite_podcast_by_podcast_id.assert_not_called() assert err.value.status == 403 def test_delete_podcast_return_data(monkeypatch, mock_current_admin_user): """Test that delete podcast returns deleted item.""" podcast_id = 1 monkeypatch.setattr(megaphone, 'delete_podcast', MagicMock(return_value=None)) result = podcast.delete_podcast(podcast_id) assert result['id'] == podcast_id def test_delete_podcast_bad_request(): """Test that delete podcast by None returns bad request.""" with pytest.raises(OwsError) as err: podcast.delete_podcast(None) assert err.value.status == status.BAD_REQUEST def test_delete_podcast_not_found(monkeypatch, mock_current_admin_user): """Test that delete podcast by wrong id returns NOT_FOUND.""" podcast_id = 10 monkeypatch.setattr(megaphone, 'delete_podcast', MagicMock(return_value=None)) with pytest.raises(OwsError) as err: podcast.delete_podcast(podcast_id) assert err.value.status == status.NOT_FOUND @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_podcasts_by_ids(mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_user): """Test get podcasts by ids.""" expected = {'items': [podcast_fixture]} monkeypatch.setattr(podcast_model, 'get_podcasts_by_ids', MagicMock(return_value=expected)) result = podcast.get_podcasts_by_ids([1, 2]) podcast_model.get_podcasts_by_ids.assert_called_once_with([1, 2]) assert result == expected assert result['items'][0]['num_episodes'] == 1 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_show_family_access_success_admin( mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test update podcast show family access success for admin user.""" data = dict( title='title 2', description='description 2' ) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': 1})) result = podcast.update_podcast(1, data) assert ApiPodcast.update.call_args[0][1] == { 'itunesCategories': ['Active Category', 'Inactive Category'], 'summary': 'description 2', 'externalId': 1, 'title': 'title 2', 'slug': 'slug-123', 'author': 'Tom', 'ownerName': 'Bob', 'copyright': 'copyright', 'link': 'http://domain.dom', 'ownerEmail': 'email@domain.dom', 'explicit': False, 'language': 'en', 'podcastType': 'episodic', 'backgroundImageFileUrl': 'http://url/images/xlarge_cover/filename.jpg' } assert result['description'] == 'description 2' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_show_family_access_success_network_admin( mock_get_feature_flag, monkeypatch, mock_current_network_admin_user, participant_fixture): """Test update podcast show family access success for network admin user.""" data = dict( title='title 2', participants=[participant_fixture], description='description 2') monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': 1})) result = podcast.update_podcast(1, data) assert ApiPodcast.update.call_args[0][1] == { 'itunesCategories': ['Active Category', 'Inactive Category'], 'summary': 'description 2', 'externalId': 1, 'title': 'title 2', 'slug': 'slug-123', 'author': 'Tom', 'ownerName': 'Bob', 'copyright': 'copyright', 'link': 'http://domain.dom', 'ownerEmail': 'email@domain.dom', 'explicit': False, 'language': 'en', 'podcastType': 'episodic', 'backgroundImageFileUrl': 'http://url/images/xlarge_cover/filename.jpg' } assert result['description'] == 'description 2' assert result['participants'] == [{'id': 1, 'name': 'Bill', 'podcast_id': 1, 'role': 'other', 'participant_id': 1}] @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_show_family_access_success_show_level_user( mock_get_feature_flag, monkeypatch, mock_current_podcast_level_user): """Test update podcast show family access success for show level user.""" data = dict( title='title 2', description='description 2' ) monkeypatch.setattr(podcast.s3, 'check_s3_file_exists', MagicMock(return_value=None)) monkeypatch.setattr(oat, 'get_podcast_assets', MagicMock( return_value={ asset_types_consts.SUBTYPE_XLARGE_COVER: 'images/xlarge_cover/filename.jpg', 'x_large_image_url': 'http://url/images/xlarge_cover/filename.jpg', } )) monkeypatch.setattr(ApiPodcast, 'update', MagicMock(return_value={'id': 1})) result = podcast.update_podcast(1, data) assert ApiPodcast.update.call_args[0][1] == { 'itunesCategories': ['Active Category', 'Inactive Category'], 'summary': 'description 2', 'externalId': 1, 'title': 'title 2', 'slug': 'slug-123', 'author': 'Tom', 'ownerName': 'Bob', 'copyright': 'copyright', 'link': 'http://domain.dom', 'ownerEmail': 'email@domain.dom', 'explicit': False, 'language': 'en', 'podcastType': 'episodic', 'backgroundImageFileUrl': 'http://url/images/xlarge_cover/filename.jpg' } assert result['description'] == 'description 2' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_show_family_access_failure_network_admin( mock_get_feature_flag, mock_current_network_admin_user_second): """Test update podcast with no show family access failurefor network admin user.""" data = dict( title='title 2', description='description 2', show_family_id=1 ) with pytest.raises(OwsError) as err: podcast.update_podcast(1, data) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_update_podcast_show_family_access_failure_show_level_user( mock_get_feature_flag, mock_current_show_level_user): """Test update podcast with no show family access failure for show level user.""" data = dict( title='title 2', description='description 2', show_family_id=1 ) with pytest.raises(OwsError) as err: podcast.update_podcast(1, data) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_podcast_by_id(mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_user): """Test get podcast by id.""" monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) result = podcast.get_podcast_by_id(1) podcast_model.get_podcast_by_id.assert_called_once_with(1) assert result == podcast_fixture @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_podcast_by_id_failure( mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_network_admin_user_second): """Test get podcast by id.""" monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) with pytest.raises(OwsError) as err: podcast.get_podcast_by_id(1) podcast_model.get_podcast_by_id.assert_called_once_with(1) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_podcast_by_id_show_family_access(mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_user): """Test get podcast by id with show family access.""" monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) result = podcast.get_podcast_by_id(1) podcast_model.get_podcast_by_id.assert_called_once_with(1) assert result == podcast_fixture @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_podcast_by_id_show_family_access_failure( mock_get_feature_flag, monkeypatch, podcast_fixture, mock_current_network_admin_user_second): """Test get podcast by id with show family access failure.""" monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) with pytest.raises(OwsError) as err: podcast.get_podcast_by_id(1) podcast_model.get_podcast_by_id.assert_called_once_with(1) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_podcasts_by_ids_show_family_access( mock_get_feature_flag, monkeypatch, podcast_fixture, podcast_fixture_2, mock_current_producer_user): """Test get podcasts by ids with show family access.""" expected = {'items': [podcast_fixture, podcast_fixture_2]} monkeypatch.setattr(podcast_model, 'get_podcasts_by_ids', MagicMock(return_value=expected)) result = podcast.get_podcasts_by_ids([2]) podcast_model.get_podcasts_by_ids.assert_called_once_with([2]) assert result == expected assert result['items'][0]['num_episodes'] == 1 assert result['items'][1]['num_episodes'] == 0 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_podcasts_by_ids_show_family_access_failure( mock_get_feature_flag, monkeypatch, podcast_fixture, podcast_fixture_2, mock_current_user): """Test get podcasts by ids with show family access.""" expected = {'items': [podcast_fixture, podcast_fixture_2]} monkeypatch.setattr(podcast_model, 'get_podcasts_by_ids', MagicMock(return_value=expected)) with pytest.raises(OwsError) as err: podcast.get_podcasts_by_ids([1, 2]) podcast_model.get_podcasts_by_ids.assert_called_once_with([1, 2]) assert err.value.status == 403 def test_attach_num_episodes(monkeypatch, podcast_fixture, podcast_fixture_2): """Test attach_num_episodes.""" podcasts = [podcast_fixture, podcast_fixture_2] monkeypatch.setattr(episode_model, 'get_num_episodes_for_podcast_ids', MagicMock(return_value={1: 1})) podcast.attach_num_episodes(podcasts) episode_model.get_num_episodes_for_podcast_ids.assert_called_once_with([1, 2]) assert podcasts[0]['num_episodes'] == 1 assert podcasts[1]['num_episodes'] == 0 def test_get_public_and_private_rss_podcasts(monkeypatch, podcast_fixture, podcast_fixture_2): """Test get_public_and_private_rss_podcasts.""" expected = {'items': [podcast_fixture, podcast_fixture_2]} monkeypatch.setattr( user_v2_logic, 'public_and_private_rss_podcasts_owned_by_current_user', MagicMock(return_value=expected) ) result = podcast.get_public_and_private_rss_podcasts() user_v2_logic.public_and_private_rss_podcasts_owned_by_current_user.assert_called_once() assert result == expected assert result['items'][0]['num_episodes'] == 1 assert result['items'][1]['num_episodes'] == 0 def test_get_object_asset_by_id_and_type_podcast_artwork_exists_in_output_bucket( monkeypatch, mock_get_object_asset_by_id_and_type_artwork, mock_current_network_admin_user): """Test get podcast artwork asset that already exists in output bucket.""" assert_url = 'https://{}/39105918_39da_4fda_a7c4_6bbb0dc269ce.jpg'.format(config.OUTPUT_CDN_BASE_URL) signed_url = '{}?Policy=policy&Signature=signature&Key-Pair-Id=key-pair'.format(assert_url) monkeypatch.setattr(s3, 'check_s3_file_exists', MagicMock(return_value='')) monkeypatch.setattr(api_utils, 'asset_url', MagicMock(return_value=assert_url)) monkeypatch.setattr(signed_urls, 'sign_url', MagicMock(return_value=signed_url)) result = podcast.get_podcast_original_artwork_asset(1) oat.get_object_asset_by_id_and_type.assert_called_once_with(1, 'podcast', ['TIF', 'JPG']) s3.check_s3_file_exists.assert_called_once_with( config.OUTPUT_ASSETS_BUCKET_NAME, '39105918_39da_4fda_a7c4_6bbb0dc269ce.jpg') api_utils.asset_url.assert_called_once_with('39105918_39da_4fda_a7c4_6bbb0dc269ce.jpg') signed_urls.sign_url.assert_called_once_with(assert_url) assert result['original_artwork_url'] == signed_url def test_get_object_asset_by_id_and_type_podcast_artwork_copy_in_output_bucket( monkeypatch, mock_get_object_asset_by_id_and_type_artwork, mock_current_user): """Test get podcast artwork asset that's copied to output bucket from input bucket.""" assert_url = 'https://{}/39105918_39da_4fda_a7c4_6bbb0dc269ce.jpg'.format(config.OUTPUT_CDN_BASE_URL) signed_url = '{}?Policy=policy&Signature=signature&Key-Pair-Id=key-pair'.format(assert_url) monkeypatch.setattr(s3, 'check_s3_file_exists', MagicMock( return_value=OwsError.internal_server_error())) monkeypatch.setattr(s3, 'copy_s3_file', MagicMock(return_value={})) monkeypatch.setattr(api_utils, 'asset_url', MagicMock(return_value=assert_url)) monkeypatch.setattr(signed_urls, 'sign_url', MagicMock(return_value=signed_url)) result = podcast.get_podcast_original_artwork_asset(1) oat.get_object_asset_by_id_and_type.assert_called_once_with(1, 'podcast', ['TIF', 'JPG']) s3.check_s3_file_exists.assert_called_once_with( config.OUTPUT_ASSETS_BUCKET_NAME, '39105918_39da_4fda_a7c4_6bbb0dc269ce.jpg') api_utils.asset_url.assert_called_once_with('39105918_39da_4fda_a7c4_6bbb0dc269ce.jpg') signed_urls.sign_url.assert_called_once_with(assert_url) assert result['original_artwork_url'] == signed_url def test_get_object_asset_by_id_and_type_podcast_artwork_copy_no_access(monkeypatch, mock_current_user): """Test get podcast artwork asset no access.""" with pytest.raises(OwsError) as err: podcast.get_podcast_original_artwork_asset(2) assert err.value.status == 403