"""Test for transcribe logic tier.""" from unittest.mock import MagicMock from unittest.mock import patch from docx import Document import pytest from podcast.logic import transcription as transcription_logic from podcast.models import ows_asset_transcoder as oat from podcast.models import transcription as transcription_model from podcast.utils.exc import OwsError mock_transcript_items = [ { 'speaker_label': 'spkr_0', 'items': [ {'end_time': '1.0', 'start_time': '0.2', 'content': 'I'}, {'end_time': '2.0', 'start_time': '1.0', 'content': 'walk'}, {'end_time': '3.0', 'start_time': '2.0', 'content': 'a'}, {'end_time': '4.0', 'start_time': '3.0', 'content': 'lonely'}, {'end_time': '4.7', 'start_time': '4.0', 'content': 'road,'}, ] }, { 'speaker_label': 'spkr_1', 'items': [ {'end_time': '6.0', 'start_time': '5.2', 'content': 'Only'}, {'end_time': '7.0', 'start_time': '6.0', 'content': 'road'}, {'end_time': '8.0', 'start_time': '7.0', 'content': 'that'}, {'end_time': '9.0', 'start_time': '8.0', 'content': 'I'}, {'end_time': '10.0', 'start_time': '9.0', 'content': 'have'}, {'end_time': '11.0', 'start_time': '10.0', 'content': 'ever'}, {'end_time': '12.0', 'start_time': '11.0', 'content': 'known.'}, {'end_time': '13.0', 'start_time': '12.0', 'content': 'I'}, {'end_time': '14.0', 'start_time': '13.0', 'content': 'walk'}, {'end_time': '15.0', 'start_time': '14.0', 'content': 'alone.'}, ] } ] @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_transcribe(mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test transcribe.""" monkeypatch.setattr(transcription_logic, '_start_transcription', MagicMock()) monkeypatch.setattr(oat, 'get_episode_input_audio', MagicMock()) transcription_logic.start_for_episode(1, {'num_speakers': 4, 'language': 'en-US'}) assert transcription_model.get(1).is_transcript_processing is True @patch('podcast.logic.transcription._transcription_client') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_transcribe_1_speaker(mock_get_feature_flag, transcribe_client, monkeypatch, mock_current_admin_user): """Test transcribe 1 speaker.""" start_transcription_job_mock = MagicMock() transcribe_client.return_value.start_transcription_job = start_transcription_job_mock monkeypatch.setattr(transcription_logic, '_timestamp', MagicMock(return_value='12')) monkeypatch.setattr(oat, 'get_episode_input_audio', MagicMock(return_value='audiopow.wav')) transcription_logic.start_for_episode(1, {'num_speakers': 1, 'language': 'en-US'}) start_transcription_job_mock.assert_called_with( LanguageCode='en-US', Media={'MediaFileUri': 's3://test-orcd-podcast-input-bucket/audiopow.wav'}, MediaFormat='wav', OutputBucketName='test-orcd-podcast-output-bucket', Settings={}, TranscriptionJobName='owspodcasttranscribe_audiopow.wav_12') @patch('podcast.logic.transcription._transcription_client') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_transcribe_2_speaker(mock_get_feature_flag, transcribe_client, monkeypatch, mock_current_admin_user): """Test transcribe 2 speaker.""" start_transcription_job_mock = MagicMock() transcribe_client.return_value.start_transcription_job = start_transcription_job_mock monkeypatch.setattr(transcription_logic, '_timestamp', MagicMock(return_value='12')) monkeypatch.setattr(oat, 'get_episode_input_audio', MagicMock(return_value='audiopow.wav')) transcription_logic.start_for_episode(1, {'num_speakers': 2, 'language': 'en-US'}) start_transcription_job_mock.assert_called_with( LanguageCode='en-US', Media={'MediaFileUri': 's3://test-orcd-podcast-input-bucket/audiopow.wav'}, MediaFormat='wav', OutputBucketName='test-orcd-podcast-output-bucket', Settings={'MaxSpeakerLabels': 2, 'ShowSpeakerLabels': True}, TranscriptionJobName='owspodcasttranscribe_audiopow.wav_12') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_start_no_permission(mock_get_feature_flag, mock_current_user): """Does a permission check on start_for_episode.""" with pytest.raises(OwsError) as err: transcription_logic.start_for_episode(3, {'num_speakers': 2, 'language': 'en-US'}) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_get_transcription_no_permission(mock_get_feature_flag, mock_current_user): """Does a permission check on get_transcription.""" with pytest.raises(OwsError) as err: transcription_logic.get_transcription(3) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_get_file_permission(mock_get_feature_flag, mock_current_user): """Does a permission check.""" with pytest.raises(OwsError) as err: transcription_logic.get_file(3, 'doc', 10) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_get_file_doc(mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test get doc file.""" mock_transcription = transcription_model.Transcription() mock_transcription.transcript = {'transcript': mock_transcript_items} monkeypatch.setattr(transcription_model, 'get', MagicMock(return_value=mock_transcription)) monkeypatch.setattr(transcription_logic, 'get_doc', MagicMock(return_value='12')) resp = transcription_logic.get_file(3, 'doc', 10) assert resp == '12' transcription_model.get.assert_called_once_with(3) transcription_logic.get_doc.assert_called_once_with(mock_transcript_items, 10) @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_get_file_vtt(mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test get vtt file.""" mock_transcription = transcription_model.Transcription() mock_transcription.transcript = {'transcript': mock_transcript_items} monkeypatch.setattr(transcription_model, 'get', MagicMock(return_value=mock_transcription)) monkeypatch.setattr(transcription_logic, 'get_vtt_or_srt', MagicMock(return_value='12')) resp = transcription_logic.get_file(3, 'vtt', 10) assert resp == '12' transcription_model.get.assert_called_once_with(3) transcription_logic.get_vtt_or_srt.assert_called_once_with(mock_transcript_items, 'vtt') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_get_file_srt(mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test get srt file.""" mock_transcription = transcription_model.Transcription() mock_transcription.transcript = {'transcript': mock_transcript_items} monkeypatch.setattr(transcription_model, 'get', MagicMock(return_value=mock_transcription)) monkeypatch.setattr(transcription_logic, 'get_vtt_or_srt', MagicMock(return_value='12')) resp = transcription_logic.get_file(3, 'srt', 10) assert resp == '12' transcription_model.get.assert_called_once_with(3) transcription_logic.get_vtt_or_srt.assert_called_once_with(mock_transcript_items, 'srt') @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_get_file_bad_filetype(mock_get_feature_flag, mock_current_admin_user): """Test raises an error when invalid filetype is requestd.""" with pytest.raises(OwsError) as err: transcription_logic.get_file(3, 'mp4', 10) assert err.value.status == 400 def test_create_captions(): """Test vtt creation with more than one speaker.""" resp = transcription_logic._create_captions(mock_transcript_items) assert len(resp.captions) == 3 assert resp.captions[0].start == '00:00:00.200' assert resp.captions[0].end == '00:00:04.700' assert resp.captions[0].text == 'I walk a lonely road,' assert resp.captions[1].start == '00:00:05.200' assert resp.captions[1].end == '00:00:12.000' assert resp.captions[1].text == 'Only road that I have ever known.' assert resp.captions[2].start == '00:00:12.000' assert resp.captions[2].end == '00:00:15.000' assert resp.captions[2].text == 'I walk alone.' def test_get_doc(monkeypatch): """Test get doc formats properly.""" resp = transcription_logic.get_doc(mock_transcript_items, 5) paragraphs = Document(resp).paragraphs assert len(paragraphs) == 2 assert paragraphs[0].text == 'spkr_0: I walk a lonely road,' assert paragraphs[1].text == 'spkr_1: [0:00:05] Only road that I have [0:00:10] ever known. I walk alone.' @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_delete_permission(mock_get_feature_flag, mock_current_user): """Does a permission check.""" with pytest.raises(OwsError) as err: transcription_logic.delete_by_episode_id(3) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_do_transcriptions_for_episodes_exist(mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test check transcription by ids.""" response = transcription_logic.do_transcriptions_for_episodes_exist([1, 2]) assert response['items'] == [ {'episode_id': 1, 'transcription': True}, {'episode_id': 2, 'transcription': False} ] @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_start_for_episode_show_family_access_success( mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test start_for_episode with show family access.""" monkeypatch.setattr(transcription_logic, '_start_transcription', MagicMock()) monkeypatch.setattr(oat, 'get_episode_input_audio', MagicMock()) transcription_logic.start_for_episode(1, {'num_speakers': 4, 'language': 'en-US'}) assert transcription_model.get(1).is_transcript_processing is True @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_start_for_episode_no_show_family_access(mock_get_feature_flag, mock_current_user): """Does a permission check on start_for_episode with no show family access.""" with pytest.raises(OwsError) as err: transcription_logic.start_for_episode(3, {'num_speakers': 2, 'language': 'en-US'}) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_get_transcription_show_family_access_success(mock_get_feature_flag, mock_current_podcast_level_user): """Does a permission check on get_transcription with show family access.""" result = transcription_logic.get_transcription(1) assert result['is_transcript_processing'] is False @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_get_transcription_no_permission_no_show_family_access( mock_get_feature_flag, mock_current_network_admin_user_second): """Does a permission check on get_transcription with no show family access.""" with pytest.raises(OwsError) as err: transcription_logic.get_transcription(3) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_do_transcriptions_for_episodes_exist_show_family_access_success( mock_get_feature_flag, monkeypatch, mock_current_network_admin_user): """Test check transcription by ids with show family access.""" response = transcription_logic.do_transcriptions_for_episodes_exist([1, 2]) assert response['items'] == [ {'episode_id': 1, 'transcription': True}, {'episode_id': 2, 'transcription': False} ] @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_do_transcriptions_for_episodes_exist_no_show_family_access( mock_get_feature_flag, monkeypatch, mock_current_podcast_level_user): """Test check transcription by ids with no show family access.""" with pytest.raises(OwsError) as err: transcription_logic.do_transcriptions_for_episodes_exist([1, 3]) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_get_file_doc_show_family_access_success(mock_get_feature_flag, monkeypatch, mock_current_admin_user): """Test get doc file with show family access.""" mock_transcription = transcription_model.Transcription() mock_transcription.transcript = {'transcript': mock_transcript_items} monkeypatch.setattr(transcription_model, 'get', MagicMock(return_value=mock_transcription)) monkeypatch.setattr(transcription_logic, 'get_doc', MagicMock(return_value='12')) resp = transcription_logic.get_file(3, 'doc', 10) assert resp == '12' transcription_model.get.assert_called_once_with(3) transcription_logic.get_doc.assert_called_once_with(mock_transcript_items, 10) @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=True) def test_get_file_permission_no_show_family_access(mock_get_feature_flag, mock_current_user): """Does a permission check with no show family access.""" with pytest.raises(OwsError) as err: transcription_logic.get_file(3, 'doc', 10) assert err.value.status == 403 @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_delete_permission_show_family_access_success(mock_get_feature_flag, mock_current_user, monkeypatch): """Does a permission check on delete permission with show family access.""" monkeypatch.setattr(transcription_model, 'delete', MagicMock()) transcription_logic.delete_by_episode_id(1) transcription_model.delete.assert_called_once_with(1) @patch('podcast.utils.feature_flag_utils.get_feature_flag', return_value=False) def test_delete_permission_no_show_family_access(mock_get_feature_flag, mock_current_podcast_level_user): """Does a permission check with no show family access.""" with pytest.raises(OwsError) as err: transcription_logic.delete_by_episode_id(3) assert err.value.status == 403