1616
1717from __future__ import annotations
1818
19+ from core import feconf
1920from core .constants import constants
2021from core .domain import (
2122 classroom_config_services ,
2223 exp_domain ,
2324 exp_fetchers ,
2425 exp_services ,
26+ state_domain ,
2527 topic_fetchers ,
2628)
2729from core .platform import models
2830from core .tests import test_utils
2931
3032MYPY = False
3133if MYPY : # pragma: no cover
32- from mypy_imports import secrets_services , translation_models
34+ from mypy_imports import (
35+ secrets_services ,
36+ translation_models ,
37+ voiceover_models ,
38+ )
3339
3440secrets_services = models .Registry .import_secrets_services ()
3541
36- (translation_models ,) = models .Registry .import_models ([
37- models .Names .TRANSLATION ])
42+ (translation_models , voiceover_models ,) = models .Registry .import_models ([
43+ models .Names .TRANSLATION ,
44+ models .Names .VOICEOVER
45+ ])
3846
3947
4048class InitializeAndroidTestDataHandlerTest (test_utils .GenericTestBase ):
@@ -133,7 +141,8 @@ def test_get_exploration_returns_correct_json(self) -> None:
133141 [{
134142 'id' : 'exp_id' ,
135143 'version' : 1 ,
136- 'payload' : exploration .to_dict ()
144+ 'payload' : exp_services .to_exploration_dict_for_android (
145+ exploration )
137146 }]
138147 )
139148
@@ -166,7 +175,8 @@ def test_get_different_versions_of_exploration_returns_correct_json(
166175 [{
167176 'id' : 'exp_id' ,
168177 'version' : 1 ,
169- 'payload' : exploration .to_dict ()
178+ 'payload' : exp_services .to_exploration_dict_for_android (
179+ exploration )
170180 }]
171181 )
172182 self .assertEqual (
@@ -179,7 +189,8 @@ def test_get_different_versions_of_exploration_returns_correct_json(
179189 [{
180190 'id' : 'exp_id' ,
181191 'version' : 2 ,
182- 'payload' : new_exploration .to_dict ()
192+ 'payload' : exp_services .to_exploration_dict_for_android (
193+ new_exploration )
183194 }]
184195 )
185196
@@ -212,11 +223,13 @@ def test_get_multiple_versions_at_a_time_returns_correct_json(self) -> None:
212223 [{
213224 'id' : 'exp_id' ,
214225 'version' : 2 ,
215- 'payload' : new_exploration .to_dict ()
226+ 'payload' : exp_services .to_exploration_dict_for_android (
227+ new_exploration )
216228 }, {
217229 'id' : 'exp_id' ,
218230 'version' : 1 ,
219- 'payload' : exploration .to_dict ()
231+ 'payload' : exp_services .to_exploration_dict_for_android (
232+ exploration )
220233 }]
221234 )
222235
@@ -231,11 +244,13 @@ def test_get_multiple_versions_at_a_time_returns_correct_json(self) -> None:
231244 [{
232245 'id' : 'exp_id' ,
233246 'version' : 1 ,
234- 'payload' : exploration .to_dict ()
247+ 'payload' : exp_services .to_exploration_dict_for_android (
248+ exploration )
235249 }, {
236250 'id' : 'exp_id' ,
237251 'version' : 2 ,
238- 'payload' : new_exploration .to_dict ()
252+ 'payload' : exp_services .to_exploration_dict_for_android (
253+ new_exploration )
239254 }]
240255 )
241256
@@ -259,7 +274,8 @@ def test_get_with_invalid_versions_returns_correct_json(self) -> None:
259274 }, {
260275 'id' : 'exp_id' ,
261276 'version' : 1 ,
262- 'payload' : exploration .to_dict ()
277+ 'payload' : exp_services .to_exploration_dict_for_android (
278+ exploration )
263279 }]
264280 )
265281
@@ -275,7 +291,8 @@ def test_get_with_invalid_versions_returns_correct_json(self) -> None:
275291 [{
276292 'id' : 'exp_id' ,
277293 'version' : 1 ,
278- 'payload' : exploration .to_dict ()
294+ 'payload' : exp_services .to_exploration_dict_for_android (
295+ exploration )
279296 }, {
280297 'id' : 'exp_id' ,
281298 'version' : 3 ,
@@ -502,6 +519,146 @@ def test_get_exploration_translation_with_zero_items_returns_correct_json(
502519 []
503520 )
504521
522+ def test_get_exploration_voiceover_without_version_fails (self ) -> None :
523+ with self .secrets_swap :
524+ self .assertEqual (
525+ self .get_json (
526+ '/android_data?activity_type=exp_voiceovers&'
527+ 'activities_data=['
528+ ' {"id": "voiceover_id", "language_code": "es"}'
529+ ']' ,
530+ headers = {'X-ApiKey' : 'secret' },
531+ expected_status_int = 400
532+ )['error' ],
533+ 'Version and language code must be specified '
534+ 'for voiceovers'
535+ )
536+
537+ def test_get_exploration_voiceover_returns_correct_json (self ) -> None :
538+ dummy_manual_voiceover_dict_1 : state_domain .VoiceoverDict = {
539+ 'filename' : 'filename1.mp3' ,
540+ 'file_size_bytes' : 3000 ,
541+ 'needs_update' : False ,
542+ 'duration_secs' : 6.1
543+ }
544+ dummy_autogenerated_voiceover_dict : state_domain .VoiceoverDict = {
545+ 'filename' : 'filename2.mp3' ,
546+ 'file_size_bytes' : 3500 ,
547+ 'needs_update' : False ,
548+ 'duration_secs' : 5.9
549+ }
550+ dummy_manual_voiceover_dict_2 : state_domain .VoiceoverDict = {
551+ 'filename' : 'filename3.mp3' ,
552+ 'file_size_bytes' : 3500 ,
553+ 'needs_update' : False ,
554+ 'duration_secs' : 5.9
555+ }
556+ voiceover_models .EntityVoiceoversModel .create_new (
557+ feconf .ENTITY_TYPE_EXPLORATION , 'exp_id_1' , 1 , 'en-US' , {
558+ 'content_0' : {
559+ 'manual' : dummy_manual_voiceover_dict_1 ,
560+ 'auto' : dummy_autogenerated_voiceover_dict
561+ }
562+ }, {}).put ()
563+
564+ voiceover_models .EntityVoiceoversModel .create_new (
565+ feconf .ENTITY_TYPE_EXPLORATION , 'exp_id_1' , 1 , 'en-NG' , {
566+ 'content_0' : {
567+ 'manual' : dummy_manual_voiceover_dict_2 ,
568+ 'auto' : None
569+ }
570+ }, {}).put ()
571+
572+ voiceover_autogeneration_policy_model = (
573+ voiceover_models .VoiceoverAutogenerationPolicyModel (
574+ id = voiceover_models .VOICEOVER_AUTOGENERATION_POLICY_ID )
575+ )
576+ voiceover_autogeneration_policy_model .language_codes_mapping = {
577+ 'en' : {
578+ 'en-US' : True ,
579+ 'en-NG' : False
580+ }
581+ }
582+ (
583+ voiceover_autogeneration_policy_model .
584+ autogenerated_voiceovers_are_enabled
585+ ) = True
586+ voiceover_autogeneration_policy_model .update_timestamps ()
587+ voiceover_autogeneration_policy_model .put ()
588+
589+ expected_payload = {
590+ 'en-NG' : {
591+ 'automated_voiceovers_audio_offsets_msecs' : {},
592+ 'entity_id' : 'exp_id_1' ,
593+ 'entity_type' : 'exploration' ,
594+ 'entity_version' : 1 ,
595+ 'language_accent_code' : 'en-NG' ,
596+ 'voiceovers_mapping' : {
597+ 'content_0' : {
598+ 'auto' : None ,
599+ 'manual' : {
600+ 'duration_secs' : 5.9 ,
601+ 'file_size_bytes' : 3500 ,
602+ 'filename' : 'filename3.mp3' ,
603+ 'needs_update' : False ,
604+ },
605+ }
606+ },
607+ },
608+ 'en-US' : {
609+ 'automated_voiceovers_audio_offsets_msecs' : {},
610+ 'entity_id' : 'exp_id_1' ,
611+ 'entity_type' : 'exploration' ,
612+ 'entity_version' : 1 ,
613+ 'language_accent_code' : 'en-US' ,
614+ 'voiceovers_mapping' : {
615+ 'content_0' : {
616+ 'auto' : {
617+ 'duration_secs' : 5.9 ,
618+ 'file_size_bytes' : 3500 ,
619+ 'filename' : 'filename2.mp3' ,
620+ 'needs_update' : False ,
621+ },
622+ 'manual' : {
623+ 'duration_secs' : 6.1 ,
624+ 'file_size_bytes' : 3000 ,
625+ 'filename' : 'filename1.mp3' ,
626+ 'needs_update' : False ,
627+ },
628+ }
629+ },
630+ },
631+ }
632+ with self .secrets_swap :
633+ response = self .get_json (
634+ '/android_data?activity_type=exp_voiceovers&'
635+ 'activities_data=[{'
636+ ' "id": "exp_id_1", '
637+ ' "language_code": "en", '
638+ ' "version": 1'
639+ '}]' ,
640+ headers = {'X-ApiKey' : 'secret' },
641+ expected_status_int = 200
642+ )
643+ self .assertEqual (response [0 ]['payload' ], expected_payload )
644+ self .assertEqual (response [0 ]['id' ], 'exp_id_1' )
645+ self .assertEqual (response [0 ]['language_code' ], 'en' )
646+ self .assertEqual (response [0 ]['version' ], 1 )
647+
648+ def test_get_exploration_voiceovers_with_zero_items_returns_correct_json (
649+ self
650+ ) -> None :
651+ with self .secrets_swap :
652+ self .assertEqual (
653+ self .get_json (
654+ '/android_data?activity_type=exp_voiceovers&'
655+ 'activities_data=[]' ,
656+ headers = {'X-ApiKey' : 'secret' },
657+ expected_status_int = 200
658+ ),
659+ []
660+ )
661+
505662 def test_get_topic_returns_correct_json (self ) -> None :
506663 topic = self .save_new_topic ('topic_id' , 'user_id' )
507664 with self .secrets_swap :
0 commit comments