def update_topic_and_subtopic_pages(
        committer_id, topic_id, change_list, commit_message):
    """Updates a topic and its subtopic pages. Commits changes.

    Args:
        committer_id: str. The id of the user who is performing the update
            action.
        topic_id: str. The topic id.
        change_list: list(TopicChange and SubtopicPageChange). These changes are
            applied in sequence to produce the resulting topic.
        commit_message: str or None. A description of changes made to the
            topic.

    Raises:
        ValueError: Current user does not have enough rights to edit a topic.
    """
    if not commit_message:
        raise ValueError(
            'Expected a commit message, received none.')

    old_topic = topic_fetchers.get_topic_by_id(topic_id)
    (
        updated_topic, updated_subtopic_pages_dict,
        deleted_subtopic_ids, newly_created_subtopic_ids,
        updated_subtopic_pages_change_cmds_dict
    ) = apply_change_list(topic_id, change_list)

    _save_topic(
        committer_id, updated_topic, commit_message, change_list
    )
    # The following loop deletes those subtopic pages that are already in the
    # datastore, which are supposed to be deleted in the current changelist.
    for subtopic_id in deleted_subtopic_ids:
        if subtopic_id not in newly_created_subtopic_ids:
            subtopic_page_services.delete_subtopic_page(
                committer_id, topic_id, subtopic_id)

    for subtopic_page_id in updated_subtopic_pages_dict:
        subtopic_page = updated_subtopic_pages_dict[subtopic_page_id]
        subtopic_page_change_list = updated_subtopic_pages_change_cmds_dict[
            subtopic_page_id]
        subtopic_id = subtopic_page.get_subtopic_id_from_subtopic_page_id()
        # The following condition prevents the creation of subtopic pages that
        # were deleted above.
        if subtopic_id not in deleted_subtopic_ids:
            subtopic_page_services.save_subtopic_page(
                committer_id, subtopic_page, commit_message,
                subtopic_page_change_list)
    generate_topic_summary(topic_id)

    if old_topic.name != updated_topic.name:
        opportunity_services.update_opportunities_with_new_topic_name(
            updated_topic.id, updated_topic.name)
Beispiel #2
0
 def setUp(self):
     super(BaseSubtopicViewerControllerTests, self).setUp()
     self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
     self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)
     self.set_admins([self.ADMIN_USERNAME])
     self.admin = user_services.UserActionsInfo(self.admin_id)
     self.topic_id = 'topic_id'
     self.subtopic_id = 1
     self.subtopic_page = (
         subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
             self.subtopic_id, self.topic_id))
     subtopic_page_services.save_subtopic_page(
         self.user_id, self.subtopic_page, 'Added subtopic', [
             topic_domain.TopicChange({
                 'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                 'subtopic_id': self.subtopic_id,
                 'title': 'Sample'
             })
         ])
     self.recorded_voiceovers_dict = {
         'voiceovers_mapping': {
             'content': {
                 'en': {
                     'filename': 'test.mp3',
                     'file_size_bytes': 100,
                     'needs_update': False
                 }
             }
         }
     }
     self.written_translations_dict = {
         'translations_mapping': {
             'content': {}
         }
     }
     self.subtopic_page.update_page_contents_html({
         'html': '<p>hello world</p>',
         'content_id': 'content'
     })
     self.subtopic_page.update_page_contents_audio(
         self.recorded_voiceovers_dict)
     subtopic_page_services.save_subtopic_page(
         self.user_id, self.subtopic_page, 'Updated page contents', [
             subtopic_page_domain.SubtopicPageChange(
                 {
                     'cmd':
                     subtopic_page_domain.CMD_UPDATE_SUBTOPIC_PAGE_PROPERTY,
                     'subtopic_id': self.subtopic_id,
                     'property_name': 'page_contents_html',
                     'new_value': 'a',
                     'old_value': 'b'
                 })
         ])
 def test_get_subtopic_page_contents_by_id(self):
     self.subtopic_page = subtopic_page_services.get_subtopic_page_by_id(
         self.TOPIC_ID, 1)
     recorded_voiceovers = {
         'voiceovers_mapping': {
             'content': {
                 'en': {
                     'filename': 'test.mp3',
                     'file_size_bytes': 100,
                     'needs_update': False
                 }
             }
         }
     }
     expected_page_contents_dict = {
         'subtitled_html': {
             'content_id': 'content',
             'html': '<p>hello world</p>'
         },
         'recorded_voiceovers': recorded_voiceovers,
         'written_translations': {
             'translations_mapping': {
                 'content': {}
             }
         }
     }
     self.subtopic_page.update_page_contents_html({
         'html': '<p>hello world</p>',
         'content_id': 'content'
     })
     self.subtopic_page.update_page_contents_audio(recorded_voiceovers)
     subtopic_page_services.save_subtopic_page(
         self.user_id, self.subtopic_page, 'Updated page contents', [
             subtopic_page_domain.SubtopicPageChange(
                 {
                     'cmd':
                     subtopic_page_domain.CMD_UPDATE_SUBTOPIC_PAGE_PROPERTY,
                     'subtopic_id': 1,
                     'property_name': 'page_contents_html',
                     'new_value': 'a',
                     'old_value': 'b'
                 })
         ])
     subtopic_page_contents = (
         subtopic_page_services.get_subtopic_page_contents_by_id(
             self.TOPIC_ID, 1))
     self.assertEqual(subtopic_page_contents.to_dict(),
                      expected_page_contents_dict)
     subtopic_page_contents = (
         subtopic_page_services.get_subtopic_page_contents_by_id(
             self.TOPIC_ID, 2, strict=False))
     self.assertEqual(subtopic_page_contents, None)
    def setUp(self) -> None:
        super(SubtopicPageServicesUnitTests, self).setUp()
        self.signup(self.CURRICULUM_ADMIN_EMAIL,
                    self.CURRICULUM_ADMIN_USERNAME)
        self.admin_id = self.get_user_id_from_email(  # type: ignore[no-untyped-call]
            self.CURRICULUM_ADMIN_EMAIL)
        self.set_curriculum_admins([self.CURRICULUM_ADMIN_USERNAME
                                    ])  # type: ignore[no-untyped-call]

        self.TOPIC_ID = topic_fetchers.get_new_topic_id()

        self.subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                self.subtopic_id, self.TOPIC_ID))
        subtopic_page_services.save_subtopic_page(
            self.user_id, self.subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample',
                    'url_fragment': 'sample-fragment'
                })
            ])
        self.subtopic_page_id = (
            subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
                self.TOPIC_ID, 1))

        self.TOPIC_ID_1 = topic_fetchers.get_new_topic_id()
        # Set up topic and subtopic.
        topic = topic_domain.Topic.create_default_topic(
            self.TOPIC_ID_1, 'Place Values', 'abbrev', 'description', 'fragm')
        topic.thumbnail_filename = 'thumbnail.svg'
        topic.thumbnail_bg_color = '#C6DCDA'
        topic.subtopics = [
            topic_domain.Subtopic(
                1, 'Naming Numbers', ['skill_id_1'], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0], 21131,
                'dummy-subtopic-url'),
            topic_domain.Subtopic(
                2, 'Subtopic Name', ['skill_id_2'], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0], 21131,
                'other-subtopic-url')
        ]
        topic.next_subtopic_id = 3
        topic.skill_ids_for_diagnostic_test = ['skill_id_1']
        topic_services.save_new_topic(self.admin_id,
                                      topic)  # type: ignore[no-untyped-call]

        # Publish the topic and its stories.
        topic_services.publish_topic(
            self.TOPIC_ID_1, self.admin_id)  # type: ignore[no-untyped-call]
