Esempio n. 1
0
    def test_migration_job_skips_deleted_story(self):
        """Tests that the story migration job skips deleted story
        and does not attempt to migrate.
        """
        story = story_domain.Story.create_default_story(
            self.STORY_ID, title='A title')
        story_services.save_new_story(self.albert_id, story)

        # Delete the story before migration occurs.
        story_services.delete_story(
            self.albert_id, self.STORY_ID)

        # Ensure the story is deleted.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            story_services.get_story_by_id(self.STORY_ID)

        # Start migration job on sample story.
        job_id = (
            story_jobs_one_off.StoryMigrationOneOffJob.create_new())
        story_jobs_one_off.StoryMigrationOneOffJob.enqueue(job_id)

        # This running without errors indicates the deleted story is
        # being ignored.
        self.process_and_flush_pending_tasks()

        # Ensure the story is still deleted.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            story_services.get_story_by_id(self.STORY_ID)

        output = story_jobs_one_off.StoryMigrationOneOffJob.get_output(job_id) # pylint: disable=line-too-long
        expected = [[u'story_deleted',
                     [u'Encountered 1 deleted stories.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
Esempio n. 2
0
    def test_migration_job_converts_old_story(self):
        """Tests that the schema conversion functions work
        correctly and an old story is converted to new
        version.
        """
        # Generate story with old(v1) story contents data.
        self.save_new_story_with_story_contents_schema_v1(
            self.STORY_ID, self.albert_id, 'A title',
            'A description', 'A note')
        story = (
            story_services.get_story_by_id(self.STORY_ID))
        self.assertEqual(story.story_contents_schema_version, 1)

        # Start migration job.
        job_id = (
            story_jobs_one_off.StoryMigrationOneOffJob.create_new())
        story_jobs_one_off.StoryMigrationOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        # Verify the story migrates correctly.
        updated_story = (
            story_services.get_story_by_id(self.STORY_ID))
        self.assertEqual(
            updated_story.story_contents_schema_version,
            feconf.CURRENT_STORY_CONTENTS_SCHEMA_VERSION)

        output = story_jobs_one_off.StoryMigrationOneOffJob.get_output(job_id) # pylint: disable=line-too-long
        expected = [[u'story_migrated',
                     [u'1 stories successfully migrated.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
Esempio n. 3
0
    def put(self, topic_id, story_id):
        """Updates properties of the given story."""
        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)
        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None or story_id not in topic.canonical_story_ids:
            raise self.PageNotFoundException

        version = self.payload.get('version')
        self._require_valid_version(version, story.version)

        commit_message = self.payload.get('commit_message')
        change_dicts = self.payload.get('change_dicts')
        change_list = [
            story_domain.StoryChange(change_dict)
            for change_dict in change_dicts
        ]
        try:
            story_services.update_story(self.user_id, story_id, change_list,
                                        commit_message)
        except utils.ValidationError as e:
            raise self.InvalidInputException(e)

        story_dict = story_services.get_story_by_id(story_id).to_dict()

        self.values.update({'story': story_dict})

        self.render_json(self.values)
Esempio n. 4
0
    def test_update_story_node_properties(self):
        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_ADD_STORY_NODE,
                'node_id': self.NODE_ID_2
            }),
            story_domain.StoryChange({
                'cmd': story_domain.CMD_UPDATE_STORY_NODE_PROPERTY,
                'property_name': (
                    story_domain.STORY_NODE_PROPERTY_DESTINATION_NODE_IDS),
                'node_id': self.NODE_ID_2,
                'old_value': [],
                'new_value': [self.NODE_ID_1]
            }),
            story_domain.StoryChange({
                'cmd': story_domain.CMD_UPDATE_STORY_CONTENTS_PROPERTY,
                'property_name': (
                    story_domain.INITIAL_NODE_ID),
                'old_value': self.NODE_ID_1,
                'new_value': self.NODE_ID_2
            })
        ]
        story_services.update_story(
            self.USER_ID, self.STORY_ID, changelist, 'Added story node.')
        story = story_services.get_story_by_id(self.STORY_ID)
        self.assertEqual(
            story.story_contents.nodes[1].destination_node_ids,
            [self.NODE_ID_1])
        self.assertEqual(story.story_contents.initial_node_id, self.NODE_ID_2)
        self.assertEqual(story.story_contents.next_node_id, 'node_3')
        self.assertEqual(story.version, 2)

        story_summary = story_services.get_story_summary_by_id(self.STORY_ID)
        self.assertEqual(story_summary.node_count, 2)

        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_DELETE_STORY_NODE,
                'node_id': self.NODE_ID_1
            })
        ]
        story_services.update_story(
            self.USER_ID, self.STORY_ID, changelist,
            'Removed a story node.')
        story_summary = story_services.get_story_summary_by_id(self.STORY_ID)
        story = story_services.get_story_by_id(self.STORY_ID)
        self.assertEqual(story_summary.node_count, 1)
        self.assertEqual(story.story_contents.nodes[0].destination_node_ids, [])
