def test_skill_contents_validation(self): self.skill.skill_contents.worked_examples = '' self._assert_validation_error('Expected worked examples to be a list') self.skill.skill_contents.worked_examples = [1] self._assert_validation_error( 'Expected worked example to be a WorkedExample object') example = skill_domain.WorkedExample('question', 'explanation') self.skill.skill_contents.worked_examples = [example] self._assert_validation_error( 'Expected example question to be a SubtitledHtml object') example = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), 'explanation') self.skill.skill_contents.worked_examples = [example] self._assert_validation_error( 'Expected example explanation to be a SubtitledHtml object') self.skill.skill_contents.explanation = 'explanation' self._assert_validation_error( 'Expected skill explanation to be a SubtitledHtml object') self.skill.skill_contents = '' self._assert_validation_error( 'Expected skill_contents to be a SkillContents object')
def test_get_concept_cards(self): json_response = self.get_json( '%s/%s,%s' % (feconf.CONCEPT_CARD_DATA_URL_PREFIX, self.skill_id, self.skill_id_1)) self.assertEqual(2, len(json_response['concept_card_dicts'])) self.assertEqual( '<p>Skill Explanation</p>', json_response['concept_card_dicts'][0]['explanation']['html']) self.assertEqual([ skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml( '3', '<p>Example Explanation 1</p>')).to_dict(), skill_domain.WorkedExample( state_domain.SubtitledHtml('4', '<p>Example Question 2</p>'), state_domain.SubtitledHtml( '5', '<p>Example Explanation 2</p>')).to_dict() ], json_response['concept_card_dicts'][0]['worked_examples']) self.assertEqual( '<p>Skill Explanation 1</p>', json_response['concept_card_dicts'][1]['explanation']['html']) self.assertEqual([ skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml( '3', '<p>Example Explanation 1</p>')).to_dict(), skill_domain.WorkedExample( state_domain.SubtitledHtml('4', '<p>Example Question 2</p>'), state_domain.SubtitledHtml( '5', '<p>Example Explanation 2</p>')).to_dict() ], json_response['concept_card_dicts'][1]['worked_examples'])
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 setUp(self): """Before each individual test, create a dummy skill.""" super(ConceptCardDataHandlerTest, self).setUp() self.signup(self.CURRICULUM_ADMIN_EMAIL, self.CURRICULUM_ADMIN_USERNAME) self.admin_id = self.get_user_id_from_email(self.CURRICULUM_ADMIN_EMAIL) self.set_curriculum_admins([self.CURRICULUM_ADMIN_USERNAME]) example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>') ) example_2 = skill_domain.WorkedExample( state_domain.SubtitledHtml('4', '<p>Example Question 2</p>'), state_domain.SubtitledHtml('5', '<p>Example Explanation 2</p>') ) self.skill_contents = skill_domain.SkillContents( state_domain.SubtitledHtml( '1', '<p>Skill Explanation</p>'), [example_1, example_2], state_domain.RecordedVoiceovers.from_dict({ 'voiceovers_mapping': { '1': {}, '2': {}, '3': {}, '4': {}, '5': {} } }), state_domain.WrittenTranslations.from_dict({ 'translations_mapping': { '1': {}, '2': {}, '3': {}, '4': {}, '5': {} } }) ) self.skill_contents_1 = skill_domain.SkillContents( state_domain.SubtitledHtml( '1', '<p>Skill Explanation 1</p>'), [example_1, example_2], state_domain.RecordedVoiceovers.from_dict({ 'voiceovers_mapping': { '1': {}, '2': {}, '3': {}, '4': {}, '5': {} } }), state_domain.WrittenTranslations.from_dict({ 'translations_mapping': { '1': {}, '2': {}, '3': {}, '4': {}, '5': {} } }) ) self.admin = user_services.get_user_actions_info(self.admin_id) self.skill_id = skill_services.get_new_skill_id() self.save_new_skill( self.skill_id, self.admin_id, description='Description', skill_contents=self.skill_contents) self.skill_id_1 = skill_services.get_new_skill_id() self.save_new_skill( self.skill_id_1, self.admin_id, description='Description', skill_contents=self.skill_contents_1) self.skill_id_2 = skill_services.get_new_skill_id()
def test_validate_duplicate_content_id(self): self.skill.skill_contents.worked_examples = ([ skill_domain.WorkedExample(self.skill.skill_contents.explanation, self.skill.skill_contents.explanation) ]) self._assert_validation_error('Found a duplicate content id 1') example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('4', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('1', '<p>Example Explanation 1</p>')) self.skill.skill_contents.worked_examples = [example_1] self._assert_validation_error('Found a duplicate content id 1')
def setUp(self) -> None: super(SkillFetchersUnitTests, self).setUp() example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>') ) skill_contents = skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict({ 'voiceovers_mapping': { '1': {}, '2': {}, '3': {} } }), state_domain.WrittenTranslations.from_dict({ 'translations_mapping': { '1': {}, '2': {}, '3': {} } }) ) misconceptions = [skill_domain.Misconception( self.MISCONCEPTION_ID_1, 'name', '<p>description</p>', '<p>default_feedback</p>', True)] self.skill_id = skill_services.get_new_skill_id() self.signup(self.CURRICULUM_ADMIN_EMAIL, self.CURRICULUM_ADMIN_USERNAME) self.user_id_admin = ( self.get_user_id_from_email(self.CURRICULUM_ADMIN_EMAIL)) # type: ignore[no-untyped-call] self.set_curriculum_admins([self.CURRICULUM_ADMIN_USERNAME]) # type: ignore[no-untyped-call] self.skill = self.save_new_skill( # type: ignore[no-untyped-call] self.skill_id, self.USER_ID, description='Description', misconceptions=misconceptions, skill_contents=skill_contents, prerequisite_skill_ids=['skill_id_1', 'skill_id_2'])
def test_get_multi_skills(self): example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>')) self.save_new_skill( 'skill_a', self.user_id_admin, description='Description A', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }}))) self.save_new_skill( 'skill_b', self.user_id_admin, description='Description B', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }}))) skills = skill_fetchers.get_multi_skills(['skill_a', 'skill_b']) self.assertEqual(len(skills), 2) self.assertEqual(skills[0].id, 'skill_a') self.assertEqual(skills[0].description, 'Description A') self.assertEqual(skills[0].misconceptions, []) self.assertEqual(skills[1].id, 'skill_b') self.assertEqual(skills[1].description, 'Description B') self.assertEqual(skills[1].misconceptions, []) with self.assertRaisesRegexp(Exception, 'No skill exists for ID skill_c'): skill_fetchers.get_multi_skills(['skill_a', 'skill_c'])
def test_get_descriptions_of_skills(self): example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>')) self.save_new_skill( 'skill_id_1', self.user_id_admin, description='Description 1', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }}))) self.save_new_skill( 'skill_id_2', self.user_id_admin, description='Description 2', misconceptions=[], skill_contents=skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }}))) skill_services.delete_skill(self.user_id_admin, 'skill_id_2') skill_descriptions, deleted_skill_ids = ( skill_services.get_descriptions_of_skills( ['skill_id_1', 'skill_id_2'])) self.assertEqual(deleted_skill_ids, ['skill_id_2']) self.assertEqual(skill_descriptions, { 'skill_id_1': 'Description 1', 'skill_id_2': None })
def test_get_skill_from_model_with_latest_schemas_version(self) -> None: commit_cmd = skill_domain.SkillChange({ 'cmd': skill_domain.CMD_CREATE_NEW }) example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>') ) model = skill_models.SkillModel( id='skill_id', description='description', language_code='en', misconceptions=[], rubrics=[], next_misconception_id=0, misconceptions_schema_version=2, rubric_schema_version=2, skill_contents_schema_version=2, all_questions_merged=False, skill_contents=skill_domain.SkillContents( # type: ignore[no-untyped-call] state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict({ 'voiceovers_mapping': { '1': {}, '2': {}, '3': {} } }), state_domain.WrittenTranslations.from_dict({ 'translations_mapping': { '1': {}, '2': {}, '3': {} } }) ).to_dict() ) commit_cmd_dicts = [commit_cmd.to_dict()] model.commit( self.user_id_admin, 'skill model created', commit_cmd_dicts) skill = skill_fetchers.get_skill_from_model(model) self.assertEqual( skill.misconceptions_schema_version, feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION ) self.assertEqual( skill.skill_contents_schema_version, feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION ) self.assertEqual( skill.rubric_schema_version, feconf.CURRENT_RUBRIC_SCHEMA_VERSION )
def setUp(self): super(SkillDomainUnitTests, self).setUp() example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>')) skill_contents = skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }})) misconceptions = [ skill_domain.Misconception(self.MISCONCEPTION_ID, 'name', '<p>notes</p>', '<p>default_feedback</p>', True) ] rubrics = [ skill_domain.Rubric(constants.SKILL_DIFFICULTIES[0], ['<p>Explanation 1</p>']), skill_domain.Rubric(constants.SKILL_DIFFICULTIES[1], ['<p>Explanation 2</p>']), skill_domain.Rubric(constants.SKILL_DIFFICULTIES[2], ['<p>Explanation 3</p>']) ] self.skill = skill_domain.Skill( self.SKILL_ID, 'Description', misconceptions, rubrics, skill_contents, feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION, feconf.CURRENT_RUBRIC_SCHEMA_VERSION, feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION, 'en', 0, 1, None, False, ['skill_id_2'], created_on=datetime.datetime.now(), last_updated=datetime.datetime.now())
def setUp(self): super(SkillServicesUnitTests, self).setUp() example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>')) skill_contents = skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }})) misconceptions = [ skill_domain.Misconception(self.MISCONCEPTION_ID_1, 'name', '<p>description</p>', '<p>default_feedback</p>', True) ] self.SKILL_ID = skill_services.get_new_skill_id() self.signup('*****@*****.**', 'A') self.signup(self.ADMIN_EMAIL, username=self.ADMIN_USERNAME) self.signup('*****@*****.**', username='******') self.user_id_a = self.get_user_id_from_email('*****@*****.**') self.user_id_admin = self.get_user_id_from_email(self.ADMIN_EMAIL) self.user_id_admin_2 = self.get_user_id_from_email( '*****@*****.**') self.set_admins([self.ADMIN_USERNAME, 'adm2']) self.user_a = user_services.UserActionsInfo(self.user_id_a) self.user_admin = user_services.UserActionsInfo(self.user_id_admin) self.user_admin_2 = user_services.UserActionsInfo(self.user_id_admin_2) self.skill = self.save_new_skill( self.SKILL_ID, self.USER_ID, description='Description', misconceptions=misconceptions, skill_contents=skill_contents, prerequisite_skill_ids=['skill_id_1', 'skill_id_2'])
def test_get_skill_from_model_with_invalid_rubric_schema_version( self ) -> None: commit_cmd = skill_domain.SkillChange({ 'cmd': skill_domain.CMD_CREATE_NEW }) example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>') ) model = skill_models.SkillModel( id='skill_id', description='description', language_code='en', misconceptions=[], rubrics=[], next_misconception_id=0, misconceptions_schema_version=2, rubric_schema_version=0, skill_contents_schema_version=2, all_questions_merged=False, skill_contents=skill_domain.SkillContents( # type: ignore[no-untyped-call] state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict({ 'voiceovers_mapping': { '1': {}, '2': {}, '3': {} } }), state_domain.WrittenTranslations.from_dict({ 'translations_mapping': { '1': {}, '2': {}, '3': {} } }) ).to_dict() ) commit_cmd_dicts = [commit_cmd.to_dict()] model.commit( self.user_id_admin, 'skill model created', commit_cmd_dicts) with self.assertRaisesRegex( # type: ignore[no-untyped-call] Exception, 'Sorry, we can only process v1-v%d rubric schemas at ' 'present.' % feconf.CURRENT_RUBRIC_SCHEMA_VERSION): skill_fetchers.get_skill_from_model(model)
def test_conversion_to_and_from_dict(self): """Test that to_dict and from_dict preserve all data within a skill_contents and misconception object. """ example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Answer 1</p>')) skill_contents = skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }})) skill_contents_dict = skill_contents.to_dict() skill_contents_from_dict = skill_domain.SkillContents.from_dict( skill_contents_dict) misconceptions = skill_domain.Misconception(self.MISCONCEPTION_ID, 'Tag Name', '<p>Description</p>', '<p>Feedback</p>', True) misconceptions_dict = misconceptions.to_dict() misconceptions_from_dict = skill_domain.Misconception.from_dict( misconceptions_dict) rubric = skill_domain.Rubric(constants.SKILL_DIFFICULTIES[0], ['<p>Explanation</p>']) rubric_dict = rubric.to_dict() rubric_from_dict = skill_domain.Rubric.from_dict(rubric_dict) self.assertEqual(skill_contents_from_dict.to_dict(), skill_contents_dict) self.assertEqual(misconceptions_from_dict.to_dict(), misconceptions_dict) self.assertEqual(rubric_from_dict.to_dict(), rubric_dict)
def setUp(self): super(SkillSummaryModelValidatorTests, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.set_admins([self.ADMIN_USERNAME]) rubrics = [ skill_domain.Rubric(constants.SKILL_DIFFICULTIES[0], ['Explanation 1']), skill_domain.Rubric(constants.SKILL_DIFFICULTIES[1], ['Explanation 2']), skill_domain.Rubric(constants.SKILL_DIFFICULTIES[2], ['Explanation 3']) ] language_codes = ['ar', 'en', 'en'] skills = [ skill_domain.Skill.create_default_skill('%s' % i, 'description %d' % i, rubrics) for i in python_utils.RANGE(3) ] example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', '<p>Example Question 1</p>'), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>')) skill_contents = skill_domain.SkillContents( state_domain.SubtitledHtml('1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict( {'voiceovers_mapping': { '1': {}, '2': {}, '3': {} }}), state_domain.WrittenTranslations.from_dict( {'translations_mapping': { '1': {}, '2': {}, '3': {} }})) misconception_dict = { 'id': 0, 'name': 'name', 'notes': '<p>notes</p>', 'feedback': '<p>default_feedback</p>', 'must_be_addressed': True } misconception = skill_domain.Misconception.from_dict( misconception_dict) for index, skill in enumerate(skills): skill.language_code = language_codes[index] skill.skill_contents = skill_contents skill.add_misconception(misconception) skill_services.save_new_skill(self.owner_id, skill) self.model_instance_0 = skill_models.SkillSummaryModel.get_by_id('0') self.model_instance_1 = skill_models.SkillSummaryModel.get_by_id('1') self.model_instance_2 = skill_models.SkillSummaryModel.get_by_id('2') self.job_class = ( prod_validation_jobs_one_off.SkillSummaryModelAuditOneOffJob)
def test_job_when_skills_have_math_rich_text_components_with_svgs(self): valid_html_1 = ( '<oppia-noninteractive-math math_content-with-value="{&q' 'uot;raw_latex&quot;: &quot;(x - a_1)(x - a_2)(x - a' '_3)...(x - a_n-1)(x - a_n)&quot;, &quot;svg_filenam' 'e&quot;: &quot;file1.svg&quot;}"></oppia-noninte' 'ractive-math>' ) valid_html_2 = ( '<oppia-noninteractive-math math_content-with-value="{&' 'quot;raw_latex&quot;: &quot;+,+,+,+&quot;, &' 'quot;svg_filename&quot;: &quot;file2.svg&quot;}">' '</oppia-noninteractive-math>' ) example_1 = skill_domain.WorkedExample( state_domain.SubtitledHtml('2', valid_html_1), state_domain.SubtitledHtml('3', '<p>Example Explanation 1</p>') ) skill_contents1 = skill_domain.SkillContents( state_domain.SubtitledHtml( '1', '<p>Explanation</p>'), [example_1], state_domain.RecordedVoiceovers.from_dict({ 'voiceovers_mapping': { '1': {}, '2': {}, '3': {} } }), state_domain.WrittenTranslations.from_dict({ 'translations_mapping': { '1': {}, '2': {}, '3': {} } }) ) misconceptions1 = [skill_domain.Misconception( 0, 'name', '<p>misconception html1</p>', '<p>misconception html2</p>', True)] rubrics1 = [ skill_domain.Rubric( constants.SKILL_DIFFICULTIES[0], [valid_html_2]), skill_domain.Rubric( constants.SKILL_DIFFICULTIES[1], ['<p>Explanation 2</p>']), skill_domain.Rubric( constants.SKILL_DIFFICULTIES[2], ['<p>Explanation 3</p>'])] skill1 = skill_domain.Skill( 'skill_id1', 'Description', misconceptions1, rubrics1, skill_contents1, feconf.CURRENT_MISCONCEPTIONS_SCHEMA_VERSION, feconf.CURRENT_RUBRIC_SCHEMA_VERSION, feconf.CURRENT_SKILL_CONTENTS_SCHEMA_VERSION, 'en', 0, 1, None, False, ['skill_id_2'] ) skill_services.save_new_skill(self.albert_id, skill1) job_id = ( skill_jobs_one_off.SkillMathRteAuditOneOffJob.create_new()) skill_jobs_one_off.SkillMathRteAuditOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() output = skill_jobs_one_off.SkillMathRteAuditOneOffJob.get_output( job_id) overall_result = ast.literal_eval(output[0]) expected_skill1_info = { 'skill_id': 'skill_id1', 'latex_strings_with_svg': [ '(x - a_1)(x - a_2)(x - a_3)...(x - a_n-1)(x - a_n)', '+,+,+,+'] } skill_latex_info = overall_result[1] self.assertEqual(skill_latex_info[0], expected_skill1_info)