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')
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])
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)
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)
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)
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')
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()
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()
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)
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])
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()
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)
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')
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])
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)
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)
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')
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()
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)