Esempio n. 5
0
    def test_update_story_properties(self):
        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_UPDATE_STORY_PROPERTY,
                'property_name': story_domain.STORY_PROPERTY_TITLE,
                'old_value': 'Title',
                'new_value': 'New Title'
            }),
            story_domain.StoryChange({
                'cmd': story_domain.CMD_UPDATE_STORY_PROPERTY,
                'property_name': story_domain.STORY_PROPERTY_DESCRIPTION,
                'old_value': 'Description',
                'new_value': 'New Description'
            })
        ]
        story_services.update_story(self.USER_ID, self.STORY_ID, changelist,
                                    'Updated Title and Description.')
        story = story_services.get_story_by_id(self.STORY_ID)
        self.assertEqual(story.title, 'New Title')
        self.assertEqual(story.description, 'New Description')
        self.assertEqual(story.version, 3)

        story_summary = story_services.get_story_summary_by_id(self.STORY_ID)
        self.assertEqual(story_summary.title, 'New Title')
        self.assertEqual(story_summary.node_count, 1)
Esempio n. 6
0
    def test_migration_job_does_not_convert_up_to_date_story(self):
        """Tests that the story migration job does not convert a
        story that is already the latest schema version.
        """
        # Create a new story that should not be affected by the
        # job.
        story = story_domain.Story.create_default_story(
            self.STORY_ID, title='A title')
        story_services.save_new_story(self.albert_id, story)
        self.assertEqual(
            story.story_contents_schema_version,
            feconf.CURRENT_STORY_CONTENTS_SCHEMA_VERSION)

        # Start migration job.
        job_id = (
            story_jobs_one_off.StoryMigrationOneOffJob.create_new())
        story_jobs_one_off.StoryMigrationOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        # Verify the story is exactly the same after migration.
        updated_story = (
            story_services.get_story_by_id(self.STORY_ID))
        self.assertEqual(
            updated_story.story_contents_schema_version,
            feconf.CURRENT_STORY_CONTENTS_SCHEMA_VERSION)

        output = story_jobs_one_off.StoryMigrationOneOffJob.get_output(job_id) # pylint: disable=line-too-long
        expected = [[u'story_migrated',
                     [u'1 stories successfully migrated.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
Esempio n. 7
0
    def get(self, topic_id, story_id):
        """Handles GET requests."""

        if not constants.ENABLE_NEW_STRUCTURES:
            raise self.PageNotFoundException

        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None or story_id not in topic.canonical_story_ids:
            raise self.PageNotFoundException

        self.values.update({
            'story_id': story.id,
            'story_title': story.title,
            'nav_mode': feconf.NAV_MODE_STORY_EDITOR
        })

        self.render_template(
            'pages/story_editor/story_editor.html', redirect_url_on_logout='/')
Esempio n. 8
0
    def map(item):
        if not constants.ENABLE_NEW_STRUCTURES:
            return

        if item.deleted:
            yield (StoryMigrationOneOffJob._DELETED_KEY, 1)
            return

        # Note: the read will bring the story up to the newest version.
        story = story_services.get_story_by_id(item.id)
        try:
            story.validate()
        except Exception as e:
            logging.error(
                'Story %s failed validation: %s' % (item.id, e))
            yield (
                StoryMigrationOneOffJob._ERROR_KEY,
                'Story %s failed validation: %s' % (item.id, e))
            return

        # Write the new story into the datastore if it's different from
        # the old version.
        if item.schema_version <= feconf.CURRENT_STORY_CONTENTS_SCHEMA_VERSION:
            commit_cmds = [story_domain.StoryChange({
                'cmd': story_domain.CMD_MIGRATE_SCHEMA_TO_LATEST_VERSION,
                'from_version': item.schema_version,
                'to_version': feconf.CURRENT_STORY_CONTENTS_SCHEMA_VERSION
            })]
            story_services.update_story(
                feconf.MIGRATION_BOT_USERNAME, item.id, commit_cmds,
                'Update story schema version to %d.' % (
                    feconf.CURRENT_STORY_CONTENTS_SCHEMA_VERSION))
            yield (StoryMigrationOneOffJob._MIGRATED_KEY, 1)
Esempio n. 9
0
    def get(self, exploration_id):
        """Handles GET request."""
        start_cursor = self.request.get('cursor')
        story_id = self.request.get('story_id')
        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.InvalidInputException

        if not story.has_exploration(exploration_id):
            raise self.InvalidInputException

        pretest_questions, next_start_cursor = (
            question_services.get_questions_by_skill_ids(
                feconf.NUM_PRETEST_QUESTIONS,
                story.get_prerequisite_skill_ids_for_exp_id(exploration_id),
                start_cursor))
        pretest_question_dicts = [
            question.to_dict() for question in pretest_questions
        ]

        self.values.update({
            'pretest_question_dicts': pretest_question_dicts,
            'next_start_cursor': next_start_cursor
        })
        self.render_json(self.values)
Esempio n. 10
0
    def get(self, story_id):
        """Handles GET requests."""
        if not constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            raise self.PageNotFoundException

        story = story_services.get_story_by_id(story_id)

        completed_nodes = [
            completed_node.to_dict()
            for completed_node in story_services.get_completed_nodes_in_story(
                self.user_id, story_id)
        ]

        pending_nodes = [
            pending_node.to_dict()
            for pending_node in story_services.get_pending_nodes_in_story(
                self.user_id, story_id)
        ]

        self.values.update({
            'story_title': story.title,
            'story_description': story.description,
            'completed_nodes': completed_nodes,
            'pending_nodes': pending_nodes
        })
        self.render_json(self.values)
Esempio n. 11
0
    def get(self, story_id):
        """Handles GET requests."""

        if not constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            raise self.PageNotFoundException

        story = story_services.get_story_by_id(story_id)

        interaction_ids = feconf.ALLOWED_QUESTION_INTERACTION_IDS

        interaction_dependency_ids = (
            interaction_registry.Registry.get_deduplicated_dependency_ids(
                interaction_ids))
        dependencies_html, additional_angular_modules = (
            dependency_registry.Registry.get_deps_html_and_angular_modules(
                interaction_dependency_ids))

        interaction_templates = (interaction_registry.Registry.
                                 get_interaction_html(interaction_ids))

        self.values.update({
            'DEFAULT_OBJECT_VALUES':
            obj_services.get_default_object_values(),
            'additional_angular_modules':
            additional_angular_modules,
            'INTERACTION_SPECS':
            interaction_registry.Registry.get_all_specs(),
            'interaction_templates':
            jinja2.utils.Markup(interaction_templates),
            'dependencies_html':
            jinja2.utils.Markup(dependencies_html),
            'story_name':
            story.title
        })
        self.render_template('dist/review-test-page.mainpage.html')
Esempio n. 12
0
    def setUp(self):
        super(StoryServicesUnitTests, self).setUp()
        self.STORY_ID = story_services.get_new_story_id()
        self.save_new_story(self.STORY_ID, self.USER_ID, 'Title',
                            'Description', 'Notes')
        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_ADD_STORY_NODE,
                'node_id': self.NODE_ID_1,
                'title': 'Title 1'
            })
        ]
        story_services.update_story(self.USER_ID, self.STORY_ID, changelist,
                                    'Added node.')
        self.story = story_services.get_story_by_id(self.STORY_ID)
        self.signup('*****@*****.**', 'A')
        self.signup('*****@*****.**', 'B')
        self.signup(self.ADMIN_EMAIL, username=self.ADMIN_USERNAME)

        self.user_id_a = self.get_user_id_from_email('*****@*****.**')
        self.user_id_b = self.get_user_id_from_email('*****@*****.**')
        self.user_id_admin = self.get_user_id_from_email(self.ADMIN_EMAIL)

        self.set_admins([self.ADMIN_USERNAME])
        self.set_topic_managers([user_services.get_username(self.user_id_a)])
        self.user_a = user_services.UserActionsInfo(self.user_id_a)
        self.user_b = user_services.UserActionsInfo(self.user_id_b)
        self.user_admin = user_services.UserActionsInfo(self.user_id_admin)
