def test_update_skill_worked_examples(self):
        skill = skill_services.get_skill_by_id(self.SKILL_ID)
        old_worked_example = skill_domain.WorkedExample(
            state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'),
            state_domain.SubtitledHtml(
                '3', '<p>Example Explanation 1</p>')).to_dict()
        new_worked_example = skill_domain.WorkedExample(
            state_domain.SubtitledHtml('2', '<p>Example Question 1 new</p>'),
            state_domain.SubtitledHtml(
                '3', '<p>Example Explanation 1 new</p>')).to_dict()

        self.assertEqual(len(skill.skill_contents.worked_examples), 1)
        self.assertEqual(skill.skill_contents.worked_examples[0].to_dict(),
                         old_worked_example)

        changelist = [
            skill_domain.SkillChange({
                'cmd':
                skill_domain.CMD_UPDATE_SKILL_CONTENTS_PROPERTY,
                'property_name':
                (skill_domain.SKILL_CONTENTS_PROPERTY_WORKED_EXAMPLES),
                'old_value': [old_worked_example],
                'new_value': [new_worked_example]
            })
        ]
        skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                    'Change worked examples.')

        skill = skill_services.get_skill_by_id(self.SKILL_ID)
        self.assertEqual(len(skill.skill_contents.worked_examples), 1)
        self.assertEqual(skill.skill_contents.worked_examples[0].to_dict(),
                         new_worked_example)
    def test_update_skill_misconception_notes(self):
        skill = skill_services.get_skill_by_id(self.SKILL_ID)

        self.assertEqual(len(skill.misconceptions), 1)
        self.assertEqual(skill.misconceptions[0].id, self.MISCONCEPTION_ID_1)
        self.assertEqual(skill.misconceptions[0].notes, 'description')

        changelist = [
            skill_domain.SkillChange({
                'cmd':
                skill_domain.CMD_UPDATE_SKILL_MISCONCEPTIONS_PROPERTY,
                'property_name':
                (skill_domain.SKILL_MISCONCEPTIONS_PROPERTY_NOTES),
                'id':
                self.MISCONCEPTION_ID_1,
                'old_value':
                'description',
                'new_value':
                'new description'
            })
        ]

        skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                    'Update misconception notes.')
        skill = skill_services.get_skill_by_id(self.SKILL_ID)

        self.assertEqual(len(skill.misconceptions), 1)
        self.assertEqual(skill.misconceptions[0].id, self.MISCONCEPTION_ID_1)
        self.assertEqual(skill.misconceptions[0].notes, 'new description')