Beispiel #5
0
 def setUp(self):
     super(SubtopicPageServicesUnitTests, self).setUp()
     self.TOPIC_ID = topic_fetchers.get_new_topic_id()
     self.subtopic_page = (
         subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
             self.subtopic_id, self.TOPIC_ID))
     subtopic_page_services.save_subtopic_page(
         self.user_id, self.subtopic_page, 'Added subtopic',
         [topic_domain.TopicChange({
             'cmd': topic_domain.CMD_ADD_SUBTOPIC,
             'subtopic_id': 1,
             'title': 'Sample'
         })]
     )
     self.subtopic_page_id = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             self.TOPIC_ID, 1))
Beispiel #6
0
 def test_get_subtopic_page_contents_by_id(self):
     self.subtopic_page = subtopic_page_services.get_subtopic_page_by_id(
         self.TOPIC_ID, 1)
     content_ids_to_audio_translations_dict = {
         'content': {
             'en': {
                 'filename': 'test.mp3',
                 'file_size_bytes': 100,
                 'needs_update': False
             }
         }
     }
     expected_page_contents_dict = {
         'content_ids_to_audio_translations':
         content_ids_to_audio_translations_dict,
         'subtitled_html': {
             'content_id': 'content',
             'html': 'hello world'
         }
     }
     self.subtopic_page.update_page_contents_html({
         'html': 'hello world',
         'content_id': 'content'
     })
     self.subtopic_page.update_page_contents_audio(
         content_ids_to_audio_translations_dict)
     subtopic_page_services.save_subtopic_page(
         self.user_id, self.subtopic_page, 'Updated page contents', [
             subtopic_page_domain.SubtopicPageChange(
                 {
                     'cmd':
                     subtopic_page_domain.CMD_UPDATE_SUBTOPIC_PAGE_PROPERTY,
                     'subtopic_id': 1,
                     'property_name': 'page_contents_html',
                     'new_value': 'a',
                     'old_value': 'b'
                 })
         ])
     subtopic_page_contents = (
         subtopic_page_services.get_subtopic_page_contents_by_id(
             self.TOPIC_ID, 1))
     self.assertEqual(subtopic_page_contents.to_dict(),
                      expected_page_contents_dict)
 def test_save_subtopic_page(self) -> None:
     subtopic_page_1 = (
         subtopic_page_domain.SubtopicPage.
         create_default_subtopic_page(  # type: ignore[no-untyped-call]
             1, 'topic_id_1'))
     subtopic_page_services.save_subtopic_page(
         self.user_id, subtopic_page_1, 'Added subtopic', [
             topic_domain.TopicChange({
                 'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                 'subtopic_id': 1,
                 'title': 'Sample',
                 'url_fragment': 'sample-fragment-one'
             })
         ])
     with self.assertRaisesRegex(  # type: ignore[no-untyped-call]
             Exception,
             'Unexpected error: received an invalid change list *'):
         subtopic_page_services.save_subtopic_page(self.user_id,
                                                   subtopic_page_1,
                                                   'Added subtopic', [])
     subtopic_page_id_1 = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             'topic_id_1', 1))
     subtopic_page_model_1 = subtopic_models.SubtopicPageModel.get(
         subtopic_page_id_1)
     subtopic_page_1.version = 2
     subtopic_page_model_1.version = 3
     with self.assertRaisesRegex(
             Exception,
             'Trying to update version *'):  # type: ignore[no-untyped-call]
         subtopic_page_services.save_subtopic_page(
             self.user_id, subtopic_page_1, 'Added subtopic', [
                 topic_domain.TopicChange({
                     'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                     'subtopic_id': 1,
                     'title': 'Sample',
                     'url_fragment': 'fragment'
                 })
             ])
     subtopic_page_1.version = 3
     subtopic_page_model_1.version = 2
     with self.assertRaisesRegex(  # type: ignore[no-untyped-call]
             Exception, 'Unexpected error: trying to update version *'):
         subtopic_page_services.save_subtopic_page(
             self.user_id, subtopic_page_1, 'Added subtopic', [
                 topic_domain.TopicChange({
                     'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                     'subtopic_id': 1,
                     'title': 'Sample',
                     'url_fragment': 'sample-frag'
                 })
             ])
 def setUp(self) -> None:
     super(SubtopicPageServicesUnitTests, self).setUp()
     self.TOPIC_ID = topic_fetchers.get_new_topic_id(
     )  # type: ignore[no-untyped-call]
     self.subtopic_page = (
         subtopic_page_domain.SubtopicPage.
         create_default_subtopic_page(  # type: ignore[no-untyped-call]
             self.subtopic_id, self.TOPIC_ID))
     subtopic_page_services.save_subtopic_page(
         self.user_id, self.subtopic_page, 'Added subtopic', [
             topic_domain.TopicChange({
                 'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                 'subtopic_id': 1,
                 'title': 'Sample',
                 'url_fragment': 'sample-fragment'
             })
         ])
     self.subtopic_page_id = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             self.TOPIC_ID, 1))
