"""Test for Feed logic tier.""" from unittest.mock import MagicMock import pytest from podcast.constants import asset_types as asset_types_consts from podcast.logic import episode as episode_logic from podcast.logic import feed from podcast.logic import podcast as podcast_logic from podcast.models import ows_asset_transcoder as oat from podcast.models import podcast as podcast_model from podcast.models import podcast_season as podcast_season_model from podcast.models.api_podcast import ApiPodcast from podcast.utils.exc import OwsError MEGAPHONE_ID = '6bf5bea4-a1d4-11e6-8dea-b334e2aa4720' def test_create_feed_public_rss( monkeypatch, mock_current_admin_user, podcast_fixture_2, podcast_2_seasons_fixture, podcast_2_seasons_replica_fixture): """Test create feed for public rss.""" podcast_fixture_2['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) podcast_fixture_2['seasons'] = podcast_2_seasons_fixture monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture_2)) monkeypatch.setattr(podcast_logic.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(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) monkeypatch.setattr(podcast_season_model, 'create_seasons', MagicMock( return_value=podcast_2_seasons_replica_fixture) ) result = feed.create_feed({ 'podcast_id': 2, 'show_family_id': 2, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'episode_ids': [1, 2], 'is_copy_ad_locations': False }) podcast_model.get_podcast_by_id.assert_called_once_with(2) oat.commit.assert_called_once() ApiPodcast.create.assert_called_once() assert podcast_season_model.create_seasons.called episode_logic.replicate_episodes_and_create_assets.assert_called_once_with( 2, result['id'], [1, 2], podcast_2_seasons_replica_fixture, 'bulk', False, False) assert result['title'] == 'test feed title' assert result['slug'] == 'testslugforpublicrss' assert result['description'] == 'test_feed_summary' assert result['owner'] == 'Sally' assert result['channel_id'] is None def test_create_feed_private_rss( monkeypatch, mock_current_admin_user, podcast_fixture_2, podcast_2_seasons_fixture, podcast_2_seasons_replica_fixture): """Test create feed for private rss.""" podcast_fixture_2['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) podcast_fixture_2['seasons'] = podcast_2_seasons_fixture monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture_2)) monkeypatch.setattr(podcast_logic.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(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) monkeypatch.setattr(podcast_season_model, 'create_seasons', MagicMock( return_value=podcast_2_seasons_replica_fixture) ) result = feed.create_feed({ 'podcast_id': 2, 'show_family_id': 2, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'slugprivaterss', 'episode_ids': [1, 2], 'is_copy_ad_locations': False }) podcast_model.get_podcast_by_id.assert_called_once_with(2) oat.commit.assert_called_once() ApiPodcast.create.assert_called_once() assert podcast_season_model.create_seasons.called episode_logic.replicate_episodes_and_create_assets.assert_called_once_with( 2, result['id'], [1, 2], podcast_2_seasons_replica_fixture, 'bulk', False, False) assert result['title'] == 'test feed title' assert result['slug'] == 'slugprivaterss' assert result['description'] == 'test_feed_summary' assert result['owner'] == 'Sally' assert result['channel_id'] is None def test_create_feed_with_no_seasons( monkeypatch, mock_current_admin_user, podcast_fixture): """Test create feed.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast_logic.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(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) monkeypatch.setattr(podcast_season_model, 'create_seasons', MagicMock()) result = feed.create_feed({ 'podcast_id': 1, 'show_family_id': 1, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'episode_ids': [1, 2], 'is_copy_ad_locations': False }) assert not podcast_season_model.create_seasons.called episode_logic.replicate_episodes_and_create_assets.assert_called_once_with( 1, result['id'], [1, 2], None, 'bulk', False, False) assert result['title'] == 'test feed title' def test_create_feed_with_show_type_episodic( monkeypatch, mock_current_admin_user, podcast_fixture, podcast_1_seasons_fixture): """Test create feed with episodic show type to assert seasons are not being created.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) podcast_fixture['seasons'] = podcast_1_seasons_fixture monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast_logic.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(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) monkeypatch.setattr(podcast_season_model, 'create_seasons', MagicMock()) result = feed.create_feed({ 'podcast_id': 1, 'show_family_id': 1, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'episode_ids': [1, 2], 'is_copy_ad_locations': False }) assert not podcast_season_model.create_seasons.called episode_logic.replicate_episodes_and_create_assets.assert_called_once_with( 1, result['id'], [1, 2], None, 'bulk', False, False) assert result['title'] == 'test feed title' def test_create_feed_without_episodes( monkeypatch, mock_current_admin_user, podcast_fixture): """Test create feed.""" podcast_fixture['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) monkeypatch.setattr(ApiPodcast, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture)) monkeypatch.setattr(podcast_logic.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(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) feed.create_feed({ 'podcast_id': 1, 'show_family_id': 1, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'episode_ids': [], 'is_copy_ad_locations': False }) assert not episode_logic.replicate_episodes_and_create_assets.called def test_create_feed_fails_for_read_only_user(mock_current_read_only_user): """Test create feed fails if user is read only.""" with pytest.raises(OwsError) as err: feed.create_feed({ 'podcast_id': 1, 'show_family_id': 1, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss' }) assert err.value.status == 403 def test_create_feed_fails_for_user_with_no_access(mock_current_network_admin_user_second): """Test create feed fails if user does not have access to show family.""" with pytest.raises(OwsError) as err: feed.create_feed({ 'podcast_id': 1, 'show_family_id': 1, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'public-rss', 'channel_id': 'test_channel_id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'is_copy_ad_locations': False }) assert err.value.status == 403 def test_create_feed_apple_subscription( monkeypatch, mock_current_admin_user, podcast_fixture_2, podcast_2_seasons_fixture, podcast_2_seasons_replica_fixture): """Test create feed for public rss.""" podcast_fixture_2['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) podcast_fixture_2['seasons'] = podcast_2_seasons_fixture monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture_2)) monkeypatch.setattr(podcast_logic.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, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) monkeypatch.setattr(podcast_season_model, 'create_seasons', MagicMock( return_value=podcast_2_seasons_replica_fixture) ) result = feed.create_feed({ 'podcast_id': 2, 'show_family_id': 2, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'apple-subscription', 'channel_id': 'apple-subscription-channel-id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'episode_ids': [1, 2], 'is_copy_ad_locations': False }) podcast_model.get_podcast_by_id.assert_called_once_with(2) oat.commit.assert_called_once() assert not ApiPodcast.create.called assert podcast_season_model.create_seasons.called episode_logic.replicate_episodes_and_create_assets.assert_called_once_with( 2, result['id'], [1, 2], podcast_2_seasons_replica_fixture, 'bulk', True, False) assert result['link'] == 'http://domain.dom' assert result['channel_id'] == 'apple-subscription-channel-id' assert result['explicit'] == 'explicit' assert result['show_type'] == 'serial' assert result['slug'] is None def test_create_feed_youtube( monkeypatch, mock_current_admin_user, podcast_fixture_2, podcast_2_seasons_fixture, podcast_2_seasons_replica_fixture): """Test create feed for public rss.""" podcast_fixture_2['megaphone_id'] = MEGAPHONE_ID megaphone_data = dict( id=MEGAPHONE_ID, uid='bang' ) podcast_fixture_2['seasons'] = podcast_2_seasons_fixture monkeypatch.setattr(podcast_model, 'get_podcast_by_id', MagicMock(return_value=podcast_fixture_2)) monkeypatch.setattr(podcast_logic.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, 'create', MagicMock(return_value=megaphone_data)) monkeypatch.setattr(episode_logic, 'replicate_episodes_and_create_assets', MagicMock()) monkeypatch.setattr(podcast_season_model, 'create_seasons', MagicMock( return_value=podcast_2_seasons_replica_fixture) ) result = feed.create_feed({ 'podcast_id': 2, 'show_family_id': 2, 'title': 'test feed title', 'description': 'test_feed_summary', 'feed_type': 'youtube', 'channel_id': 'youtube-channel-id', 'artwork_filename': 'test_artwork.jpg', 'slug': 'testslugforpublicrss', 'episode_ids': [1, 2], 'is_copy_ad_locations': False }) podcast_model.get_podcast_by_id.assert_called_once_with(2) oat.commit.assert_called_once() assert not ApiPodcast.create.called assert podcast_season_model.create_seasons.called episode_logic.replicate_episodes_and_create_assets.assert_called_once_with( 2, result['id'], [1, 2], podcast_2_seasons_replica_fixture, 'bulk', False, False) assert result['copyright'] == 'copyright' assert result['channel_id'] == 'youtube-channel-id' assert result['categories'] == [3, 4] assert result['host'] == 'Betty' assert result['slug'] is None def test_get_feeds_by_show_family_id(monkeypatch, podcast_fixture, mock_current_admin_user): """Test get feeds(podcasts) by show family id.""" expected = {'items': [podcast_fixture]} monkeypatch.setattr(podcast_model, 'get_feeds_by_show_family_id', MagicMock(return_value=expected)) result = feed.get_feeds_by_show_family_id(1) podcast_model.get_feeds_by_show_family_id.assert_called_once_with(1) assert expected == result def test_get_feeds_by_show_family_id_with_show_family_access(monkeypatch, podcast_fixture, mock_current_podcast_level_user): """Test get feeds(podcasts) by show family id for using having access to show family.""" expected = {'items': [podcast_fixture]} monkeypatch.setattr(podcast_model, 'get_feeds_by_show_family_id', MagicMock(return_value=expected)) result = feed.get_feeds_by_show_family_id(1) podcast_model.get_feeds_by_show_family_id.assert_called_once_with(1) assert expected == result def test_get_feeds_by_show_family_id_fails_with_no_show_family_access(mock_current_user): """Test get feeds(podcasts) fails if user does not have access to show family.""" with pytest.raises(OwsError) as err: feed.get_feeds_by_show_family_id(2) assert err.value.status == 403 def test_get_earliest_feeds_by_show_family_ids_admin_user( monkeypatch, podcast_fixture, podcast_fixture_2, mock_current_admin_user): """Test get_earliest_feeds_by_show_family_ids for org admin user.""" expected_data = [podcast_fixture, podcast_fixture_2] monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock( return_value={'items': expected_data})) result = feed.get_earliest_feeds_by_show_family_ids(['1', '2']) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_with(['1', '2']) assert result['items'] == expected_data assert result['items'][0]['num_episodes'] == 1 assert result['items'][1]['num_episodes'] == 0 def test_get_earliest_feeds_by_show_family_ids_network_admin_user( monkeypatch, podcast_fixture, mock_current_network_admin_user): """Test get_earliest_feeds_by_show_family_ids for network admin user.""" expected_data = [podcast_fixture] monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock( return_value={'items': expected_data})) result = feed.get_earliest_feeds_by_show_family_ids([1]) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_with([1]) assert result['items'] == expected_data assert result['items'][0]['num_episodes'] == 1 def test_get_earliest_feeds_by_show_family_ids_network_admin_user_no_access( monkeypatch, mock_current_network_admin_user_second): """Test get_earliest_feeds_by_show_family_ids for network admin user with no access.""" with pytest.raises(OwsError) as err: feed.get_earliest_feeds_by_show_family_ids([1]) assert err.value.status == 403 def test_get_earliest_feeds_by_show_family_ids_network_admin_user_no_show_family( monkeypatch, mock_current_network_admin_user): """Test get_earliest_feeds_by_show_family_ids for network admin user with no active show family.""" with pytest.raises(OwsError) as err: feed.get_earliest_feeds_by_show_family_ids([3]) assert err.value.status == 404 def test_get_earliest_feeds_by_show_family_ids_producer_user( monkeypatch, podcast_fixture, mock_current_user): """Test get_earliest_feeds_by_show_family_ids for producer user.""" expected_data = [podcast_fixture] monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock( return_value={'items': expected_data})) result = feed.get_earliest_feeds_by_show_family_ids([1]) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_with([1]) assert result['items'] == expected_data assert result['items'][0]['num_episodes'] == 1 def test_get_earliest_feeds_by_show_family_ids_show_level_user( monkeypatch, podcast_fixture, mock_current_podcast_level_user): """Test get_earliest_feeds_by_show_family_ids for show level user.""" expected_data = [podcast_fixture] monkeypatch.setattr( podcast_model, 'get_earliest_feeds_by_show_family_ids', MagicMock( return_value={'items': expected_data})) result = feed.get_earliest_feeds_by_show_family_ids([1]) podcast_model.get_earliest_feeds_by_show_family_ids.assert_called_with([1]) assert result['items'] == expected_data assert result['items'][0]['num_episodes'] == 1 def test_get_earliest_feeds_by_show_family_ids_show_level_user_no_access(monkeypatch, mock_current_show_level_user): """Test get_earliest_feeds_by_show_family_ids for show level user with no access.""" with pytest.raises(OwsError) as err: feed.get_earliest_feeds_by_show_family_ids([2]) assert err.value.status == 403