Esempio n. 13
0
 def test_delete_story(self):
     story_services.delete_story(self.USER_ID, self.STORY_ID)
     self.assertEqual(
         story_services.get_story_by_id(self.STORY_ID, strict=False), None)
     self.assertEqual(
         story_services.get_story_summary_by_id(self.STORY_ID,
                                                strict=False), None)
Esempio n. 14
0
 def test_story_creation(self):
     self.login(self.ADMIN_EMAIL)
     csrf_token = self.get_new_csrf_token()
     json_response = self.post_json(
         '%s/%s' % (feconf.TOPIC_EDITOR_STORY_URL, self.topic_id),
         {'title': 'Story title'},
         csrf_token=csrf_token)
     story_id = json_response['storyId']
     self.assertEqual(len(story_id), 12)
     self.assertIsNotNone(
         story_services.get_story_by_id(story_id, strict=False))
     self.logout()
Esempio n. 15
0
    def delete(self, topic_id, story_id):
        """Handles Delete requests."""
        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        story_services.delete_story(self.user_id, story_id)

        self.render_json(self.values)
Esempio n. 16
0
    def get(self, topic_id, story_id):
        """Handles GET requests."""
        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None or story_id not in topic.canonical_story_ids:
            raise self.PageNotFoundException

        self.render_template('dist/story-editor-page.mainpage.html')