Beispiel #9
0
    def _publish_valid_topic(self, topic, uncategorized_skill_ids):
        """Saves and publishes a valid topic with linked skills and subtopic.

        Args:
            topic: Topic. The topic to be saved and published.
            uncategorized_skill_ids: list(str). List of uncategorized skills IDs
                to add to the supplied topic.
        """
        topic.thumbnail_filename = 'thumbnail.svg'
        topic.thumbnail_bg_color = '#C6DCDA'
        subtopic_id = 1
        subtopic_skill_id = 'subtopic_skill_id' + topic.id
        topic.subtopics = [
            topic_domain.Subtopic(
                subtopic_id, 'Title', [subtopic_skill_id], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0], 21131,
                'dummy-subtopic')
        ]
        topic.next_subtopic_id = 2
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                subtopic_id, topic.id))
        subtopic_page_services.save_subtopic_page(
            self.owner_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        topic_services.save_new_topic(self.owner_id, topic)
        topic_services.publish_topic(topic.id, self.admin_id)

        for skill_id in uncategorized_skill_ids:
            self.save_new_skill(skill_id,
                                self.admin_id,
                                description='skill_description')
            topic_services.add_uncategorized_skill(self.admin_id, topic.id,
                                                   skill_id)
    def test_job_when_subtopics_do_not_have_math_rich_text(self):
        topic_id1 = topic_services.get_new_topic_id()
        subtopic_page1 = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, topic_id1))
        subtopic_page_services.save_subtopic_page(
            self.albert_id, subtopic_page1, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])

        job_id = (
            topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.create_new())
        topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        output = (topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.
                  get_output(job_id))

        self.assertEqual(output, [])
Beispiel #11
0
 def test_save_subtopic_page(self):
     subtopic_page_1 = (
         subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
             1, 'topic_id_1'))
     subtopic_page_services.save_subtopic_page(
         self.user_id, subtopic_page_1, 'Added subtopic', [
             topic_domain.TopicChange({
                 'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                 'subtopic_id': 1,
                 'title': 'Sample'
             })
         ])
     with self.assertRaisesRegexp(
             Exception,
             'Unexpected error: received an invalid change list *'):
         subtopic_page_services.save_subtopic_page(self.user_id,
                                                   subtopic_page_1,
                                                   'Added subtopic', [])
     subtopic_page_id_1 = (
         subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
             'topic_id_1', 1))
     subtopic_page_model_1 = subtopic_models.SubtopicPageModel.get(
         subtopic_page_id_1)
     subtopic_page_1.version = 2
     subtopic_page_model_1.version = 3
     with self.assertRaisesRegexp(Exception, 'Trying to update version *'):
         subtopic_page_services.save_subtopic_page(
             self.user_id, subtopic_page_1, 'Added subtopic', [
                 topic_domain.TopicChange({
                     'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                     'subtopic_id': 1,
                     'title': 'Sample'
                 })
             ])
     subtopic_page_1.version = 3
     subtopic_page_model_1.version = 2
     with self.assertRaisesRegexp(
             Exception, 'Unexpected error: trying to update version *'):
         subtopic_page_services.save_subtopic_page(
             self.user_id, subtopic_page_1, 'Added subtopic', [
                 topic_domain.TopicChange({
                     'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                     'subtopic_id': 1,
                     'title': 'Sample'
                 })
             ])
 def setUp(self):
     super(BaseSubtopicViewerControllerTests, self).setUp()
     self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
     self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)
     self.set_admins([self.ADMIN_USERNAME])
     self.admin = user_services.UserActionsInfo(self.admin_id)
     self.topic_id = 'topic_id'
     self.subtopic_id = 1
     self.subtopic_page = (
         subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
             self.subtopic_id, self.topic_id))
     subtopic_page_services.save_subtopic_page(
         self.admin_id, self.subtopic_page, 'Added subtopic', [
             topic_domain.TopicChange({
                 'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                 'subtopic_id': self.subtopic_id,
                 'title': 'Sample'
             })
         ])
     subtopic_page_2 = (
         subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
             self.subtopic_id, 'topic_id_2'))
     subtopic_page_services.save_subtopic_page(
         self.admin_id, subtopic_page_2, 'Added subtopic', [
             topic_domain.TopicChange({
                 'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                 'subtopic_id': self.subtopic_id,
                 'title': 'Sample'
             })
         ])
     subtopic = topic_domain.Subtopic.create_default_subtopic(
         1, 'Subtopic Title')
     self.save_new_topic(self.topic_id,
                         self.admin_id,
                         name='Name',
                         abbreviated_name='abbrev',
                         thumbnail_filename=None,
                         description='Description',
                         canonical_story_ids=[],
                         additional_story_ids=[],
                         uncategorized_skill_ids=[],
                         subtopics=[subtopic],
                         next_subtopic_id=2)
     topic_services.publish_topic(self.topic_id, self.admin_id)
     self.save_new_topic('topic_id_2',
                         self.admin_id,
                         name='Private_Name',
                         abbreviated_name='abbrev',
                         thumbnail_filename=None,
                         description='Description',
                         canonical_story_ids=[],
                         additional_story_ids=[],
                         uncategorized_skill_ids=[],
                         subtopics=[subtopic],
                         next_subtopic_id=2)
     self.recorded_voiceovers_dict = {
         'voiceovers_mapping': {
             'content': {
                 'en': {
                     'filename': 'test.mp3',
                     'file_size_bytes': 100,
                     'needs_update': False,
                     'duration_secs': 0.34234
                 }
             }
         }
     }
     self.written_translations_dict = {
         'translations_mapping': {
             'content': {}
         }
     }
     self.subtopic_page.update_page_contents_html(
         state_domain.SubtitledHtml.from_dict({
             'html': '<p>hello world</p>',
             'content_id': 'content'
         }))
     self.subtopic_page.update_page_contents_audio(
         state_domain.RecordedVoiceovers.from_dict(
             self.recorded_voiceovers_dict))
     subtopic_page_services.save_subtopic_page(
         self.admin_id, self.subtopic_page, 'Updated page contents', [
             subtopic_page_domain.SubtopicPageChange(
                 {
                     'cmd':
                     subtopic_page_domain.CMD_UPDATE_SUBTOPIC_PAGE_PROPERTY,
                     'subtopic_id': self.subtopic_id,
                     'property_name': 'page_contents_html',
                     'new_value': 'a',
                     'old_value': 'b'
                 })
         ])
    def setUp(self):
        super(OpportunityServicesIntegrationTest, self).setUp()
        self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
        self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME)

        self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)
        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        self.set_admins([self.ADMIN_USERNAME])
        self.admin = user_services.UserActionsInfo(self.admin_id)

        self.TOPIC_ID = 'topic'
        self.STORY_ID = 'story'
        self.USER_ID = 'user'
        self.SKILL_ID = 'skill'
        self.QUESTION_ID = question_services.get_new_question_id()
        self.THREAD_ID = 'exploration.exp1.thread_1'

        # Since a valid exploration is created here, it has EndExploration
        # state as well, so the content in that has to be taken into account as
        # well when checking content_count in the tests.
        explorations = [
            self.save_new_valid_exploration('%s' % i,
                                            self.owner_id,
                                            title='title %d' % i,
                                            category='category%d' % i,
                                            end_state_name='End State',
                                            correctness_feedback_enabled=True)
            for i in python_utils.RANGE(5)
        ]

        for exp in explorations:
            self.publish_exploration(self.owner_id, exp.id)

        topic = topic_domain.Topic.create_default_topic(
            self.TOPIC_ID, 'topic', 'abbrev', 'description')
        topic.thumbnail_filename = 'thumbnail.svg'
        topic.thumbnail_bg_color = '#C6DCDA'
        topic.subtopics = [
            topic_domain.Subtopic(
                1, 'Title', ['skill_id_1'], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0],
                'dummy-subtopic-url')
        ]
        topic.next_subtopic_id = 2
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, self.TOPIC_ID))
        subtopic_page_services.save_subtopic_page(
            self.owner_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        topic_services.save_new_topic(self.owner_id, topic)
        topic_services.publish_topic(self.TOPIC_ID, self.admin_id)

        story = story_domain.Story.create_default_story(
            self.STORY_ID, 'A story', 'description', self.TOPIC_ID,
            'story-one')
        story_services.save_new_story(self.owner_id, story)
        topic_services.add_canonical_story(self.owner_id, self.TOPIC_ID,
                                           self.STORY_ID)
        topic_services.publish_story(self.TOPIC_ID, self.STORY_ID,
                                     self.admin_id)
Beispiel #14
0
    def _load_dummy_new_structures_data(self):
        """Loads the database with two topics (one of which is empty), a story
        and three skills in the topic (two of them in a subtopic) and a question
        attached to each skill.

        Raises:
            Exception: Cannot load new structures data in production mode.
            Exception: User does not have enough rights to generate data.
        """
        if constants.DEV_MODE:
            if self.user.role != feconf.ROLE_ID_ADMIN:
                raise Exception(
                    'User does not have enough rights to generate data.')
            topic_id_1 = topic_services.get_new_topic_id()
            topic_id_2 = topic_services.get_new_topic_id()
            story_id = story_services.get_new_story_id()
            skill_id_1 = skill_services.get_new_skill_id()
            skill_id_2 = skill_services.get_new_skill_id()
            skill_id_3 = skill_services.get_new_skill_id()
            question_id_1 = question_services.get_new_question_id()
            question_id_2 = question_services.get_new_question_id()
            question_id_3 = question_services.get_new_question_id()

            skill_1 = self._create_dummy_skill(skill_id_1, 'Dummy Skill 1',
                                               '<p>Dummy Explanation 1</p>')
            skill_2 = self._create_dummy_skill(skill_id_2, 'Dummy Skill 2',
                                               '<p>Dummy Explanation 2</p>')
            skill_3 = self._create_dummy_skill(skill_id_3, 'Dummy Skill 3',
                                               '<p>Dummy Explanation 3</p>')

            question_1 = self._create_dummy_question(question_id_1,
                                                     'Question 1',
                                                     [skill_id_1])
            question_2 = self._create_dummy_question(question_id_2,
                                                     'Question 2',
                                                     [skill_id_2])
            question_3 = self._create_dummy_question(question_id_3,
                                                     'Question 3',
                                                     [skill_id_3])
            question_services.add_question(self.user_id, question_1)
            question_services.add_question(self.user_id, question_2)
            question_services.add_question(self.user_id, question_3)

            question_services.create_new_question_skill_link(
                self.user_id, question_id_1, skill_id_1, 0.3)
            question_services.create_new_question_skill_link(
                self.user_id, question_id_2, skill_id_2, 0.5)
            question_services.create_new_question_skill_link(
                self.user_id, question_id_3, skill_id_3, 0.7)

            topic_1 = topic_domain.Topic.create_default_topic(
                topic_id_1, 'Dummy Topic 1', 'abbrev')
            topic_2 = topic_domain.Topic.create_default_topic(
                topic_id_2, 'Empty Topic', 'abbrev')

            topic_1.add_canonical_story(story_id)
            topic_1.add_uncategorized_skill_id(skill_id_1)
            topic_1.add_uncategorized_skill_id(skill_id_2)
            topic_1.add_uncategorized_skill_id(skill_id_3)
            topic_1.add_subtopic(1, 'Dummy Subtopic Title')
            topic_1.move_skill_id_to_subtopic(None, 1, skill_id_2)
            topic_1.move_skill_id_to_subtopic(None, 1, skill_id_3)

            subtopic_page = (
                subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                    1, topic_id_1))
            self._reload_exploration('0')
            self._reload_exploration('16')
            story = story_domain.Story.create_default_story(
                story_id, 'Dummy Story 1', topic_id_1)
            story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, 1),
                           'Dummy Chapter 1')
            story.update_node_destination_node_ids(
                '%s%d' % (story_domain.NODE_ID_PREFIX, 1),
                ['%s%d' % (story_domain.NODE_ID_PREFIX, 2)])
            story.update_node_exploration_id(
                '%s%d' % (story_domain.NODE_ID_PREFIX, 1), '0')

            story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, 2),
                           'Dummy Chapter 2')
            story.update_node_exploration_id(
                '%s%d' % (story_domain.NODE_ID_PREFIX, 2), '16')

            skill_services.save_new_skill(self.user_id, skill_1)
            skill_services.save_new_skill(self.user_id, skill_2)
            skill_services.save_new_skill(self.user_id, skill_3)
            story_services.save_new_story(self.user_id, story)
            topic_services.save_new_topic(self.user_id, topic_1)
            topic_services.save_new_topic(self.user_id, topic_2)
            subtopic_page_services.save_subtopic_page(
                self.user_id, subtopic_page, 'Added subtopic', [
                    topic_domain.TopicChange({
                        'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                        'subtopic_id': 1,
                        'title': 'Dummy Subtopic Title'
                    })
                ])

            topic_services.publish_story(topic_id_1, story_id, self.user_id)
            topic_services.publish_topic(topic_id_1, self.user_id)
        else:
            raise Exception('Cannot load new structures data in production.')