Exemple #3
0
    def put(self, skill_id):
        """Updates properties of the given skill."""
        skill_domain.Skill.require_valid_skill_id(skill_id)
        skill = skill_services.get_skill_by_id(skill_id, strict=False)
        if skill is None:
            raise self.PageNotFoundException(
                Exception('The skill with the given id doesn\'t exist.'))

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

        commit_message = self.payload.get('commit_message')
        change_dicts = self.payload.get('change_dicts')
        change_list = [
            skill_domain.SkillChange(change_dict)
            for change_dict in change_dicts
        ]
        try:
            skill_services.update_skill(self.user_id, skill_id, change_list,
                                        commit_message)
        except utils.ValidationError as e:
            raise self.InvalidInputException(e)

        skill_dict = skill_services.get_skill_by_id(skill_id).to_dict()

        self.values.update({'skill': skill_dict})

        self.render_json(self.values)
 def post(self):
     """Handles the POST request."""
     if not constants.ENABLE_NEW_STRUCTURE_EDITORS:
         raise self.PageNotFoundException
     old_skill_id = self.payload.get('old_skill_id')
     new_skill_id = self.payload.get('new_skill_id')
     new_skill = skill_services.get_skill_by_id(new_skill_id, strict=False)
     if new_skill is None:
         raise self.PageNotFoundException(
             Exception('The new skill with the given id doesn\'t exist.'))
     old_skill = skill_services.get_skill_by_id(old_skill_id, strict=False)
     if old_skill is None:
         raise self.PageNotFoundException(
             Exception('The old skill with the given id doesn\'t exist.'))
     question_services.update_skill_ids_of_questions(
         old_skill_id, old_skill.description, new_skill_id)
     changelist = [
         skill_domain.SkillChange({
             'cmd': skill_domain.CMD_UPDATE_SKILL_PROPERTY,
             'property_name': (
                 skill_domain.SKILL_PROPERTY_ALL_QUESTIONS_MERGED),
             'old_value': False,
             'new_value': True
         })
     ]
     skill_services.update_skill(
         self.user_id, old_skill_id, changelist,
         'Marking the skill as having being merged successfully.')
     self.render_json({
         'merged_into_skill': new_skill_id
     })
    def test_update_skill_worked_examples(self):
        skill = skill_services.get_skill_by_id(self.SKILL_ID)
        old_worked_examples = {'content_id': '2', 'html': '<p>Example 1</p>'}
        new_worked_examples = {'content_id': '2', 'html': '<p>Example 2</p>'}

        self.assertEqual(len(skill.skill_contents.worked_examples), 1)
        self.assertEqual(
            skill.skill_contents.worked_examples[0].to_dict(),
            old_worked_examples)

        changelist = [
            skill_domain.SkillChange({
                'cmd': skill_domain.CMD_UPDATE_SKILL_CONTENTS_PROPERTY,
                'property_name': (
                    skill_domain.SKILL_CONTENTS_PROPERTY_WORKED_EXAMPLES),
                'old_value': [old_worked_examples],
                'new_value': [new_worked_examples]
            })
        ]
        skill_services.update_skill(
            self.USER_ID, self.SKILL_ID, changelist, 'Change worked examples.')

        skill = skill_services.get_skill_by_id(self.SKILL_ID)
        self.assertEqual(len(skill.skill_contents.worked_examples), 1)
        self.assertEqual(
            skill.skill_contents.worked_examples[0].to_dict(),
            new_worked_examples)
    def test_update_skill_misconception_feedback(self):
        skill = skill_services.get_skill_by_id(self.SKILL_ID)

        self.assertEqual(len(skill.misconceptions), 1)
        self.assertEqual(skill.misconceptions[0].id, self.MISCONCEPTION_ID_1)
        self.assertEqual(skill.misconceptions[0].feedback, 'default_feedback')

        changelist = [
            skill_domain.SkillChange({
                'cmd':
                skill_domain.CMD_UPDATE_SKILL_MISCONCEPTIONS_PROPERTY,
                'property_name':
                (skill_domain.SKILL_MISCONCEPTIONS_PROPERTY_FEEDBACK),
                'id':
                self.MISCONCEPTION_ID_1,
                'old_value':
                'default_feedback',
                'new_value':
                'new feedback'
            })
        ]

        skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                    'Update misconception feedback.')
        skill = skill_services.get_skill_by_id(self.SKILL_ID)

        self.assertEqual(len(skill.misconceptions), 1)
        self.assertEqual(skill.misconceptions[0].id, self.MISCONCEPTION_ID_1)
        self.assertEqual(skill.misconceptions[0].feedback, 'new feedback')
    def test_update_skill_explanation(self):
        skill = skill_services.get_skill_by_id(self.SKILL_ID)
        old_explanation = {'content_id': '1', 'html': 'Explanation'}
        new_explanation = {'content_id': '1', 'html': 'New explanation'}

        self.assertEqual(skill.skill_contents.explanation.to_dict(),
                         old_explanation)

        changelist = [
            skill_domain.SkillChange({
                'cmd':
                skill_domain.CMD_UPDATE_SKILL_CONTENTS_PROPERTY,
                'property_name':
                (skill_domain.SKILL_CONTENTS_PROPERTY_EXPLANATION),
                'old_value':
                old_explanation,
                'new_value':
                new_explanation
            })
        ]
        skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                    'Change explanation.')

        skill = skill_services.get_skill_by_id(self.SKILL_ID)
        self.assertEqual(skill.skill_contents.explanation.to_dict(),
                         new_explanation)
    def test_migration_job_skips_deleted_skill(self):
        """Tests that the skill migration job skips deleted skill
        and does not attempt to migrate.
        """
        skill = skill_domain.Skill.create_default_skill(
            self.SKILL_ID, description='A description')
        skill_services.save_new_skill(self.albert_id, skill)

        # Delete the skill before migration occurs.
        skill_services.delete_skill(self.albert_id, self.SKILL_ID)

        # Ensure the skill is deleted.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            skill_services.get_skill_by_id(self.SKILL_ID)

        # Start migration job on sample skill.
        job_id = (skill_jobs_one_off.SkillMigrationOneOffJob.create_new())
        skill_jobs_one_off.SkillMigrationOneOffJob.enqueue(job_id)

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

        # Ensure the skill is still deleted.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            skill_services.get_skill_by_id(self.SKILL_ID)

        output = skill_jobs_one_off.SkillMigrationOneOffJob.get_output(job_id)  # pylint: disable=line-too-long
        expected = [[u'skill_deleted', [u'Encountered 1 deleted skills.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
    def test_migration_job_converts_old_skill(self):
        """Tests that the schema conversion functions work
        correctly and an old skill is converted to new
        version.
        """

        # Generate skill with old(v1) misconceptions schema
        # version and old(v1) skill contents schema version.
        skill_contents = {
            'worked_examples': [],
            'explanation': {
                'content_id': 'explanation',
                'html': feconf.DEFAULT_SKILL_EXPLANATION
            },
            'content_ids_to_audio_translations': {
                'explanation': {}
            },
            'written_translations': {
                'translations_mapping': {
                    'explanation': {}
                }
            }
        }
        self.save_new_skill_with_story_and_skill_contents_schema_version(
            self.SKILL_ID, self.albert_id, 'A description', 0,
            misconceptions=[], skill_contents=skill_contents)
        skill = (
            skill_services.get_skill_by_id(self.SKILL_ID))
        self.assertEqual(skill.misconceptions_schema_version, 1)
        self.assertEqual(skill.skill_contents_schema_version, 1)

        # Start migration job.
        with self.swap(constants, 'ENABLE_NEW_STRUCTURE_EDITORS', True):
            job_id = (
                skill_jobs_one_off.SkillMigrationOneOffJob.create_new())
            skill_jobs_one_off.SkillMigrationOneOffJob.enqueue(job_id)
            self.process_and_flush_pending_tasks()

            # Verify that the skill migrates correctly.
            updated_skill = (
                skill_services.get_skill_by_id(self.SKILL_ID))

        self.assertEqual(
            updated_skill.skill_contents_schema_version,
            feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION)
        self.assertEqual(
            updated_skill.misconceptions_schema_version,
            feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION)

        output = skill_jobs_one_off.SkillMigrationOneOffJob.get_output(job_id) # pylint: disable=line-too-long
        expected = [[u'skill_migrated',
                     [u'1 skills successfully migrated.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
Exemple #10
0
 def test_delete_skill(self):
     skill_services.delete_skill(self.USER_ID, self.SKILL_ID)
     self.assertEqual(
         skill_services.get_skill_by_id(self.SKILL_ID, strict=False), None)
     self.assertEqual(
         skill_services.get_skill_summary_by_id(self.SKILL_ID,
                                                strict=False), None)
Exemple #11
0
    def post(self, skill_id):
        """Handles POST requests."""
        if not constants.ENABLE_NEW_STRUCTURE_EDITORS:
            raise self.PageNotFoundException

        skill_domain.Skill.require_valid_skill_id(skill_id)
        skill = skill_services.get_skill_by_id(skill_id, strict=False)
        if skill is None:
            raise self.PageNotFoundException(
                'The skill with the given id doesn\'t exist.')

        question_dict = self.payload.get('question_dict')
        if (
                (question_dict['id'] is not None) or
                ('question_state_data' not in question_dict) or
                ('language_code' not in question_dict) or
                (question_dict['version'] != 1)):
            raise self.InvalidInputException

        question_dict['question_state_data_schema_version'] = (
            feconf.CURRENT_STATE_SCHEMA_VERSION)
        question_dict['id'] = question_services.get_new_question_id()
        try:
            question = question_domain.Question.from_dict(question_dict)
        except:
            raise self.InvalidInputException
        question_services.add_question(self.user_id, question)
        # TODO(vinitamurthi): Replace DEFAULT_SKILL_DIFFICULTY
        # with a value passed from the frontend.
        question_services.create_new_question_skill_link(
            question.id, skill_id, constants.DEFAULT_SKILL_DIFFICULTY)
        self.values.update({
            'question_id': question.id
        })
        self.render_json(self.values)
Exemple #12
0
 def test_merge_skill(self):
     changelist = [
         skill_domain.SkillChange({
             'cmd':
             skill_domain.CMD_UPDATE_SKILL_PROPERTY,
             'property_name':
             (skill_domain.SKILL_PROPERTY_SUPERSEDING_SKILL_ID),
             'id':
             0,
             'old_value':
             '',
             'new_value':
             'TestSkillId'
         }),
         skill_domain.SkillChange({
             'cmd':
             skill_domain.CMD_UPDATE_SKILL_PROPERTY,
             'property_name':
             (skill_domain.SKILL_PROPERTY_ALL_QUESTIONS_MERGED),
             'id':
             0,
             'old_value':
             None,
             'new_value':
             False
         })
     ]
     skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                 'Merging skill.')
     skill = skill_services.get_skill_by_id(self.SKILL_ID)
     self.assertEqual(skill.version, 2)
     self.assertEqual(skill.superseding_skill_id, 'TestSkillId')
     self.assertEqual(skill.all_questions_merged, False)
 def test_set_merge_complete_for_skill(self):
     changelist = [
         skill_domain.SkillChange({
             'cmd':
             skill_domain.CMD_UPDATE_SKILL_PROPERTY,
             'property_name':
             (skill_domain.SKILL_PROPERTY_SUPERSEDING_SKILL_ID),
             'old_value':
             None,
             'new_value':
             self.SKILL_ID
         }),
         skill_domain.SkillChange({
             'cmd':
             skill_domain.CMD_UPDATE_SKILL_PROPERTY,
             'property_name':
             (skill_domain.SKILL_PROPERTY_ALL_QUESTIONS_MERGED),
             'id':
             0,
             'old_value':
             False,
             'new_value':
             True
         })
     ]
     skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                 'Setting merge complete for skill.')
     skill = skill_services.get_skill_by_id(self.SKILL_ID)
     self.assertEqual(skill.version, 2)
     self.assertEqual(skill.all_questions_merged, True)
Exemple #14
0
    def get(self, skill_id):
        """Handles GET requests."""
        skill_domain.Skill.require_valid_skill_id(skill_id)

        skill = skill_services.get_skill_by_id(skill_id, strict=False)

        if skill is None:
            raise self.PageNotFoundException(
                Exception('The skill with the given id doesn\'t exist.'))

        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 + self.EDITOR_PAGE_DEPENDENCY_IDS))

        self.values.update({
            'additional_angular_modules':
            additional_angular_modules,
            'dependencies_html':
            jinja2.utils.Markup(dependencies_html)
        })

        self.render_template('dist/skill-editor-page.mainpage.html')
Exemple #15
0
 def test_skill_creation(self):
     self.login(self.ADMIN_EMAIL)
     csrf_token = self.get_new_csrf_token()
     rubrics = [{
         'difficulty': constants.SKILL_DIFFICULTIES[0],
         'explanation': 'Explanation 1'
     }, {
         'difficulty': constants.SKILL_DIFFICULTIES[1],
         'explanation': 'Explanation 2'
     }, {
         'difficulty': constants.SKILL_DIFFICULTIES[2],
         'explanation': 'Explanation 3'
     }]
     json_response = self.post_json(self.url, {
         'description':
         'Skill Description',
         'rubrics':
         rubrics,
         'explanation_dict':
         state_domain.SubtitledHtml('1', '<p>Explanation</p>').to_dict()
     },
                                    csrf_token=csrf_token)
     skill_id = json_response['skillId']
     self.assertEqual(len(skill_id), 12)
     self.assertIsNotNone(
         skill_services.get_skill_by_id(skill_id, strict=False))
     self.logout()
Exemple #16
0
 def test_skill_creation(self):
     self.login(self.ADMIN_EMAIL)
     csrf_token = self.get_new_csrf_token()
     rubrics = [{
         'difficulty': constants.SKILL_DIFFICULTIES[0],
         'explanations': ['Explanation 1']
     }, {
         'difficulty': constants.SKILL_DIFFICULTIES[1],
         'explanations': ['Explanation 2']
     }, {
         'difficulty': constants.SKILL_DIFFICULTIES[2],
         'explanations': ['Explanation 3']
     }]
     json_response = self.post_json(
         self.url, {
             'description':
             'Skill Description',
             'rubrics':
             rubrics,
             'explanation_dict':
             state_domain.SubtitledHtml('1',
                                        '<p>Explanation</p>').to_dict(),
             'thumbnail_filename':
             'image.svg'
         },
         csrf_token=csrf_token,
         upload_files=(('image', 'unused_filename',
                        self.original_image_content), ))
     skill_id = json_response['skillId']
     self.assertEqual(len(skill_id), 12)
     self.assertIsNotNone(
         skill_services.get_skill_by_id(skill_id, strict=False))
     self.logout()
Exemple #17
0
    def get(self, skill_id):
        """Populates the data on the individual skill page."""
        skill_domain.Skill.require_valid_skill_id(skill_id)
        skill = skill_services.get_skill_by_id(skill_id, strict=False)

        if skill is None:
            raise self.PageNotFoundException(
                Exception('The skill with the given id doesn\'t exist.'))

        topics = topic_fetchers.get_all_topics()
        grouped_skill_summary_dicts = {}

        for topic in topics:
            skill_summaries = skill_services.get_multi_skill_summaries(
                topic.get_all_skill_ids())
            skill_summary_dicts = [
                summary.to_dict() for summary in skill_summaries
            ]
            grouped_skill_summary_dicts[topic.name] = skill_summary_dicts

        self.values.update({
            'skill':
            skill.to_dict(),
            'grouped_skill_summaries':
            grouped_skill_summary_dicts
        })

        self.render_json(self.values)
Exemple #18
0
 def test_update_skill(self):
     changelist = [
         skill_domain.SkillChange({
             'cmd': skill_domain.CMD_ADD_SKILL_MISCONCEPTION,
             'new_misconception_dict': {
                 'id': 0,
                 'name': 'test name',
                 'notes': 'test notes',
                 'feedback': 'test feedback'
             }
         }),
         skill_domain.SkillChange({
             'cmd':
             skill_domain.CMD_UPDATE_SKILL_MISCONCEPTIONS_PROPERTY,
             'property_name':
             (skill_domain.SKILL_MISCONCEPTIONS_PROPERTY_NAME),
             'id':
             0,
             'old_value':
             'test name',
             'new_value':
             'Name'
         })
     ]
     skill_services.update_skill(self.USER_ID, self.SKILL_ID, changelist,
                                 'Updated misconception name.')
     skill = skill_services.get_skill_by_id(self.SKILL_ID)
     skill_summary = skill_services.get_skill_summary_by_id(self.SKILL_ID)
     self.assertEqual(skill_summary.misconception_count, 2)
     self.assertEqual(skill_summary.version, 2)
     self.assertEqual(skill.version, 2)
     self.assertEqual(skill.misconceptions[1].name, 'Name')
    def test_migration_job_does_not_convert_up_to_date_skill(self):
        """Tests that the skill migration job does not convert a
        skill that is already the latest schema version.
        """
        # Create a new skill that should not be affected by the
        # job.
        skill = skill_domain.Skill.create_default_skill(
            self.SKILL_ID, description='A description', rubrics=self.rubrics)
        skill_services.save_new_skill(self.albert_id, skill)
        self.assertEqual(skill.skill_contents_schema_version,
                         feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION)
        self.assertEqual(skill.misconceptions_schema_version,
                         feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION)
        self.assertEqual(skill.rubric_schema_version,
                         feconf.CURRENT_RUBRIC_SCHEMA_VERSION)

        # Start migration job.
        job_id = (skill_jobs_one_off.SkillMigrationOneOffJob.create_new())
        skill_jobs_one_off.SkillMigrationOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        # Verify the skill is exactly the same after migration.
        updated_skill = (skill_services.get_skill_by_id(self.SKILL_ID))
        self.assertEqual(updated_skill.skill_contents_schema_version,
                         feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION)
        self.assertEqual(updated_skill.misconceptions_schema_version,
                         feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION)
        self.assertEqual(updated_skill.rubric_schema_version,
                         feconf.CURRENT_RUBRIC_SCHEMA_VERSION)

        output = skill_jobs_one_off.SkillMigrationOneOffJob.get_output(job_id)
        expected = [[u'skill_migrated', [u'1 skills successfully migrated.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
Exemple #20
0
 def test_skill_creation_in_valid_topic(self):
     self.login(self.ADMIN_EMAIL)
     csrf_token = self.get_new_csrf_token()
     rubrics = [{
         'difficulty': constants.SKILL_DIFFICULTIES[0],
         'explanation': 'Explanation 1'
     }, {
         'difficulty': constants.SKILL_DIFFICULTIES[1],
         'explanation': 'Explanation 2'
     }, {
         'difficulty': constants.SKILL_DIFFICULTIES[2],
         'explanation': 'Explanation 3'
     }]
     payload = {
         'description':
         'Skill Description',
         'linked_topic_ids': [self.topic_id],
         'rubrics':
         rubrics,
         'explanation_dict':
         state_domain.SubtitledHtml('1', '<p>Explanation</p>').to_dict()
     }
     json_response = self.post_json(self.url,
                                    payload,
                                    csrf_token=csrf_token)
     skill_id = json_response['skillId']
     self.assertEqual(len(skill_id), 12)
     self.assertIsNotNone(
         skill_services.get_skill_by_id(skill_id, strict=False))
     topic = topic_fetchers.get_topic_by_id(self.topic_id)
     self.assertEqual(topic.uncategorized_skill_ids,
                      [self.linked_skill_id, skill_id])
     self.logout()
Exemple #21
0
    def post(self, skill_id):
        """Handles POST requests."""
        if not constants.ENABLE_NEW_STRUCTURES:
            raise self.PageNotFoundException

        skill_domain.Skill.require_valid_skill_id(skill_id)
        skill = skill_services.get_skill_by_id(skill_id, strict=False)
        if skill is None:
            raise self.PageNotFoundException(
                'The skill with the given id doesn\'t exist.')

        question_dict = self.payload.get('question_dict')
        if ((question_dict['id'] is not None)
                or ('question_state_data' not in question_dict)
                or ('language_code' not in question_dict)
                or (question_dict['version'] != 1)
                or (question_dict['question_state_schema_version'] !=
                    (feconf.CURRENT_STATES_SCHEMA_VERSION))):
            raise self.InvalidInputException

        question_dict['id'] = question_services.get_new_question_id()
        question = question_domain.Question.from_dict(question_dict)
        question_services.add_question(self.user_id, question)
        question_services.create_new_question_skill_link(question.id, skill_id)
        self.values.update({'question_id': question.id})
        self.render_json(self.values)
Exemple #22
0
    def put(self, skill_id):
        """Publishes a skill."""
        skill = skill_services.get_skill_by_id(skill_id)
        version = self.payload.get('version')
        _require_valid_version(version, skill.version)

        skill_domain.Skill.require_valid_skill_id(skill_id)

        try:
            skill_services.publish_skill(skill_id, self.user_id)
        except Exception as e:
            raise self.UnauthorizedUserException(e)

        skill_rights = skill_services.get_skill_rights(skill_id, strict=False)
        user_actions_info = user_services.UserActionsInfo(self.user_id)
        can_edit_skill_description = check_can_edit_skill_description(
            user_actions_info)

        self.values.update({
            'skill_is_private':
            skill_rights.skill_is_private,
            'creator_id':
            skill_rights.creator_id,
            'can_edit_skill_description':
            can_edit_skill_description
        })

        self.render_json(self.values)
    def test_delete_skill_misconception(self):
        skill = skill_services.get_skill_by_id(self.SKILL_ID)

        self.assertEqual(len(skill.misconceptions), 1)
        self.assertEqual(skill.misconceptions[0].id, self.MISCONCEPTION_ID_1)

        changelist = [
            skill_domain.SkillChange({
                'cmd': skill_domain.CMD_DELETE_SKILL_MISCONCEPTION,
                'misconception_id': self.MISCONCEPTION_ID_1,
            })
        ]

        skill_services.update_skill(
            self.USER_ID, self.SKILL_ID, changelist, 'Delete misconception.')
        skill = skill_services.get_skill_by_id(self.SKILL_ID)

        self.assertEqual(skill.misconceptions, [])
    def test_get_skill_by_id_with_different_versions(self):
        changelist = [
            skill_domain.SkillChange({
                'cmd': skill_domain.CMD_UPDATE_SKILL_PROPERTY,
                'property_name': skill_domain.SKILL_PROPERTY_LANGUAGE_CODE,
                'old_value': 'en',
                'new_value': 'bn'
            })
        ]
        skill_services.update_skill(
            self.USER_ID, self.SKILL_ID, changelist, 'update language code')

        skill = skill_services.get_skill_by_id(self.SKILL_ID, version=1)
        self.assertEqual(skill.id, self.SKILL_ID)
        self.assertEqual(skill.language_code, 'en')

        skill = skill_services.get_skill_by_id(self.SKILL_ID, version=2)
        self.assertEqual(skill.id, self.SKILL_ID)
        self.assertEqual(skill.language_code, 'bn')
Exemple #25
0
    def test_migration_job_converts_old_skill(self):
        """Tests that the schema conversion functions work
        correctly and an old skill is converted to new
        version.
        """

        # Generate skill with old(v1) misconceptions schema
        # version and old(v1) skill contents schema version.
        skill_contents = {
            'worked_examples': [],
            'explanation': {
                'content_id': 'explanation',
                'html': feconf.DEFAULT_SKILL_EXPLANATION
            },
            'recorded_voiceovers': {
                'voiceovers_mapping': {
                    'explanation': {}
                }
            },
            'written_translations': {
                'translations_mapping': {
                    'explanation': {}
                }
            }
        }
        self.save_new_skill_with_defined_schema_versions(
            self.SKILL_ID, self.albert_id, 'A description', 0,
            misconceptions=[], skill_contents=skill_contents,
            misconceptions_schema_version=1, skill_contents_schema_version=1,
            rubric_schema_version=1)

        # Start migration job.
        job_id = (
            skill_jobs_one_off.SkillMigrationOneOffJob.create_new())
        skill_jobs_one_off.SkillMigrationOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_tasks()

        # Verify that the skill migrates correctly.
        updated_skill = (
            skill_services.get_skill_by_id(self.SKILL_ID))

        self.assertEqual(
            updated_skill.skill_contents_schema_version,
            feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION)
        self.assertEqual(
            updated_skill.misconceptions_schema_version,
            feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION)
        self.assertEqual(
            updated_skill.rubric_schema_version,
            feconf.CURRENT_RUBRIC_SCHEMA_VERSION)

        output = skill_jobs_one_off.SkillMigrationOneOffJob.get_output(job_id)
        expected = [[u'skill_migrated',
                     [u'1 skills successfully migrated.']]]
        self.assertEqual(expected, [ast.literal_eval(x) for x in output])
Exemple #26
0
    def map(item):
        if item.deleted:
            yield (SkillMigrationOneOffJob._DELETED_KEY, 1)
            return

        # Note: the read will bring the skill up to the newest version.
        skill = skill_services.get_skill_by_id(item.id)
        try:
            skill.validate()
        except Exception as e:
            logging.error(
                'Skill %s failed validation: %s' % (item.id, e))
            yield (
                SkillMigrationOneOffJob._ERROR_KEY,
                'Skill %s failed validation: %s' % (item.id, e))
            return

        # Write the new skill into the datastore if it's different from
        # the old version.
        commit_cmds = []
        if (
                item.skill_contents_schema_version <=
                feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION):
            commit_cmds.append(skill_domain.SkillChange({
                'cmd': skill_domain.CMD_MIGRATE_CONTENTS_SCHEMA_TO_LATEST_VERSION, # pylint: disable=line-too-long
                'from_version': item.skill_contents_schema_version,
                'to_version': feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION
            }))
        if (
                item.misconceptions_schema_version <=
                feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION):
            commit_cmds.append(skill_domain.SkillChange({
                'cmd': skill_domain.CMD_MIGRATE_MISCONCEPTIONS_SCHEMA_TO_LATEST_VERSION, # pylint: disable=line-too-long
                'from_version': item.misconceptions_schema_version,
                'to_version': feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION
            }))
        if (
                item.rubric_schema_version <=
                feconf.CURRENT_RUBRIC_SCHEMA_VERSION):
            commit_cmds.append(skill_domain.SkillChange({
                'cmd': skill_domain.CMD_MIGRATE_RUBRICS_SCHEMA_TO_LATEST_VERSION, # pylint: disable=line-too-long
                'from_version': item.rubric_schema_version,
                'to_version': feconf.CURRENT_RUBRIC_SCHEMA_VERSION
            }))

        if commit_cmds:
            skill_services.update_skill(
                feconf.MIGRATION_BOT_USERNAME, item.id, commit_cmds,
                'Update skill content schema version to %d and '
                'skill misconceptions schema version to %d and '
                'skill rubrics schema version to %d.' % (
                    feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION,
                    feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION,
                    feconf.CURRENT_RUBRIC_SCHEMA_VERSION))
            yield (SkillMigrationOneOffJob._MIGRATED_KEY, 1)
Exemple #27
0
    def get(self, skill_id):
        """Populates the data on the individual skill page."""
        skill_domain.Skill.require_valid_skill_id(skill_id)
        skill = skill_services.get_skill_by_id(skill_id, strict=False)
        if skill is None:
            raise self.PageNotFoundException(
                Exception('The skill with the given id doesn\'t exist.'))

        self.values.update({'skill': skill.to_dict()})

        self.render_json(self.values)
Exemple #28
0
    def get(self, skill_id):
        """Handles GET requests."""
        skill_domain.Skill.require_valid_skill_id(skill_id)

        skill = skill_services.get_skill_by_id(skill_id, strict=False)

        if skill is None:
            raise self.PageNotFoundException(
                Exception('The skill with the given id doesn\'t exist.'))

        self.render_template('skill-editor-page.mainpage.html')
Exemple #29
0
    def test_skill_creation(self):
        self.login(self.ADMIN_EMAIL)
        csrf_token = self.get_new_csrf_token()

        json_response = self.post_json(
            self.url, {'description': 'Skill Description'},
            csrf_token=csrf_token)
        skill_id = json_response['skillId']
        self.assertEqual(len(skill_id), 12)
        self.assertIsNotNone(
            skill_services.get_skill_by_id(skill_id, strict=False))
        self.logout()
Exemple #30
0
    def get(self, skill_id):
        """Handles GET requests."""

        if not constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            raise self.PageNotFoundException

        skill = skill_services.get_skill_by_id(skill_id, strict=False)

        skill_dict = skill.to_dict()
        self.values.update({'concept_card_dict': skill_dict['skill_contents']})

        self.render_json(self.values)