Esempio n. 17
0
 def test_story_creation(self):
     self.login(self.ADMIN_EMAIL)
     with self.swap(constants, 'ENABLE_NEW_STRUCTURES', True):
         response = self.testapp.get(
             '%s/%s' % (feconf.TOPIC_EDITOR_URL_PREFIX, self.topic_id))
         csrf_token = self.get_csrf_token_from_response(response)
         json_response = self.post_json(
             '%s/%s' % (feconf.TOPIC_EDITOR_STORY_URL, self.topic_id),
             {'title': 'Story title'},
             csrf_token=csrf_token)
         story_id = json_response['storyId']
         self.assertEqual(len(story_id), 12)
         self.assertIsNotNone(
             story_services.get_story_by_id(story_id, strict=False))
     self.logout()
Esempio n. 18
0
    def get(self, topic_id, story_id):
        """Populates the data on the individual story page."""
        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None or story_id not in topic.canonical_story_ids:
            raise self.PageNotFoundException

        self.values.update({
            'story': story.to_dict(),
            'topic_name': topic.name
        })

        self.render_json(self.values)
Esempio n. 19
0
    def get(self, story_id):
        """Handles GET requests."""
        if not constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            raise self.PageNotFoundException

        story = story_services.get_story_by_id(story_id)
        latest_completed_node_ids = (
            story_services.get_latest_completed_node_ids(
                self.user_id, story_id))

        if len(latest_completed_node_ids) == 0:
            raise self.PageNotFoundException

        try:
            skills = skill_services.get_multi_skills(
                story.get_acquired_skill_ids_for_node_ids(
                    latest_completed_node_ids))
        except Exception, e:
            raise self.PageNotFoundException(e)
Esempio n. 20
0
    def get(self, story_id):
        """Handles GET requests."""
        if not constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            raise self.PageNotFoundException

        story = story_services.get_story_by_id(story_id)

        completed_node_ids = [
            completed_node.id
            for completed_node in story_services.get_completed_nodes_in_story(
                self.user_id, story_id)
        ]

        ordered_node_dicts = [
            node.to_dict()
            for node in story.story_contents.get_ordered_nodes()
            # TODO(aks681): Once the story publication is done, add a check so
            # that only if all explorations in the story are published, can the
            # story itself be published. After which, remove the following
            # condition.
            if node.exploration_id
        ]
        for node in ordered_node_dicts:
            node['completed'] = False
            if node['id'] in completed_node_ids:
                node['completed'] = True

        exp_ids = [node['exploration_id'] for node in ordered_node_dicts]
        exp_summary_dicts = (
            summary_services.get_displayable_exp_summary_dicts_matching_ids(
                exp_ids, user=self.user))

        for ind, node in enumerate(ordered_node_dicts):
            node['exp_summary_dict'] = exp_summary_dicts[ind]

        self.values.update({
            'story_title': story.title,
            'story_description': story.description,
            'story_nodes': ordered_node_dicts
        })
        self.render_json(self.values)