Beispiel #15
0
    def _load_dummy_new_structures_data(self):
        """Loads the database with two topics (one of which is empty), a story
        and three skills in the topic (two of them in a subtopic) and a question
        attached to each skill.

        Raises:
            Exception: Cannot load new structures data in production mode.
            Exception: User does not have enough rights to generate data.
        """
        if constants.DEV_MODE:
            if self.user.role != feconf.ROLE_ID_ADMIN:
                raise Exception(
                    'User does not have enough rights to generate data.')
            topic_id_1 = topic_services.get_new_topic_id()
            topic_id_2 = topic_services.get_new_topic_id()
            story_id = story_services.get_new_story_id()
            skill_id_1 = skill_services.get_new_skill_id()
            skill_id_2 = skill_services.get_new_skill_id()
            skill_id_3 = skill_services.get_new_skill_id()
            question_id_1 = question_services.get_new_question_id()
            question_id_2 = question_services.get_new_question_id()
            question_id_3 = question_services.get_new_question_id()

            skill_1 = self._create_dummy_skill(skill_id_1, 'Dummy Skill 1',
                                               '<p>Dummy Explanation 1</p>')
            skill_2 = self._create_dummy_skill(skill_id_2, 'Dummy Skill 2',
                                               '<p>Dummy Explanation 2</p>')
            skill_3 = self._create_dummy_skill(skill_id_3, 'Dummy Skill 3',
                                               '<p>Dummy Explanation 3</p>')

            question_1 = self._create_dummy_question(question_id_1,
                                                     'Question 1',
                                                     [skill_id_1])
            question_2 = self._create_dummy_question(question_id_2,
                                                     'Question 2',
                                                     [skill_id_2])
            question_3 = self._create_dummy_question(question_id_3,
                                                     'Question 3',
                                                     [skill_id_3])
            question_services.add_question(self.user_id, question_1)
            question_services.add_question(self.user_id, question_2)
            question_services.add_question(self.user_id, question_3)

            question_services.create_new_question_skill_link(
                self.user_id, question_id_1, skill_id_1, 0.3)
            question_services.create_new_question_skill_link(
                self.user_id, question_id_2, skill_id_2, 0.5)
            question_services.create_new_question_skill_link(
                self.user_id, question_id_3, skill_id_3, 0.7)

            topic_1 = topic_domain.Topic.create_default_topic(
                topic_id_1, 'Dummy Topic 1', 'abbrev', 'description')
            topic_2 = topic_domain.Topic.create_default_topic(
                topic_id_2, 'Empty Topic', 'abbrev', 'description')

            topic_1.add_canonical_story(story_id)
            topic_1.add_uncategorized_skill_id(skill_id_1)
            topic_1.add_uncategorized_skill_id(skill_id_2)
            topic_1.add_uncategorized_skill_id(skill_id_3)
            topic_1.add_subtopic(1, 'Dummy Subtopic Title')
            topic_1.move_skill_id_to_subtopic(None, 1, skill_id_2)
            topic_1.move_skill_id_to_subtopic(None, 1, skill_id_3)

            subtopic_page = (
                subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                    1, topic_id_1))
            # These explorations were chosen since they pass the validations
            # for published stories.
            self._reload_exploration('15')
            self._reload_exploration('25')
            self._reload_exploration('13')

            story = story_domain.Story.create_default_story(
                story_id, 'Help Jaime win the Arcade', topic_id_1)

            story_node_dicts = [{
                'exp_id':
                '15',
                'title':
                'What are the place values?',
                'description':
                'Jaime learns the place value of each digit ' +
                'in a big number.'
            }, {
                'exp_id':
                '25',
                'title':
                'Finding the value of a number',
                'description':
                'Jaime understands the value of his ' + 'arcade score.'
            }, {
                'exp_id':
                '13',
                'title':
                'Comparing Numbers',
                'description':
                'Jaime learns if a number is smaller or ' +
                'greater than another number.'
            }]

            def generate_dummy_story_nodes(node_id, exp_id, title,
                                           description):
                """Generates and connects sequential story nodes.

                Args:
                    node_id: int. The node id.
                    exp_id: str. The exploration id.
                    title: str. The title of the story node.
                    description: str. The description of the story node.
                """

                story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, node_id),
                               title)
                story.update_node_description(
                    '%s%d' % (story_domain.NODE_ID_PREFIX, node_id),
                    description)
                story.update_node_exploration_id(
                    '%s%d' % (story_domain.NODE_ID_PREFIX, node_id), exp_id)

                if node_id != len(story_node_dicts):
                    story.update_node_destination_node_ids(
                        '%s%d' % (story_domain.NODE_ID_PREFIX, node_id),
                        ['%s%d' % (story_domain.NODE_ID_PREFIX, node_id + 1)])

                exp_services.update_exploration(self.user_id, exp_id, [
                    exp_domain.ExplorationChange({
                        'cmd': exp_domain.CMD_EDIT_EXPLORATION_PROPERTY,
                        'property_name': 'category',
                        'new_value': 'Astronomy'
                    })
                ], 'Change category')

            for i, story_node_dict in enumerate(story_node_dicts):
                generate_dummy_story_nodes(i + 1, **story_node_dict)

            skill_services.save_new_skill(self.user_id, skill_1)
            skill_services.save_new_skill(self.user_id, skill_2)
            skill_services.save_new_skill(self.user_id, skill_3)
            story_services.save_new_story(self.user_id, story)
            topic_services.save_new_topic(self.user_id, topic_1)
            topic_services.save_new_topic(self.user_id, topic_2)
            subtopic_page_services.save_subtopic_page(
                self.user_id, subtopic_page, 'Added subtopic', [
                    topic_domain.TopicChange({
                        'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                        'subtopic_id': 1,
                        'title': 'Dummy Subtopic Title'
                    })
                ])

            topic_services.publish_story(topic_id_1, story_id, self.user_id)
        else:
            raise Exception('Cannot load new structures data in production.')
