from unittest import TestCase from mock import MagicMock import json from youtube_transcript_api import YouTubeTranscriptApi, VideoUnavailable from youtube_transcript_api._cli import YouTubeTranscriptCli class TestYouTubeTranscriptCli(TestCase): def setUp(self): self.transcript_mock = MagicMock() self.transcript_mock.fetch = MagicMock(return_value=[ {'text': 'Hey, this is just a test', 'start': 0.0, 'duration': 1.54}, {'text': 'this is not the original transcript', 'start': 1.54, 'duration': 4.16}, {'text': 'just something shorter, I made up for testing', 'start': 5.7, 'duration': 3.239} ]) self.transcript_mock.translate = MagicMock(return_value=self.transcript_mock) self.transcript_list_mock = MagicMock() self.transcript_list_mock.find_generated_transcript = MagicMock(return_value=self.transcript_mock) self.transcript_list_mock.find_manually_created_transcript = MagicMock(return_value=self.transcript_mock) self.transcript_list_mock.find_transcript = MagicMock(return_value=self.transcript_mock) YouTubeTranscriptApi.list_transcripts = MagicMock(return_value=self.transcript_list_mock) def test_argument_parsing(self): parsed_args = YouTubeTranscriptCli('v1 v2 --format json --languages de en'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.http_proxy, '') self.assertEqual(parsed_args.https_proxy, '') parsed_args = YouTubeTranscriptCli('v1 v2 --languages de en --format json'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.http_proxy, '') self.assertEqual(parsed_args.https_proxy, '') parsed_args = YouTubeTranscriptCli(' --format json v1 v2 --languages de en'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.http_proxy, '') self.assertEqual(parsed_args.https_proxy, '') parsed_args = YouTubeTranscriptCli( 'v1 v2 --languages de en --format json --http-proxy http://user:pass@domain:port --https-proxy https://user:pass@domain:port'.split() )._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.http_proxy, 'http://user:pass@domain:port') self.assertEqual(parsed_args.https_proxy, 'https://user:pass@domain:port') parsed_args = YouTubeTranscriptCli( 'v1 v2 --languages de en --format json --http-proxy http://user:pass@domain:port'.split() )._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.http_proxy, 'http://user:pass@domain:port') self.assertEqual(parsed_args.https_proxy, '') parsed_args = YouTubeTranscriptCli( 'v1 v2 --languages de en --format json --https-proxy https://user:pass@domain:port'.split() )._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.https_proxy, 'https://user:pass@domain:port') self.assertEqual(parsed_args.http_proxy, '') def test_argument_parsing__only_video_ids(self): parsed_args = YouTubeTranscriptCli('v1 v2'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, None) self.assertEqual(parsed_args.languages, ['en']) def test_argument_parsing__fail_without_video_ids(self): with self.assertRaises(SystemExit): YouTubeTranscriptCli('--format json'.split())._parse_args() def test_argument_parsing__json(self): parsed_args = YouTubeTranscriptCli('v1 v2 --format json'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['en']) parsed_args = YouTubeTranscriptCli('--format json v1 v2'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, 'json') self.assertEqual(parsed_args.languages, ['en']) def test_argument_parsing__languages(self): parsed_args = YouTubeTranscriptCli('v1 v2 --languages de en'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, None) self.assertEqual(parsed_args.languages, ['de', 'en']) def test_argument_parsing__proxies(self): parsed_args = YouTubeTranscriptCli( 'v1 v2 --http-proxy http://user:pass@domain:port'.split() )._parse_args() self.assertEqual(parsed_args.http_proxy, 'http://user:pass@domain:port') parsed_args = YouTubeTranscriptCli( 'v1 v2 --https-proxy https://user:pass@domain:port'.split() )._parse_args() self.assertEqual(parsed_args.https_proxy, 'https://user:pass@domain:port') parsed_args = YouTubeTranscriptCli( 'v1 v2 --http-proxy http://user:pass@domain:port --https-proxy https://user:pass@domain:port'.split() )._parse_args() self.assertEqual(parsed_args.http_proxy, 'http://user:pass@domain:port') self.assertEqual(parsed_args.https_proxy, 'https://user:pass@domain:port') parsed_args = YouTubeTranscriptCli( 'v1 v2'.split() )._parse_args() self.assertEqual(parsed_args.http_proxy, '') self.assertEqual(parsed_args.https_proxy, '') def test_argument_parsing__list_transcripts(self): parsed_args = YouTubeTranscriptCli('--list-transcripts v1 v2'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertTrue(parsed_args.list_transcripts) parsed_args = YouTubeTranscriptCli('v1 v2 --list-transcripts'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertTrue(parsed_args.list_transcripts) def test_argument_parsing__translate(self): parsed_args = YouTubeTranscriptCli('v1 v2 --languages de en --translate cz'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, None) self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.translate, 'cz') parsed_args = YouTubeTranscriptCli('v1 v2 --translate cz --languages de en'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertEqual(parsed_args.format, None) self.assertEqual(parsed_args.languages, ['de', 'en']) self.assertEqual(parsed_args.translate, 'cz') def test_argument_parsing__manually_or_generated(self): parsed_args = YouTubeTranscriptCli('v1 v2 --exclude-manually-created'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertTrue(parsed_args.exclude_manually_created) self.assertFalse(parsed_args.exclude_generated) parsed_args = YouTubeTranscriptCli('v1 v2 --exclude-generated'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertFalse(parsed_args.exclude_manually_created) self.assertTrue(parsed_args.exclude_generated) parsed_args = YouTubeTranscriptCli('v1 v2 --exclude-manually-created --exclude-generated'.split())._parse_args() self.assertEqual(parsed_args.video_ids, ['v1', 'v2']) self.assertTrue(parsed_args.exclude_manually_created) self.assertTrue(parsed_args.exclude_generated) def test_run(self): YouTubeTranscriptCli('v1 v2 --languages de en'.split()).run() YouTubeTranscriptApi.list_transcripts.assert_any_call('v1', proxies=None, cookies=None) YouTubeTranscriptApi.list_transcripts.assert_any_call('v2', proxies=None, cookies=None) self.transcript_list_mock.find_transcript.assert_any_call(['de', 'en']) def test_run__failing_transcripts(self): YouTubeTranscriptApi.list_transcripts = MagicMock(side_effect=VideoUnavailable('video_id')) output = YouTubeTranscriptCli('v1 --languages de en'.split()).run() self.assertEqual(output, str(VideoUnavailable('video_id'))) def test_run__exclude_generated(self): YouTubeTranscriptCli('v1 v2 --languages de en --exclude-generated'.split()).run() self.transcript_list_mock.find_manually_created_transcript.assert_any_call(['de', 'en']) def test_run__exclude_manually_created(self): YouTubeTranscriptCli('v1 v2 --languages de en --exclude-manually-created'.split()).run() self.transcript_list_mock.find_generated_transcript.assert_any_call(['de', 'en']) def test_run__exclude_manually_created_and_generated(self): self.assertEqual( YouTubeTranscriptCli('v1 v2 --languages de en --exclude-manually-created --exclude-generated'.split()).run(), '' ) def test_run__translate(self): YouTubeTranscriptCli('v1 v2 --languages de en --translate cz'.split()).run(), self.transcript_mock.translate.assert_any_call('cz') def test_run__list_transcripts(self): YouTubeTranscriptCli('--list-transcripts v1 v2'.split()).run() YouTubeTranscriptApi.list_transcripts.assert_any_call('v1', proxies=None, cookies=None) YouTubeTranscriptApi.list_transcripts.assert_any_call('v2', proxies=None, cookies=None) def test_run__json_output(self): output = YouTubeTranscriptCli('v1 v2 --languages de en --format json'.split()).run() # will fail if output is not valid json json.loads(output) def test_run__proxies(self): YouTubeTranscriptCli( ( 'v1 v2 --languages de en ' '--http-proxy http://user:pass@domain:port ' '--https-proxy https://user:pass@domain:port' ).split() ).run() YouTubeTranscriptApi.list_transcripts.assert_any_call( 'v1', proxies={'http': 'http://user:pass@domain:port', 'https': 'https://user:pass@domain:port'}, cookies= None ) YouTubeTranscriptApi.list_transcripts.assert_any_call( 'v2', proxies={'http': 'http://user:pass@domain:port', 'https': 'https://user:pass@domain:port'}, cookies=None ) def test_run__cookies(self): YouTubeTranscriptCli( ( 'v1 v2 --languages de en ' '--cookies blahblah.txt' ).split() ).run() YouTubeTranscriptApi.list_transcripts.assert_any_call('v1', proxies=None, cookies='blahblah.txt') YouTubeTranscriptApi.list_transcripts.assert_any_call('v2', proxies=None, cookies='blahblah.txt')