Esempio n. 21
0
    def get(self, story_id):
        """Handles GET requests."""
        if not constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            raise self.PageNotFoundException

        story = story_services.get_story_by_id(story_id)
        latest_completed_node_ids = (
            story_services.get_latest_completed_node_ids(
                self.user_id, story_id))

        if story is None:
            raise self.PageNotFoundException(
                Exception('The story with the given id doesn\'t exist.'))
        if len(latest_completed_node_ids) == 0:
            raise self.PageNotFoundException

        acquired_skill_ids = story.get_acquired_skill_ids_for_node_ids(
            latest_completed_node_ids)

        self.values.update({'skill_ids': acquired_skill_ids})
        self.render_json(self.values)
Esempio n. 22
0
    def delete(self, topic_id, story_id):
        """Handles Delete requests."""
        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None:
            raise self.PageNotFoundException(
                Exception('The topic with the given id doesn\'t exist.'))

        story_services.delete_story(self.user_id, story_id)

        self.render_json(self.values)
Esempio n. 23
0
    def get(self, topic_id, story_id):
        """Handles GET requests."""

        if not constants.ENABLE_NEW_STRUCTURE_EDITORS:
            raise self.PageNotFoundException

        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None or story_id not in topic.canonical_story_ids:
            raise self.PageNotFoundException

        self.values.update({
            'story_id': story.id,
        })

        self.render_template('dist/story_editor.html')
Esempio n. 24
0
    def delete(self, topic_id, story_id):
        """Handles Delete requests."""
        if not feconf.ENABLE_NEW_STRUCTURES:
            raise self.PageNotFoundException

        story_domain.Story.require_valid_story_id(story_id)
        topic_domain.Topic.require_valid_topic_id(topic_id)

        story = story_services.get_story_by_id(story_id, strict=False)
        if story is None:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None or story_id not in topic.canonical_story_ids:
            raise self.PageNotFoundException

        topic = topic_services.get_topic_by_id(topic_id, strict=False)
        if topic is None:
            raise self.PageNotFoundException(
                Exception('The topic with the given id doesn\'t exist.'))

        story_services.delete_story(self.user_id, story_id)
        topic_services.delete_story(self.user_id, topic_id, story_id)
Esempio n. 25
0
    def test_update_story_node_properties(self):
        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_ADD_STORY_NODE,
                'node_id': self.NODE_ID_2,
                'title': 'Title 2'
            }),
            story_domain.StoryChange({
                'cmd':
                story_domain.CMD_UPDATE_STORY_NODE_PROPERTY,
                'property_name':
                (story_domain.STORY_NODE_PROPERTY_DESTINATION_NODE_IDS),
                'node_id':
                self.NODE_ID_2,
                'old_value': [],
                'new_value': [self.NODE_ID_1]
            }),
            story_domain.StoryChange({
                'cmd': story_domain.CMD_UPDATE_STORY_NODE_OUTLINE_STATUS,
                'node_id': self.NODE_ID_2,
                'old_value': False,
                'new_value': True
            }),
            story_domain.StoryChange({
                'cmd':
                story_domain.CMD_UPDATE_STORY_CONTENTS_PROPERTY,
                'property_name': (story_domain.INITIAL_NODE_ID),
                'old_value':
                self.NODE_ID_1,
                'new_value':
                self.NODE_ID_2
            })
        ]
        story_services.update_story(self.USER_ID, self.STORY_ID, changelist,
                                    'Added story node.')
        story = story_services.get_story_by_id(self.STORY_ID)
        self.assertEqual(story.story_contents.nodes[1].destination_node_ids,
                         [self.NODE_ID_1])
        self.assertEqual(story.story_contents.nodes[1].outline_is_finalized,
                         True)
        self.assertEqual(story.story_contents.nodes[1].title, 'Title 2')
        self.assertEqual(story.story_contents.initial_node_id, self.NODE_ID_2)
        self.assertEqual(story.story_contents.next_node_id, 'node_3')
        self.assertEqual(story.version, 3)

        story_summary = story_services.get_story_summary_by_id(self.STORY_ID)
        self.assertEqual(story_summary.node_count, 2)

        changelist = [
            story_domain.StoryChange({
                'cmd': story_domain.CMD_DELETE_STORY_NODE,
                'node_id': self.NODE_ID_1
            }),
            story_domain.StoryChange({
                'cmd': story_domain.CMD_UPDATE_STORY_NODE_OUTLINE_STATUS,
                'node_id': self.NODE_ID_2,
                'old_value': True,
                'new_value': False
            }),
            story_domain.StoryChange({
                'cmd':
                story_domain.CMD_UPDATE_STORY_NODE_PROPERTY,
                'property_name': (story_domain.STORY_NODE_PROPERTY_TITLE),
                'node_id':
                self.NODE_ID_2,
                'old_value':
                'Title 2',
                'new_value':
                'Modified title 2'
            }),
        ]
        story_services.update_story(self.USER_ID, self.STORY_ID, changelist,
                                    'Removed a story node.')
        story_summary = story_services.get_story_summary_by_id(self.STORY_ID)
        story = story_services.get_story_by_id(self.STORY_ID)
        self.assertEqual(story_summary.node_count, 1)
        self.assertEqual(story.story_contents.nodes[0].title,
                         'Modified title 2')
        self.assertEqual(story.story_contents.nodes[0].destination_node_ids,
                         [])
        self.assertEqual(story.story_contents.nodes[0].outline_is_finalized,
                         False)
