def test_that_subsidiary_models_are_created_when_new_model_is_saved( self) -> None: """Tests the _trusted_commit() method.""" # SubtopicPage is created but not committed/saved. subtopic_page = subtopic_models.SubtopicPageModel( id=self.SUBTOPIC_PAGE_ID, topic_id='topic_id', page_contents={}, page_contents_schema_version=( feconf.CURRENT_SUBTOPIC_PAGE_CONTENTS_SCHEMA_VERSION), language_code='en') # We check that subtopic page has not been saved before calling # commit(). self.assertIsNone( subtopic_models.SubtopicPageModel.get( entity_id=self.SUBTOPIC_PAGE_ID, strict=False)) # We call commit() expecting that _trusted_commit works fine # and saves subtopic page to datastore. subtopic_page.commit(committer_id=feconf.SYSTEM_COMMITTER_ID, commit_message='Created new topic', commit_cmds=[{ 'cmd': topic_domain.CMD_CREATE_NEW }]) # Now we check that subtopic page is not None and that actually # now subtopic page exists, that means that commit() worked fine. self.assertIsNotNone( subtopic_models.SubtopicPageModel.get( entity_id=self.SUBTOPIC_PAGE_ID, strict=False))
def save_subtopic_page(committer_id: str, subtopic_page: subtopic_page_domain.SubtopicPage, commit_message: str, change_list: List[change_domain.BaseChange]) -> None: """Validates a subtopic page and commits it to persistent storage. If successful, increments the version number of the incoming subtopic page domain object by 1. Args: committer_id: str. ID of the given committer. subtopic_page: SubtopicPage. The subtopic page domain object to be saved. commit_message: str. The commit message. change_list: list(SubtopicPageChange). List of changes applied to a subtopic page. Raises: Exception. Received invalid change list. Exception. The subtopic page model and the incoming subtopic page domain object have different version numbers. """ if not change_list: raise Exception( 'Unexpected error: received an invalid change list when trying to ' 'save topic %s: %s' % (subtopic_page.id, change_list)) subtopic_page.validate() # type: ignore[no-untyped-call] subtopic_page_model = subtopic_models.SubtopicPageModel.get( subtopic_page.id, strict=False) if subtopic_page_model is None: subtopic_page_model = subtopic_models.SubtopicPageModel( id=subtopic_page.id) else: if subtopic_page.version > subtopic_page_model.version: raise Exception( 'Unexpected error: trying to update version %s of topic ' 'from version %s. Please reload the page and try again.' % (subtopic_page_model.version, subtopic_page.version)) if subtopic_page.version < subtopic_page_model.version: raise Exception( 'Trying to update version %s of topic from version %s, ' 'which is too old. Please reload the page and try again.' % (subtopic_page_model.version, subtopic_page.version)) subtopic_page_model.topic_id = subtopic_page.topic_id subtopic_page_model.page_contents = subtopic_page.page_contents.to_dict() subtopic_page_model.language_code = subtopic_page.language_code subtopic_page_model.page_contents_schema_version = ( subtopic_page.page_contents_schema_version) change_dicts = [change.to_dict() for change in change_list] subtopic_page_model.commit(committer_id, commit_message, change_dicts) subtopic_page.version += 1
def test_migrate_page_contents_from_v2_to_v3_schema(self) -> None: current_schema_version_swap = self.swap( feconf, 'CURRENT_SUBTOPIC_PAGE_CONTENTS_SCHEMA_VERSION', 3) html_content = ('<oppia-noninteractive-svgdiagram ' 'svg_filename-with-value=""img1.svg""' ' alt-with-value=""Image"">' '</oppia-noninteractive-svgdiagram>') expected_html_content = ( '<oppia-noninteractive-image alt-with-value=\'\"Image\"\'' ' caption-with-value="&quot;&quot;" ' 'filepath-with-value=\'\"img1.svg\"\'>' '</oppia-noninteractive-image>') written_translations_dict = { 'translations_mapping': { 'content1': { 'en': { 'data_format': 'html', 'translation': html_content, 'needs_update': True }, 'hi': { 'data_format': 'html', 'translation': 'Hey!', 'needs_update': False } }, 'feedback_1': { 'hi': { 'data_format': 'html', 'translation': 'Testing!', 'needs_update': False }, 'en': { 'data_format': 'html', 'translation': 'hello!', 'needs_update': False } } } } written_translations_dict_math = { 'translations_mapping': { 'content1': { 'en': { 'data_format': 'html', 'translation': expected_html_content, 'needs_update': True }, 'hi': { 'data_format': 'html', 'translation': 'Hey!', 'needs_update': False } }, 'feedback_1': { 'hi': { 'data_format': 'html', 'translation': 'Testing!', 'needs_update': False }, 'en': { 'data_format': 'html', 'translation': 'hello!', 'needs_update': False } } } } recorded_voiceovers = { 'voiceovers_mapping': { 'content': { 'en': { 'filename': 'test.mp3', 'file_size_bytes': 100, 'needs_update': False, 'duration_secs': 7.213 } } } } page_contents_dict = { 'subtitled_html': { 'content_id': 'content', 'html': html_content }, 'recorded_voiceovers': recorded_voiceovers, 'written_translations': written_translations_dict } expected_page_contents_dict = { 'subtitled_html': { 'content_id': 'content', 'html': expected_html_content }, 'recorded_voiceovers': recorded_voiceovers, 'written_translations': written_translations_dict_math } subtopic_page_id = subtopic_models.SubtopicPageModel.get_new_id('') subtopic_page_model = subtopic_models.SubtopicPageModel( id=subtopic_page_id, topic_id=self.TOPIC_ID, page_contents=page_contents_dict, page_contents_schema_version=2, language_code='en') self.assertEqual(subtopic_page_model.page_contents_schema_version, 2) with current_schema_version_swap: subtopic_page = subtopic_page_services.get_subtopic_page_from_model( subtopic_page_model) self.assertEqual(subtopic_page.page_contents_schema_version, 3) self.assertEqual(subtopic_page.page_contents.to_dict(), expected_page_contents_dict)
def test_migrate_page_contents_from_v3_to_v4_schema(self) -> None: current_schema_version_swap = self.swap( feconf, 'CURRENT_SUBTOPIC_PAGE_CONTENTS_SCHEMA_VERSION', 4) expected_html_content = ('<p>1 × 3 😕 😊</p>') html_content = ('<p>1 × 3 😕 😊</p>') written_translations_dict = { 'translations_mapping': { 'content1': { 'en': { 'data_format': 'html', 'translation': html_content, 'needs_update': True }, 'hi': { 'data_format': 'html', 'translation': 'Hey!', 'needs_update': False } }, 'feedback_1': { 'hi': { 'data_format': 'html', 'translation': 'Testing!', 'needs_update': False }, 'en': { 'data_format': 'html', 'translation': 'hello!', 'needs_update': False } } } } written_translations_dict_math = { 'translations_mapping': { 'content1': { 'en': { 'data_format': 'html', 'translation': expected_html_content, 'needs_update': True }, 'hi': { 'data_format': 'html', 'translation': 'Hey!', 'needs_update': False } }, 'feedback_1': { 'hi': { 'data_format': 'html', 'translation': 'Testing!', 'needs_update': False }, 'en': { 'data_format': 'html', 'translation': 'hello!', 'needs_update': False } } } } recorded_voiceovers = { 'voiceovers_mapping': { 'content': { 'en': { 'filename': 'test.mp3', 'file_size_bytes': 100, 'needs_update': False, 'duration_secs': 7.213 } } } } page_contents_dict = { 'subtitled_html': { 'content_id': 'content', 'html': html_content }, 'recorded_voiceovers': recorded_voiceovers, 'written_translations': written_translations_dict } expected_page_contents_dict = { 'subtitled_html': { 'content_id': 'content', 'html': expected_html_content }, 'recorded_voiceovers': recorded_voiceovers, 'written_translations': written_translations_dict_math } subtopic_page_id = subtopic_models.SubtopicPageModel.get_new_id('') subtopic_page_model = subtopic_models.SubtopicPageModel( id=subtopic_page_id, topic_id=self.TOPIC_ID, page_contents=page_contents_dict, page_contents_schema_version=3, language_code='en') self.assertEqual(subtopic_page_model.page_contents_schema_version, 3) with current_schema_version_swap: subtopic_page = subtopic_page_services.get_subtopic_page_from_model( subtopic_page_model) self.assertEqual(subtopic_page.page_contents_schema_version, 4) self.assertEqual(subtopic_page.page_contents.to_dict(), expected_page_contents_dict)
def test_migrate_page_contents_from_v1_to_v2_schema(self) -> None: current_schema_version_swap = self.swap( feconf, 'CURRENT_SUBTOPIC_PAGE_CONTENTS_SCHEMA_VERSION', 2) html_content = ( '<p>Value</p><oppia-noninteractive-math raw_latex-with-value="&a' 'mp;quot;+,-,-,+&quot;"></oppia-noninteractive-math>') expected_html_content = ( '<p>Value</p><oppia-noninteractive-math math_content-with-value=' '"{&quot;raw_latex&quot;: &quot;+,-,-,+&quot;, &' 'amp;quot;svg_filename&quot;: &quot;&quot;}"></oppia' '-noninteractive-math>') written_translations_dict = { 'translations_mapping': { 'content1': { 'en': { 'data_format': 'html', 'translation': html_content, 'needs_update': True }, 'hi': { 'data_format': 'html', 'translation': 'Hey!', 'needs_update': False } }, 'feedback_1': { 'hi': { 'data_format': 'html', 'translation': 'Testing!', 'needs_update': False }, 'en': { 'data_format': 'html', 'translation': 'hello!', 'needs_update': False } } } } written_translations_dict_math = { 'translations_mapping': { 'content1': { 'en': { 'data_format': 'html', 'translation': expected_html_content, 'needs_update': True }, 'hi': { 'data_format': 'html', 'translation': 'Hey!', 'needs_update': False } }, 'feedback_1': { 'hi': { 'data_format': 'html', 'translation': 'Testing!', 'needs_update': False }, 'en': { 'data_format': 'html', 'translation': 'hello!', 'needs_update': False } } } } recorded_voiceovers = { 'voiceovers_mapping': { 'content': { 'en': { 'filename': 'test.mp3', 'file_size_bytes': 100, 'needs_update': False, 'duration_secs': 7.213 } } } } page_contents_dict = { 'subtitled_html': { 'content_id': 'content', 'html': html_content }, 'recorded_voiceovers': recorded_voiceovers, 'written_translations': written_translations_dict } expected_page_contents_dict = { 'subtitled_html': { 'content_id': 'content', 'html': expected_html_content }, 'recorded_voiceovers': recorded_voiceovers, 'written_translations': written_translations_dict_math } subtopic_page_id = subtopic_models.SubtopicPageModel.get_new_id('') subtopic_page_model = subtopic_models.SubtopicPageModel( id=subtopic_page_id, topic_id=self.TOPIC_ID, page_contents=page_contents_dict, page_contents_schema_version=1, language_code='en') self.assertEqual(subtopic_page_model.page_contents_schema_version, 1) with current_schema_version_swap: subtopic_page = subtopic_page_services.get_subtopic_page_from_model( subtopic_page_model) self.assertEqual(subtopic_page.page_contents_schema_version, 2) self.assertEqual(subtopic_page.page_contents.to_dict(), expected_page_contents_dict)