def test_no_username_shown_for_logged_out_learners(self): NEW_EXP_ID = 'new_eid' exploration = exp_domain.Exploration.create_default_exploration( NEW_EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.EDITOR_ID, exploration) rights_manager.publish_exploration(self.EDITOR_ID, NEW_EXP_ID) response = self.testapp.get('/create/%s' % NEW_EXP_ID) csrf_token = self.get_csrf_token_from_response(response) self.post_json( '/explorehandler/give_feedback/%s' % NEW_EXP_ID, { 'state_name': None, 'subject': 'Test thread', 'feedback': 'Test thread text', 'include_author': False, }, csrf_token) response_dict = self.get_json( '%s/%s' % (feconf.FEEDBACK_THREADLIST_URL_PREFIX, NEW_EXP_ID)) threadlist = response_dict['threads'] self.assertIsNone(threadlist[0]['original_author_username']) response_dict = self.get_json('%s/%s/%s' % ( feconf.FEEDBACK_THREAD_URL_PREFIX, NEW_EXP_ID, threadlist[0]['thread_id'])) self.assertIsNone(response_dict['messages'][0]['author_username'])
def save_new_valid_exploration( self, exploration_id, owner_id, title='A title', category='A category', objective='An objective', end_state_name=None): """Saves a new strictly-validated exploration. Returns the exploration domain object. """ exploration = exp_domain.Exploration.create_default_exploration( exploration_id, title, category) exploration.states[exploration.init_state_name].update_interaction_id( 'TextInput') exploration.objective = objective # If an end state name is provided, add terminal node with that name if end_state_name is not None: exploration.add_states([end_state_name]) exploration.states[end_state_name].update_interaction_id( 'EndExploration') # Link first state to ending state (to maintain validity) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.handlers[0].rule_specs[0].dest = end_state_name exp_services.save_new_exploration(owner_id, exploration) return exploration
def test_migration_job_does_not_convert_up_to_date_exp(self): """Tests that the exploration migration job does not convert an exploration that is already the latest states schema version. """ # Create a new, default exploration that should not be affected by the # job. exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, 'title', 'category') init_state = exploration.states[exploration.init_state_name] init_state.update_interaction_id('EndExploration') init_state.interaction.default_outcome = None exp_services.save_new_exploration(self.albert_id, exploration) self.assertEqual( exploration.states_schema_version, feconf.CURRENT_EXPLORATION_STATES_SCHEMA_VERSION) yaml_before_migration = exploration.to_yaml() # Start migration job on sample exploration. job_id = exp_jobs_one_off.ExplorationMigrationJobManager.create_new() exp_jobs_one_off.ExplorationMigrationJobManager.enqueue(job_id) self.process_and_flush_pending_tasks() # Verify the exploration is exactly the same after migration. updated_exp = exp_services.get_exploration_by_id(self.VALID_EXP_ID) self.assertEqual( updated_exp.states_schema_version, feconf.CURRENT_EXPLORATION_STATES_SCHEMA_VERSION) after_converted_yaml = updated_exp.to_yaml() self.assertEqual(after_converted_yaml, yaml_before_migration)
def test_recording_answer_for_different_rules(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'title', 'category') exp_services.save_new_exploration('user_id', exp) rule = exp_domain.RuleSpec.from_dict({ 'rule_type': 'LessThan', 'inputs': {'x': 5} }) rule_str = rule.stringify_classified_rule() state_name = exp.init_state_name event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.DEFAULT_RULESPEC_STR, 'answer1') event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, rule_str, 'answer2') default_rule_answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.DEFAULT_RULESPEC_STR) self.assertEquals(default_rule_answer_log.answers, {'answer1': 1}) self.assertEquals(default_rule_answer_log.total_answer_count, 1) other_rule_answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, rule_str) self.assertEquals(other_rule_answer_log.answers, {'answer2': 1}) self.assertEquals(other_rule_answer_log.total_answer_count, 1)
def test_incomplete_and_default_flags(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) state_name = exp.init_state_name # Hit the default rule once, and fail to answer twice. The result # should be classified as incomplete. for _ in range(3): event_services.StateHitEventHandler.record( 'eid', state_name, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') self.assertEquals(stats_services.get_state_improvements('eid'), [{ 'rank': 2, 'type': 'incomplete', 'state_name': state_name }]) # Now hit the default two more times. The result should be classified # as default. for i in range(2): event_services.StateHitEventHandler.record( 'eid', state_name, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') self.assertEquals(stats_services.get_state_improvements('eid'), [{ 'rank': 3, 'type': 'default', 'state_name': state_name }])
def test_adding_new_exploration_viewer_role_does_not_result_in_subscription(self): exploration = exp_domain.Exploration.create_default_exploration(EXP_ID, "Title", "Category") exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual(self._get_exploration_ids_subscribed_to(self.viewer_id), []) rights_manager.assign_role_for_exploration(self.owner_id, EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER) self.assertEqual(self._get_exploration_ids_subscribed_to(self.viewer_id), [])
def test_deleting_exploration_does_not_delete_subscription(self): exploration = exp_domain.Exploration.create_default_exploration(EXP_ID, "Title", "Category") exp_services.save_new_exploration(self.owner_id, exploration) self.assertEqual(self._get_exploration_ids_subscribed_to(self.owner_id), [EXP_ID]) exp_services.delete_exploration(self.owner_id, EXP_ID) self.assertEqual(self._get_exploration_ids_subscribed_to(self.owner_id), [EXP_ID])
def test_creating_exploration_results_in_subscription(self): self.assertEqual( self._get_exploration_ids_subscribed_to(USER_ID), []) exp_services.save_new_exploration( USER_ID, exp_domain.Exploration.create_default_exploration(EXP_ID)) self.assertEqual( self._get_exploration_ids_subscribed_to(USER_ID), [EXP_ID])
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration""" self.exploration = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.EXP_ID, self.exploration) self.assertEqual( rating_services.get_overall_ratings(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0}) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating(self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating(self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating(self.USER_ID_1, self.EXP_ID, 3) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings(self.EXP_ID), {'1': 0, '2': 0, '3': 1, '4': 1, '5': 0}) rating_services.assign_rating(self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 2, '5': 0})
def test_get_top_improvable_states(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) state_name = exp.init_state_name for _ in range(5): stats_services.EventHandler.record_state_hit( 'eid', state_name, True) stats_services.EventHandler.record_answer_submitted( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, '1') for _ in range(2): stats_services.EventHandler.record_answer_submitted( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, '2') expected_top_state = { 'exp_id': 'eid', 'type': 'default', 'rank': 3, 'state_name': exp.init_state_name } states = stats_services.get_top_improvable_states(['eid'], 10) self.assertEquals(len(states), 1) self.assertDictContainsSubset(expected_top_state, states[0])
def save_new_valid_exploration( self, exploration_id, owner_id, title='A title', category='A category', objective='An objective', language_code=feconf.DEFAULT_LANGUAGE_CODE, end_state_name=None): """Saves a new strictly-validated exploration. Returns the exploration domain object. """ exploration = exp_domain.Exploration.create_default_exploration( exploration_id, title=title, category=category, language_code=language_code) exploration.states[exploration.init_state_name].update_interaction_id( 'TextInput') exploration.objective = objective # If an end state name is provided, add terminal node with that name if end_state_name is not None: exploration.add_states([end_state_name]) end_state = exploration.states[end_state_name] end_state.update_interaction_id('EndExploration') end_state.interaction.default_outcome = None # Link first state to ending state (to maintain validity) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = end_state_name exp_services.save_new_exploration(owner_id, exploration) return exploration
def test_no_improvement_flag_hit(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) not_default_rule_spec = exp_domain.RuleSpec({ 'rule_type': rule_domain.ATOMIC_RULE_TYPE, 'name': 'NotDefault', 'inputs': {}, 'subject': 'answer' }, exp.init_state_name, [], [], 'NormalizedString') default_rule_spec = exp_domain.RuleSpec.get_default_rule_spec(feconf.END_DEST, 'NormalizedString') exp.init_state.widget.handlers[0].rule_specs = [ not_default_rule_spec, default_rule_spec ] exp_services._save_exploration('*****@*****.**', exp, '', []) stats_services.EventHandler.record_state_hit( 'eid', exp.init_state_name, True) stats_services.EventHandler.record_answer_submitted( 'eid', 1, exp.init_state_name, self.SUBMIT_HANDLER, not_default_rule_spec, '1') states = stats_services.get_top_improvable_states(['eid'], 1) self.assertEquals(len(states), 0)
def test_get_user_stats(self): exp0 = exp_domain.Exploration.create_default_exploration( 'eid0', 'title0', 'category') exp_services.save_new_exploration('uid0', exp0) exp1 = exp_domain.Exploration.create_default_exploration( 'eid1', 'title1', 'category') exp_services.save_new_exploration('uid0', exp1) f0 = stats_domain.FeedbackItem.create_feedback_for_state( 'eid0', 'welcome', 'my feedback', None, 'uid0') f1 = stats_domain.FeedbackItem.create_feedback_for_exploration( 'eid1', 'another feedback', None, 'uid0') # This should return the both the feedback. self.assertEquals(stats_services.get_user_stats('uid0'), {'feedback': { f0.id: { 'content': 'my feedback', 'exp_id': 'eid0', 'exp_title': 'title0', 'state_name': 'welcome', 'status': 'new', 'target_id': 'state:eid0.welcome', }, f1.id: { 'content': 'another feedback', 'exp_id': 'eid1', 'exp_title': 'title1', 'state_name': None, 'status': 'new', 'target_id': 'exploration:eid1', }, }}) # uid1 does not have any feedbacks. self.assertEquals(stats_services.get_user_stats('uid1'), {'feedback':{}})
def test_deletion_rights_for_published_exploration(self): """Test rights management for deletion of published explorations.""" PUBLISHED_EXP_ID = "published_eid" exploration = exp_domain.Exploration.create_default_exploration(PUBLISHED_EXP_ID, "A title", "A category") exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role(self.owner_id, PUBLISHED_EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_exploration(self.owner_id, PUBLISHED_EXP_ID) self.login(self.EDITOR_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.VIEWER_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.OWNER_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.ADMIN_EMAIL) response = self.testapp.delete("/createhandler/data/%s" % PUBLISHED_EXP_ID) self.assertEqual(response.status_int, 200) self.logout()
def test_recording_answer_for_different_rules(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'title', 'category') exp_services.save_new_exploration('user_id', exp) rule = exp_domain.RuleSpec.from_dict_and_obj_type({ 'definition': { 'rule_type': 'atomic', 'name': 'LessThan', 'subject': 'answer', 'inputs': {'x': 5} }, 'dest': 'dest', 'feedback': None, 'param_changes': [] }, 'Real') state_name = exp.init_state_name event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, 'answer1') event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.SUBMIT_HANDLER, rule, 'answer2') default_rule_answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR) self.assertEquals(default_rule_answer_log.answers, {'answer1': 1}) self.assertEquals(default_rule_answer_log.total_answer_count, 1) other_rule_answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, str(rule)) self.assertEquals(other_rule_answer_log.answers, {'answer2': 1}) self.assertEquals(other_rule_answer_log.total_answer_count, 1)
def test_resolving_answers(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'title', 'category') exp_services.save_new_exploration('user_id', exp) state_name = exp.init_state_name answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.DEFAULT_RULESPEC_STR) self.assertEquals(answer_log.answers, {}) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.DEFAULT_RULESPEC_STR, 'answer1') event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.DEFAULT_RULESPEC_STR, 'answer1') event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.DEFAULT_RULESPEC_STR, 'answer2') answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.DEFAULT_RULESPEC_STR) self.assertEquals(answer_log.answers, {'answer1': 2, 'answer2': 1}) self.assertEquals(answer_log.total_answer_count, 3) event_services.DefaultRuleAnswerResolutionEventHandler.record( 'eid', state_name, ['answer1']) answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.DEFAULT_RULESPEC_STR) self.assertEquals(answer_log.answers, {'answer2': 1}) self.assertEquals(answer_log.total_answer_count, 1)
def test_deletion_rights_for_published_exploration(self): """Test rights management for deletion of published explorations.""" published_exp_id = 'published_eid' exploration = exp_domain.Exploration.create_default_exploration( published_exp_id, 'A title', 'A category') exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role_for_exploration( self.owner_id, published_exp_id, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_exploration(self.owner_id, published_exp_id) self.login(self.EDITOR_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.VIEWER_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.OWNER_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.ADMIN_EMAIL) response = self.testapp.delete( '/createhandler/data/%s' % published_exp_id) self.assertEqual(response.status_int, 200) self.logout()
def setUp(self): """Create an exploration and register the event listener manually.""" super(ContinuousComputationTests, self).setUp() exploration = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'title', 'A category') exp_services.save_new_exploration('owner_id', exploration)
def test_request_new_state_template(self): """Test requesting a new state template when adding a new state.""" # Register and log in as an admin. self.register_editor('*****@*****.**') self.login('*****@*****.**') EXP_ID = 'eid' exploration = exp_domain.Exploration.create_default_exploration( EXP_ID, 'A title', 'A category') exploration.states[exploration.init_state_name].widget.handlers[ 0].rule_specs[0].dest = feconf.END_DEST exp_services.save_new_exploration( self.get_current_logged_in_user_id(), exploration) response = self.testapp.get('/create/%s' % EXP_ID) csrf_token = self.get_csrf_token_from_response(response) # Add a new state called 'New valid state name'. response_dict = self.post_json( '/createhandler/new_state_template/%s' % EXP_ID, { 'state_name': 'New valid state name' }, csrf_token) self.assertDictContainsSubset({ 'content': [{'type': 'text', 'value': ''}], 'unresolved_answers': {} }, response_dict['new_state']) self.assertTrue('widget' in response_dict['new_state']) self.logout()
def test_no_username_shown_for_nonregistered_users(self): NEW_EXP_ID = 'new_eid' exploration = exp_domain.Exploration.create_default_exploration( NEW_EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.EDITOR_ID, exploration) rights_manager.publish_exploration(self.EDITOR_ID, NEW_EXP_ID) self.login('*****@*****.**') response = self.testapp.get('/create/%s' % NEW_EXP_ID) csrf_token = self.get_csrf_token_from_response(response) self.post_json( '%s/%s' % (feconf.FEEDBACK_THREADLIST_URL_PREFIX, NEW_EXP_ID), { 'state_name': None, 'subject': 'Test thread', 'text': 'Test thread text', }, csrf_token) response_dict = self.get_json( '%s/%s' % (feconf.FEEDBACK_THREADLIST_URL_PREFIX, NEW_EXP_ID)) threadlist = response_dict['threads'] self.assertIsNone(threadlist[0]['original_author_username']) response_dict = self.get_json('%s/%s/%s' % ( feconf.FEEDBACK_THREAD_URL_PREFIX, NEW_EXP_ID, threadlist[0]['thread_id'])) self.assertIsNone(response_dict['messages'][0]['author_username']) self.logout()
def test_get_state_improvements(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) for ind in range(5): event_services.StartExplorationEventHandler.record( 'eid', 1, exp.init_state_name, 'session_id_%s' % ind, {}, feconf.PLAY_TYPE_NORMAL) event_services.StateHitEventHandler.record( 'eid', 1, exp.init_state_name, 'session_id_%s' % ind, {}, feconf.PLAY_TYPE_NORMAL) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, self.DEFAULT_RULESPEC_STR, '1') for _ in range(2): event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, self.DEFAULT_RULESPEC_STR, '2') ModifiedStatisticsAggregator.start_computation() self.process_and_flush_pending_tasks() with self.swap(stats_jobs.StatisticsAggregator, 'get_statistics', ModifiedStatisticsAggregator.get_statistics): self.assertEquals( stats_services.get_state_improvements('eid', 1), [{ 'type': 'default', 'rank': 3, 'state_name': exp.init_state_name }])
def test_deletion_rights_for_published_exploration(self): """Test rights management for deletion of published explorations.""" PUBLISHED_EXP_ID = 'published_eid' exploration = exp_domain.Exploration.create_default_exploration( PUBLISHED_EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role( self.owner_id, PUBLISHED_EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_exploration(self.owner_id, PUBLISHED_EXP_ID) self.login(self.editor_email) response = self.testapp.delete( '/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.viewer_email) response = self.testapp.delete( '/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.owner_email) response = self.testapp.delete( '/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.admin_email) response = self.testapp.delete( '/createhandler/data/%s' % PUBLISHED_EXP_ID) self.assertEqual(response.status_int, 200) self.logout()
def setUp(self): """Create an exploration so that there is something to count.""" super(MapReduceJobIntegrationTests, self).setUp() exploration = exp_domain.Exploration.create_default_exploration( 'exp_id') exp_services.save_new_exploration('owner_id', exploration) self.process_and_flush_pending_tasks()
def test_newly_created_exploration(self): exp = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.user_id_a, exp) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view(self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_edit(self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_delete(self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_admin).can_view(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).can_edit(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_admin).can_delete(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete(self.EXP_ID))
def test_inviting_playtester(self): exp = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.user_id_a, exp) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete(self.EXP_ID)) rights_manager.assign_role( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) self.assertTrue( rights_manager.Actor(self.user_id_b).can_play(self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit(self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete(self.EXP_ID))
def test_resolving_answers(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'title', 'category') exp_services.save_new_exploration('user_id', exp) state_name = exp.init_state_name answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR) self.assertEquals(answer_log.answers, {}) stats_services.EventHandler.record_answer_submitted( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, 'answer1') stats_services.EventHandler.record_answer_submitted( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, 'answer1') stats_services.EventHandler.record_answer_submitted( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, 'answer2') answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR) self.assertEquals(answer_log.answers, {'answer1': 2, 'answer2': 1}) self.assertEquals(answer_log.total_answer_count, 3) stats_services.EventHandler.resolve_answers_for_default_rule( 'eid', state_name, self.SUBMIT_HANDLER, ['answer1']) answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR) self.assertEquals(answer_log.answers, {'answer2': 1}) self.assertEquals(answer_log.total_answer_count, 1)
def test_inviting_playtester_to_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_edit( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_delete( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID))
def test_setting_rights_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) with self.assertRaisesRegexp(Exception, 'Could not assign new role.'): rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_EDITOR) with self.assertRaisesRegexp(Exception, 'Could not assign new role.'): rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_d, rights_manager.ROLE_EDITOR) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_e, rights_manager.ROLE_VIEWER)
def test_changing_viewability_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration( self.EXP_ID, title='A title', category='A category') exp_services.save_new_exploration(self.user_id_a, exp) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue(rights_manager.Actor( self.user_id_a).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse(rights_manager.Actor( self.user_id_b).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue(rights_manager.Actor( self.user_id_admin).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) with self.assertRaisesRegexp(Exception, 'already the current value'): rights_manager.set_private_viewability_of_exploration( self.user_id_a, self.EXP_ID, False) with self.assertRaisesRegexp(Exception, 'cannot be changed'): rights_manager.set_private_viewability_of_exploration( self.user_id_b, self.EXP_ID, True) rights_manager.set_private_viewability_of_exploration( self.user_id_a, self.EXP_ID, True) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.set_private_viewability_of_exploration( self.user_id_a, self.EXP_ID, False) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.publish_exploration(self.user_id_a, self.EXP_ID) self.assertFalse(rights_manager.Actor( self.user_id_a).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.unpublish_exploration(self.user_id_admin, self.EXP_ID) self.assertTrue(rights_manager.Actor( self.user_id_a).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse(rights_manager.Actor( self.user_id_b).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue(rights_manager.Actor( self.user_id_admin).can_change_private_viewability( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID))
def reduce(exp_id, list_of_exps): from core.domain import exp_services from core.domain import rights_manager for stringified_exp in list_of_exps: exploration = exp_domain.Exploration.from_yaml(exp_id, "Copy", "Copies", stringified_exp) exp_services.save_new_exploration(feconf.SYSTEM_COMMITTER_ID, exploration) rights_manager.publish_exploration(feconf.SYSTEM_COMMITTER_ID, exp_id)
def test_get_user_stats(self): exp0 = exp_domain.Exploration.create_default_exploration( 'eid0', 'title0', 'category') exp_services.save_new_exploration('uid0', exp0) exp1 = exp_domain.Exploration.create_default_exploration( 'eid1', 'title1', 'category') exp_services.save_new_exploration('uid0', exp1) f0 = stats_domain.FeedbackItem.create_feedback_for_state( 'eid0', 'welcome', 'my feedback', None, 'uid0') f1 = stats_domain.FeedbackItem.create_feedback_for_exploration( 'eid1', 'another feedback', None, 'uid0') # This should return the both the feedback. self.assertEquals( stats_services.get_user_stats('uid0'), { 'feedback': { f0.id: { 'content': 'my feedback', 'exp_id': 'eid0', 'exp_title': 'title0', 'state_name': 'welcome', 'status': 'new', 'target_id': 'state:eid0.welcome', }, f1.id: { 'content': 'another feedback', 'exp_id': 'eid1', 'exp_title': 'title1', 'state_name': None, 'status': 'new', 'target_id': 'exploration:eid1', }, } }) # uid1 does not have any feedbacks. self.assertEquals(stats_services.get_user_stats('uid1'), {'feedback': {}})
def test_publishing_and_unpublishing_exploration(self): exp = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.user_id_a, exp) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.publish_exploration(self.user_id_a, self.EXP_ID) self.assertTrue( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_a).can_unpublish( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) rights_manager.unpublish_exploration(self.user_id_admin, self.EXP_ID) self.assertTrue( rights_manager.Actor(self.user_id_a).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertTrue( rights_manager.Actor(self.user_id_a).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_play( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID)) self.assertFalse( rights_manager.Actor(self.user_id_b).can_view( rights_manager.ACTIVITY_TYPE_EXPLORATION, self.EXP_ID))
def test_newly_created_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue( rights_manager.check_can_access_activity(self.user_a, exp_rights)) self.assertTrue( rights_manager.check_can_edit_activity(self.user_a, exp_rights)) self.assertTrue( rights_manager.check_can_delete_activity(self.user_a, exp_rights)) self.assertTrue( rights_manager.check_can_access_activity(self.user_admin, exp_rights)) self.assertTrue( rights_manager.check_can_edit_activity(self.user_admin, exp_rights)) self.assertTrue( rights_manager.check_can_delete_activity(self.user_admin, exp_rights)) self.assertTrue( rights_manager.check_can_access_activity(self.user_moderator, exp_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_moderator, exp_rights)) self.assertFalse( rights_manager.check_can_delete_activity(self.user_moderator, exp_rights)) self.assertFalse( rights_manager.check_can_access_activity(self.user_b, exp_rights)) self.assertFalse( rights_manager.check_can_edit_activity(self.user_b, exp_rights)) self.assertFalse( rights_manager.check_can_delete_activity(self.user_b, exp_rights))
def setUp(self): super(OpportunityServicesIntegrationTest, self).setUp() self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.set_admins([self.ADMIN_USERNAME]) self.admin = user_services.UserActionsInfo(self.admin_id) self.TOPIC_ID = 'topic' self.STORY_ID = 'story' self.USER_ID = 'user' self.SKILL_ID = 'skill' self.QUESTION_ID = question_services.get_new_question_id() explorations = [ exp_domain.Exploration.create_default_exploration( '%s' % i, title='title %d' % i, category='category%d' % i, ) for i in python_utils.RANGE(5) ] for exp in explorations: exp_services.save_new_exploration(self.owner_id, exp) topic = topic_domain.Topic.create_default_topic( topic_id=self.TOPIC_ID, name='topic', abbreviated_name='abbrev') topic_services.save_new_topic(self.owner_id, topic) story = story_domain.Story.create_default_story( self.STORY_ID, title='A story', corresponding_topic_id=self.TOPIC_ID) story_services.save_new_story(self.owner_id, story) topic_services.add_canonical_story(self.owner_id, self.TOPIC_ID, self.STORY_ID)
def test_migration_job_detects_invalid_exploration(self): exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, title='title', category='category') exp_services.save_new_exploration(self.albert_id, exploration) exploration_model = exp_models.ExplorationModel.get(self.VALID_EXP_ID) exploration_model.language_code = 'invalid_language_code' exploration_model.commit(self.albert_id, 'Changed language_code.', []) caching_services.delete_multi( caching_services.CACHE_NAMESPACE_EXPLORATION, None, [self.VALID_EXP_ID]) job_id = exp_jobs_one_off.ExpSnapshotsMigrationJob.create_new() exp_jobs_one_off.ExpSnapshotsMigrationJob.enqueue(job_id) self.process_and_flush_pending_mapreduce_tasks() actual_output = ( exp_jobs_one_off.ExpSnapshotsMigrationJob.get_output(job_id)) expected_output_message = ( '[u\'INFO - Exploration %s-1 failed non-strict validation\', ' '[u\'Invalid language_code: invalid_language_code\']]' % self.VALID_EXP_ID) self.assertIn(expected_output_message, actual_output)
def test_time_of_ratings_recorded(self): """Check that the time a rating is given is recorded correctly.""" time_allowed_for_computation = datetime.timedelta(seconds=10) exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 1) first_rating_time = rating_services.get_when_exploration_rated( self.USER_ID_1, self.EXP_ID) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) second_rating_time = rating_services.get_when_exploration_rated( self.USER_ID_1, self.EXP_ID) self.assertLess( datetime.datetime.utcnow(), first_rating_time + time_allowed_for_computation) self.assertLess(first_rating_time, second_rating_time) self.assertLess(second_rating_time, datetime.datetime.utcnow())
def test_get_state_improvements(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) for _ in range(5): event_services.StateHitEventHandler.record('eid', exp.init_state_name, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') for _ in range(2): event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '2') self.assertEquals(stats_services.get_state_improvements('eid'), [{ 'type': 'default', 'rank': 3, 'state_name': exp.init_state_name }])
def test_inviting_playtester_to_exploration(self): exp = exp_domain.Exploration.create_default_exploration(self.EXP_ID) exp_services.save_new_exploration(self.user_id_a, exp) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertFalse(rights_manager.check_can_access_activity( self.user_b, exp_rights)) self.assertFalse(rights_manager.check_can_edit_activity( self.user_b, exp_rights)) self.assertFalse(rights_manager.check_can_delete_activity( self.user_b, exp_rights)) rights_manager.assign_role_for_exploration( self.user_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue(rights_manager.check_can_access_activity( self.user_b, exp_rights)) self.assertFalse(rights_manager.check_can_edit_activity( self.user_b, exp_rights)) self.assertFalse(rights_manager.check_can_delete_activity( self.user_b, exp_rights))
def test_single_default_rule_hit(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) state_name = exp.init_state_name event_services.StartExplorationEventHandler.record( 'eid', 1, state_name, 'session_id', {}, feconf.PLAY_TYPE_NORMAL) event_services.StateHitEventHandler.record( 'eid', 1, state_name, 'session_id', {}, feconf.PLAY_TYPE_NORMAL) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.DEFAULT_RULESPEC_STR, '1') ModifiedStatisticsAggregator.start_computation() self.process_and_flush_pending_tasks() with self._get_swap_context(): self.assertEquals( stats_services.get_state_improvements('eid', 1), [{ 'type': 'default', 'rank': 1, 'state_name': exp.init_state_name }])
def post(self): """Handles POST requests.""" title = self.payload.get('title') category = self.payload.get('category') objective = self.payload.get('objective') language_code = self.payload.get('language_code') if not title: raise self.InvalidInputException('No title supplied.') if not category: raise self.InvalidInputException('No category chosen.') if not language_code: raise self.InvalidInputException('No language chosen.') new_exploration_id = exp_services.get_new_exploration_id() exploration = exp_domain.Exploration.create_default_exploration( new_exploration_id, title, category, objective=objective, language_code=language_code) exp_services.save_new_exploration(self.user_id, exploration) self.render_json({ EXPLORATION_ID_KEY: new_exploration_id })
def test_recording_answer_for_different_rules(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'title', 'category') exp_services.save_new_exploration('user_id', exp) rule = exp_domain.RuleSpec.from_dict_and_obj_type( { 'definition': { 'rule_type': 'atomic', 'name': 'LessThan', 'subject': 'answer', 'inputs': { 'x': 5 } }, 'dest': 'dest', 'feedback': None, 'param_changes': [] }, 'Real') state_name = exp.init_state_name event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, 'answer1') event_services.AnswerSubmissionEventHandler.record( 'eid', 1, state_name, self.SUBMIT_HANDLER, rule, 'answer2') default_rule_answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR) self.assertEquals(default_rule_answer_log.answers, {'answer1': 1}) self.assertEquals(default_rule_answer_log.total_answer_count, 1) other_rule_answer_log = stats_domain.StateRuleAnswerLog.get( 'eid', state_name, self.SUBMIT_HANDLER, str(rule)) self.assertEquals(other_rule_answer_log.answers, {'answer2': 1}) self.assertEquals(other_rule_answer_log.total_answer_count, 1)
def test_incomplete_and_default_flags(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) state_name = exp.init_state_name # Hit the default rule once, and fail to answer twice. The result # should be classified as incomplete. for _ in range(3): stats_services.EventHandler.record_state_hit( 'eid', state_name, True) stats_services.EventHandler.record_answer_submitted( 'eid', 1, state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_top_improvable_states(['eid'], 2) self.assertEquals(len(states), 1) self.assertEquals(states[0]['rank'], 2) self.assertEquals(states[0]['type'], 'incomplete') # Now hit the default two more times. The result should be classified # as default. for i in range(2): stats_services.EventHandler.record_state_hit( 'eid', state_name, True) stats_services.EventHandler.record_answer_submitted( 'eid', 1, state_name, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_top_improvable_states(['eid'], 2) self.assertEquals(len(states), 1) self.assertEquals(states[0]['rank'], 3) self.assertEquals(states[0]['type'], 'default')
def test_deletion_rights_for_published_exploration(self): """Test rights management for deletion of published explorations.""" PUBLISHED_EXP_ID = 'published_eid' exploration = exp_domain.Exploration.create_default_exploration( PUBLISHED_EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.owner_id, exploration) rights_manager.assign_role(self.owner_id, PUBLISHED_EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR) rights_manager.publish_exploration(self.owner_id, PUBLISHED_EXP_ID) self.login(self.EDITOR_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.VIEWER_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.OWNER_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 401) self.logout() self.login(self.ADMIN_EMAIL) response = self.testapp.delete('/createhandler/data/%s' % PUBLISHED_EXP_ID) self.assertEqual(response.status_int, 200) self.logout()
def test_rating_assignations_do_not_conflict(self): """Check that ratings of different explorations are independant.""" EXP_ID_A = 'exp_id_A' EXP_ID_B = 'exp_id_B' self.exploration = exp_domain.Exploration.create_default_exploration( EXP_ID_A, 'A title', 'A category') exp_services.save_new_exploration(EXP_ID_A, self.exploration) self.exploration = exp_domain.Exploration.create_default_exploration( EXP_ID_B, 'A title', 'A category') exp_services.save_new_exploration(EXP_ID_B, self.exploration) rating_services.assign_rating(self.USER_ID_1, EXP_ID_A, 1) rating_services.assign_rating(self.USER_ID_1, EXP_ID_B, 3) rating_services.assign_rating(self.USER_ID_2, EXP_ID_A, 2) rating_services.assign_rating(self.USER_ID_2, EXP_ID_B, 5) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_1, EXP_ID_A), 1) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_1, EXP_ID_B), 3) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_2, EXP_ID_A), 2) self.assertEqual( rating_services.get_user_specific_rating( self.USER_ID_2, EXP_ID_B), 5) self.assertEqual( rating_services.get_overall_ratings(EXP_ID_A), {'1': 1, '2': 1, '3': 0, '4': 0, '5': 0}) self.assertEqual( rating_services.get_overall_ratings(EXP_ID_B), {'1': 0, '2': 0, '3': 1, '4': 0, '5': 1})
def test_migration_job_skips_deleted_explorations(self): """Tests that the exploration migration job skips deleted explorations and does not attempt to migrate. """ swap_states_schema_41 = self.swap(feconf, 'CURRENT_STATE_SCHEMA_VERSION', 41) swap_exp_schema_46 = self.swap(exp_domain.Exploration, 'CURRENT_EXP_SCHEMA_VERSION', 46) with swap_states_schema_41, swap_exp_schema_46: exploration = exp_domain.Exploration.create_default_exploration( self.NEW_EXP_ID, title=self.EXP_TITLE) exp_services.save_new_exploration(self.albert_id, exploration) # Note: This creates a summary based on the upgraded model (which is # fine). A summary is needed to delete the exploration. exp_services.regenerate_exploration_and_contributors_summaries( self.NEW_EXP_ID) # Delete the exploration before migration occurs. exp_services.delete_exploration(self.albert_id, self.NEW_EXP_ID) # Ensure the exploration is deleted. with self.assertRaisesRegexp(Exception, 'Entity .* not found'): exp_fetchers.get_exploration_by_id(self.NEW_EXP_ID) # Start migration job on sample exploration. job_id = exp_jobs_one_off.ExplorationMigrationJobManager.create_new() exp_jobs_one_off.ExplorationMigrationJobManager.enqueue(job_id) # This running without errors indicates the deleted exploration is # being ignored, since otherwise exp_fetchers.get_exploration_by_id # (used within the job) will raise an error. self.process_and_flush_pending_mapreduce_tasks() # Ensure the exploration is still deleted. with self.assertRaisesRegexp(Exception, 'Entity .* not found'): exp_fetchers.get_exploration_by_id(self.NEW_EXP_ID)
def test_no_action_is_performed_for_deleted_exploration(self): """Test that no action is performed on deleted explorations.""" exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, title='title', category='category') exploration.add_states(['State1']) state1 = exploration.states['State1'] state1.update_interaction_id('ItemSelectionInput') customization_args_dict = { 'minAllowableSelectionCount': { 'value': '1b' }, 'maxAllowableSelectionCount': { 'value': 1 }, 'choices': { 'value': [{ 'html': '<p>This is value1 for ItemSelection</p>', 'content_id': 'ca_choices_0' }] }, } state1.update_interaction_customization_args(customization_args_dict) exp_services.save_new_exploration(self.albert_id, exploration) exp_services.delete_exploration(self.albert_id, self.VALID_EXP_ID) run_job_for_deleted_exp( self, interaction_jobs_one_off. InteractionCustomizationArgsValidationOneOffJob)
def test_setting_rights_of_exploration(self): exp = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.user_id_a, exp) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_VIEWER) with self.assertRaisesRegexp(Exception, 'Could not assign new role.'): rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_EDITOR) with self.assertRaisesRegexp(Exception, 'Could not assign new role.'): rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_VIEWER) rights_manager.assign_role_for_exploration( self.user_id_a, self.EXP_ID, self.user_id_b, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_c, rights_manager.ROLE_OWNER) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_d, rights_manager.ROLE_EDITOR) rights_manager.assign_role_for_exploration( self.user_id_b, self.EXP_ID, self.user_id_e, rights_manager.ROLE_VIEWER)
def test_exploration_migration_job_output(self): """Test that Exploration Migration job output is correct.""" exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, title='title', category='category') exp_services.save_new_exploration(self.albert_id, exploration) swap_states_schema_41 = self.swap(feconf, 'CURRENT_STATE_SCHEMA_VERSION', 41) swap_exp_schema_46 = self.swap(exp_domain.Exploration, 'CURRENT_EXP_SCHEMA_VERSION', 46) with swap_states_schema_41, swap_exp_schema_46: exploration = exp_domain.Exploration.create_default_exploration( self.NEW_EXP_ID, title=self.EXP_TITLE) exp_services.save_new_exploration(self.albert_id, exploration) # Start migration job on sample exploration. job_id = exp_jobs_one_off.ExplorationMigrationJobManager.create_new() exp_jobs_one_off.ExplorationMigrationJobManager.enqueue(job_id) self.process_and_flush_pending_mapreduce_tasks() actual_output = ( exp_jobs_one_off.ExplorationMigrationJobManager.get_output(job_id)) expected_output = ['[u\'SUCCESS\', 1]'] self.assertEqual(actual_output, expected_output)
def test_publishing_and_unpublishing_exploration(self): exp = exp_domain.Exploration.create_default_exploration( self.EXP_ID, title='A title', category='A category') exp_services.save_new_exploration(self.user_id_a, exp) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertFalse(rights_manager.check_can_access_activity( self.user_b, exp_rights)) rights_manager.publish_exploration(self.user_a, self.EXP_ID) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue(rights_manager.check_can_access_activity( self.user_b, exp_rights)) self.assertFalse(rights_manager.check_can_unpublish_activity( self.user_a, exp_rights)) rights_manager.unpublish_exploration(self.user_admin, self.EXP_ID) exp_rights = rights_manager.get_exploration_rights(self.EXP_ID) self.assertTrue(rights_manager.check_can_access_activity( self.user_a, exp_rights)) self.assertFalse(rights_manager.check_can_access_activity( self.user_b, exp_rights))
def test_stop_computation_with_finished_jobs(self): self.login(self.ADMIN_EMAIL, is_super_admin=True) exploration = exp_domain.Exploration.create_default_exploration( 'exp_id') exp_services.save_new_exploration('owner_id', exploration) self.assertEqual( jobs_test.StartExplorationEventCounter.get_count('exp_id'), 0) jobs_test.StartExplorationEventCounter.start_computation() self.process_and_flush_pending_tasks() status = jobs_test.StartExplorationEventCounter.get_status_code() self.assertEqual( status, job_models.CONTINUOUS_COMPUTATION_STATUS_CODE_RUNNING) with self.swap( jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', [jobs_test.StartExplorationEventCounter]): self.get_json('/adminhandler') csrf_token = self.get_new_csrf_token() self.post_json( '/adminhandler', { 'action': 'stop_computation', 'computation_type': 'StartExplorationEventCounter' }, csrf_token=csrf_token) status = jobs_test.StartExplorationEventCounter.get_status_code() self.assertEqual( status, job_models.CONTINUOUS_COMPUTATION_STATUS_CODE_IDLE) self.logout()
def save_new_valid_exploration(self, exploration_id, owner_id, title='A title', category='A category', objective='An objective', language_code=feconf.DEFAULT_LANGUAGE_CODE, end_state_name=None, interaction_id='TextInput'): """Saves a new strictly-validated exploration. Returns the exploration domain object. """ exploration = exp_domain.Exploration.create_default_exploration( exploration_id, title=title, category=category, language_code=language_code) exploration.states[exploration.init_state_name].update_interaction_id( interaction_id) exploration.objective = objective # If an end state name is provided, add terminal node with that name if end_state_name is not None: exploration.add_states([end_state_name]) end_state = exploration.states[end_state_name] end_state.update_interaction_id('EndExploration') end_state.interaction.default_outcome = None # Link first state to ending state (to maintain validity) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = end_state_name exp_services.save_new_exploration(owner_id, exploration) return exploration
def test_fixes_invalid_unicode_translations(self): exp_id = 'EXP_ID' exploration = exp_domain.Exploration.create_default_exploration( exp_id, title='title', category='category', language_code='bn') self.set_interaction_for_state( exploration.states[exploration.init_state_name], 'Continue') exp_services.save_new_exploration(self.albert_id, exploration) add_translation_change_dict = { 'cmd': exp_domain.CMD_ADD_WRITTEN_TRANSLATION, 'state_name': 'Introduction', 'content_id': 'ca_buttonText_0', 'language_code': 'bn', 'content_html': 'Continue', 'translation_html': '<p>চালিয়ে যান</p>', 'data_format': 'html' } invalid_suggestion = suggestion_services.create_suggestion( feconf.SUGGESTION_TYPE_TRANSLATE_CONTENT, feconf.ENTITY_TYPE_EXPLORATION, exp_id, exploration.version, self.albert_id, add_translation_change_dict, 'test description') self.assertEqual(invalid_suggestion.change.data_format, 'html') self.assertEqual(invalid_suggestion.change.translation_html, '<p>চালিয়ে যান</p>') expected_output = [ u'[u\'UPDATED\', [u\'%s | ca_buttonText_0\']]' % invalid_suggestion.suggestion_id, u'[u\'PROCESSED\', 1]' ] self._run_job_and_verify_output(expected_output) valid_suggestion = suggestion_services.get_suggestion_by_id( invalid_suggestion.suggestion_id) self.assertEqual(valid_suggestion.change.data_format, 'unicode') self.assertEqual(valid_suggestion.change.translation_html, 'চালিয়ে যান')
def test_for_customization_arg_validation_job(self): """Check that expected errors are produced for invalid customization args. """ exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, title='title', category='category') exploration.add_states(['State1', 'State2']) state1 = exploration.states['State1'] state2 = exploration.states['State2'] state1.update_interaction_id('ItemSelectionInput') customization_args_dict1 = { 'minAllowableSelectionCount': {'value': 1}, 'maxAllowableSelectionCount': {'value': 1}, 'choices': {'value': [{ 'html': '<p>This is value1 for ItemSelection</p>', 'content_id': 'ca_choices_0' }]}, } state1.update_interaction_customization_args(customization_args_dict1) exp_services.save_new_exploration(self.albert_id, exploration) # Start ItemSelectionInteractionOneOff job on sample exploration. job_id = ( interaction_jobs_one_off .InteractionCustomizationArgsValidationOneOffJob.create_new()) ( interaction_jobs_one_off .InteractionCustomizationArgsValidationOneOffJob.enqueue(job_id)) self.process_and_flush_pending_mapreduce_tasks() actual_output = ( interaction_jobs_one_off .InteractionCustomizationArgsValidationOneOffJob.get_output(job_id)) self.assertEqual(actual_output, []) customization_args_dict2 = { 'minAllowableSelectionCount': {'value': '1bθ'}, 'maxAllowableSelectionCount': {'value': 1}, 'choices': {'value': [{ 'html': '<p>This is value1 for ItemSelection</p>', 'content_id': 'ca_choices_0' }]}, } state2.update_interaction_id('ItemSelectionInput') state2.update_interaction_customization_args(customization_args_dict2) exp_services.save_new_exploration(self.albert_id, exploration) # Start ItemSelectionInteractionOneOff job on sample exploration. job_id = ( interaction_jobs_one_off .InteractionCustomizationArgsValidationOneOffJob.create_new()) ( interaction_jobs_one_off .InteractionCustomizationArgsValidationOneOffJob.enqueue(job_id)) self.process_and_flush_pending_mapreduce_tasks() actual_output = ( interaction_jobs_one_off .InteractionCustomizationArgsValidationOneOffJob.get_output(job_id)) expected_output = [( u'[u\'Failed customization args validation for exp id exp_id0\', ' '[u\'ItemSelectionInput: Could not convert unicode to int: ' '1b\\u03b8\']]')] self.assertEqual(actual_output, expected_output)
def setUp(self): super(ContributionOpportunitiesHandlerTest, self).setUp() self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.set_admins([self.ADMIN_USERNAME]) explorations = [exp_domain.Exploration.create_default_exploration( '%s' % i, title='title %d' % i, category='category%d' % i, ) for i in python_utils.RANGE(2)] for exp in explorations: exp_services.save_new_exploration(self.owner_id, exp) topic = topic_domain.Topic.create_default_topic( topic_id='0', name='topic', abbreviated_name='abbrev') topic_services.save_new_topic(self.owner_id, topic) self.skill_id_0 = 'skill_id_0' self.skill_id_1 = 'skill_id_1' self.skill_ids = [self.skill_id_0, self.skill_id_1] for skill_id in self.skill_ids: self.save_new_skill(skill_id, self.admin_id, 'skill_description') topic_services.add_uncategorized_skill( self.admin_id, '0', skill_id) self.expected_skill_opportunity_dict_0 = { 'id': self.skill_id_0, 'skill_description': 'skill_description', 'question_count': 0, 'topic_name': 'topic' } self.expected_skill_opportunity_dict_1 = { 'id': self.skill_id_1, 'skill_description': 'skill_description', 'question_count': 0, 'topic_name': 'topic' } stories = [story_domain.Story.create_default_story( '%s' % i, title='title %d' % i, corresponding_topic_id='0' ) for i in python_utils.RANGE(2)] for index, story in enumerate(stories): story.language_code = 'en' story_services.save_new_story(self.owner_id, story) topic_services.add_canonical_story( self.owner_id, topic.id, story.id) story_services.update_story( self.owner_id, story.id, [story_domain.StoryChange({ 'cmd': 'add_story_node', 'node_id': 'node_1', 'title': 'Node1', }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'exploration_id', 'node_id': 'node_1', 'old_value': None, 'new_value': explorations[index].id })], 'Changes.') self.expected_opportunity_dict_1 = { 'id': '0', 'topic_name': 'topic', 'story_title': 'title 0', 'chapter_title': 'Node1', 'content_count': 2, 'translation_counts': {} } self.expected_opportunity_dict_2 = { 'id': '1', 'topic_name': 'topic', 'story_title': 'title 1', 'chapter_title': 'Node1', 'content_count': 2, 'translation_counts': {} }
def test_exp_state_pairs_are_produced_for_item_selection_interactions(self): """Checks (exp, state) pairs are produced correctly for ItemSelection interactions. """ owner = user_services.get_user_actions_info(self.albert_id) exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, title='title', category='category') exploration.add_states(['State1', 'State2']) state1 = exploration.states['State1'] state2 = exploration.states['State2'] customization_args_dict1 = { 'choices': {'value': [{ 'html': '<p>This is value1 for ItemSelection</p>', 'content_id': 'ca_choices_0' }, { 'html': '<p>This is value2 for ItemSelection</p>', 'content_id': 'ca_choices_1' }]}, 'minAllowableSelectionCount': {'value': 0}, 'maxAllowableSelectionCount': {'value': 1} } state_answer_group_list1 = [state_domain.AnswerGroup( state_domain.Outcome( 'Introduction', state_domain.SubtitledHtml( 'feedback', '<p>Outcome for state1</p>'), False, [], None, None), [ state_domain.RuleSpec( 'Equals', { 'x': ['<p>This is value1 for ItemSelection</p>'] }), state_domain.RuleSpec( 'Equals', { 'x': ['<p>This is value2 for ItemSelection</p>'] }) ], [], None )] solution1 = state_domain.Solution.from_dict('ItemSelectionInput', { 'answer_is_exclusive': True, 'correct_answer': ['<p>This is value2 for DragAndDropSort</p>'], 'explanation': { 'content_id': 'solution', 'html': '' } }) hint_list1 = [state_domain.Hint.from_dict({ 'hint_content': { 'content_id': 'hint_0', 'html': '' } })] state1.update_interaction_id('ItemSelectionInput') state1.update_interaction_customization_args(customization_args_dict1) state1.update_next_content_id_index(2) state1.update_interaction_answer_groups(state_answer_group_list1) exp_services.save_new_exploration(self.albert_id, exploration) state1.update_interaction_solution(solution1) state1.update_interaction_hints(hint_list1) # Start RuleInputToCustomizationArgsMappingOneOffJob job on sample # exploration. job_id = ( interaction_jobs_one_off .RuleInputToCustomizationArgsMappingOneOffJob.create_new()) ( interaction_jobs_one_off .RuleInputToCustomizationArgsMappingOneOffJob.enqueue(job_id)) self.process_and_flush_pending_mapreduce_tasks() actual_output = ( interaction_jobs_one_off .RuleInputToCustomizationArgsMappingOneOffJob.get_output(job_id)) self.assertEqual(actual_output, []) customization_args_dict2 = { 'choices': {'value': [{ 'html': '<p>This is value1 for ItemSelection</p>', 'content_id': 'ca_choices_0' }, { 'html': '<p>This is value2 for ItemSelection</p>', 'content_id': 'ca_choices_1' }]}, 'minAllowableSelectionCount': {'value': 0}, 'maxAllowableSelectionCount': {'value': 1} } state_answer_group_list2 = [state_domain.AnswerGroup( state_domain.Outcome( 'State1', state_domain.SubtitledHtml( 'feedback', '<p>Outcome for state2</p>'), False, [], None, None), [ state_domain.RuleSpec( 'Equals', { 'x': ['<p>This is value1 for ItemSelection</p>'] }), state_domain.RuleSpec( 'Equals', { 'x': ['<p>This is value3 for ItemSelection</p>'] }) ], [], None )] solution2 = state_domain.Solution.from_dict('ItemSelectionInput', { 'answer_is_exclusive': True, 'correct_answer': ['<p>This is value3 for DragAndDropSort</p>'], 'explanation': { 'content_id': 'solution', 'html': '' } }) hint_list2 = [state_domain.Hint.from_dict({ 'hint_content': { 'content_id': 'hint_0', 'html': '' } })] state2.update_interaction_id('ItemSelectionInput') state2.update_interaction_customization_args(customization_args_dict2) state2.update_next_content_id_index(2) state2.update_interaction_answer_groups(state_answer_group_list2) state2.update_interaction_solution(solution2) state2.update_interaction_hints(hint_list2) exp_services.save_new_exploration(self.albert_id, exploration) rights_manager.publish_exploration(owner, self.VALID_EXP_ID) # Start ItemSelectionInteractionOneOff job on sample exploration. job_id = ( interaction_jobs_one_off .RuleInputToCustomizationArgsMappingOneOffJob.create_new()) ( interaction_jobs_one_off .RuleInputToCustomizationArgsMappingOneOffJob.enqueue(job_id)) self.process_and_flush_pending_mapreduce_tasks() actual_output = ( interaction_jobs_one_off .RuleInputToCustomizationArgsMappingOneOffJob.get_output(job_id)) expected_output = [( u'[u\'exp_id0\', [u"<ItemSelectionInput Answer> State: State2, ' 'Invalid Values: [\'<p>This is value3 for DragAndDropSort</p>\']"' ', u"<ItemSelectionInput Rule> State: State2, ' 'Answer Group Index: 0, Invalid Values: [u\'<p>This is value3 ' 'for ItemSelection</p>\']", u"<ItemSelectionInput Answer> State: ' 'State1, Invalid Values: [\'<p>This is value2 for ' 'DragAndDropSort</p>\']"]]' )] self.assertEqual(actual_output, expected_output)
def _create_exploration(self, exp_id, user_id): exploration = exp_domain.Exploration.create_default_exploration( exp_id, 'A title', 'A category') exp_services.save_new_exploration(user_id, exploration) return exploration
def setUp(self): super(StoryModelValidatorTests, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) explorations = [exp_domain.Exploration.create_default_exploration( '%s' % i, title='title %d' % i, category='category', ) for i in python_utils.RANGE(6)] for exp in explorations: exp_services.save_new_exploration(self.owner_id, exp) self.publish_exploration(self.owner_id, exp.id) topic = topic_domain.Topic.create_default_topic( '0', 'topic', 'abbrev', 'description') topic_services.save_new_topic(self.owner_id, topic) language_codes = ['ar', 'en', 'en'] stories = [story_domain.Story.create_default_story( '%s' % i, 'title %d' % i, 'description %d' % i, '0', 'title-%s' % chr(97 + i) ) for i in python_utils.RANGE(3)] for index, story in enumerate(stories): story.language_code = language_codes[index] story_services.save_new_story(self.owner_id, story) topic_services.add_canonical_story( self.owner_id, topic.id, story.id) story_services.update_story( self.owner_id, story.id, [story_domain.StoryChange({ 'cmd': 'add_story_node', 'node_id': 'node_1', 'title': 'Node1', }), story_domain.StoryChange({ 'cmd': 'add_story_node', 'node_id': 'node_2', 'title': 'Node2', }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'destination_node_ids', 'node_id': 'node_1', 'old_value': [], 'new_value': ['node_2'] }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'exploration_id', 'node_id': 'node_1', 'old_value': None, 'new_value': explorations[index * 2].id }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'exploration_id', 'node_id': 'node_2', 'old_value': None, 'new_value': explorations[index * 2 + 1].id })], 'Changes.') self.model_instance_0 = story_models.StoryModel.get_by_id('0') self.model_instance_1 = story_models.StoryModel.get_by_id('1') self.model_instance_2 = story_models.StoryModel.get_by_id('2') self.job_class = ( prod_validation_jobs_one_off.StoryModelAuditOneOffJob)
def setUp(self): super(ExplorationOpportunitySummaryModelRegenerationJobTest, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.topic_id_1 = 'topic1' self.topic_id_2 = 'topic2' story_id_1 = 'story1' story_id_2 = 'story2' explorations = [ exp_domain.Exploration.create_default_exploration( '%s' % i, title='title %d' % i, category='category%d' % i, ) for i in python_utils.RANGE(2) ] for exp in explorations: exp_services.save_new_exploration(self.owner_id, exp) self.publish_exploration(self.owner_id, exp.id) topic_1 = topic_domain.Topic.create_default_topic( topic_id=self.topic_id_1, name='topic1', abbreviated_name='abbrev') topic_services.save_new_topic(self.owner_id, topic_1) topic_2 = topic_domain.Topic.create_default_topic( topic_id=self.topic_id_2, name='topic2', abbreviated_name='abbrev') topic_services.save_new_topic(self.owner_id, topic_2) story_1 = story_domain.Story.create_default_story( story_id_1, title='A story', corresponding_topic_id=self.topic_id_1) story_2 = story_domain.Story.create_default_story( story_id_2, title='A story', corresponding_topic_id=self.topic_id_2) story_services.save_new_story(self.owner_id, story_1) story_services.save_new_story(self.owner_id, story_2) topic_services.add_canonical_story(self.owner_id, self.topic_id_1, story_id_1) topic_services.add_canonical_story(self.owner_id, self.topic_id_2, story_id_2) story_services.update_story(self.owner_id, story_id_1, [ story_domain.StoryChange({ 'cmd': 'add_story_node', 'node_id': 'node_1', 'title': 'Node1', }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'exploration_id', 'node_id': 'node_1', 'old_value': None, 'new_value': '0' }) ], 'Changes.') story_services.update_story(self.owner_id, story_id_2, [ story_domain.StoryChange({ 'cmd': 'add_story_node', 'node_id': 'node_1', 'title': 'Node1', }), story_domain.StoryChange({ 'cmd': 'update_story_node_property', 'property_name': 'exploration_id', 'node_id': 'node_1', 'old_value': None, 'new_value': '1' }) ], 'Changes.')
def test_for_validation_job(self): """Tests that the exploration validation job validates the content without skipping any tags. """ exploration = exp_domain.Exploration.create_default_exploration( self.VALID_EXP_ID, title='title', category='category') exploration.add_states(['State1', 'State2']) state1 = exploration.states['State1'] state2 = exploration.states['State2'] content1_dict = { 'html': '''<blockquote><div><p>Hello, this <i>is</i> state1 </p> </div> </blockquote> <pre>I'm looking for a particular <b>Hello Oppia</b> message</pre>. <p> Don't you want to say hello? You can learn more about oppia <oppia-noninteractive-link url-with-value="&quot; https://www.example.com&quot;" text-with-value="&quot; here&quot;"></oppia-noninteractive-link></p>''', 'audio_translations': {} } content2_dict = { 'html': '''<pre>Hello, this is state2.</pre> <blockquote> <ol> <li>item1</li> <li>item2</li> </ol> </blockquote>.<p> You can see this equation <b> <oppia-noninteractive-math raw_latex-with-value="&quot;\\frac{x}{y}& quot;"></oppia-noninteractive-math></b></p> ''', 'audio_translations': {} } state1.update_content(content1_dict) state2.update_content(content2_dict) exp_services.save_new_exploration(self.albert_id, exploration) # Start validation job on sample exploration. job_id = exp_jobs_one_off.ExplorationContentValidationJob.create_new() exp_jobs_one_off.ExplorationContentValidationJob.enqueue(job_id) self.process_and_flush_pending_tasks() actual_output = (exp_jobs_one_off.ExplorationContentValidationJob. get_output(job_id)) expected_output = [u"[u'Errors', [u'{}']]"] self.assertEqual(actual_output, expected_output) default_outcome_dict = { 'dest': 'State2', 'feedback': { 'html': '''<p>Sorry, it doesn't look like your <span>program </span>prints any output</p>.<p> <blockquote> Could you get it to print something?</blockquote> You can do this by using a statement like print</p>. <br> You can ask any doubt if you have <oppia-noninteractive-link url-with-value="&quot; https://www.example.com&quot;" text-with-value=" &quot;Here&quot;"></oppia-noninteractive-link>. ''', 'audio_translations': {} }, 'labelled_as_correct': False, 'param_changes': [], 'refresher_exploration_id': None } state1.update_interaction_default_outcome(default_outcome_dict) exp_services.save_new_exploration(self.albert_id, exploration) job_id = exp_jobs_one_off.ExplorationContentValidationJob.create_new() exp_jobs_one_off.ExplorationContentValidationJob.enqueue(job_id) self.process_and_flush_pending_tasks() actual_output = (exp_jobs_one_off.ExplorationContentValidationJob. get_output(job_id)) expected_output = [u'[u\'Errors\', [u"{\'invalidTags\': [u\'span\'], u\'oppia-noninteractive-link\': [u\'[document]\'], u\'br\': [u\'[document]\']}"]]'] # pylint: disable=line-too-long self.assertEqual(actual_output, expected_output)
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration.""" exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), { '1': 0, '2': 0, '3': 0, '4': 0, '5': 0 }) exp_summary = exp_fetchers.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual(exp_summary.scaled_average_rating, 0) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating_to_exploration(self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating_to_exploration(self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating_to_exploration(self.USER_ID_1, self.EXP_ID, 3) exp_summary = exp_fetchers.get_exploration_summary_by_id(self.EXP_ID) self.assertAlmostEqual(exp_summary.scaled_average_rating, 1.5667471839848, places=4) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), { '1': 0, '2': 0, '3': 1, '4': 1, '5': 0 }) rating_services.assign_rating_to_exploration(self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), { '1': 0, '2': 0, '3': 0, '4': 2, '5': 0 })