Esempio n. 1
0
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)
Esempio n. 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)
Esempio n. 4
0
    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]
Esempio n. 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))
Esempio n. 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))
Esempio n. 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, [])
Esempio n. 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'
                 })
             ])
Esempio n. 12
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.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)
Esempio n. 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.')
Esempio n. 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.')
Esempio n. 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.')
Esempio n. 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'))
Esempio n. 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)
Esempio n. 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': ''
                    })
            ])