"""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