def test_state_download_handler_for_default_exploration(self): self.login(self.EDITOR_EMAIL) self.OWNER_ID = self.get_user_id_from_email(self.EDITOR_EMAIL) # Create a simple exploration EXP_ID = 'eid' self.save_new_valid_exploration( EXP_ID, self.OWNER_ID, title='The title for states download handler test!', category='This is just a test category') exploration = exp_services.get_exploration_by_id(EXP_ID) exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exploration.rename_state('State 2', 'State B') exploration.delete_state('State 3') exp_services._save_exploration(self.OWNER_ID, exploration, '', []) response = self.testapp.get('/create/%s' % EXP_ID) # Check download state as YAML string self.maxDiff = None state_name = 'State%20A' EXPLORATION_DOWNLOAD_URL = ( '/createhandler/download_state/%s?state=%s&width=50' % (EXP_ID, state_name)) response = self.testapp.get(EXPLORATION_DOWNLOAD_URL) self.assertEqual(self.SAMPLE_STATE_STRING, response.body) self.logout()
def test_export_by_versions(self): """Test export_to_zip_file() for different versions.""" exploration = self.save_new_default_exploration(self.EXP_ID) self.assertEqual(exploration.version, 1) exploration.add_states(['New state']) with open(os.path.join(feconf.TESTS_DATA_DIR, 'img.png')) as f: raw_image = f.read() fs = fs_domain.AbstractFileSystem( fs_domain.ExplorationFileSystem(self.EXP_ID)) fs.commit(self.OWNER_ID, 'abc.png', raw_image) exp_services._save_exploration(self.OWNER_ID, exploration, '', []) self.assertEqual(exploration.version, 2) exploration.rename_state('New state', 'Renamed state') exp_services._save_exploration(self.OWNER_ID, exploration, '', []) self.assertEqual(exploration.version, 3) # Download version 2 zip_file_output = exp_services.export_to_zip_file(self.EXP_ID, 2) zf = zipfile.ZipFile(StringIO.StringIO(zip_file_output)) self.assertEqual( zf.open('A title.yaml').read(), self.SAMPLE_YAML_CONTENT) # Download version 3 zip_file_output = exp_services.export_to_zip_file(self.EXP_ID, 3) zf = zipfile.ZipFile(StringIO.StringIO(zip_file_output)) self.assertEqual( zf.open('A title.yaml').read(), self.UPDATED_YAML_CONTENT)
def test_state_download_handler_for_default_exploration(self): self.login(self.EDITOR_EMAIL) owner_id = self.get_user_id_from_email(self.EDITOR_EMAIL) # Create a simple exploration exp_id = 'eid' self.save_new_valid_exploration( exp_id, owner_id, title='The title for states download handler test!', category='This is just a test category') exploration = exp_services.get_exploration_by_id(exp_id) exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exploration.rename_state('State 2', 'State B') exploration.delete_state('State 3') exp_services._save_exploration( # pylint: disable=protected-access owner_id, exploration, '', []) response = self.testapp.get('/create/%s' % exp_id) # Check download state as YAML string self.maxDiff = None state_name = 'State%20A' download_url = ( '/createhandler/download_state/%s?state=%s&width=50' % (exp_id, state_name)) response = self.testapp.get(download_url) self.assertEqual(self.SAMPLE_STATE_STRING, response.body) self.logout()
def test_state_download_handler_for_default_exploration(self): self.login(self.EDITOR_EMAIL) self.OWNER_ID = self.get_user_id_from_email(self.EDITOR_EMAIL) # Create a simple exploration EXP_ID = "eid" self.save_new_valid_exploration( EXP_ID, self.OWNER_ID, title="The title for states download handler test!", category="This is just a test category", ) exploration = exp_services.get_exploration_by_id(EXP_ID) exploration.add_states(["State A", "State 2", "State 3"]) exploration.states["State A"].update_interaction_id("TextInput") exploration.states["State 2"].update_interaction_id("TextInput") exploration.states["State 3"].update_interaction_id("TextInput") exploration.rename_state("State 2", "State B") exploration.delete_state("State 3") exp_services._save_exploration(self.OWNER_ID, exploration, "", []) response = self.testapp.get("/create/%s" % EXP_ID) # Check download state as YAML string self.maxDiff = None state_name = "State%20A" EXPLORATION_DOWNLOAD_URL = "/createhandler/download_state/%s?state=%s&width=50" % (EXP_ID, state_name) response = self.testapp.get(EXPLORATION_DOWNLOAD_URL) self.assertEqual(self.SAMPLE_STATE_STRING, response.body) self.logout()
def test_update_widget_handlers(self): """Test updating of widget_handlers.""" # We create a second state to use as a rule destination exploration = exp_services.get_exploration_by_id(self.EXP_ID) exploration.add_states(['State 2']) exp_services._save_exploration(self.OWNER_ID, exploration, '', []) exploration = exp_services.get_exploration_by_id(self.EXP_ID) self.widget_handlers['submit'][1]['dest'] = 'State 2' exp_services.update_exploration( self.OWNER_ID, self.EXP_ID, _get_change_list( self.init_state_name, 'widget_id', 'MultipleChoiceInput') + _get_change_list( self.init_state_name, 'widget_handlers', self.widget_handlers), '') exploration = exp_services.get_exploration_by_id(self.EXP_ID) rule_specs = exploration.init_state.widget.handlers[0].rule_specs self.assertEqual(rule_specs[0].definition, { 'rule_type': 'atomic', 'name': 'Equals', 'inputs': {'x': 0}, 'subject': 'answer' }) self.assertEqual(rule_specs[0].feedback, ['Try again']) self.assertEqual(rule_specs[0].dest, self.init_state_name) self.assertEqual(rule_specs[1].dest, 'State 2')
def setUp(self): super(SuggestionIntegrationTests, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.AUTHOR_EMAIL, 'author') self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.author_id = self.get_user_id_from_email(self.AUTHOR_EMAIL) self.reviewer_id = self.editor_id self.editor = user_services.UserActionsInfo(self.editor_id) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. exploration = ( self.save_new_linear_exp_with_state_names_and_interactions( self.EXP_ID, self.editor_id, ['State 1', 'State 2'], ['TextInput'], category='Algebra')) self.old_content = state_domain.SubtitledHtml('content', 'old content').to_dict() recorded_voiceovers_dict = { 'voiceovers_mapping': { 'content': { self.TRANSLATION_LANGUAGE_CODE: { 'filename': 'filename3.mp3', 'file_size_bytes': 3000, 'needs_update': False } }, 'default_outcome': {} } } self.old_recorded_voiceovers = (state_domain.RecordedVoiceovers. from_dict(recorded_voiceovers_dict)) # Create content in State A with a single audio subtitle. exploration.states['State 1'].update_content(self.old_content) exploration.states['State 1'].update_recorded_voiceovers( self.old_recorded_voiceovers) exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) self.new_content = state_domain.SubtitledHtml('content', 'new content').to_dict() self.change = { 'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY, 'property_name': exp_domain.STATE_PROPERTY_CONTENT, 'state_name': 'State 1', 'new_value': self.new_content } self.target_version_at_submission = exploration.version
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_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, '', []) event_services.StateHitEventHandler.record('eid', exp.init_state_name, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, self.SUBMIT_HANDLER, not_default_rule_spec, '1') self.assertEquals(stats_services.get_state_improvements('eid'), [])
def test_state_hit(self): with self.swap( jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CONTINUOUS_COMPUTATION_MANAGERS_FOR_TESTS): exp_id = 'eid' exploration = self.save_new_valid_exploration(exp_id, 'owner') time.sleep(1) stats_jobs_continuous._STATE_COUNTER_CUTOFF_DATE = ( datetime.datetime.utcnow()) original_init_state = exploration.init_state_name new_init_state_name = 'New init state' exploration.rename_state(original_init_state, new_init_state_name) exp_services._save_exploration('owner', exploration, '', []) exp_version = 2 state2_name = 'sid2' self._record_state_hit( exp_id, exp_version, new_init_state_name, 'session1') self._record_state_hit( exp_id, exp_version, new_init_state_name, 'session2') self._create_state_counter(exp_id, original_init_state, 18) self._record_state_hit( exp_id, exp_version, state2_name, 'session1') self._create_state_counter(exp_id, state2_name, 9) self.process_and_flush_pending_tasks() ModifiedStatisticsAggregator.start_computation() self.assertEqual(self.count_jobs_in_taskqueue(), 1) self.process_and_flush_pending_tasks() state_hit_counts = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( exp_id, exp_version)['state_hit_counts']) self.assertEqual( state_hit_counts[new_init_state_name]['first_entry_count'], 2) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 1) output_model = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( exp_id, stats_jobs_continuous.VERSION_NONE)) state_hit_counts = output_model['state_hit_counts'] self.assertEqual( state_hit_counts[original_init_state]['first_entry_count'], 18) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 9) self.assertEqual(output_model['start_exploration_count'], 18) state_hit_counts = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( exp_id, stats_jobs_continuous.VERSION_ALL)['state_hit_counts']) self.assertEqual( state_hit_counts[original_init_state]['first_entry_count'], 18) self.assertEqual( state_hit_counts[new_init_state_name]['first_entry_count'], 2) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 10)
def test_state_hit(self): with self._get_swap_context(): exp_id = 'eid' exploration = self.save_new_valid_exploration(exp_id, 'owner') time.sleep(1) stats_jobs_continuous._STATE_COUNTER_CUTOFF_DATE = ( # pylint: disable=protected-access datetime.datetime.utcnow()) original_init_state = exploration.init_state_name new_init_state_name = 'New init state' exploration.rename_state(original_init_state, new_init_state_name) exp_services._save_exploration('owner', exploration, '', []) # pylint: disable=protected-access exp_version = 2 state2_name = 'sid2' self._record_state_hit(exp_id, exp_version, new_init_state_name, 'session1') self._record_state_hit(exp_id, exp_version, new_init_state_name, 'session2') self._create_state_counter(exp_id, original_init_state, 18) self._record_state_hit(exp_id, exp_version, state2_name, 'session1') self._create_state_counter(exp_id, state2_name, 9) self.process_and_flush_pending_tasks() ModifiedStatisticsAggregator.start_computation() self.assertEqual( self.count_jobs_in_taskqueue( taskqueue_services.QUEUE_NAME_CONTINUOUS_JOBS), 1) self.process_and_flush_pending_tasks() state_hit_counts = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( exp_id, exp_version)['state_hit_counts']) self.assertEqual( state_hit_counts[new_init_state_name]['first_entry_count'], 2) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 1) output_model = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( exp_id, stats_jobs_continuous.VERSION_NONE)) state_hit_counts = output_model['state_hit_counts'] self.assertEqual( state_hit_counts[original_init_state]['first_entry_count'], 18) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 9) self.assertEqual(output_model['start_exploration_count'], 18) state_hit_counts = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( exp_id, stats_jobs_continuous.VERSION_ALL)['state_hit_counts']) self.assertEqual( state_hit_counts[original_init_state]['first_entry_count'], 18) self.assertEqual( state_hit_counts[new_init_state_name]['first_entry_count'], 2) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 10)
def setUp(self): super(SuggestionIntegrationTests, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.AUTHOR_EMAIL, 'author') self.signup(self.ASSIGNED_REVIEWER_EMAIL, 'assignedReviewer') self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.author_id = self.get_user_id_from_email(self.AUTHOR_EMAIL) self.reviewer_id = self.editor_id self.assigned_reviewer_id = self.get_user_id_from_email( self.ASSIGNED_REVIEWER_EMAIL) self.editor = user_services.UserActionsInfo(self.editor_id) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. exploration = ( self.save_new_linear_exp_with_state_names_and_interactions( self.EXP_ID, self.editor_id, ['State 1', 'State 2'], ['TextInput'], category='Algebra')) self.old_content = exp_domain.SubtitledHtml( 'old content', { self.TRANSLATION_LANGUAGE_CODE: exp_domain.AudioTranslation('filename.mp3', 20, False) }).to_dict() # Create content in State A with a single audio subtitle. exploration.states['State 1'].update_content(self.old_content) exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) self.new_content = exp_domain.SubtitledHtml( 'new content', { self.TRANSLATION_LANGUAGE_CODE: exp_domain.AudioTranslation('filename.mp3', 20, False) }).to_dict() self.change_cmd = { 'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY, 'property_name': exp_domain.STATE_PROPERTY_CONTENT, 'state_name': 'State 1', 'new_value': self.new_content } self.target_version_at_submission = exploration.version
def test_two_state_default_hit(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) FIRST_STATE_NAME = exp.init_state_name SECOND_STATE_NAME = 'State 2' exp.add_states([SECOND_STATE_NAME]) exp_services._save_exploration('*****@*****.**', exp, '', []) # Hit the default rule of state 1 once, and the default rule of state 2 # twice. event_services.StateHitEventHandler.record( 'eid', FIRST_STATE_NAME, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') for i in range(2): event_services.StateHitEventHandler.record( 'eid', SECOND_STATE_NAME, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, SECOND_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_state_improvements('eid') self.assertEquals(states, [{ 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }, { 'rank': 1, 'type': 'default', 'state_name': FIRST_STATE_NAME }]) # Hit the default rule of state 1 two more times. for i in range(2): event_services.StateHitEventHandler.record( 'eid', FIRST_STATE_NAME, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_state_improvements('eid') self.assertEquals(states, [{ 'rank': 3, 'type': 'default', 'state_name': FIRST_STATE_NAME }, { 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }])
def test_two_state_default_hit(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) FIRST_STATE_NAME = exp.init_state_name SECOND_STATE_NAME = 'State 2' exp.add_states([SECOND_STATE_NAME]) exp_services._save_exploration('*****@*****.**', exp, '', []) # Hit the default rule of state 1 once, and the default rule of state 2 # twice. event_services.StateHitEventHandler.record('eid', FIRST_STATE_NAME, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') for i in range(2): event_services.StateHitEventHandler.record('eid', SECOND_STATE_NAME, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, SECOND_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_state_improvements('eid') self.assertEquals(states, [{ 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }, { 'rank': 1, 'type': 'default', 'state_name': FIRST_STATE_NAME }]) # Hit the default rule of state 1 two more times. for i in range(2): event_services.StateHitEventHandler.record('eid', FIRST_STATE_NAME, True) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_state_improvements('eid') self.assertEquals(states, [{ 'rank': 3, 'type': 'default', 'state_name': FIRST_STATE_NAME }, { 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }])
def test_export_to_zip_file(self): """Test the export_to_zip_file() method.""" exploration = self.save_new_default_exploration(self.EXP_ID) exploration.add_states(['New state']) exp_services._save_exploration(self.OWNER_ID, exploration, '', []) zip_file_output = exp_services.export_to_zip_file(self.EXP_ID) zf = zipfile.ZipFile(StringIO.StringIO(zip_file_output)) self.assertEqual(zf.namelist(), ['A title.yaml']) self.assertEqual( zf.open('A title.yaml').read(), self.SAMPLE_YAML_CONTENT)
def test_state_hit(self): with self.swap(jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CONTINUOUS_COMPUTATION_MANAGERS_FOR_TESTS): exp_id = 'eid' exploration = self.save_new_valid_exploration(exp_id, 'owner') time.sleep(1) stats_jobs._STATE_COUNTER_CUTOFF_DATE = datetime.datetime.utcnow() original_init_state = exploration.init_state_name new_init_state_name = 'New init state' exploration.rename_state(original_init_state, new_init_state_name) exp_services._save_exploration('owner', exploration, '', []) exp_version = 2 state2_name = 'sid2' self._record_state_hit(exp_id, exp_version, new_init_state_name, 'session1') self._record_state_hit(exp_id, exp_version, new_init_state_name, 'session2') self._create_state_counter(exp_id, original_init_state, 18) self._record_state_hit(exp_id, exp_version, state2_name, 'session1') self._create_state_counter(exp_id, state2_name, 9) self.process_and_flush_pending_tasks() ModifiedStatisticsAggregator.start_computation() self.assertEqual(self.count_jobs_in_taskqueue(), 1) self.process_and_flush_pending_tasks() state_hit_counts = stats_jobs.StatisticsAggregator.get_statistics( exp_id, exp_version)['state_hit_counts'] self.assertEqual( state_hit_counts[new_init_state_name]['first_entry_count'], 2) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 1) output_model = stats_jobs.StatisticsAggregator.get_statistics( exp_id, stats_jobs._NO_SPECIFIED_VERSION_STRING) state_hit_counts = output_model['state_hit_counts'] self.assertEqual( state_hit_counts[original_init_state]['first_entry_count'], 18) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 9) self.assertEqual(output_model['start_exploration_count'], 18) state_hit_counts = stats_jobs.StatisticsAggregator.get_statistics( exp_id, stats_jobs._ALL_VERSIONS_STRING)['state_hit_counts'] self.assertEqual( state_hit_counts[original_init_state]['first_entry_count'], 18) self.assertEqual( state_hit_counts[new_init_state_name]['first_entry_count'], 2) self.assertEqual( state_hit_counts[state2_name]['first_entry_count'], 10)
def test_save_and_retrieve_exploration(self): exploration = self.save_new_default_exploration(self.EXP_ID) exploration.param_specs = { 'theParameter': param_domain.ParamSpec('Int')} exp_services._save_exploration('A user id', exploration, '', []) retrieved_exploration = exp_services.get_exploration_by_id(self.EXP_ID) self.assertEqual(retrieved_exploration.title, 'A title') self.assertEqual(retrieved_exploration.category, 'A category') self.assertEqual(len(retrieved_exploration.states), 1) self.assertEqual(len(retrieved_exploration.param_specs), 1) self.assertEqual( retrieved_exploration.param_specs.keys()[0], 'theParameter')
def test_exploration_download_handler_for_default_exploration(self): # Register and log in as an editor. self.register_editor('*****@*****.**') self.login('*****@*****.**') self.OWNER_ID = self.get_user_id_from_email('*****@*****.**') # Create a simple exploration EXP_ID = 'eid' exploration = exp_domain.Exploration.create_default_exploration( EXP_ID, 'The title for ZIP download handler test!', 'This is just a test category') exploration.add_states(['State A', 'State 2', 'State 3']) exp_services.save_new_exploration(self.OWNER_ID, exploration) exploration.rename_state('State 2', 'State B') exploration.delete_state('State 3') exp_services._save_exploration(self.OWNER_ID, exploration, '', []) response = self.testapp.get('/create/%s' % EXP_ID) # Download to zip file using download handler EXPLORATION_DOWNLOAD_URL = '/createhandler/download/%s' % EXP_ID response = self.testapp.get(EXPLORATION_DOWNLOAD_URL) # Check downloaded zip file self.assertEqual(response.headers['Content-Type'], 'text/plain') filename = 'oppia-ThetitleforZIPdownloadhandlertest!-v2.zip' self.assertEqual(response.headers['Content-Disposition'], 'attachment; filename=%s' % str(filename)) zf_saved = zipfile.ZipFile(StringIO.StringIO(response.body)) self.assertEqual( zf_saved.namelist(), ['The title for ZIP download handler test!.yaml']) # Load golden zip file with open(os.path.join( feconf.TESTS_DATA_DIR, 'oppia-ThetitleforZIPdownloadhandlertest!-v2-gold.zip'), 'rb') as f: golden_zipfile = f.read() zf_gold = zipfile.ZipFile(StringIO.StringIO(golden_zipfile)) # Compare saved with golden file self.assertEqual( zf_saved.open( 'The title for ZIP download handler test!.yaml' ).read(), zf_gold.open( 'The title for ZIP download handler test!.yaml' ).read()) self.logout()
def test_update_invalid_generator(self): """Test for check that the generator_id in param_changes exists.""" exploration = exp_services.get_exploration_by_id(self.EXP_ID) exploration.param_specs = {'myParam': param_domain.ParamSpec('Int')} exp_services._save_exploration(self.OWNER_ID, exploration, '', []) self.param_changes[0]['generator_id'] = 'fake' with self.assertRaisesRegexp( utils.ValidationError, 'Invalid generator id fake'): exp_services.update_exploration( self.OWNER_ID, self.EXP_ID, _get_change_list( self.init_state_name, 'param_changes', self.param_changes), '')
def test_versioning_with_reverting(self): exploration = self.save_new_valid_exploration( self.EXP_ID, self.OWNER_ID) # In version 1, the title was 'A title'. # In version 2, the title becomes 'V2 title'. exploration.title = 'V2 title' exp_services._save_exploration( self.OWNER_ID, exploration, 'Changed title.', []) # In version 3, a new state is added. exploration = exp_services.get_exploration_by_id(self.EXP_ID) exploration.add_states(['New state']) exp_services._save_exploration( 'committer_id_v3', exploration, 'Added new state', []) # It is not possible to revert from anything other than the most # current version. with self.assertRaisesRegexp(Exception, 'too old'): exp_services.revert_exploration( 'committer_id_v4', self.EXP_ID, 2, 1) # Version 4 is a reversion to version 1. exp_services.revert_exploration('committer_id_v4', self.EXP_ID, 3, 1) exploration = exp_services.get_exploration_by_id(self.EXP_ID) self.assertEqual(exploration.title, 'A title') self.assertEqual(len(exploration.states), 1) self.assertEqual(exploration.version, 4) snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 5) commit_dict_4 = { 'committer_id': 'committer_id_v4', 'commit_message': 'Reverted exploration to version 1', 'version_number': 4, } commit_dict_3 = { 'committer_id': 'committer_id_v3', 'commit_message': 'Added new state', 'version_number': 3, } self.assertEqual(len(snapshots_metadata), 4) self.assertDictContainsSubset( commit_dict_4, snapshots_metadata[0]) self.assertDictContainsSubset(commit_dict_3, snapshots_metadata[1]) self.assertGreaterEqual( snapshots_metadata[0]['created_on'], snapshots_metadata[1]['created_on'])
def test_update_param_changes(self): """Test updating of param_changes.""" exploration = exp_services.get_exploration_by_id(self.EXP_ID) exploration.param_specs = {'myParam': param_domain.ParamSpec('Int')} exp_services._save_exploration(self.OWNER_ID, exploration, '', []) exp_services.update_exploration( self.OWNER_ID, self.EXP_ID, _get_change_list( self.init_state_name, 'param_changes', self.param_changes), '') exploration = exp_services.get_exploration_by_id(self.EXP_ID) param_changes = exploration.init_state.param_changes[0] self.assertEqual(param_changes._name, 'myParam') self.assertEqual(param_changes._generator_id, 'RandomSelector') self.assertEqual( param_changes._customization_args, {'list_of_values': ['1', '2'], 'parse_with_jinja': False})
def test_no_improvement_flag_hit(self): self.save_new_valid_exploration('eid', '*****@*****.**', end_state_name='End') exp = exp_services.get_exploration_by_id('eid') not_default_rule_spec = exp_domain.RuleSpec('Equals', {'x': 'Text'}) init_interaction = exp.init_state.interaction init_interaction.answer_groups.append( exp_domain.AnswerGroup( exp_domain.Outcome(exp.init_state_name, [], {}), [not_default_rule_spec])) init_interaction.default_outcome = exp_domain.Outcome('End', [], {}) exp_services._save_exploration('*****@*****.**', exp, '', []) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, not_default_rule_spec.stringify_classified_rule(), '1') self.assertEquals(stats_services.get_state_improvements('eid', 1), [])
def test_no_improvement_flag_hit(self): self.save_new_valid_exploration( 'eid', '*****@*****.**', end_state_name='End') exp = exp_services.get_exploration_by_id('eid') not_default_rule_spec = exp_domain.RuleSpec('Equals', {'x': 'Text'}) init_interaction = exp.init_state.interaction init_interaction.answer_groups.append(exp_domain.AnswerGroup( exp_domain.Outcome(exp.init_state_name, [], {}), [not_default_rule_spec])) init_interaction.default_outcome = exp_domain.Outcome( 'End', [], {}) exp_services._save_exploration('*****@*****.**', exp, '', []) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, not_default_rule_spec.stringify_classified_rule(), '1') self.assertEquals(stats_services.get_state_improvements('eid', 1), [])
def test_export_to_zip_file_with_assets(self): """Test exporting an exploration with assets to a zip file.""" exploration = self.save_new_default_exploration(self.EXP_ID) exploration.add_states(['New state']) exp_services._save_exploration(self.OWNER_ID, exploration, '', []) with open(os.path.join(feconf.TESTS_DATA_DIR, 'img.png')) as f: raw_image = f.read() fs = fs_domain.AbstractFileSystem( fs_domain.ExplorationFileSystem(self.EXP_ID)) fs.commit(self.OWNER_ID, 'abc.png', raw_image) zip_file_output = exp_services.export_to_zip_file(self.EXP_ID) zf = zipfile.ZipFile(StringIO.StringIO(zip_file_output)) self.assertEqual(zf.namelist(), ['A title.yaml', 'assets/abc.png']) self.assertEqual( zf.open('A title.yaml').read(), self.SAMPLE_YAML_CONTENT) self.assertEqual(zf.open('assets/abc.png').read(), raw_image)
def test_clone_exploration(self): """Test cloning an exploration with assets.""" exploration = self.save_new_default_exploration(self.EXP_ID) exploration.add_states(['New state']) exp_services._save_exploration(self.OWNER_ID, exploration, '', []) with open(os.path.join(feconf.TESTS_DATA_DIR, 'img.png')) as f: raw_image = f.read() fs = fs_domain.AbstractFileSystem( fs_domain.ExplorationFileSystem(exploration.id)) fs.commit(self.OWNER_ID, 'abc.png', raw_image) new_eid = exp_services.clone_exploration(self.OWNER_ID, exploration.id) new_fs = fs_domain.AbstractFileSystem( fs_domain.ExplorationFileSystem(new_eid)) new_exploration = exp_services.get_exploration_by_id(new_eid) self.assertEqual(new_exploration.title, 'Copy of A title') self.assertEqual(new_exploration.category, 'A category') self.assertEqual(new_fs.get('abc.png'), raw_image)
def test_no_improvement_flag_hit(self): self.save_new_valid_exploration('eid', '*****@*****.**') exp = exp_services.get_exploration_by_id('eid') 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.interaction.handlers[0].rule_specs = [ not_default_rule_spec, default_rule_spec ] exp_services._save_exploration('*****@*****.**', exp, '', []) event_services.AnswerSubmissionEventHandler.record( 'eid', 1, exp.init_state_name, feconf.SUBMIT_HANDLER_NAME, not_default_rule_spec, '1') self.assertEquals(stats_services.get_state_improvements('eid', 1), [])
def setUp(self): super(SuggestionMigrationOneOffJobTest, self).setUp() self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.AUTHOR_EMAIL, 'author') self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.author_id = self.get_user_id_from_email(self.AUTHOR_EMAIL) self.editor = user_services.UserActionsInfo(self.editor_id) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. self.save_new_valid_exploration(self.EXP_ID, self.editor_id, title='Exploration for suggestions', category='Algebra', objective='Test a suggestion.') exploration = exp_services.get_exploration_by_id(self.EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(['State 1']) self.old_content = exp_domain.SubtitledHtml('content', 'old content').to_dict() # Create content in State A with a single audio subtitle. exploration.states['State 1'].update_content(self.old_content) exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR)
def test_library_handler_for_created_explorations(self): """Test the library data handler for manually created explorations.""" self.set_admins([self.ADMIN_USERNAME]) self.login(self.ADMIN_EMAIL) response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertDictContainsSubset( { 'is_admin': True, 'is_moderator': True, 'is_super_admin': False, 'activity_list': [], 'user_email': self.ADMIN_EMAIL, 'username': self.ADMIN_USERNAME, 'search_cursor': None, }, response_dict) # Create exploration A. exploration = self.save_new_valid_exploration('A', self.admin_id, title='Title A', category='Category A', objective='Objective A') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration A', []) # Test that the private exploration isn't displayed. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(response_dict['activity_list'], []) # Create exploration B. exploration = self.save_new_valid_exploration('B', self.admin_id, title='Title B', category='Category B', objective='Objective B') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration B', []) rights_manager.publish_exploration(self.admin, 'B') # Publish exploration A. rights_manager.publish_exploration(self.admin, 'A') exp_services.index_explorations_given_ids(['A', 'B']) # Load the search results with an empty query. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(len(response_dict['activity_list']), 2) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][1]) self.assertDictContainsSubset( { 'id': 'A', 'category': 'Category A', 'title': 'Title A', 'language_code': 'en', 'objective': 'Objective A', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][0]) # Delete exploration A. exp_services.delete_exploration(self.admin_id, 'A') # Load the search results with an empty query. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(len(response_dict['activity_list']), 1) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][0])
def setUp(self): super(SuggestionsIntegrationTests, self).setUp() # Register users. self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL) # Load exploration 0. exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. self.save_new_valid_exploration( self.EXP_ID, self.editor_id, title='Exploration for suggestions', category='This is just a test category', objective='Test a suggestion.') exploration = exp_services.get_exploration_by_id(self.EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor_id, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor_id, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) response = self.testapp.get('/explore/%s' % self.EXP_ID) csrf_token = self.get_csrf_token_from_response(response) # Create suggestions. self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 3, 'state_name': u'State A', 'description': u'Suggestion for state A.', 'suggestion_content': { 'type': 'text', 'value': u'new accepted suggestion for state A' }, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'A new value.', 'suggestion_content': { 'type': 'text', 'value': 'some new value' }, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Empty suggestion', 'suggestion_content': { 'type': 'text', 'value': '' }, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State A', 'description': u'Just a space.', 'suggestion_content': { 'type': 'text', 'value': ' ' }, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'Random characters.', 'suggestion_content': { 'type': 'text', 'value': '#!$%' }, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Very bizarre characters.', 'suggestion_content': { 'type': 'text', 'value': u'Ֆݓॵক' }, }, csrf_token) self.logout()
def setUp(self): super(SuggestionUnitTests, self).setUp() self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.AUTHOR_EMAIL, 'author') self.signup(self.AUTHOR_EMAIL_2, 'author2') self.signup(self.NORMAL_USER_EMAIL, 'normalUser') self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.author_id = self.get_user_id_from_email(self.AUTHOR_EMAIL) self.author_id_2 = self.get_user_id_from_email(self.AUTHOR_EMAIL_2) self.reviewer_id = self.editor_id self.set_admins([self.ADMIN_USERNAME]) self.editor = user_services.UserActionsInfo(self.editor_id) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) exploration = ( self.save_new_linear_exp_with_state_names_and_interactions( self.EXP_ID, self.editor_id, ['State 1', 'State 2', 'State 3'], ['TextInput'], category='Algebra')) self.old_content = state_domain.SubtitledHtml( 'content', '<p>old content html</p>').to_dict() exploration.states['State 1'].update_content(self.old_content) exploration.states['State 2'].update_content(self.old_content) exploration.states['State 3'].update_content(self.old_content) exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) self.new_content = state_domain.SubtitledHtml( 'content', '<p>new content html</p>').to_dict() self.resubmit_change_content = state_domain.SubtitledHtml( 'content', '<p>resubmit change content html</p>').to_dict() self.logout() self.login(self.AUTHOR_EMAIL) csrf_token = self.get_new_csrf_token() self.post_json('%s/' % feconf.SUGGESTION_URL_PREFIX, { 'suggestion_type': (suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT), 'target_type': (suggestion_models.TARGET_TYPE_EXPLORATION), 'target_id': 'exp1', 'target_version_at_submission': exploration.version, 'change': { 'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY, 'property_name': exp_domain.STATE_PROPERTY_CONTENT, 'state_name': 'State 1', 'old_value': self.old_content, 'new_value': self.new_content }, 'description': 'change to state 1', 'final_reviewer_id': self.reviewer_id, }, csrf_token=csrf_token) self.logout() self.login(self.AUTHOR_EMAIL_2) csrf_token = self.get_new_csrf_token() self.post_json('%s/' % feconf.SUGGESTION_URL_PREFIX, { 'suggestion_type': (suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT), 'target_type': (suggestion_models.TARGET_TYPE_EXPLORATION), 'target_id': 'exp1', 'target_version_at_submission': exploration.version, 'change': { 'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY, 'property_name': exp_domain.STATE_PROPERTY_CONTENT, 'state_name': 'State 2', 'old_value': self.old_content, 'new_value': self.new_content }, 'description': 'change to state 2', 'final_reviewer_id': self.reviewer_id, }, csrf_token=csrf_token) self.post_json('%s/' % feconf.SUGGESTION_URL_PREFIX, { 'suggestion_type': (suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT), 'target_type': (suggestion_models.TARGET_TYPE_EXPLORATION), 'target_id': 'exp1', 'target_version_at_submission': exploration.version, 'change': { 'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY, 'property_name': exp_domain.STATE_PROPERTY_CONTENT, 'state_name': 'State 3', 'old_value': self.old_content, 'new_value': self.new_content }, 'description': 'change to state 3', 'final_reviewer_id': self.reviewer_id, }, csrf_token=csrf_token) self.logout()
def test_exploration_download_handler_for_default_exploration(self): self.login(self.EDITOR_EMAIL) self.OWNER_ID = self.get_user_id_from_email(self.EDITOR_EMAIL) # Create a simple exploration EXP_ID = "eid" self.save_new_valid_exploration( EXP_ID, self.OWNER_ID, title="The title for ZIP download handler test!", category="This is just a test category", objective="", ) exploration = exp_services.get_exploration_by_id(EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(["State A", "State 2", "State 3"]) exploration.states["State A"].update_interaction_id("TextInput") exploration.states["State 2"].update_interaction_id("TextInput") exploration.states["State 3"].update_interaction_id("TextInput") exploration.rename_state("State 2", "State B") exploration.delete_state("State 3") exp_services._save_exploration(self.OWNER_ID, exploration, "", []) response = self.testapp.get("/create/%s" % EXP_ID) # Check download to zip file # Download to zip file using download handler EXPLORATION_DOWNLOAD_URL = "/createhandler/download/%s" % EXP_ID response = self.testapp.get(EXPLORATION_DOWNLOAD_URL) # Check downloaded zip file self.assertEqual(response.headers["Content-Type"], "text/plain") filename = "oppia-ThetitleforZIPdownloadhandlertest!-v2.zip" self.assertEqual(response.headers["Content-Disposition"], "attachment; filename=%s" % str(filename)) zf_saved = zipfile.ZipFile(StringIO.StringIO(response.body)) self.assertEqual(zf_saved.namelist(), ["The title for ZIP download handler test!.yaml"]) # Load golden zip file with open( os.path.join(feconf.TESTS_DATA_DIR, "oppia-ThetitleforZIPdownloadhandlertest!-v2-gold.zip"), "rb" ) as f: golden_zipfile = f.read() zf_gold = zipfile.ZipFile(StringIO.StringIO(golden_zipfile)) # Compare saved with golden file self.assertEqual( zf_saved.open("The title for ZIP download handler test!.yaml").read(), zf_gold.open("The title for ZIP download handler test!.yaml").read(), ) # Check download to JSON exploration.update_objective("Test JSON download") exp_services._save_exploration(self.OWNER_ID, exploration, "", []) # Download to JSON string using download handler self.maxDiff = None EXPLORATION_DOWNLOAD_URL = "/createhandler/download/%s?output_format=%s&width=50" % ( EXP_ID, feconf.OUTPUT_FORMAT_JSON, ) response = self.get_json(EXPLORATION_DOWNLOAD_URL) # Check downloaded dict self.assertEqual(self.SAMPLE_JSON_CONTENT, response) self.logout()
def test_gallery_handler_for_created_explorations(self): """Test the gallery data handler for manually created explirations.""" self.set_admins([self.ADMIN_USERNAME]) self.login(self.ADMIN_EMAIL) response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual({ 'is_admin': True, 'is_moderator': True, 'is_super_admin': False, 'explorations_list': [], 'user_email': self.ADMIN_EMAIL, 'username': self.ADMIN_USERNAME, 'search_cursor': None, 'profile_picture_data_url': None, 'preferred_language_codes': [feconf.DEFAULT_LANGUAGE_CODE], }, response_dict) # Create exploration A exploration = self.save_new_valid_exploration( 'A', self.admin_id, title='Title A', category='Category A', objective='Objective A') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration A', []) # Test that the private exploration isn't displayed. response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(response_dict['explorations_list'], []) # Create exploration B exploration = self.save_new_valid_exploration( 'B', self.admin_id, title='Title B', category='Category B', objective='Objective B') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration B', []) rights_manager.publish_exploration(self.admin_id, 'B') rights_manager.publicize_exploration(self.admin_id, 'B') # Publish exploration A rights_manager.publish_exploration(self.admin_id, 'A') exp_services.index_explorations_given_ids(['A', 'B']) # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 2) self.assertDictContainsSubset({ 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0]) self.assertDictContainsSubset({ 'id': 'A', 'category': 'Category A', 'title': 'Title A', 'language_code': 'en', 'objective': 'Objective A', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['explorations_list'][1]) # Delete exploration A exp_services.delete_exploration(self.admin_id, 'A') # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset({ 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def test_exploration_download_handler_for_default_exploration(self): self.login(self.EDITOR_EMAIL) owner_id = self.get_user_id_from_email(self.EDITOR_EMAIL) # Create a simple exploration exp_id = 'eid' self.save_new_valid_exploration( exp_id, owner_id, title='The title for ZIP download handler test!', category='This is just a test category', objective='') exploration = exp_services.get_exploration_by_id(exp_id) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exploration.rename_state('State 2', 'State B') exploration.delete_state('State 3') exp_services._save_exploration( # pylint: disable=protected-access owner_id, exploration, '', []) response = self.testapp.get('/create/%s' % exp_id) # Check download to zip file # Download to zip file using download handler download_url = '/createhandler/download/%s' % exp_id response = self.testapp.get(download_url) # Check downloaded zip file self.assertEqual(response.headers['Content-Type'], 'text/plain') filename = 'oppia-ThetitleforZIPdownloadhandlertest!-v2.zip' self.assertEqual(response.headers['Content-Disposition'], 'attachment; filename=%s' % str(filename)) zf_saved = zipfile.ZipFile(StringIO.StringIO(response.body)) self.assertEqual( zf_saved.namelist(), ['The title for ZIP download handler test!.yaml']) # Load golden zip file with open(os.path.join( feconf.TESTS_DATA_DIR, 'oppia-ThetitleforZIPdownloadhandlertest!-v2-gold.zip'), 'rb') as f: golden_zipfile = f.read() zf_gold = zipfile.ZipFile(StringIO.StringIO(golden_zipfile)) # Compare saved with golden file self.assertEqual( zf_saved.open( 'The title for ZIP download handler test!.yaml').read(), zf_gold.open( 'The title for ZIP download handler test!.yaml').read()) # Check download to JSON exploration.update_objective('Test JSON download') exp_services._save_exploration( # pylint: disable=protected-access owner_id, exploration, '', []) # Download to JSON string using download handler self.maxDiff = None download_url = ( '/createhandler/download/%s?output_format=%s&width=50' % (exp_id, feconf.OUTPUT_FORMAT_JSON)) response = self.get_json(download_url) # Check downloaded dict self.assertEqual(self.SAMPLE_JSON_CONTENT, response) self.logout()
def test_two_state_default_hit(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) FIRST_STATE_NAME = exp.init_state_name SECOND_STATE_NAME = 'State 2' exp.add_states([SECOND_STATE_NAME]) exp_services._save_exploration('*****@*****.**', exp, '', []) # Hit the default rule of state 1 once, and the default rule of state 2 # twice. stats_services.EventHandler.record_state_hit('eid', FIRST_STATE_NAME, True) stats_services.EventHandler.record_answer_submitted( 'eid', 1, FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') for i in range(2): stats_services.EventHandler.record_state_hit( 'eid', SECOND_STATE_NAME, True) stats_services.EventHandler.record_answer_submitted( 'eid', 1, SECOND_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_top_improvable_states(['eid'], 5) self.assertEquals(len(states), 2) self.assertDictContainsSubset( { 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }, states[0]) self.assertDictContainsSubset( { 'rank': 1, 'type': 'default', 'state_name': FIRST_STATE_NAME }, states[1]) # Hit the default rule of state 1 two more times. for i in range(2): stats_services.EventHandler.record_state_hit( 'eid', FIRST_STATE_NAME, True) stats_services.EventHandler.record_answer_submitted( 'eid', 1, FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC, '1') states = stats_services.get_top_improvable_states(['eid'], 5) self.assertEquals(len(states), 2) self.assertDictContainsSubset( { 'rank': 3, 'type': 'default', 'state_name': FIRST_STATE_NAME }, states[0]) self.assertDictContainsSubset( { 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }, states[1]) # Try getting just the top improvable state. states = stats_services.get_top_improvable_states(['eid'], 1) self.assertEquals(len(states), 1) self.assertDictContainsSubset( { 'rank': 3, 'type': 'default', 'state_name': FIRST_STATE_NAME }, states[0])
def test_gallery_handler_for_created_explorations(self): """Test the gallery data handler for manually created explirations.""" self.set_admins([self.ADMIN_EMAIL]) self.login(self.ADMIN_EMAIL) response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual( { 'is_admin': True, 'is_moderator': True, 'is_super_admin': False, 'explorations_list': [], 'user_email': self.ADMIN_EMAIL, 'username': self.ADMIN_USERNAME, 'search_cursor': None, 'profile_picture_data_url': None, 'preferred_language_codes': [feconf.DEFAULT_LANGUAGE_CODE], }, response_dict) # Create exploration A exploration = self.save_new_valid_exploration('A', self.ADMIN_ID, title='Title A', category='Category A', objective='Objective A') exp_services._save_exploration(self.ADMIN_ID, exploration, 'Exploration A', []) # Test that the private exploration isn't displayed. response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(response_dict['explorations_list'], []) # Create exploration B exploration = self.save_new_valid_exploration('B', self.ADMIN_ID, title='Title B', category='Category B', objective='Objective B') exp_services._save_exploration(self.ADMIN_ID, exploration, 'Exploration B', []) rights_manager.publish_exploration(self.ADMIN_ID, 'B') rights_manager.publicize_exploration(self.ADMIN_ID, 'B') # Publish exploration A rights_manager.publish_exploration(self.ADMIN_ID, 'A') exp_services.index_explorations_given_ids(['A', 'B']) # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 2) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0]) self.assertDictContainsSubset( { 'id': 'A', 'category': 'Category A', 'title': 'Title A', 'language_code': 'en', 'objective': 'Objective A', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['explorations_list'][1]) # Delete exploration A exp_services.delete_exploration(self.ADMIN_ID, 'A') # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def test_fallbacks_are_listed(self): """Tests that fallbacks are listed.""" explorations = [ self.save_new_valid_exploration(EXP_ID, self.owner_id, objective='The objective', end_state_name='end') for EXP_ID in self.EXP_IDS ] for exploration in explorations: init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = 'state 1' init_state.update_interaction_fallbacks(self.FALLBACK) exploration.add_states(['state 1']) new_state = exploration.states['state 1'] new_state.interaction.default_outcome.dest = 'end' new_state.update_interaction_fallbacks(self.FALLBACK) exploration.states['end'].update_interaction_id('EndExploration') exp_services._save_exploration(self.owner_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.owner_id, exploration.id) job_id = exp_jobs_one_off.FallbackOneOffJob.create_new() exp_jobs_one_off.FallbackOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() actual_values = exp_jobs_one_off.FallbackOneOffJob.get_output(job_id) expected_values = [[ u'exp_id0: Introduction', [ u'3: <p>feedback 0</p>', u'4: <p>feedback 1</p>', u'5: <p>feedback 2</p>' ] ], [ u'exp_id0: state 1', [ u'3: <p>feedback 0</p>', u'4: <p>feedback 1</p>', u'5: <p>feedback 2</p>' ] ], [ u'exp_id1: Introduction', [ u'3: <p>feedback 0</p>', u'4: <p>feedback 1</p>', u'5: <p>feedback 2</p>' ] ], [ u'exp_id1: state 1', [ u'3: <p>feedback 0</p>', u'4: <p>feedback 1</p>', u'5: <p>feedback 2</p>' ] ]] actual_values.sort() for index, actual_value in enumerate(actual_values): self.assertEqual(actual_value.encode('ascii'), str(expected_values[index]))
def setUp(self): super(SuggestionsIntegrationTests, self).setUp() # Register users. self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL) self.editor = user_services.UserActionsInfo(self.editor_id) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. self.save_new_valid_exploration( self.EXP_ID, self.editor_id, title='Exploration for suggestions', category='This is just a test category', objective='Test a suggestion.') exploration = exp_services.get_exploration_by_id(self.EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') # Create content in State A with a single audio subtitle. content_id = exploration.states['State A'].content.content_id exploration.states['State A'].update_content( exp_domain.SubtitledHtml(content_id, 'old content').to_dict()) exploration.states['State A'].update_content_ids_to_audio_translations( { content_id: { self.TRANSLATION_LANGUAGE_CODE: exp_domain.AudioTranslation('filename.mp3', 20, False).to_dict() }, 'default_outcome': {} }) exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor, self.EXP_ID) rights_manager.assign_role_for_exploration(self.editor, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) response = self.testapp.get('/explore/%s' % self.EXP_ID) csrf_token = self.get_csrf_token_from_response(response) # Create suggestions. self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 3, 'state_name': u'State A', 'description': u'Suggestion for state A.', 'suggestion_html': 'new accepted suggestion for state A', }, csrf_token=csrf_token) self.post_json('%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'A new value.', 'suggestion_html': 'some new value', }, csrf_token=csrf_token) self.post_json('%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Empty suggestion', 'suggestion_html': '', }, csrf_token=csrf_token) self.post_json('%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State A', 'description': u'Just a space.', 'suggestion_html': ' ', }, csrf_token=csrf_token) self.post_json('%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'Random characters.', 'suggestion_html': '#!$%', }, csrf_token=csrf_token) self.post_json('%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Very bizarre characters.', 'suggestion_html': u'Ֆݓॵক', }, csrf_token=csrf_token) self.logout()
def test_exploration_download_handler_for_default_exploration(self): self.login(self.EDITOR_EMAIL) self.OWNER_ID = self.get_user_id_from_email(self.EDITOR_EMAIL) # Create a simple exploration EXP_ID = 'eid' self.save_new_valid_exploration( EXP_ID, self.OWNER_ID, title='The title for ZIP download handler test!', category='This is just a test category', objective='') exploration = exp_services.get_exploration_by_id(EXP_ID) exploration.states[exploration.init_state_name].interaction.handlers[ 0].rule_specs[0].dest = exploration.init_state_name exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exploration.rename_state('State 2', 'State B') exploration.delete_state('State 3') exp_services._save_exploration(self.OWNER_ID, exploration, '', []) response = self.testapp.get('/create/%s' % EXP_ID) # Check download to zip file # Download to zip file using download handler EXPLORATION_DOWNLOAD_URL = '/createhandler/download/%s' % EXP_ID response = self.testapp.get(EXPLORATION_DOWNLOAD_URL) # Check downloaded zip file self.assertEqual(response.headers['Content-Type'], 'text/plain') filename = 'oppia-ThetitleforZIPdownloadhandlertest!-v2.zip' self.assertEqual(response.headers['Content-Disposition'], 'attachment; filename=%s' % str(filename)) zf_saved = zipfile.ZipFile(StringIO.StringIO(response.body)) self.assertEqual(zf_saved.namelist(), ['The title for ZIP download handler test!.yaml']) # Load golden zip file with open( os.path.join( feconf.TESTS_DATA_DIR, 'oppia-ThetitleforZIPdownloadhandlertest!-v2-gold.zip'), 'rb') as f: golden_zipfile = f.read() zf_gold = zipfile.ZipFile(StringIO.StringIO(golden_zipfile)) # Compare saved with golden file self.assertEqual( zf_saved.open( 'The title for ZIP download handler test!.yaml').read(), zf_gold.open( 'The title for ZIP download handler test!.yaml').read()) # Check download to JSON exploration.update_objective('Test JSON download') exp_services._save_exploration(self.OWNER_ID, exploration, '', []) # Download to JSON string using download handler self.maxDiff = None EXPLORATION_DOWNLOAD_URL = ( '/createhandler/download/%s?output_format=%s&width=50' % (EXP_ID, feconf.OUTPUT_FORMAT_JSON)) response = self.get_json(EXPLORATION_DOWNLOAD_URL) # Check downloaded dict self.assertEqual(self.SAMPLE_JSON_CONTENT, response) self.logout()
def test_two_state_default_hit(self): exp = exp_domain.Exploration.create_default_exploration( 'eid', 'A title', 'A category') exp_services.save_new_exploration('*****@*****.**', exp) FIRST_STATE_NAME = exp.init_state_name SECOND_STATE_NAME = 'State 2' exp.add_states([SECOND_STATE_NAME]) exp_services._save_exploration('*****@*****.**', exp, '', []) # Hit the default rule of state 1 once, and the default rule of state 2 # twice. stats_services.EventHandler.record_state_hit( 'eid', FIRST_STATE_NAME, True) stats_services.EventHandler.record_answer_submitted( 'eid', FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, '1') for i in range(2): stats_services.EventHandler.record_state_hit( 'eid', SECOND_STATE_NAME, True) stats_services.EventHandler.record_answer_submitted( 'eid', SECOND_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, '1') states = stats_services.get_top_improvable_states(['eid'], 5) self.assertEquals(len(states), 2) self.assertDictContainsSubset({ 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }, states[0]) self.assertDictContainsSubset({ 'rank': 1, 'type': 'default', 'state_name': FIRST_STATE_NAME }, states[1]) # Hit the default rule of state 1 two more times. for i in range(2): stats_services.EventHandler.record_state_hit( 'eid', FIRST_STATE_NAME, True) stats_services.EventHandler.record_answer_submitted( 'eid', FIRST_STATE_NAME, self.SUBMIT_HANDLER, self.DEFAULT_RULESPEC_STR, '1') states = stats_services.get_top_improvable_states(['eid'], 5) self.assertEquals(len(states), 2) self.assertDictContainsSubset({ 'rank': 3, 'type': 'default', 'state_name': FIRST_STATE_NAME }, states[0]) self.assertDictContainsSubset({ 'rank': 2, 'type': 'default', 'state_name': SECOND_STATE_NAME }, states[1]) # Try getting just the top improvable state. states = stats_services.get_top_improvable_states(['eid'], 1) self.assertEquals(len(states), 1) self.assertDictContainsSubset({ 'rank': 3, 'type': 'default', 'state_name': FIRST_STATE_NAME }, states[0])
def test_get_exploration_snapshots_metadata(self): v1_exploration = self.save_new_valid_exploration( self.EXP_ID, self.OWNER_ID) snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 3) self.assertEqual(len(snapshots_metadata), 1) self.assertDictContainsSubset({ 'commit_cmds': [{ 'cmd': 'create_new', 'title': 'A title', 'category': 'A category', }], 'committer_id': self.OWNER_ID, 'commit_message': ( 'New exploration created with title \'A title\'.'), 'commit_type': 'create', 'version_number': 1 }, snapshots_metadata[0]) self.assertIn('created_on', snapshots_metadata[0]) # Publish the exploration. This does not affect the exploration version # history. rights_manager.publish_exploration(self.OWNER_ID, self.EXP_ID) snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 3) self.assertEqual(len(snapshots_metadata), 1) self.assertDictContainsSubset({ 'commit_cmds': [{ 'cmd': 'create_new', 'title': 'A title', 'category': 'A category' }], 'committer_id': self.OWNER_ID, 'commit_message': ( 'New exploration created with title \'A title\'.'), 'commit_type': 'create', 'version_number': 1 }, snapshots_metadata[0]) self.assertIn('created_on', snapshots_metadata[0]) # Modify the exploration. This affects the exploration version history. change_list = [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'First title' }] exp_services.update_exploration( self.OWNER_ID, self.EXP_ID, change_list, 'Changed title.') snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 3) self.assertEqual(len(snapshots_metadata), 2) self.assertIn('created_on', snapshots_metadata[0]) self.assertDictContainsSubset({ 'commit_cmds': change_list, 'committer_id': self.OWNER_ID, 'commit_message': 'Changed title.', 'commit_type': 'edit', 'version_number': 2, }, snapshots_metadata[0]) self.assertDictContainsSubset({ 'commit_cmds': [{ 'cmd': 'create_new', 'title': 'A title', 'category': 'A category' }], 'committer_id': self.OWNER_ID, 'commit_message': ( 'New exploration created with title \'A title\'.'), 'commit_type': 'create', 'version_number': 1 }, snapshots_metadata[1]) self.assertGreaterEqual( snapshots_metadata[0]['created_on'], snapshots_metadata[1]['created_on']) # Using the old version of the exploration should raise an error. with self.assertRaisesRegexp(Exception, 'version 1, which is too old'): exp_services._save_exploration( 'committer_id_2', v1_exploration, '', []) # Another person modifies the exploration. new_change_list = [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New title' }] exp_services.update_exploration( 'committer_id_2', self.EXP_ID, new_change_list, 'Second commit.') snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 5) self.assertEqual(len(snapshots_metadata), 3) self.assertDictContainsSubset({ 'commit_cmds': new_change_list, 'committer_id': 'committer_id_2', 'commit_message': 'Second commit.', 'commit_type': 'edit', 'version_number': 3, }, snapshots_metadata[0]) self.assertDictContainsSubset({ 'commit_cmds': change_list, 'committer_id': self.OWNER_ID, 'commit_message': 'Changed title.', 'commit_type': 'edit', 'version_number': 2, }, snapshots_metadata[1]) self.assertDictContainsSubset({ 'commit_cmds': [{ 'cmd': 'create_new', 'title': 'A title', 'category': 'A category' }], 'committer_id': self.OWNER_ID, 'commit_message': ( 'New exploration created with title \'A title\'.'), 'commit_type': 'create', 'version_number': 1 }, snapshots_metadata[2]) self.assertGreaterEqual( snapshots_metadata[0]['created_on'], snapshots_metadata[1]['created_on'])
def setUp(self): super(SuggestionsIntegrationTests, self).setUp() # Register users. self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME) self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL) self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL) self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL) # Load exploration 0. exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) # Login and create exploration and suggestions. self.login(self.EDITOR_EMAIL) # Create exploration. self.save_new_valid_exploration( self.EXP_ID, self.editor_id, title='Exploration for suggestions', category='This is just a test category', objective='Test a suggestion.') exploration = exp_services.get_exploration_by_id(self.EXP_ID) init_state = exploration.states[exploration.init_state_name] init_interaction = init_state.interaction init_interaction.default_outcome.dest = exploration.init_state_name exploration.add_states(['State A', 'State 2', 'State 3']) exploration.states['State A'].update_interaction_id('TextInput') exploration.states['State 2'].update_interaction_id('TextInput') exploration.states['State 3'].update_interaction_id('TextInput') exp_services._save_exploration(self.editor_id, exploration, '', []) # pylint: disable=protected-access rights_manager.publish_exploration(self.editor_id, self.EXP_ID) rights_manager.assign_role_for_exploration( self.editor_id, self.EXP_ID, self.owner_id, rights_manager.ROLE_EDITOR) response = self.testapp.get('/explore/%s' % self.EXP_ID) csrf_token = self.get_csrf_token_from_response(response) # Create suggestions. self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 3, 'state_name': u'State A', 'description': u'Suggestion for state A.', 'suggestion_content': { 'type': 'text', 'value': u'new accepted suggestion for state A'}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'A new value.', 'suggestion_content': { 'type': 'text', 'value': 'some new value'}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Empty suggestion', 'suggestion_content': {'type': 'text', 'value': ''}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State A', 'description': u'Just a space.', 'suggestion_content': {'type': 'text', 'value': ' '}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 1, 'state_name': u'State 2', 'description': u'Random characters.', 'suggestion_content': {'type': 'text', 'value': '#!$%'}, }, csrf_token) self.post_json( '%s/%s' % (feconf.SUGGESTION_URL_PREFIX, self.EXP_ID), { 'exploration_version': 2, 'state_name': u'State 3', 'description': u'Very bizarre characters.', 'suggestion_content': {'type': 'text', 'value': u'Ֆݓॵক'}, }, csrf_token) self.logout()
def test_versioning_with_add_and_delete_states(self): exploration = self.save_new_valid_exploration( self.EXP_ID, self.OWNER_ID) exploration.title = 'First title' exp_services._save_exploration( self.OWNER_ID, exploration, 'Changed title.', []) commit_dict_2 = { 'committer_id': self.OWNER_ID, 'commit_message': 'Changed title.', 'version_number': 2, } snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 5) self.assertEqual(len(snapshots_metadata), 2) exploration = exp_services.get_exploration_by_id(self.EXP_ID) exploration.add_states(['New state']) exp_services._save_exploration( 'committer_id_2', exploration, 'Added new state', []) commit_dict_3 = { 'committer_id': 'committer_id_2', 'commit_message': 'Added new state', 'version_number': 3, } snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 5) self.assertEqual(len(snapshots_metadata), 3) self.assertDictContainsSubset( commit_dict_3, snapshots_metadata[0]) self.assertDictContainsSubset(commit_dict_2, snapshots_metadata[1]) self.assertGreaterEqual( snapshots_metadata[0]['created_on'], snapshots_metadata[1]['created_on']) # Perform an invalid action: delete a state that does not exist. This # should not create a new version. with self.assertRaisesRegexp(ValueError, 'does not exist'): exploration.delete_state('invalid_state_name') # Now delete the new state. exploration.delete_state('New state') exp_services._save_exploration( 'committer_id_3', exploration, 'Deleted state: New state', []) commit_dict_4 = { 'committer_id': 'committer_id_3', 'commit_message': 'Deleted state: New state', 'version_number': 4, } snapshots_metadata = exp_services.get_exploration_snapshots_metadata( self.EXP_ID, 5) self.assertEqual(len(snapshots_metadata), 4) self.assertDictContainsSubset(commit_dict_4, snapshots_metadata[0]) self.assertDictContainsSubset(commit_dict_3, snapshots_metadata[1]) self.assertDictContainsSubset(commit_dict_2, snapshots_metadata[2]) self.assertGreaterEqual( snapshots_metadata[0]['created_on'], snapshots_metadata[1]['created_on']) self.assertGreaterEqual( snapshots_metadata[1]['created_on'], snapshots_metadata[2]['created_on']) # The final exploration should have exactly one state. exploration = exp_services.get_exploration_by_id(self.EXP_ID) self.assertEqual(len(exploration.states), 1)