Esempio n. 26
0
 def test_get_story_by_id(self):
     expected_story = self.story.to_dict()
     story = story_services.get_story_by_id(self.STORY_ID)
     self.assertEqual(story.to_dict(), expected_story)
Esempio n. 27
0
    def get(self, exploration_id):
        """Populates the data on the individual exploration page.

        Args:
            exploration_id: str. The ID of the exploration.
        """
        version = self.request.get('v')
        story_id = self.request.get('story_id')
        version = int(version) if version else None

        try:
            exploration = exp_services.get_exploration_by_id(
                exploration_id, version=version)
        except Exception as e:
            raise self.PageNotFoundException(e)

        exploration_rights = rights_manager.get_exploration_rights(
            exploration_id, strict=False)
        user_settings = user_services.get_user_settings(self.user_id)

        preferred_audio_language_code = None
        if user_settings is not None:
            preferred_audio_language_code = (
                user_settings.preferred_audio_language_code)

        # Retrieve all classifiers for the exploration.
        state_classifier_mapping = {}
        classifier_training_jobs = (
            classifier_services.get_classifier_training_jobs(
                exploration_id, exploration.version, exploration.states))
        for index, state_name in enumerate(exploration.states):
            if classifier_training_jobs[index] is not None:
                classifier_data = classifier_training_jobs[
                    index].classifier_data
                algorithm_id = classifier_training_jobs[index].algorithm_id
                data_schema_version = (
                    classifier_training_jobs[index].data_schema_version)
                state_classifier_mapping[state_name] = {
                    'algorithm_id': algorithm_id,
                    'classifier_data': classifier_data,
                    'data_schema_version': data_schema_version
                }

        pretest_question_dicts = []
        next_cursor = None
        if story_id:
            story = story_services.get_story_by_id(story_id, strict=False)
            if story is None:
                raise self.InvalidInputException

            if not story.has_exploration(exploration_id):
                raise self.InvalidInputException

            pretest_questions, next_cursor = (
                question_services.get_questions_by_skill_ids(
                    feconf.NUM_PRETEST_QUESTIONS,
                    story.get_prerequisite_skill_ids_for_exp_id(exploration_id),
                    '')
            )
            pretest_question_dicts = [
                question.to_dict() for question in pretest_questions
            ]

        self.values.update({
            'can_edit': (
                rights_manager.check_can_edit_activity(
                    self.user, exploration_rights)),
            'exploration': exploration.to_player_dict(),
            'exploration_id': exploration_id,
            'pretest_question_dicts': pretest_question_dicts,
            'next_cursor_for_pretests': next_cursor,
            'is_logged_in': bool(self.user_id),
            'session_id': utils.generate_new_session_id(),
            'version': exploration.version,
            'preferred_audio_language_code': preferred_audio_language_code,
            'state_classifier_mapping': state_classifier_mapping,
            'auto_tts_enabled': exploration.auto_tts_enabled,
            'correctness_feedback_enabled': (
                exploration.correctness_feedback_enabled),
        })
        self.render_json(self.values)