def setUp(self): """Create exploration with two versions""" super(VersioningIntegrationTest, self).setUp() self.EXP_ID = '0' exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) EDITOR_EMAIL = '*****@*****.**' self.register_editor(EDITOR_EMAIL) self.login(EDITOR_EMAIL) # In version 2, change the objective and the initial state content. exploration = exp_services.get_exploration_by_id(self.EXP_ID) exp_services.update_exploration( EDITOR_EMAIL, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'the objective', }, { 'cmd': 'edit_state_property', 'property_name': 'content', 'state_name': exploration.init_state_name, 'new_value': [{'type': 'text', 'value': 'ABC'}], }], 'Change objective and init state content')
def test_editor_page(self): """Test access to editor pages for the sample exploration.""" exp_services.delete_demo('0') exp_services.load_demo('0') # Check that non-editors can access, but not edit, the editor page. response = self.testapp.get('/create/0') self.assertEqual(response.status_int, 200) self.assertIn('Welcome to Oppia!', response.body) self.assert_cannot_edit(response.body) # Log in as an editor. self.login(self.EDITOR_EMAIL) # Check that it is now possible to access and edit the editor page. response = self.testapp.get('/create/0') self.assertIn('Welcome to Oppia!', response.body) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) self.assertIn('Stats', response.body) self.assertIn('History', response.body) # Test that the value generator JS is included. self.assertIn('RandomSelector', response.body) self.logout()
def post(self): """Handles POST requests.""" try: if self.payload.get('action') == 'reload_exploration': exploration_id = self.payload.get('explorationId') logging.info( '[ADMIN] %s reloaded exploration %s' % (self.user_id, exploration_id)) exp_services.delete_demo(unicode(exploration_id)) exp_services.load_demo(unicode(exploration_id)) elif self.payload.get('action') == 'save_config_properties': new_config_property_values = self.payload.get( 'new_config_property_values') logging.info('[ADMIN] %s saved config property values: %s' % (self.user_id, new_config_property_values)) for (name, value) in new_config_property_values.iteritems(): config_services.set_property(self.user_id, name, value) elif self.payload.get('action') == 'revert_config_property': config_property_id = self.payload.get('config_property_id') logging.info('[ADMIN] %s reverted config property: %s' % (self.user_id, config_property_id)) config_services.revert_property( self.user_id, config_property_id) elif self.payload.get('action') == 'refresh_computed_property': computed_property_name = self.payload.get( 'computed_property_name') config_domain.Registry.get_config_property( computed_property_name).refresh_default_value() self.render_json({}) except Exception as e: self.render_json({'error': unicode(e)}) raise
def test_loading_and_validation_and_deletion_of_demo_explorations(self): """Test loading, validation and deletion of the demo explorations.""" self.assertEqual(exp_services.count_explorations(), 0) self.assertGreaterEqual( len(feconf.DEMO_EXPLORATIONS), 1, msg='There must be at least one demo exploration.') for ind in range(len(feconf.DEMO_EXPLORATIONS)): start_time = datetime.datetime.utcnow() exp_id = str(ind) exp_services.load_demo(exp_id) exploration = exp_services.get_exploration_by_id(exp_id) warnings = exploration.validate(strict=True) if warnings: raise Exception(warnings) duration = datetime.datetime.utcnow() - start_time processing_time = duration.seconds + duration.microseconds / 1E6 print 'Loaded and validated exploration %s (%.2f seconds)' % ( exploration.title.encode('utf-8'), processing_time) self.assertEqual( exp_services.count_explorations(), len(feconf.DEMO_EXPLORATIONS)) for ind in range(len(feconf.DEMO_EXPLORATIONS)): exp_services.delete_demo(str(ind)) self.assertEqual(exp_services.count_explorations(), 0)
def setUp(self): """Before the test, create an exploration_dict.""" super(ClassifyHandlerTest, self).setUp() self.enable_string_classifier = self.swap( feconf, 'ENABLE_STRING_CLASSIFIER', True) # Reading YAML exploration into a dictionary. yaml_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../tests/data/string_classifier_test.yaml') with open(yaml_path, 'r') as yaml_file: self.yaml_content = yaml_file.read() self.login(self.VIEWER_EMAIL) self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) # Load demo exploration. self.exp_id = '0' self.title = 'Testing String Classifier' self.category = 'Test' exp_services.delete_demo(self.exp_id) exp_services.load_demo(self.exp_id) # Creating the exploration domain object. self.exploration = exp_domain.Exploration.from_untitled_yaml( self.exp_id, self.title, self.category, self.yaml_content)
def setUp(self): """Load a demo exploration and register self.EDITOR_EMAIL.""" super(ImageHandlerTest, self).setUp() exp_services.delete_demo('0') exp_services.load_demo('0') self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
def post(self): """Handles POST requests.""" try: if self.payload.get('action') == 'reload_exploration': exploration_id = self.payload.get('explorationId') logging.info('[ADMIN] %s reloaded exploration %s' % (self.user_id, exploration_id)) exp_services.delete_demo(unicode(exploration_id)) exp_services.load_demo(unicode(exploration_id)) elif self.payload.get('action') == 'save_config_properties': new_config_property_values = self.payload.get( 'new_config_property_values') logging.info('[ADMIN] %s saved config property values: %s' % (self.user_id, new_config_property_values)) for (name, value) in new_config_property_values.iteritems(): config_services.set_property(self.user_id, name, value) elif self.payload.get('action') == 'revert_config_property': config_property_id = self.payload.get('config_property_id') logging.info('[ADMIN] %s reverted config property: %s' % (self.user_id, config_property_id)) config_services.revert_property(self.user_id, config_property_id) elif self.payload.get('action') == 'refresh_computed_property': computed_property_name = self.payload.get( 'computed_property_name') config_domain.Registry.get_config_property( computed_property_name).refresh_default_value() self.render_json({}) except Exception as e: self.render_json({'error': unicode(e)}) raise
def setUp(self): """Create exploration with two versions""" super(VersioningIntegrationTest, self).setUp() self.EXP_ID = '0' exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) self.login(self.EDITOR_EMAIL) # In version 2, change the objective and the initial state content. exploration = exp_services.get_exploration_by_id(self.EXP_ID) exp_services.update_exploration( self.EDITOR_EMAIL, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'the objective', }, { 'cmd': 'edit_state_property', 'property_name': 'content', 'state_name': exploration.init_state_name, 'new_value': [{ 'type': 'text', 'value': 'ABC' }], }], 'Change objective and init state content')
def test_give_feedback_handler(self): """Test giving feedback handler.""" self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) # Load demo exploration exp_id = '0' exp_services.delete_demo('0') exp_services.load_demo('0') # Viewer opens exploration self.login(self.VIEWER_EMAIL) exploration_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, exp_id)) state_name_1 = exploration_dict['exploration']['init_state_name'] # Viewer gives 1st feedback self.post_json( '/explorehandler/give_feedback/%s' % exp_id, { 'state_name': state_name_1, 'feedback': 'This is a feedback message.', } ) self.logout()
def test_give_feedback_handler(self): """Test giving feedback handler.""" self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) # Load demo exploration exp_id = '0' exp_services.delete_demo('0') exp_services.load_demo('0') # Viewer opens exploration self.login(self.VIEWER_EMAIL) exploration_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, exp_id)) state_name_1 = exploration_dict['exploration']['init_state_name'] # Viewer gives 1st feedback self.post_json( '/explorehandler/give_feedback/%s' % exp_id, { 'state_name': state_name_1, 'feedback': 'This is a feedback message.', }) # Viewer submits answer '0' result_dict = self.submit_answer(exp_id, state_name_1, '0') state_name_2 = result_dict['state_name'] # Viewer gives 2nd feedback self.post_json( '/explorehandler/give_feedback/%s' % exp_id, { 'state_name': state_name_2, 'feedback': 'This is a 2nd feedback message.', }) self.logout()
def post(self): """Handles POST requests.""" try: if self.payload.get('action') == 'reload_exploration': exploration_id = self.payload.get('exploration_id') logging.info( '[ADMIN] %s reloaded exploration %s' % (self.user_id, exploration_id)) exp_services.delete_demo(unicode(exploration_id)) exp_services.load_demo(unicode(exploration_id)) elif self.payload.get('action') == 'clear_search_index': exp_services.clear_search_index() elif self.payload.get('action') == 'save_config_properties': new_config_property_values = self.payload.get( 'new_config_property_values') logging.info('[ADMIN] %s saved config property values: %s' % (self.user_id, new_config_property_values)) for (name, value) in new_config_property_values.iteritems(): config_services.set_property(self.user_id, name, value) elif self.payload.get('action') == 'revert_config_property': config_property_id = self.payload.get('config_property_id') logging.info('[ADMIN] %s reverted config property: %s' % (self.user_id, config_property_id)) config_services.revert_property( self.user_id, config_property_id) elif self.payload.get('action') == 'refresh_computed_property': computed_property_name = self.payload.get( 'computed_property_name') config_domain.Registry.get_config_property( computed_property_name).refresh_default_value() elif self.payload.get('action') == 'start_new_job': for klass in jobs_registry.ONE_OFF_JOB_MANAGERS: if klass.__name__ == self.payload.get('job_type'): klass.enqueue(klass.create_new()) break elif self.payload.get('action') == 'cancel_job': job_id = self.payload.get('job_id') job_type = self.payload.get('job_type') for klass in jobs_registry.ONE_OFF_JOB_MANAGERS: if klass.__name__ == job_type: klass.cancel(job_id, self.user_id) break elif self.payload.get('action') == 'start_computation': computation_type = self.payload.get('computation_type') for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS: if klass.__name__ == computation_type: klass.start_computation() break elif self.payload.get('action') == 'stop_computation': computation_type = self.payload.get('computation_type') for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS: if klass.__name__ == computation_type: klass.stop_computation(self.user_id) break self.render_json({}) except Exception as e: self.render_json({'error': unicode(e)}) raise
def setUp(self): super(AudioDevHandlerTest, self).setUp() exp_services.delete_demo('0') self.system_user = user_services.get_system_user() exp_services.load_demo('0') rights_manager.release_ownership_of_exploration(self.system_user, '0') self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
def setUp(self): super(FeedbackThreadIntegrationTests, self).setUp() self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) self.EDITOR_ID = self.get_user_id_from_email(self.EDITOR_EMAIL) # Load exploration 0. exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID)
def post(self): """Handles POST requests.""" try: if self.payload.get('action') == 'reload_exploration': exploration_id = self.payload.get('exploration_id') logging.info('[ADMIN] %s reloaded exploration %s' % (self.user_id, exploration_id)) exp_services.delete_demo(unicode(exploration_id)) exp_services.load_demo(unicode(exploration_id)) elif self.payload.get('action') == 'clear_search_index': exp_services.clear_search_index() elif self.payload.get('action') == 'save_config_properties': new_config_property_values = self.payload.get( 'new_config_property_values') logging.info('[ADMIN] %s saved config property values: %s' % (self.user_id, new_config_property_values)) for (name, value) in new_config_property_values.iteritems(): config_services.set_property(self.user_id, name, value) elif self.payload.get('action') == 'revert_config_property': config_property_id = self.payload.get('config_property_id') logging.info('[ADMIN] %s reverted config property: %s' % (self.user_id, config_property_id)) config_services.revert_property(self.user_id, config_property_id) elif self.payload.get('action') == 'refresh_computed_property': computed_property_name = self.payload.get( 'computed_property_name') config_domain.Registry.get_config_property( computed_property_name).refresh_default_value() elif self.payload.get('action') == 'start_new_job': for klass in jobs_registry.ONE_OFF_JOB_MANAGERS: if klass.__name__ == self.payload.get('job_type'): klass.enqueue(klass.create_new()) break elif self.payload.get('action') == 'cancel_job': job_id = self.payload.get('job_id') job_type = self.payload.get('job_type') for klass in jobs_registry.ONE_OFF_JOB_MANAGERS: if klass.__name__ == job_type: klass.cancel(job_id, self.user_id) break elif self.payload.get('action') == 'start_computation': computation_type = self.payload.get('computation_type') for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS: if klass.__name__ == computation_type: klass.start_computation() break elif self.payload.get('action') == 'stop_computation': computation_type = self.payload.get('computation_type') for klass in jobs_registry.ALL_CONTINUOUS_COMPUTATION_MANAGERS: if klass.__name__ == computation_type: klass.stop_computation(self.user_id) break self.render_json({}) except Exception as e: self.render_json({'error': unicode(e)}) raise
def setUp(self): """Load a demo exploration and register self.EDITOR_EMAIL.""" super(ImageHandlerTest, self).setUp() exp_services.delete_demo('0') exp_services.load_demo('0') rights_manager.release_ownership_of_exploration( feconf.SYSTEM_COMMITTER_ID, '0') self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
def get(self): """Handles GET requests.""" if not exp_services.get_exploration_by_id('0', strict=False): exp_services.delete_demo('0') exp_services.load_demo('0') self.values.update({ 'gallery_login_url': user_services.create_login_url('/gallery'), }) self.render_template('pages/index.html')
def setUp(self): """Load a demo exploration and register self.EDITOR_EMAIL.""" super(AssetDevHandlerImageTests, self).setUp() exp_services.delete_demo('0') self.system_user = user_services.get_system_user() exp_services.load_demo('0') rights_manager.release_ownership_of_exploration(self.system_user, '0') self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
def test_state_stats_for_default_exploration(self): exp_services.delete_demo('0') exp_services.load_demo('0') EXPLORATION_STATISTICS_URL = '/createhandler/statistics/0' # Check, from the editor perspective, that no stats have been recorded. self.register_editor('*****@*****.**') self.login('*****@*****.**') editor_exploration_dict = self.get_json(EXPLORATION_STATISTICS_URL) self.assertEqual(editor_exploration_dict['num_starts'], 0) self.assertEqual(editor_exploration_dict['num_completions'], 0) # Switch to the reader perspective. First submit the first # multiple-choice answer, then submit 'blah'. self.logout() exploration_dict = self.get_json( '%s/0' % feconf.EXPLORATION_INIT_URL_PREFIX) self.assertEqual(exploration_dict['title'], 'Welcome to Oppia!') state_name = exploration_dict['state_name'] exploration_dict = self.post_json( '%s/0/%s' % (feconf.EXPLORATION_TRANSITION_URL_PREFIX, state_name), { 'answer': '0', 'handler': 'submit', 'state_history': exploration_dict['state_history'], } ) state_name = exploration_dict['state_name'] self.post_json( '%s/0/%s' % (feconf.EXPLORATION_TRANSITION_URL_PREFIX, state_name), { 'answer': 'blah', 'handler': 'submit', 'state_history': exploration_dict['state_history'] } ) # Ensure that all events get propagated. self.process_and_flush_pending_tasks() # Now switch back to the editor perspective. self.login('*****@*****.**') editor_exploration_dict = self.get_json(EXPLORATION_STATISTICS_URL) self.assertEqual(editor_exploration_dict['num_starts'], 1) self.assertEqual(editor_exploration_dict['num_completions'], 0) # TODO(sll): Add more checks here. self.logout()
def setUp(self): super(AssetDevHandlerAudioTest, self).setUp() exp_services.delete_demo('0') self.system_user = user_services.get_system_user() exp_services.load_demo('0') rights_manager.release_ownership_of_exploration(self.system_user, '0') self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) mock_accepted_audio_extensions = { 'mp3': ['audio/mp3'], 'flac': ['audio/flac'] } self.accepted_audio_extensions_swap = self.swap( feconf, 'ACCEPTED_AUDIO_EXTENSIONS', mock_accepted_audio_extensions)
def get(self): if SPLASH_PAGE_EXPLORATION_ID.value: splash_exp_id = SPLASH_PAGE_EXPLORATION_ID.value if not exp_services.get_exploration_by_id( splash_exp_id, strict=False): exp_services.delete_demo(splash_exp_id) exp_services.load_demo(splash_exp_id) self.values.update({ 'BANNER_ALT_TEXT': BANNER_ALT_TEXT.value, 'SITE_FORUM_URL': SITE_FORUM_URL.value, 'SITE_NAME': SITE_NAME.value, 'SPLASH_PAGE_EXPLORATION_ID': SPLASH_PAGE_EXPLORATION_ID.value, 'SPLASH_PAGE_EXPLORATION_VERSION': ( SPLASH_PAGE_EXPLORATION_VERSION.value), }) self.render_template('pages/splash.html')
def _get_splash_page(self): if SPLASH_PAGE_EXPLORATION_ID.value: splash_exp_id = SPLASH_PAGE_EXPLORATION_ID.value if not exp_services.get_exploration_by_id( splash_exp_id, strict=False): exp_services.delete_demo(splash_exp_id) exp_services.load_demo(splash_exp_id) self.values.update({ 'BANNER_ALT_TEXT': BANNER_ALT_TEXT.value, 'SITE_FORUM_URL': pages.SITE_FORUM_URL.value, 'SITE_NAME': pages.SITE_NAME.value, 'SPLASH_PAGE_EXPLORATION_ID': SPLASH_PAGE_EXPLORATION_ID.value, 'SPLASH_PAGE_EXPLORATION_VERSION': ( SPLASH_PAGE_EXPLORATION_VERSION.value), }) self.render_template('pages/splash.html')
def test_give_feedback_handler(self): """Test giving feedback handler.""" viewer_email = '*****@*****.**' # Load demo exploration EXP_ID = '0' exp_services.delete_demo('0') exp_services.load_demo('0') # Viewer opens exploration self.login(viewer_email) exploration_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) state_name_1 = exploration_dict['state_name'] # Viewer gives 1st feedback self.post_json( '/explorehandler/give_feedback/%s' % EXP_ID, { 'state_name': state_name_1, 'feedback': 'This is a feedback message.', } ) # Viewer submits answer '0' exploration_dict = self.post_json( '%s/%s/%s' % (feconf.EXPLORATION_TRANSITION_URL_PREFIX, EXP_ID, state_name_1), { 'answer': '0', 'handler': 'submit', 'state_history': exploration_dict['state_history'] } ) state_name_2 = exploration_dict['state_name'] # Viewer gives 2nd feedback self.post_json( '/explorehandler/give_feedback/%s' % EXP_ID, { 'state_name': state_name_2, 'feedback': 'This is a 2nd feedback message.', } ) self.logout()
def setUp(self): super(FeedbackThreadPermissionsTests, self).setUp() self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) # Load exploration 0. exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) # Get the CSRF token and create a single thread with a single message. # The corresponding user has already registered as an editor, and has a # username. self.login(self.EDITOR_EMAIL) self.csrf_token = self.get_new_csrf_token() self.post_json('%s/%s' % ( feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID ), { 'subject': self._get_unicode_test_string('subject'), 'text': self._get_unicode_test_string('text'), }, csrf_token=self.csrf_token) self.logout()
def test_versioning_for_default_exploration(self): EXP_ID = '0' exp_services.delete_demo(EXP_ID) exp_services.load_demo(EXP_ID) # In version 2, change the initial state content. exploration = exp_services.get_exploration_by_id(EXP_ID) exp_services.update_exploration( '*****@*****.**', EXP_ID, [{ 'cmd': 'edit_state_property', 'property_name': 'content', 'state_name': exploration.init_state_name, 'new_value': [{ 'type': 'text', 'value': 'ABC' }], }], 'Change init state content') # The latest version contains 'ABC'. reader_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) self.assertIn('ABC', reader_dict['init_html']) self.assertNotIn('Hi, welcome to Oppia!', reader_dict['init_html']) # v1 contains 'Hi, welcome to Oppia!'. reader_dict = self.get_json( '%s/%s?v=1' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) self.assertIn('Hi, welcome to Oppia!', reader_dict['init_html']) self.assertNotIn('ABC', reader_dict['init_html']) # v2 contains 'ABC'. reader_dict = self.get_json( '%s/%s?v=2' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) self.assertIn('ABC', reader_dict['init_html']) self.assertNotIn('Hi, welcome to Oppia!', reader_dict['init_html']) # v3 does not exist. response = self.testapp.get( '%s/%s?v=3' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID), expect_errors=True) self.assertEqual(response.status_int, 404)
def test_creation_of_state_classifier_mapping(self): super(ExplorationStateClassifierMappingTests, self).setUp() exploration_id = '15' self.login(self.VIEWER_EMAIL) self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) exp_services.delete_demo(exploration_id) # We enable ENABLE_ML_CLASSIFIERS so that the subsequent call to # save_exploration handles job creation for trainable states. # Since only one demo exploration has a trainable state, we modify our # values for MIN_ASSIGNED_LABELS and MIN_TOTAL_TRAINING_EXAMPLES to let # the classifier_demo_exploration.yaml be trainable. This is # completely for testing purposes. with self.swap(feconf, 'ENABLE_ML_CLASSIFIERS', True): with self.swap(feconf, 'MIN_TOTAL_TRAINING_EXAMPLES', 5): with self.swap(feconf, 'MIN_ASSIGNED_LABELS', 1): exp_services.load_demo(exploration_id) # Retrieve job_id of created job (because of save_exp). all_jobs = classifier_models.ClassifierTrainingJobModel.get_all() self.assertEqual(all_jobs.count(), 1) for job in all_jobs: job_id = job.id classifier_services.store_classifier_data(job_id, {}) expected_state_classifier_mapping = { 'text': { 'algorithm_id': 'LDAStringClassifier', 'classifier_data': {}, 'data_schema_version': 1 } } # Call the handler. exploration_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, exploration_id)) retrieved_state_classifier_mapping = exploration_dict[ 'state_classifier_mapping'] self.assertEqual(expected_state_classifier_mapping, retrieved_state_classifier_mapping)
def init_player(self, exploration_id, expected_title, expected_response): """Starts a reader session and gets the first state from the server. `expected_response` will be interpreted as a regex string. """ exp_services.delete_demo(exploration_id) exp_services.load_demo(exploration_id) self.EXP_ID = exploration_id reader_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, self.EXP_ID)) self.last_params = reader_dict['params'] self.last_state_name = reader_dict['state_name'] self.state_history = [self.last_state_name] self.assertEqual(reader_dict['state_history'], self.state_history) self.assertRegexpMatches(reader_dict['init_html'], expected_response) self.assertEqual(reader_dict['title'], expected_title)
def init_player(self, exploration_id, expected_title, expected_response): """Starts a reader session and gets the first state from the server. `expected_response` will be interpreted as a regex string. """ exp_services.delete_demo(exploration_id) exp_services.load_demo(exploration_id) self.exp_id = exploration_id # pylint: disable=attribute-defined-outside-init reader_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, self.exp_id)) self.last_state_name = reader_dict['exploration']['init_state_name'] # pylint: disable=attribute-defined-outside-init init_state_data = ( reader_dict['exploration']['states'][self.last_state_name]) init_content = init_state_data['content'][0]['value'] self.assertRegexpMatches(init_content, expected_response) self.assertEqual(reader_dict['exploration']['title'], expected_title)
def test_editor_page(self): """Test access to editor pages for the sample exploration.""" exp_services.delete_demo('0') exp_services.load_demo('0') # Check that non-editors cannot access the editor page. response = self.testapp.get('/create/0') self.assertEqual(response.status_int, 302) # Register and login as an admin. self.register_editor('*****@*****.**') self.login('*****@*****.**', is_admin=True) # Check that it is now possible to access the editor page. response = self.testapp.get('/create/0') self.assertEqual(response.status_int, 200) self.assertIn('Exploration Metadata', response.body) # Test that the value generator JS is included. self.assertIn('RandomSelector', response.body) self.logout()
def test_give_feedback_handler(self): """Test giving feedback handler.""" self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME) # Load demo exploration exp_id = "0" exp_services.delete_demo("0") exp_services.load_demo("0") # Viewer opens exploration self.login(self.VIEWER_EMAIL) exploration_dict = self.get_json("%s/%s" % (feconf.EXPLORATION_INIT_URL_PREFIX, exp_id)) state_name_1 = exploration_dict["exploration"]["init_state_name"] # Viewer gives 1st feedback self.post_json( "/explorehandler/give_feedback/%s" % exp_id, {"state_name": state_name_1, "feedback": "This is a feedback message."}, ) self.logout()
def test_versioning_for_default_exploration(self): EXP_ID = '0' exp_services.delete_demo(EXP_ID) exp_services.load_demo(EXP_ID) # In version 2, change the initial state content. exploration = exp_services.get_exploration_by_id(EXP_ID) exp_services.update_exploration( '*****@*****.**', EXP_ID, [{ 'cmd': 'edit_state_property', 'property_name': 'content', 'state_name': exploration.init_state_name, 'new_value': [{'type': 'text', 'value': 'ABC'}], }], 'Change init state content') # The latest version contains 'ABC'. reader_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) self.assertIn('ABC', reader_dict['init_html']) self.assertNotIn('Hi, welcome to Oppia!', reader_dict['init_html']) # v1 contains 'Hi, welcome to Oppia!'. reader_dict = self.get_json( '%s/%s?v=1' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) self.assertIn('Hi, welcome to Oppia!', reader_dict['init_html']) self.assertNotIn('ABC', reader_dict['init_html']) # v2 contains 'ABC'. reader_dict = self.get_json( '%s/%s?v=2' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) self.assertIn('ABC', reader_dict['init_html']) self.assertNotIn('Hi, welcome to Oppia!', reader_dict['init_html']) # v3 does not exist. response = self.testapp.get( '%s/%s?v=3' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID), expect_errors=True) self.assertEqual(response.status_int, 404)
def test_user_banning(self): """Test that banned users are banned.""" EXP_ID = '0' exp_services.delete_demo(EXP_ID) exp_services.load_demo(EXP_ID) # Sign-up new editors Joe and Sandra. self.signup('*****@*****.**', 'joe') self.signup('*****@*****.**', 'sandra') # Joe logs in. self.login('*****@*****.**') response = self.testapp.get(feconf.GALLERY_URL) self.assertEqual(response.status_int, 200) response = self.testapp.get('/create/%s' % EXP_ID) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) # Ban joe. config_services.set_property(feconf.ADMIN_COMMITTER_ID, 'banned_usernames', ['joe']) # Test that Joe is banned. (He can still access the gallery.) response = self.testapp.get(feconf.GALLERY_URL, expect_errors=True) self.assertEqual(response.status_int, 200) response = self.testapp.get('/create/%s' % EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 200) self.assert_cannot_edit(response.body) # Joe logs out. self.logout() # Sandra logs in and is unaffected. self.login('*****@*****.**') response = self.testapp.get('/create/%s' % EXP_ID) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) self.logout()
def test_give_feedback_handler(self): """Test giving feedback handler.""" viewer_email = '*****@*****.**' # Load demo exploration EXP_ID = '0' exp_services.delete_demo('0') exp_services.load_demo('0') # Viewer opens exploration self.login(viewer_email) exploration_dict = self.get_json( '%s/%s' % (feconf.EXPLORATION_INIT_URL_PREFIX, EXP_ID)) state_name_1 = exploration_dict['state_name'] # Viewer gives 1st feedback self.post_json( '/explorehandler/give_feedback/%s' % EXP_ID, { 'state_name': state_name_1, 'feedback': 'This is a feedback message.', }) # Viewer submits answer '0' exploration_dict = self.post_json( '%s/%s/%s' % (feconf.EXPLORATION_TRANSITION_URL_PREFIX, EXP_ID, state_name_1), { 'answer': '0', 'handler': 'submit', 'state_history': exploration_dict['state_history'] }) state_name_2 = exploration_dict['state_name'] # Viewer gives 2nd feedback self.post_json( '/explorehandler/give_feedback/%s' % EXP_ID, { 'state_name': state_name_2, 'feedback': 'This is a 2nd feedback message.', }) self.logout()
def test_editor_page(self): """Test access to editor pages for the sample exploration.""" exp_services.delete_demo('0') exp_services.load_demo('0') # Check that non-editors cannot access the editor page. response = self.testapp.get('/create/0') self.assertEqual(response.status_int, 302) # Register and login as an editor. self.register_editor('*****@*****.**') self.login('*****@*****.**') # Check that it is now possible to access the editor page. response = self.testapp.get('/create/0') self.assertEqual(response.status_int, 200) self.assertIn('Stats', response.body) self.assertIn('History', response.body) # Test that the value generator JS is included. self.assertIn('RandomSelector', response.body) self.logout()
def test_user_banning(self): """Test that banned users are banned.""" EXP_ID = '0' exp_services.delete_demo(EXP_ID) exp_services.load_demo(EXP_ID) # Register new editors Joe and Sandra. self.register_editor('*****@*****.**', username='******') self.register_editor('*****@*****.**', username='******') # Joe logs in. self.login('*****@*****.**') response = self.testapp.get('/contribute', expect_errors=True) self.assertEqual(response.status_int, 200) response = self.testapp.get('/create/%s' % EXP_ID) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) # Ban joe. config_services.set_property( feconf.ADMIN_COMMITTER_ID, 'banned_usernames', ['joe']) # Test that Joe is banned. response = self.testapp.get('/contribute', expect_errors=True) self.assertEqual(response.status_int, 401) response = self.testapp.get('/create/%s' % EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 200) self.assert_cannot_edit(response.body) # Joe logs out. self.logout() # Sandra logs in and is unaffected. self.login('*****@*****.**') response = self.testapp.get('/create/%s' % EXP_ID) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) self.logout()
def setUp(self): super(FeedbackThreadPermissionsTests, self).setUp() self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME) # Load exploration 0. exp_services.delete_demo(self.EXP_ID) exp_services.load_demo(self.EXP_ID) # Get the CSRF token and create a single thread with a single message. # The corresponding user has already registered as an editor, and has a # username. self.login(self.EDITOR_EMAIL) response = self.testapp.get('/create/%s' % self.EXP_ID) self.csrf_token = self.get_csrf_token_from_response(response) self.post_json('%s/%s' % ( feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID), { 'state_name': self._get_unicode_test_string('statename'), 'subject': self._get_unicode_test_string('subject'), 'text': self._get_unicode_test_string('text'), }, self.csrf_token) self.logout()
def test_user_banning(self): """Test that banned users are banned.""" EXP_ID = '0' exp_services.delete_demo(EXP_ID) exp_services.load_demo(EXP_ID) # Sign-up new editors Joe and Sandra. self.signup('*****@*****.**', 'joe') self.signup('*****@*****.**', 'sandra') # Joe logs in. self.login('*****@*****.**') response = self.testapp.get(feconf.GALLERY_URL) self.assertEqual(response.status_int, 200) response = self.testapp.get('/create/%s' % EXP_ID) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) # Ban joe. config_services.set_property( feconf.SYSTEM_COMMITTER_ID, 'banned_usernames', ['joe']) # Test that Joe is banned. (He can still access the gallery.) response = self.testapp.get(feconf.GALLERY_URL, expect_errors=True) self.assertEqual(response.status_int, 200) response = self.testapp.get('/create/%s' % EXP_ID, expect_errors=True) self.assertEqual(response.status_int, 200) self.assert_cannot_edit(response.body) # Joe logs out. self.logout() # Sandra logs in and is unaffected. self.login('*****@*****.**') response = self.testapp.get('/create/%s' % EXP_ID) self.assertEqual(response.status_int, 200) self.assert_can_edit(response.body) self.logout()
def test_resolved_answers_handler(self): exp_services.delete_demo('0') exp_services.load_demo('0') # In the reader perspective, submit the first multiple-choice answer, # then submit 'blah' once, 'blah2' twice and 'blah3' three times. # TODO(sll): Use the ExplorationPlayer in reader_test for this. exploration_dict = self.get_json( '%s/0' % feconf.EXPLORATION_INIT_URL_PREFIX) self.assertEqual( exploration_dict['exploration']['title'], 'Welcome to Oppia!') state_name = exploration_dict['exploration']['init_state_name'] result_dict = self.submit_answer('0', state_name, '0') state_name = result_dict['state_name'] self.submit_answer('0', state_name, 'blah') for _ in range(2): self.submit_answer('0', state_name, 'blah2') for _ in range(3): self.submit_answer('0', state_name, 'blah3') # Log in as an editor. self.login(self.EDITOR_EMAIL) response = self.testapp.get('/create/0') csrf_token = self.get_csrf_token_from_response(response) url = str('/createhandler/resolved_answers/0/%s' % state_name) def _get_unresolved_answers(): return stats_domain.StateRuleAnswerLog.get( '0', state_name, exp_domain.DEFAULT_RULESPEC_STR ).answers self.assertEqual( _get_unresolved_answers(), {'blah': 1, 'blah2': 2, 'blah3': 3}) # An empty request should result in an error. response_dict = self.put_json( url, {'something_else': []}, csrf_token, expect_errors=True, expected_status_int=400) self.assertIn('Expected a list', response_dict['error']) # A request of the wrong type should result in an error. response_dict = self.put_json( url, {'resolved_answers': 'this_is_a_string'}, csrf_token, expect_errors=True, expected_status_int=400) self.assertIn('Expected a list', response_dict['error']) # Trying to remove an answer that wasn't submitted has no effect. response_dict = self.put_json( url, {'resolved_answers': ['not_submitted_answer']}, csrf_token) self.assertEqual( _get_unresolved_answers(), {'blah': 1, 'blah2': 2, 'blah3': 3}) # A successful request should remove the answer in question. response_dict = self.put_json( url, {'resolved_answers': ['blah']}, csrf_token) self.assertEqual( _get_unresolved_answers(), {'blah2': 2, 'blah3': 3}) # It is possible to remove more than one answer at a time. response_dict = self.put_json( url, {'resolved_answers': ['blah2', 'blah3']}, csrf_token) self.assertEqual(_get_unresolved_answers(), {}) self.logout()
def _initialize(self): exp_services.delete_demo('0') exp_services.load_demo('0') self.register_editor(self.EDITOR_EMAIL)
def test_resolved_answers_handler(self): exp_services.delete_demo('0') exp_services.load_demo('0') # In the reader perspective, submit the first multiple-choice answer, # then submit 'blah' once, 'blah2' twice and 'blah3' three times. # TODO(sll): Use the ExplorationPlayer in reader_test for this. exploration_dict = self.get_json('%s/0' % feconf.EXPLORATION_INIT_URL_PREFIX) self.assertEqual(exploration_dict['exploration']['title'], 'Welcome to Oppia!') state_name = exploration_dict['exploration']['init_state_name'] exploration_dict = self.submit_answer('0', state_name, '0') state_name = exploration_dict['state_name'] self.submit_answer('0', state_name, 'blah') for _ in range(2): self.submit_answer('0', state_name, 'blah2') for _ in range(3): self.submit_answer('0', state_name, 'blah3') # Log in as an editor. self.login(self.EDITOR_EMAIL) response = self.testapp.get('/create/0') csrf_token = self.get_csrf_token_from_response(response) url = str('/createhandler/resolved_answers/0/%s' % state_name) def _get_unresolved_answers(): return stats_domain.StateRuleAnswerLog.get( '0', state_name, feconf.SUBMIT_HANDLER_NAME, exp_domain.DEFAULT_RULESPEC_STR).answers self.assertEqual(_get_unresolved_answers(), { 'blah': 1, 'blah2': 2, 'blah3': 3 }) # An empty request should result in an error. response_dict = self.put_json(url, {'something_else': []}, csrf_token, expect_errors=True, expected_status_int=400) self.assertIn('Expected a list', response_dict['error']) # A request of the wrong type should result in an error. response_dict = self.put_json(url, {'resolved_answers': 'this_is_a_string'}, csrf_token, expect_errors=True, expected_status_int=400) self.assertIn('Expected a list', response_dict['error']) # Trying to remove an answer that wasn't submitted has no effect. response_dict = self.put_json( url, {'resolved_answers': ['not_submitted_answer']}, csrf_token) self.assertEqual(_get_unresolved_answers(), { 'blah': 1, 'blah2': 2, 'blah3': 3 }) # A successful request should remove the answer in question. response_dict = self.put_json(url, {'resolved_answers': ['blah']}, csrf_token) self.assertEqual(_get_unresolved_answers(), {'blah2': 2, 'blah3': 3}) # It is possible to remove more than one answer at a time. response_dict = self.put_json(url, {'resolved_answers': ['blah2', 'blah3']}, csrf_token) self.assertEqual(_get_unresolved_answers(), {}) self.logout()
def test_add_new_state_error_cases(self): """Test the error cases for adding a new state to an exploration.""" exp_services.delete_demo('0') exp_services.load_demo('0') CURRENT_VERSION = 1 self.login(self.EDITOR_EMAIL) response = self.testapp.get('/create/0') csrf_token = self.get_csrf_token_from_response(response) def _get_payload(new_state_name, version=None): result = { 'change_list': [{ 'cmd': 'add_state', 'state_name': new_state_name }], 'commit_message': 'Add new state', } if version is not None: result['version'] = version return result def _put_and_expect_400_error(payload): return self.put_json('/createhandler/data/0', payload, csrf_token, expect_errors=True, expected_status_int=400) # A request with no version number is invalid. response_dict = _put_and_expect_400_error(_get_payload('New state')) self.assertIn('a version must be specified', response_dict['error']) # A request with the wrong version number is invalid. response_dict = _put_and_expect_400_error( _get_payload('New state', 123)) self.assertIn('which is too old', response_dict['error']) # A request with an empty state name is invalid. response_dict = _put_and_expect_400_error( _get_payload('', CURRENT_VERSION)) self.assertIn('should be between 1 and 50', response_dict['error']) # A request with a really long state name is invalid. response_dict = _put_and_expect_400_error( _get_payload('a' * 100, CURRENT_VERSION)) self.assertIn('should be between 1 and 50', response_dict['error']) # A request with a state name containing invalid characters is # invalid. response_dict = _put_and_expect_400_error( _get_payload('[Bad State Name]', CURRENT_VERSION)) self.assertIn('Invalid character [', response_dict['error']) # A request with a state name of feconf.END_DEST is invalid. response_dict = _put_and_expect_400_error( _get_payload(feconf.END_DEST, CURRENT_VERSION)) self.assertIn('Invalid state name', response_dict['error']) # Even if feconf.END_DEST is mixed case, it is still invalid. response_dict = _put_and_expect_400_error( _get_payload('eNd', CURRENT_VERSION)) self.assertEqual('eNd'.lower(), feconf.END_DEST.lower()) self.assertIn('Invalid state name', response_dict['error']) # A name cannot have spaces at the front or back. response_dict = _put_and_expect_400_error( _get_payload(' aa', CURRENT_VERSION)) self.assertIn('start or end with whitespace', response_dict['error']) response_dict = _put_and_expect_400_error( _get_payload('aa\t', CURRENT_VERSION)) self.assertIn('end with whitespace', response_dict['error']) response_dict = _put_and_expect_400_error( _get_payload('\n', CURRENT_VERSION)) self.assertIn('end with whitespace', response_dict['error']) # A name cannot have consecutive whitespace. response_dict = _put_and_expect_400_error( _get_payload('The B', CURRENT_VERSION)) self.assertIn('Adjacent whitespace', response_dict['error']) response_dict = _put_and_expect_400_error( _get_payload('The\t\tB', CURRENT_VERSION)) self.assertIn('Adjacent whitespace', response_dict['error']) self.logout()
def setUp(self): super(RatingsIntegrationTests, self).setUp() self.EXP_ID = '0' exp_services.delete_demo('0') exp_services.load_demo('0')
def post(self): """Reloads the default explorations.""" if self.payload.get('action') == 'reload_exploration': exploration_id = self.payload.get('explorationId') exp_services.delete_demo(str(exploration_id)) exp_services.load_demo(str(exploration_id))
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(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_add_new_state_error_cases(self): """Test the error cases for adding a new state to an exploration.""" exp_services.delete_demo('0') exp_services.load_demo('0') CURRENT_VERSION = 1 self.login(self.EDITOR_EMAIL) response = self.testapp.get('/create/0') csrf_token = self.get_csrf_token_from_response(response) def _get_payload(new_state_name, version=None): result = { 'change_list': [{ 'cmd': 'add_state', 'state_name': new_state_name }], 'commit_message': 'Add new state', } if version is not None: result['version'] = version return result def _put_and_expect_400_error(payload): return self.put_json( '/createhandler/data/0', payload, csrf_token, expect_errors=True, expected_status_int=400) # A request with no version number is invalid. response_dict = _put_and_expect_400_error(_get_payload('New state')) self.assertIn('a version must be specified', response_dict['error']) # A request with the wrong version number is invalid. response_dict = _put_and_expect_400_error( _get_payload('New state', 123)) self.assertIn('which is too old', response_dict['error']) # A request with an empty state name is invalid. response_dict = _put_and_expect_400_error( _get_payload('', CURRENT_VERSION)) self.assertIn('should be between 1 and 50', response_dict['error']) # A request with a really long state name is invalid. response_dict = _put_and_expect_400_error( _get_payload('a' * 100, CURRENT_VERSION)) self.assertIn('should be between 1 and 50', response_dict['error']) # A request with a state name containing invalid characters is # invalid. response_dict = _put_and_expect_400_error( _get_payload('[Bad State Name]', CURRENT_VERSION)) self.assertIn('Invalid character [', response_dict['error']) # A name cannot have spaces at the front or back. response_dict = _put_and_expect_400_error( _get_payload(' aa', CURRENT_VERSION)) self.assertIn('start or end with whitespace', response_dict['error']) response_dict = _put_and_expect_400_error( _get_payload('aa\t', CURRENT_VERSION)) self.assertIn('end with whitespace', response_dict['error']) response_dict = _put_and_expect_400_error( _get_payload('\n', CURRENT_VERSION)) self.assertIn('end with whitespace', response_dict['error']) # A name cannot have consecutive whitespace. response_dict = _put_and_expect_400_error( _get_payload('The B', CURRENT_VERSION)) self.assertIn('Adjacent whitespace', response_dict['error']) response_dict = _put_and_expect_400_error( _get_payload('The\t\tB', CURRENT_VERSION)) self.assertIn('Adjacent whitespace', response_dict['error']) self.logout()