Beispiel #16
0
    def setUp(self):
        super(ExplorationOpportunitySummaryModelRegenerationJobTest,
              self).setUp()
        self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
        self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME)

        self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)
        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        self.set_admins([self.ADMIN_USERNAME])

        self.topic_id_1 = 'topic1'
        self.topic_id_2 = 'topic2'

        story_id_1 = 'story1'
        story_id_2 = 'story2'

        explorations = [
            self.save_new_valid_exploration('%s' % i,
                                            self.owner_id,
                                            title='title %d' % i,
                                            end_state_name='End State',
                                            correctness_feedback_enabled=True)
            for i in python_utils.RANGE(2)
        ]

        for exp in explorations:
            self.publish_exploration(self.owner_id, exp.id)

        topic_1 = topic_domain.Topic.create_default_topic(
            self.topic_id_1, 'topic', 'abbrev-one', 'description')
        topic_1.thumbnail_filename = 'thumbnail.svg'
        topic_1.thumbnail_bg_color = '#C6DCDA'
        topic_1.subtopics = [
            topic_domain.Subtopic(
                1, 'Title', ['skill_id_1'], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0],
                'dummy-subtopic-three')
        ]
        topic_1.next_subtopic_id = 2
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, self.topic_id_1))
        subtopic_page_services.save_subtopic_page(
            self.owner_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        topic_services.save_new_topic(self.owner_id, topic_1)
        topic_services.publish_topic(self.topic_id_1, self.admin_id)

        topic_2 = topic_domain.Topic.create_default_topic(
            self.topic_id_2, 'topic2', 'abbrev-two', 'description')
        topic_2.thumbnail_filename = 'thumbnail.svg'
        topic_2.thumbnail_bg_color = '#C6DCDA'
        topic_2.subtopics = [
            topic_domain.Subtopic(
                1, 'Title', ['skill_id_2'], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0],
                'dummy-subtopic-three')
        ]
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, self.topic_id_2))
        subtopic_page_services.save_subtopic_page(
            self.owner_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        topic_2.next_subtopic_id = 2
        topic_services.save_new_topic(self.owner_id, topic_2)
        topic_services.publish_topic(self.topic_id_2, self.admin_id)

        story_1 = story_domain.Story.create_default_story(
            story_id_1, 'A story', 'description', self.topic_id_1, 'story-one')
        story_2 = story_domain.Story.create_default_story(
            story_id_2, 'A story', 'description', self.topic_id_2, 'story-two')

        story_services.save_new_story(self.owner_id, story_1)
        story_services.save_new_story(self.owner_id, story_2)
        topic_services.add_canonical_story(self.owner_id, self.topic_id_1,
                                           story_id_1)
        topic_services.publish_story(self.topic_id_1, story_id_1,
                                     self.admin_id)
        topic_services.add_canonical_story(self.owner_id, self.topic_id_2,
                                           story_id_2)
        topic_services.publish_story(self.topic_id_2, story_id_2,
                                     self.admin_id)
        story_services.update_story(self.owner_id, story_id_1, [
            story_domain.StoryChange({
                'cmd': 'add_story_node',
                'node_id': 'node_1',
                'title': 'Node1',
            }),
            story_domain.StoryChange({
                'cmd': 'update_story_node_property',
                'property_name': 'exploration_id',
                'node_id': 'node_1',
                'old_value': None,
                'new_value': '0'
            })
        ], 'Changes.')
        story_services.update_story(self.owner_id, story_id_2, [
            story_domain.StoryChange({
                'cmd': 'add_story_node',
                'node_id': 'node_1',
                'title': 'Node1',
            }),
            story_domain.StoryChange({
                'cmd': 'update_story_node_property',
                'property_name': 'exploration_id',
                'node_id': 'node_1',
                'old_value': None,
                'new_value': '1'
            })
        ], 'Changes.')
Beispiel #17
0
    def setUp(self):
        super(ExplorationOpportunitySummaryModelValidatorTests, self).setUp()

        self.job_class = (prod_validation_jobs_one_off.
                          ExplorationOpportunitySummaryModelAuditOneOffJob)
        self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME)
        self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)

        self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)
        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        self.set_admins([self.ADMIN_USERNAME])

        self.TOPIC_ID = 'topic'
        self.STORY_ID = 'story'
        explorations = [
            self.save_new_valid_exploration('%s' % i,
                                            self.owner_id,
                                            title='title %d' % i,
                                            category='category',
                                            end_state_name='End State',
                                            correctness_feedback_enabled=True)
            for i in python_utils.RANGE(5)
        ]

        for exp in explorations:
            self.publish_exploration(self.owner_id, exp.id)

        topic = topic_domain.Topic.create_default_topic(
            self.TOPIC_ID, 'topic', 'abbrev', 'description')
        topic.thumbnail_filename = 'thumbnail.svg'
        topic.thumbnail_bg_color = '#C6DCDA'
        topic.subtopics = [
            topic_domain.Subtopic(
                1, 'Title', ['skill_id_2'], 'image.svg',
                constants.ALLOWED_THUMBNAIL_BG_COLORS['subtopic'][0],
                'dummy-subtopic-three')
        ]
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, self.TOPIC_ID))
        subtopic_page_services.save_subtopic_page(
            self.owner_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        topic.next_subtopic_id = 2
        topic_services.save_new_topic(self.owner_id, topic)
        topic_services.publish_topic(self.TOPIC_ID, self.admin_id)

        story = story_domain.Story.create_default_story(
            self.STORY_ID, 'A story', 'Description', self.TOPIC_ID,
            'story-one')
        story_services.save_new_story(self.owner_id, story)
        topic_services.add_canonical_story(self.owner_id, self.TOPIC_ID,
                                           self.STORY_ID)
        topic_services.publish_story(self.TOPIC_ID, self.STORY_ID,
                                     self.admin_id)

        story_change_list = [
            story_domain.StoryChange({
                'cmd': 'add_story_node',
                'node_id': 'node_%s' % i,
                'title': 'Node %s' % i,
            }) for i in python_utils.RANGE(1, 4)
        ]

        story_change_list += [
            story_domain.StoryChange({
                'cmd': 'update_story_node_property',
                'property_name': 'destination_node_ids',
                'node_id': 'node_%s' % i,
                'old_value': [],
                'new_value': ['node_%s' % (i + 1)]
            }) for i in python_utils.RANGE(1, 3)
        ]

        story_change_list += [
            story_domain.StoryChange({
                'cmd': 'update_story_node_property',
                'property_name': 'exploration_id',
                'node_id': 'node_%s' % i,
                'old_value': None,
                'new_value': '%s' % i
            }) for i in python_utils.RANGE(1, 4)
        ]

        story_services.update_story(self.owner_id, self.STORY_ID,
                                    story_change_list, 'Changes.')

        self.model_instance_1 = (
            opportunity_models.ExplorationOpportunitySummaryModel.get_by_id(
                '1'))
        self.model_instance_2 = (
            opportunity_models.ExplorationOpportunitySummaryModel.get_by_id(
                '2'))
        self.model_instance_3 = (
            opportunity_models.ExplorationOpportunitySummaryModel.get_by_id(
                '3'))
Beispiel #18
0
    def post(self):
        """Generates structures for Android end-to-end tests.

        This handler generates structures for Android end-to-end tests in
        order to evaluate the integration of network requests from the
        Android client to the backend. This handler should only be called
        once (or otherwise raises an exception), and can only be used in
        development mode (this handler is unavailable in production).

        Note that the handler outputs an empty JSON dict when the request is
        successful.

        The specific structures that are generated:
            Topic: A topic with both a test story and a subtopic.
            Story: A story with 'android_interactions' as a exploration
                node.
            Exploration: 'android_interactions' from the local assets.
            Subtopic: A dummy subtopic to validate the topic.
            Skill: A dummy skill to validate the subtopic.

        Raises:
            Exception. When used in production mode.
            InvalidInputException. The topic is already
                created but not published.
            InvalidInputException. The topic is already published.
        """

        if not constants.DEV_MODE:
            raise Exception('Cannot load new structures data in production.')
        if topic_services.does_topic_with_name_exist('Android test'):
            topic = topic_fetchers.get_topic_by_name('Android test')
            topic_rights = topic_fetchers.get_topic_rights(topic.id,
                                                           strict=False)
            if topic_rights.topic_is_published:
                raise self.InvalidInputException(
                    'The topic is already published.')

            raise self.InvalidInputException(
                'The topic exists but is not published.')
        exp_id = '26'
        user_id = feconf.SYSTEM_COMMITTER_ID
        # Generate new Structure id for topic, story, skill and question.
        topic_id = topic_fetchers.get_new_topic_id()
        story_id = story_services.get_new_story_id()
        skill_id = skill_services.get_new_skill_id()
        question_id = question_services.get_new_question_id()

        # Create dummy skill and question.
        skill = self._create_dummy_skill(skill_id, 'Dummy Skill for Android',
                                         '<p>Dummy Explanation 1</p>')
        question = self._create_dummy_question(question_id, 'Question 1',
                                               [skill_id])
        question_services.add_question(user_id, question)
        question_services.create_new_question_skill_link(
            user_id, question_id, skill_id, 0.3)

        # Create and update topic to validate before publishing.
        topic = topic_domain.Topic.create_default_topic(
            topic_id, 'Android test', 'test-topic-one', 'description', 'fragm')
        topic.update_url_fragment('test-topic')
        topic.update_meta_tag_content('tag')
        topic.update_page_title_fragment_for_web('page title for topic')
        # Save the dummy image to the filesystem to be used as thumbnail.
        with utils.open_file(os.path.join(feconf.TESTS_DATA_DIR,
                                          'test_svg.svg'),
                             'rb',
                             encoding=None) as f:
            raw_image = f.read()
        fs = fs_services.GcsFileSystem(feconf.ENTITY_TYPE_TOPIC, topic_id)
        fs.commit('%s/test_svg.svg' % (constants.ASSET_TYPE_THUMBNAIL),
                  raw_image,
                  mimetype='image/svg+xml')
        # Update thumbnail properties.
        topic_services.update_thumbnail_filename(topic, 'test_svg.svg')
        topic.update_thumbnail_bg_color('#C6DCDA')

        # Add other structures to the topic.
        topic.add_canonical_story(story_id)
        topic.add_uncategorized_skill_id(skill_id)
        topic.add_subtopic(1, 'Test Subtopic Title', 'testsubtop')

        # Update and validate subtopic.
        topic_services.update_subtopic_thumbnail_filename(
            topic, 1, 'test_svg.svg')
        topic.update_subtopic_thumbnail_bg_color(1, '#FFFFFF')
        topic.update_subtopic_url_fragment(1, 'suburl')
        topic.move_skill_id_to_subtopic(None, 1, skill_id)
        subtopic_page = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, topic_id))

        # Upload local exploration to the datastore and enable feedback.
        exp_services.load_demo(exp_id)
        rights_manager.release_ownership_of_exploration(
            user_services.get_system_user(), exp_id)
        exp_services.update_exploration(
            user_id, exp_id, [
                exp_domain.ExplorationChange({
                    'cmd': exp_domain.CMD_EDIT_EXPLORATION_PROPERTY,
                    'property_name': 'correctness_feedback_enabled',
                    'new_value': True
                })
            ], 'Changed correctness_feedback_enabled.')

        # Add and update the exploration/node to the story.
        story = story_domain.Story.create_default_story(
            story_id, 'Android End to End testing', 'Description', topic_id,
            'android-end-to-end-testing')

        story.add_node('%s%d' % (story_domain.NODE_ID_PREFIX, 1),
                       'Testing with UI Automator')

        story.update_node_description(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1),
            'To test all Android interactions')
        story.update_node_exploration_id(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1), exp_id)

        # Save the dummy image to the filesystem to be used as thumbnail.
        with utils.open_file(os.path.join(feconf.TESTS_DATA_DIR,
                                          'test_svg.svg'),
                             'rb',
                             encoding=None) as f:
            raw_image = f.read()
        fs = fs_services.GcsFileSystem(feconf.ENTITY_TYPE_STORY, story_id)
        fs.commit('%s/test_svg.svg' % (constants.ASSET_TYPE_THUMBNAIL),
                  raw_image,
                  mimetype='image/svg+xml')

        story.update_node_thumbnail_filename(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1), 'test_svg.svg')
        story.update_node_thumbnail_bg_color(
            '%s%d' % (story_domain.NODE_ID_PREFIX, 1), '#F8BF74')

        # Update and validate the story.
        story.update_meta_tag_content('tag')
        story.update_thumbnail_filename('test_svg.svg')
        story.update_thumbnail_bg_color(
            constants.ALLOWED_THUMBNAIL_BG_COLORS['story'][0])

        # Save the previously created structures
        # (skill, story, topic, subtopic).
        skill_services.save_new_skill(user_id, skill)
        story_services.save_new_story(user_id, story)
        topic_services.save_new_topic(user_id, topic)
        subtopic_page_services.save_subtopic_page(
            user_id, subtopic_page, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Dummy Subtopic Title',
                    'url_fragment': 'dummy-fragment'
                })
            ])

        # Generates translation opportunities for the Contributor Dashboard.
        exp_ids_in_story = story.story_contents.get_all_linked_exp_ids()
        opportunity_services.add_new_exploration_opportunities(
            story_id, exp_ids_in_story)

        # Publish the story and topic.
        topic_services.publish_story(topic_id, story_id, user_id)
        topic_services.publish_topic(topic_id, user_id)

        # Upload thumbnails to be accessible through AssetsDevHandler.
        self._upload_thumbnail(topic_id, feconf.ENTITY_TYPE_TOPIC)
        self._upload_thumbnail(story_id, feconf.ENTITY_TYPE_STORY)
        self.render_json({})
    def test_job_when_subtopics_have_math_rich_text_with_svgs(self):

        valid_html_1 = (
            '<oppia-noninteractive-math math_content-with-value="{&amp;q'
            'uot;raw_latex&amp;quot;: &amp;quot;(x - a_1)(x - a_2)(x - a'
            '_3)...(x - a_n-1)(x - a_n)&amp;quot;, &amp;quot;svg_filenam'
            'e&amp;quot;: &amp;quot;file1.svg&amp;quot;}"></oppia-nonint'
            'eractive-math>')
        valid_html_2 = (
            '<oppia-noninteractive-math math_content-with-value="{&amp;'
            'quot;raw_latex&amp;quot;: &amp;quot;+,+,+,+&amp;quot;, &amp;'
            'quot;svg_filename&amp;quot;: &amp;quot;file1.svg&amp;quot;}"></'
            'oppia-noninteractive-math>')
        topic_id1 = topic_services.get_new_topic_id()
        subtopic_page1 = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                1, topic_id1))

        subtopic_page1.update_page_contents_html(
            state_domain.SubtitledHtml.from_dict({
                'html': valid_html_1,
                'content_id': 'content'
            }))

        subtopic_page_services.save_subtopic_page(
            self.albert_id, subtopic_page1, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 1,
                    'title': 'Sample'
                })
            ])
        subtopic_page1_id = (
            subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
                topic_id1, 1))

        topic_id2 = topic_services.get_new_topic_id()
        subtopic_page2 = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                2, topic_id2))

        subtopic_page2.update_page_contents_html(
            state_domain.SubtitledHtml.from_dict({
                'html': valid_html_2,
                'content_id': 'content'
            }))

        subtopic_page_services.save_subtopic_page(
            self.albert_id, subtopic_page2, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': 2,
                    'title': 'Sample'
                })
            ])
        subtopic_page2_id = (
            subtopic_page_domain.SubtopicPage.get_subtopic_page_id(
                topic_id2, 2))

        job_id = (
            topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.create_new())
        topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        output = (topic_jobs_one_off.SubTopicPageMathRteAuditOneOffJob.
                  get_output(job_id))

        overall_result = ast.literal_eval(output[0])
        expected_subtopic1_info = {
            'subtopic_id':
            subtopic_page1_id,
            'latex_strings_with_svg':
            ['(x - a_1)(x - a_2)(x - a_3)...(x - a_n-1)(x - a_n)']
        }
        expected_subtopic2_info = {
            'subtopic_id': subtopic_page2_id,
            'latex_strings_with_svg': ['+,+,+,+']
        }
        subtopic_latex_info = sorted(overall_result[1])
        self.assertEqual(subtopic_latex_info[0], expected_subtopic1_info)
        self.assertEqual(subtopic_latex_info[1], expected_subtopic2_info)
Beispiel #20
0
    def setUp(self):
        super(BaseSubtopicViewerControllerTests, self).setUp()
        self.signup(self.CURRICULUM_ADMIN_EMAIL,
                    self.CURRICULUM_ADMIN_USERNAME)
        self.admin_id = self.get_user_id_from_email(
            self.CURRICULUM_ADMIN_EMAIL)
        self.set_curriculum_admins([self.CURRICULUM_ADMIN_USERNAME])
        self.admin = user_services.get_user_actions_info(self.admin_id)
        self.topic_id = 'topic_id'
        self.subtopic_id_1 = 1
        self.subtopic_id_2 = 2
        self.subtopic_page_1 = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                self.subtopic_id_1, self.topic_id))
        self.subtopic_page_2 = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                self.subtopic_id_2, self.topic_id))
        subtopic_page_services.save_subtopic_page(
            self.admin_id, self.subtopic_page_1, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': self.subtopic_id_1,
                    'title': 'Sample',
                    'url_fragment': 'sample-fragment'
                })
            ])
        subtopic_page_services.save_subtopic_page(
            self.admin_id, self.subtopic_page_2, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': self.subtopic_id_2,
                    'title': 'Sample',
                    'url_fragment': 'dummy-fragment'
                })
            ])
        subtopic_page_private_topic = (
            subtopic_page_domain.SubtopicPage.create_default_subtopic_page(
                self.subtopic_id_1, 'topic_id_2'))
        subtopic_page_services.save_subtopic_page(
            self.admin_id, subtopic_page_private_topic, 'Added subtopic', [
                topic_domain.TopicChange({
                    'cmd': topic_domain.CMD_ADD_SUBTOPIC,
                    'subtopic_id': self.subtopic_id_1,
                    'title': 'Sample',
                    'url_fragment': 'dummy-fragment-one'
                })
            ])
        subtopic = topic_domain.Subtopic.create_default_subtopic(
            1, 'Subtopic Title', 'url-frag')
        subtopic.skill_ids = ['skill_id_1']
        subtopic.url_fragment = 'sub-url-frag-one'
        subtopic2 = topic_domain.Subtopic.create_default_subtopic(
            2, 'Subtopic Title 2', 'url-frag-two')
        subtopic2.skill_ids = ['skill_id_2']
        subtopic2.url_fragment = 'sub-url-frag-two'

        self.save_new_topic(self.topic_id,
                            self.admin_id,
                            name='Name',
                            abbreviated_name='name',
                            url_fragment='name',
                            description='Description',
                            canonical_story_ids=[],
                            additional_story_ids=[],
                            uncategorized_skill_ids=[],
                            subtopics=[subtopic, subtopic2],
                            next_subtopic_id=3)
        topic_services.publish_topic(self.topic_id, self.admin_id)
        self.save_new_topic('topic_id_2',
                            self.admin_id,
                            name='Private_Name',
                            abbreviated_name='pvttopic',
                            url_fragment='pvttopic',
                            description='Description',
                            canonical_story_ids=[],
                            additional_story_ids=[],
                            uncategorized_skill_ids=[],
                            subtopics=[subtopic],
                            next_subtopic_id=2)
        self.recorded_voiceovers_dict = {
            'voiceovers_mapping': {
                'content': {
                    'en': {
                        'filename': 'test.mp3',
                        'file_size_bytes': 100,
                        'needs_update': False,
                        'duration_secs': 0.34234
                    }
                }
            }
        }
        self.written_translations_dict = {
            'translations_mapping': {
                'content': {}
            }
        }
        self.subtopic_page_1.update_page_contents_html(
            state_domain.SubtitledHtml.from_dict({
                'html': '<p>hello world</p>',
                'content_id': 'content'
            }))
        self.subtopic_page_1.update_page_contents_audio(
            state_domain.RecordedVoiceovers.from_dict(
                self.recorded_voiceovers_dict))
        subtopic_page_services.save_subtopic_page(
            self.admin_id, self.subtopic_page_1, 'Updated page contents', [
                subtopic_page_domain.SubtopicPageChange(
                    {
                        'cmd':
                        subtopic_page_domain.CMD_UPDATE_SUBTOPIC_PAGE_PROPERTY,
                        'subtopic_id': self.subtopic_id_1,
                        'property_name': 'page_contents_html',
                        'new_value': '<p>hello world</p>',
                        'old_value': ''
                    })
            ])
        self.subtopic_page_2.update_page_contents_html(
            state_domain.SubtitledHtml.from_dict({
                'html': '<p>hello world 2</p>',
                'content_id': 'content'
            }))
        self.subtopic_page_2.update_page_contents_audio(
            state_domain.RecordedVoiceovers.from_dict(
                self.recorded_voiceovers_dict))
        subtopic_page_services.save_subtopic_page(
            self.admin_id, self.subtopic_page_2, 'Updated page contents', [
                subtopic_page_domain.SubtopicPageChange(
                    {
                        'cmd':
                        subtopic_page_domain.CMD_UPDATE_SUBTOPIC_PAGE_PROPERTY,
                        'subtopic_id': self.subtopic_id_2,
                        'property_name': 'page_contents_html',
                        'new_value': '<p>hello world 2</p>',
                        'old_value': ''
                    })
            ])