def get(self): interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.ADDITIONAL_DEPENDENCY_IDS)) interaction_templates = ( interaction_registry.Registry.get_interaction_html( interaction_ids)) self.values.update({ 'allow_yaml_file_upload': feconf.ALLOW_YAML_FILE_UPLOAD, 'DEFAULT_TWITTER_SHARE_MESSAGE_DASHBOARD': ( DEFAULT_TWITTER_SHARE_MESSAGE_DASHBOARD.value), 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'ALLOWED_INTERACTION_CATEGORIES': ( feconf.ALLOWED_INTERACTION_CATEGORIES), 'additional_angular_modules': additional_angular_modules, 'interaction_templates': jinja2.utils.Markup( interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html) }) self.render_template( 'pages/creator_dashboard/creator_dashboard.html', redirect_url_on_logout='/')
def get(self): interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.ADDITIONAL_DEPENDENCY_IDS)) interaction_templates = (interaction_registry.Registry. get_interaction_html(interaction_ids)) self.values.update({ 'DEFAULT_TWITTER_SHARE_MESSAGE_DASHBOARD': (DEFAULT_TWITTER_SHARE_MESSAGE_DASHBOARD.value), 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'additional_angular_modules': additional_angular_modules, 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html) }) self.render_template('dist/creator_dashboard.html')
def get(self, skill_id): """Handles GET requests.""" skill_domain.Skill.require_valid_skill_id(skill_id) skill = skill_services.get_skill_by_id(skill_id, strict=False) if skill is None: raise self.PageNotFoundException( Exception('The skill with the given id doesn\'t exist.')) interaction_ids = feconf.ALLOWED_QUESTION_INTERACTION_IDS interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = ( interaction_registry.Registry.get_interaction_html( interaction_ids)) self.values.update({ 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'additional_angular_modules': additional_angular_modules, 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'interaction_templates': jinja2.utils.Markup( interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html) }) self.render_template('dist/skill-editor-page.mainpage.html')
def get(self, topic_name): """Handles GET requests.""" if not constants.ENABLE_NEW_STRUCTURE_PLAYERS: raise self.PageNotFoundException # Topic cannot be None as an exception will be thrown from its decorator # if so. topic = topic_services.get_topic_by_name(topic_name) interaction_ids = feconf.ALLOWED_QUESTION_INTERACTION_IDS interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids)) interaction_templates = ( interaction_registry.Registry.get_interaction_html( interaction_ids)) self.values.update({ 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'additional_angular_modules': additional_angular_modules, 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'interaction_templates': jinja2.utils.Markup( interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'topic_name': topic.name, }) self.render_template('dist/practice-session-page.mainpage.html')
def get(self, story_id): """Handles GET requests.""" if not constants.ENABLE_NEW_STRUCTURE_PLAYERS: raise self.PageNotFoundException story = story_services.get_story_by_id(story_id) interaction_ids = feconf.ALLOWED_QUESTION_INTERACTION_IDS interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids)) interaction_templates = (interaction_registry.Registry. get_interaction_html(interaction_ids)) self.values.update({ 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'additional_angular_modules': additional_angular_modules, 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'story_name': story.title }) self.render_template('dist/review-test-page.mainpage.html')
def get(self, topic_name): """Handles GET requests.""" if not constants.ENABLE_NEW_STRUCTURE_PLAYERS: raise self.PageNotFoundException topic = topic_services.get_topic_by_name(topic_name) if topic is None: raise self.PageNotFoundException( Exception('The topic with the given name doesn\'t exist.')) interaction_ids = feconf.ALLOWED_QUESTION_INTERACTION_IDS interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids)) interaction_templates = ( interaction_registry.Registry.get_interaction_html( interaction_ids)) self.values.update({ 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'additional_angular_modules': additional_angular_modules, 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'interaction_templates': jinja2.utils.Markup( interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'topic_name': topic.name, }) self.render_template('dist/practice_session.html')
def test_get_object_default_values_is_valid(self): """Checks that the default values provided by get_default_values() correspond to the ones defined in objects.py. """ object_default_vals = obj_services.get_default_object_values() all_object_classes = obj_services.Registry.get_all_object_classes() for (obj_type, default_value) in object_default_vals.iteritems(): self.assertIn(obj_type, all_object_classes) self.assertEqual(default_value, all_object_classes[obj_type].default_value)
def test_get_object_default_values_is_valid(self): """Checks that the default values provided by get_default_values() correspond to the ones defined in objects.py. """ object_default_vals = obj_services.get_default_object_values() all_object_classes = obj_services.Registry.get_all_object_classes() for (obj_type, default_value) in object_default_vals.iteritems(): self.assertIn(obj_type, all_object_classes) self.assertEqual( default_value, all_object_classes[obj_type].default_value)
def get(self, topic_id): """Handles GET requests.""" if not feconf.ENABLE_NEW_STRUCTURES: raise self.PageNotFoundException topic_domain.Topic.require_valid_topic_id(topic_id) topic = topic_services.get_topic_by_id(topic_id, strict=False) if topic is None: raise self.PageNotFoundException( Exception('The topic with the given id doesn\'t exist.')) interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = (interaction_registry.Registry. get_interaction_html(interaction_ids)) self.values.update({ 'topic_id': topic.id, 'topic_name': topic.name, 'nav_mode': feconf.NAV_MODE_TOPIC_EDITOR, 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'additional_angular_modules': additional_angular_modules, 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'ALLOWED_INTERACTION_CATEGORIES': (feconf.ALLOWED_INTERACTION_CATEGORIES) }) self.render_template('pages/topic_editor/topic_editor.html', redirect_url_on_logout='/')
def get(self, skill_id): """Handles GET requests.""" if not constants.ENABLE_NEW_STRUCTURE_EDITORS: raise self.PageNotFoundException skill_domain.Skill.require_valid_skill_id(skill_id) skill = skill_services.get_skill_by_id(skill_id, strict=False) if skill is None: raise self.PageNotFoundException( Exception('The skill with the given id doesn\'t exist.')) interaction_ids = feconf.ALLOWED_QUESTION_INTERACTION_IDS interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = (interaction_registry.Registry. get_interaction_html(interaction_ids)) self.values.update({ 'skill_id': skill.id, 'nav_mode': feconf.NAV_MODE_CREATE, 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'additional_angular_modules': additional_angular_modules, 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'ALLOWED_INTERACTION_CATEGORIES': (feconf.ALLOWED_QUESTION_INTERACTION_CATEGORIES) }) self.render_template('pages/skill_editor/skill_editor.html', redirect_url_on_logout='/')
def test_all_rule_input_fields_have_default_values(self): """Checks that all rule input fields have a default value, and this is provided in get_default_values(). """ interactions = interaction_registry.Registry.get_all_interactions() object_default_vals = obj_services.get_default_object_values() for interaction in interactions: for rule_name in interaction.rules_dict: param_list = interaction.get_rule_param_list(rule_name) for (_, param_obj_type) in param_list: param_obj_type_name = param_obj_type.__name__ default_value = param_obj_type.default_value self.assertIsNotNone( default_value, msg=( 'No default value specified for object class %s.' % param_obj_type_name)) self.assertIn(param_obj_type_name, object_default_vals) self.assertEqual( default_value, object_default_vals[param_obj_type_name])
def test_all_rule_input_fields_have_default_values(self): """Checks that all rule input fields have a default value, and this is provided in get_default_values(). """ interactions = interaction_registry.Registry.get_all_interactions() object_default_vals = obj_services.get_default_object_values() for interaction in interactions: for rule_name in interaction.rules_dict: param_list = interaction.get_rule_param_list(rule_name) for (_, param_obj_type) in param_list: param_obj_type_name = param_obj_type.__name__ default_value = param_obj_type.default_value self.assertIsNotNone( default_value, msg=( 'No default value specified for object class %s.' % param_obj_type_name)) self.assertIn(param_obj_type_name, object_default_vals) self.assertEqual(default_value, object_default_vals[param_obj_type_name])
def get(self, exploration_id): """Handles GET requests.""" if exploration_id in constants.DISABLED_EXPLORATION_IDS: self.render_template('pages/error/disabled_exploration.html', iframe_restriction=None) return (exploration, exploration_rights) = ( exp_services.get_exploration_and_exploration_rights_by_id( exploration_id)) visualizations_html = visualization_registry.Registry.get_full_html() interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = (interaction_registry.Registry. get_interaction_html(interaction_ids)) self.values.update({ 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR': (DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR.value), 'additional_angular_modules': additional_angular_modules, 'can_delete': rights_manager.check_can_delete_activity(self.user, exploration_rights), 'can_edit': rights_manager.check_can_edit_activity(self.user, exploration_rights), 'can_modify_roles': (rights_manager.check_can_modify_activity_roles( self.user, exploration_rights)), 'can_publish': rights_manager.check_can_publish_activity(self.user, exploration_rights), 'can_release_ownership': (rights_manager.check_can_release_ownership( self.user, exploration_rights)), 'can_unpublish': rights_manager.check_can_unpublish_activity( self.user, exploration_rights), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'meta_description': feconf.CREATE_PAGE_DESCRIPTION, 'nav_mode': feconf.NAV_MODE_CREATE, 'value_generators_js': jinja2.utils.Markup(get_value_generators_js()), 'title': exploration.title, 'visualizations_html': jinja2.utils.Markup(visualizations_html), 'ALLOWED_INTERACTION_CATEGORIES': (feconf.ALLOWED_INTERACTION_CATEGORIES), 'INVALID_PARAMETER_NAMES': feconf.INVALID_PARAMETER_NAMES, 'NEW_STATE_TEMPLATE': NEW_STATE_TEMPLATE, 'SHOW_TRAINABLE_UNRESOLVED_ANSWERS': (feconf.SHOW_TRAINABLE_UNRESOLVED_ANSWERS), 'TAG_REGEX': feconf.TAG_REGEX, }) self.render_template( 'pages/exploration_editor/exploration_editor.html', redirect_url_on_logout=( '%s/%s' % (feconf.EDITOR_URL_PREFIX, exploration_id)))
def test_default_interactions_are_valid(self): """Test that the default interactions are valid.""" all_interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) for interaction_id in all_interaction_ids: # Check that the interaction id is valid. self.assertTrue(self._is_camel_cased(interaction_id)) # Check that the interaction directory exists. interaction_dir = os.path.join( feconf.INTERACTIONS_DIR, interaction_id) self.assertTrue(os.path.isdir(interaction_dir)) # In this directory there should only be a config .py file, an # html file, a JS file, a validator.js file, a directory named # 'static' that contains (at least) a .png thumbnail file, # (optionally) a JS test spec file, (optionally) a JS test spec # file for rules, (optionally) a stats_response.html file and # (optionally) a protractor.js file. dir_contents = self._listdir_omit_ignored(interaction_dir) optional_dirs_and_files_count = 0 try: self.assertTrue(os.path.isfile( os.path.join(interaction_dir, 'stats_response.html'))) optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, '%sSpec.js' % interaction_id))) optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, 'validatorSpec.js'))) optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, '%sRulesServiceSpec.js' % interaction_id))) optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, 'protractor.js'))) optional_dirs_and_files_count += 1 except Exception: pass self.assertEqual( optional_dirs_and_files_count + 5, len(dir_contents), dir_contents ) py_file = os.path.join(interaction_dir, '%s.py' % interaction_id) html_file = os.path.join( interaction_dir, '%s.html' % interaction_id) js_file = os.path.join(interaction_dir, '%s.js' % interaction_id) validator_js_file = os.path.join(interaction_dir, 'validator.js') self.assertTrue(os.path.isfile(py_file)) self.assertTrue(os.path.isfile(html_file)) self.assertTrue(os.path.isfile(js_file)) # Check that the PNG thumbnail image has the correct dimensions. static_dir = os.path.join(interaction_dir, 'static') self.assertTrue(os.path.isdir(static_dir)) png_file = os.path.join( interaction_dir, 'static', '%s.png' % interaction_id) self.assertTrue(os.path.isfile(png_file)) with open(png_file, 'rb') as f: img_data = f.read() width, height = struct.unpack('>LL', img_data[16:24]) self.assertEqual(int(width), INTERACTION_THUMBNAIL_WIDTH_PX) self.assertEqual(int(height), INTERACTION_THUMBNAIL_HEIGHT_PX) js_file_content = utils.get_file_contents(js_file) html_file_content = utils.get_file_contents(html_file) validator_js_file_content = utils.get_file_contents( validator_js_file) self.assertIn( 'oppiaInteractive%s' % interaction_id, js_file_content) self.assertIn('oppiaResponse%s' % interaction_id, js_file_content) directive_prefix = '<script type="text/ng-template"' self.assertIn( '%s id="interaction/%s"' % (directive_prefix, interaction_id), html_file_content) self.assertIn( '%s id="response/%s"' % (directive_prefix, interaction_id), html_file_content) # Check that the html template includes js script for the # interaction. self.assertIn( '<script src="{{cache_slug}}/extensions/interactions/%s/%s.js">' '</script>' % (interaction_id, interaction_id), html_file_content) self.assertIn( '<script src="{{cache_slug}}/extensions/interactions/%s/' 'validator.js"></script>' % interaction_id, html_file_content) self.assertNotIn('<script>', js_file_content) self.assertNotIn('</script>', js_file_content) self.assertIn( 'oppiaInteractive%sValidator' % interaction_id, validator_js_file_content) self.assertNotIn('<script>', validator_js_file_content) self.assertNotIn('</script>', validator_js_file_content) interaction = interaction_registry.Registry.get_interaction_by_id( interaction_id) # Check that the specified interaction id is the same as the class # name. self.assertTrue(interaction_id, interaction.__class__.__name__) # Check that the configuration file contains the correct # top-level keys, and that these keys have the correct types. for item, item_type in _INTERACTION_CONFIG_SCHEMA: self.assertTrue(isinstance( getattr(interaction, item), item_type)) if item_type == basestring: self.assertTrue(getattr(interaction, item)) self.assertIn(interaction.display_mode, base.ALLOWED_DISPLAY_MODES) if interaction.is_linear or interaction.is_terminal: self.assertIsNone(interaction.answer_type) else: # Check that the answer_type corresponds to a valid object # class. obj_services.Registry.get_object_class_by_type( interaction.answer_type) self._validate_customization_arg_specs( interaction._customization_arg_specs) # pylint: disable=protected-access self._validate_dependencies(interaction.dependency_ids) # Check that supplemental interactions have instructions, and # inline ones do not. if interaction.display_mode == base.DISPLAY_MODE_INLINE: self.assertIsNone(interaction.instructions) self.assertIsNone(interaction.narrow_instructions) else: self.assertTrue( isinstance(interaction.instructions, basestring)) self.assertIsNotNone(interaction.instructions) self.assertIsNotNone(interaction.narrow_instructions) # Check that terminal interactions are not linear. if interaction.is_terminal: self.assertFalse(interaction.is_linear) # Check that only linear interactions have a # default_outcome_heading property. if interaction.is_linear: self.assertTrue( isinstance(interaction.default_outcome_heading, basestring) and interaction.default_outcome_heading) else: self.assertIsNone(interaction.default_outcome_heading) default_object_values = obj_services.get_default_object_values() # Check that the rules for this interaction have object editor # templates and default values. for rule_name, rule_dict in interaction.rules_dict.iteritems(): param_list = interaction.get_rule_param_list(rule_name) for (_, param_obj_cls) in param_list: # TODO(sll): Get rid of these special cases. if param_obj_cls.__name__ in [ 'NonnegativeInt', 'ListOfGraph', 'ListOfCoordTwoDim', 'SetOfNormalizedString']: continue # Check that the rule has an object editor template. self.assertTrue( param_obj_cls.has_editor_js_template(), msg='(%s)' % rule_dict['description']) # Check that the rule has a default value. self.assertIn( param_obj_cls.__name__, default_object_values)
def get(self, exploration_id): """Handles GET requests.""" if exploration_id in feconf.DISABLED_EXPLORATION_IDS: self.render_template('error/disabled_exploration.html', iframe_restriction=None) return exploration = exp_services.get_exploration_by_id(exploration_id, strict=False) if (exploration is None or not rights_manager.Actor(self.user_id).can_view( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)): self.redirect('/') return can_edit = (bool(self.user_id) and self.username not in config_domain.BANNED_USERNAMES.value and rights_manager.Actor(self.user_id).can_edit( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)) interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = ( rte_component_registry.Registry.get_html_for_all_components() + interaction_registry.Registry.get_interaction_html(interaction_ids) ) interaction_validators_html = ( interaction_registry.Registry.get_validators_html(interaction_ids)) gadget_types = gadget_registry.Registry.get_all_gadget_types() gadget_templates = ( gadget_registry.Registry.get_gadget_html(gadget_types)) self.values.update({ 'GADGET_SPECS': gadget_registry.Registry.get_all_specs(), 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'PANEL_SPECS': feconf.PANELS_PROPERTIES, 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR': (DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR.value), 'additional_angular_modules': additional_angular_modules, 'can_delete': rights_manager.Actor(self.user_id).can_delete( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_edit': can_edit, 'can_modify_roles': rights_manager.Actor(self.user_id).can_modify_roles( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_publicize': rights_manager.Actor(self.user_id).can_publicize( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_publish': rights_manager.Actor(self.user_id).can_publish( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_release_ownership': rights_manager.Actor(self.user_id).can_release_ownership( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_unpublicize': rights_manager.Actor(self.user_id).can_unpublicize( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_unpublish': rights_manager.Actor(self.user_id).can_unpublish( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'gadget_templates': jinja2.utils.Markup(gadget_templates), 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'interaction_validators_html': jinja2.utils.Markup(interaction_validators_html), 'meta_description': feconf.CREATE_PAGE_DESCRIPTION, 'nav_mode': feconf.NAV_MODE_CREATE, 'value_generators_js': jinja2.utils.Markup(get_value_generators_js()), 'title': exploration.title, 'ALL_LANGUAGE_CODES': feconf.ALL_LANGUAGE_CODES, 'ALLOWED_GADGETS': feconf.ALLOWED_GADGETS, 'ALLOWED_INTERACTION_CATEGORIES': (feconf.ALLOWED_INTERACTION_CATEGORIES), 'INVALID_PARAMETER_NAMES': feconf.INVALID_PARAMETER_NAMES, 'NEW_STATE_TEMPLATE': NEW_STATE_TEMPLATE, 'SHOW_TRAINABLE_UNRESOLVED_ANSWERS': (feconf.SHOW_TRAINABLE_UNRESOLVED_ANSWERS), 'TAG_REGEX': feconf.TAG_REGEX, }) self.render_template('exploration_editor/exploration_editor.html')
def get(self, exploration_id): """Handles GET requests.""" exploration_rights = rights_manager.get_exploration_rights( exploration_id) interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = (interaction_registry.Registry. get_interaction_html(interaction_ids)) self.values.update({ 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR': (DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR.value), 'additional_angular_modules': additional_angular_modules, 'can_delete': rights_manager.check_can_delete_activity(self.user, exploration_rights), 'can_edit': rights_manager.check_can_edit_activity(self.user, exploration_rights), 'can_modify_roles': (rights_manager.check_can_modify_activity_roles( self.user, exploration_rights)), 'can_publish': rights_manager.check_can_publish_activity(self.user, exploration_rights), 'can_release_ownership': (rights_manager.check_can_release_ownership( self.user, exploration_rights)), 'can_voiceover': (rights_manager.check_can_voiceover_activity( self.user, exploration_rights)), 'can_unpublish': rights_manager.check_can_unpublish_activity( self.user, exploration_rights), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'interaction_templates': jinja2.utils.Markup(interaction_templates), 'meta_description': feconf.CREATE_PAGE_DESCRIPTION, 'INVALID_PARAMETER_NAMES': feconf.INVALID_PARAMETER_NAMES, 'SHOW_TRAINABLE_UNRESOLVED_ANSWERS': (feconf.SHOW_TRAINABLE_UNRESOLVED_ANSWERS), 'TAG_REGEX': feconf.TAG_REGEX, }) self.render_template('dist/exploration-editor-page.mainpage.html')
def test_default_interactions_are_valid(self): """Test that the default interactions are valid.""" all_interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) for interaction_id in all_interaction_ids: # Check that the interaction id is valid. self.assertTrue(self._is_camel_cased(interaction_id)) # Check that the interaction directory exists. interaction_dir = os.path.join( feconf.INTERACTIONS_DIR, interaction_id) self.assertTrue(os.path.isdir(interaction_dir)) # The interaction directory should contain the following files: # Required: # * A python file called {InteractionName}.py. # * An __init__.py file used to import the Python file. # * A TypeScript file called {InteractionName}.ts. # * A directory name 'directives' containing TS and HTML files # for directives # * A directory named 'static' containing at least a .png file. # Optional: # * A JS file called protractor.js. interaction_dir_contents = ( self._listdir_omit_ignored(interaction_dir)) interaction_dir_optional_dirs_and_files_count = 0 try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, 'protractor.js'))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, '%sPredictionService.ts' % interaction_id))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass try: self.assertTrue(os.path.isfile(os.path.join( interaction_dir, '%sPredictionServiceSpec.ts' % interaction_id))) interaction_dir_optional_dirs_and_files_count += 1 except Exception: pass self.assertEqual( interaction_dir_optional_dirs_and_files_count + 5, len(interaction_dir_contents) ) py_file = os.path.join(interaction_dir, '%s.py' % interaction_id) ts_file = os.path.join( interaction_dir, '%s.ts' % interaction_id) self.assertTrue(os.path.isfile(py_file)) self.assertTrue(os.path.isfile(ts_file)) # Check that __init__.py file exists. init_file = os.path.join(interaction_dir, '__init__.py') self.assertTrue(os.path.isfile(init_file)) # Check that the directives subdirectory exists. directives_dir = os.path.join( interaction_dir, 'directives') self.assertTrue(os.path.isdir(directives_dir)) # The directives directory should contain the following files: # Required: # * A TS file called # OppiaInteractive{InteractionName}Directive.ts. # * A TS file called OppiaResponse{InteractionName}Directive.ts. # * A TS file called # OppiaShortResponse{InteractionName}Directive.ts. # * A TS file called {InteractionName}RulesService.ts. # * A TS file called {InteractionName}ValidationService.ts. # * A HTML file called # {InteractionName}_interaction_directive.html. # * A HTML file called # {InteractionName}_response_directive.html. # * A HTML file called # {InteractionName}_short_response_directive.html. # Optional: # * A TS file called {InteractionName}ValidationServiceSpecs.ts. # * A TS file called {InteractionName}RulesServiceSpecs.ts. snakecase_interaction_id = ( utils.camelcase_to_snakecase(interaction_id)) interaction_directive_ts_file = os.path.join( directives_dir, 'OppiaInteractive%sDirective.ts' % ( interaction_id)) response_directive_ts_file = os.path.join( directives_dir, 'OppiaResponse%sDirective.ts' % interaction_id) short_response_directive_ts_file = os.path.join( directives_dir, 'OppiaShortResponse%sDirective.ts' % ( interaction_id)) rules_service_ts_file = os.path.join( directives_dir, '%sRulesService.ts' % interaction_id) validation_service_ts_file = os.path.join( directives_dir, '%sValidationService.ts' % interaction_id) interaction_directive_html = os.path.join( directives_dir, '%s_interaction_directive.html' % snakecase_interaction_id) response_directive_html = os.path.join( directives_dir, '%s_response_directive.html' % snakecase_interaction_id) short_response_directive_html = os.path.join( directives_dir, '%s_short_response_directive.html' % snakecase_interaction_id) self.assertTrue(os.path.isfile(interaction_directive_ts_file)) self.assertTrue(os.path.isfile(response_directive_ts_file)) self.assertTrue(os.path.isfile(short_response_directive_ts_file)) self.assertTrue(os.path.isfile(rules_service_ts_file)) self.assertTrue(os.path.isfile(validation_service_ts_file)) self.assertTrue(os.path.isfile(interaction_directive_html)) self.assertTrue(os.path.isfile(response_directive_html)) self.assertTrue(os.path.isfile(short_response_directive_html)) # Check that the PNG thumbnail image has the correct dimensions. static_dir = os.path.join(interaction_dir, 'static') self.assertTrue(os.path.isdir(static_dir)) png_file = os.path.join( interaction_dir, 'static', '%s.png' % interaction_id) self.assertTrue(os.path.isfile(png_file)) with python_utils.open_file(png_file, 'rb', encoding=None) as f: img_data = f.read() width, height = struct.unpack('>LL', img_data[16:24]) self.assertEqual(int(width), INTERACTION_THUMBNAIL_WIDTH_PX) self.assertEqual(int(height), INTERACTION_THUMBNAIL_HEIGHT_PX) interaction_directive_ts_file_content = utils.get_file_contents( interaction_directive_ts_file) response_directive_ts_file_content = utils.get_file_contents( response_directive_ts_file) short_response_directive_ts_file_content = utils.get_file_contents( short_response_directive_ts_file) ts_file_content = utils.get_file_contents(ts_file) rules_service_ts_file_content = utils.get_file_contents( rules_service_ts_file) validation_service_ts_file_content = utils.get_file_contents( validation_service_ts_file) self.assertIn( 'oppiaInteractive%s' % interaction_id, interaction_directive_ts_file_content) self.assertIn( 'oppiaResponse%s' % interaction_id, response_directive_ts_file_content) self.assertIn( 'oppiaShortResponse%s' % interaction_id, short_response_directive_ts_file_content) self.assertIn( '%sRulesService' % ( interaction_id[0] + interaction_id[1:]), rules_service_ts_file_content) self.assertIn( '%sValidationService' % interaction_id, validation_service_ts_file_content) # Check that the html template includes js script for the # interaction. self.assertIn( 'OppiaInteractive%sDirective.ts' % interaction_id, ts_file_content) self.assertIn( 'OppiaResponse%sDirective.ts' % interaction_id, ts_file_content) self.assertIn( 'OppiaShortResponse%sDirective.ts' % interaction_id, ts_file_content) self.assertIn( '%sRulesService.ts' % interaction_id, ts_file_content) self.assertIn( '%sValidationService.ts' % interaction_id, ts_file_content) self.assertNotIn('<script>', interaction_directive_ts_file_content) self.assertNotIn('</script>', interaction_directive_ts_file_content) self.assertNotIn('<script>', response_directive_ts_file_content) self.assertNotIn('</script>', response_directive_ts_file_content) self.assertNotIn( '<script>', short_response_directive_ts_file_content) self.assertNotIn( '</script>', short_response_directive_ts_file_content) self.assertNotIn('<script>', rules_service_ts_file_content) self.assertNotIn('</script>', rules_service_ts_file_content) self.assertNotIn('<script>', validation_service_ts_file_content) self.assertNotIn('</script>', validation_service_ts_file_content) interaction = interaction_registry.Registry.get_interaction_by_id( interaction_id) # Check that the specified interaction id is the same as the class # name. self.assertTrue(interaction_id, msg=interaction.__class__.__name__) # Check that the configuration file contains the correct # top-level keys, and that these keys have the correct types. for item, item_type in _INTERACTION_CONFIG_SCHEMA: self.assertTrue(isinstance( getattr(interaction, item), item_type)) if item_type == python_utils.BASESTRING: self.assertTrue(getattr(interaction, item)) self.assertIn(interaction.display_mode, base.ALLOWED_DISPLAY_MODES) if interaction.is_linear or interaction.is_terminal: self.assertIsNone(interaction.answer_type) else: # Check that the answer_type corresponds to a valid object # class. obj_services.Registry.get_object_class_by_type( interaction.answer_type) self._validate_customization_arg_specs( interaction._customization_arg_specs) # pylint: disable=protected-access self._validate_dependencies(interaction.dependency_ids) answer_visualization_specs = ( interaction.answer_visualization_specs) self._validate_answer_visualization_specs( answer_visualization_specs) answer_visualizations = interaction.answer_visualizations for ind, visualization in enumerate(answer_visualizations): self.assertEqual( visualization.id, answer_visualization_specs[ind]['id']) self.assertEqual( visualization.calculation_id, answer_visualization_specs[ind]['calculation_id']) self.assertEqual( visualization.options, answer_visualization_specs[ind]['options']) # Check that the derived visualization is valid. visualization.validate() # Check that supplemental interactions have instructions, and # inline ones do not. if interaction.display_mode == base.DISPLAY_MODE_INLINE: self.assertIsNone(interaction.instructions) self.assertIsNone(interaction.narrow_instructions) else: self.assertTrue( isinstance( interaction.instructions, python_utils.BASESTRING)) self.assertIsNotNone(interaction.instructions) self.assertIsNotNone(interaction.narrow_instructions) # Check that terminal interactions are not linear. if interaction.is_terminal: self.assertFalse(interaction.is_linear) # Check that only linear interactions have a # default_outcome_heading property. if interaction.is_linear: self.assertTrue( isinstance( interaction.default_outcome_heading, python_utils.BASESTRING) and interaction.default_outcome_heading) else: self.assertIsNone(interaction.default_outcome_heading) # Check that interactions that can have solution cannot be linear. if interaction.can_have_solution: self.assertFalse(interaction.is_linear) default_object_values = obj_services.get_default_object_values() # Check that the rules for this interaction have object editor # templates and default values. for rule_name in list(interaction.rules_dict.keys()): param_list = interaction.get_rule_param_list(rule_name) for (_, param_obj_cls) in param_list: # TODO(sll): Get rid of these special cases. if param_obj_cls.__name__ in [ 'NonnegativeInt', 'ListOfCodeEvaluation', 'ListOfCoordTwoDim', 'ListOfGraph', 'SetOfNormalizedString']: continue # Check that the rule has a default value. self.assertIn( param_obj_cls.__name__, default_object_values)
def get(self, exploration_id): """Handles GET requests.""" if exploration_id in feconf.DISABLED_EXPLORATION_IDS: self.render_template( 'error/disabled_exploration.html', iframe_restriction=None) return exploration = exp_services.get_exploration_by_id( exploration_id, strict=False) if (exploration is None or not rights_manager.Actor(self.user_id).can_view( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)): self.redirect('/') return can_edit = ( bool(self.user_id) and self.username not in config_domain.BANNED_USERNAMES.value and rights_manager.Actor(self.user_id).can_edit( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id)) interaction_ids = ( interaction_registry.Registry.get_all_interaction_ids()) interaction_dependency_ids = ( interaction_registry.Registry.get_deduplicated_dependency_ids( interaction_ids)) dependencies_html, additional_angular_modules = ( dependency_registry.Registry.get_deps_html_and_angular_modules( interaction_dependency_ids + self.EDITOR_PAGE_DEPENDENCY_IDS)) interaction_templates = ( rte_component_registry.Registry.get_html_for_all_components() + interaction_registry.Registry.get_interaction_html( interaction_ids)) interaction_validators_html = ( interaction_registry.Registry.get_validators_html( interaction_ids)) gadget_types = gadget_registry.Registry.get_all_gadget_types() gadget_templates = ( gadget_registry.Registry.get_gadget_html(gadget_types)) self.values.update({ 'GADGET_SPECS': gadget_registry.Registry.get_all_specs(), 'INTERACTION_SPECS': interaction_registry.Registry.get_all_specs(), 'PANEL_SPECS': feconf.PANELS_PROPERTIES, 'DEFAULT_OBJECT_VALUES': obj_services.get_default_object_values(), 'DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR': ( DEFAULT_TWITTER_SHARE_MESSAGE_EDITOR.value), 'additional_angular_modules': additional_angular_modules, 'can_delete': rights_manager.Actor( self.user_id).can_delete( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_edit': can_edit, 'can_modify_roles': rights_manager.Actor( self.user_id).can_modify_roles( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_publicize': rights_manager.Actor( self.user_id).can_publicize( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_publish': rights_manager.Actor( self.user_id).can_publish( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_release_ownership': rights_manager.Actor( self.user_id).can_release_ownership( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_unpublicize': rights_manager.Actor( self.user_id).can_unpublicize( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'can_unpublish': rights_manager.Actor( self.user_id).can_unpublish( feconf.ACTIVITY_TYPE_EXPLORATION, exploration_id), 'dependencies_html': jinja2.utils.Markup(dependencies_html), 'gadget_templates': jinja2.utils.Markup(gadget_templates), 'interaction_templates': jinja2.utils.Markup( interaction_templates), 'interaction_validators_html': jinja2.utils.Markup( interaction_validators_html), 'meta_description': feconf.CREATE_PAGE_DESCRIPTION, 'nav_mode': feconf.NAV_MODE_CREATE, 'value_generators_js': jinja2.utils.Markup( get_value_generators_js()), 'title': exploration.title, 'ALL_LANGUAGE_CODES': feconf.ALL_LANGUAGE_CODES, 'ALLOWED_GADGETS': feconf.ALLOWED_GADGETS, 'ALLOWED_INTERACTION_CATEGORIES': ( feconf.ALLOWED_INTERACTION_CATEGORIES), 'INVALID_PARAMETER_NAMES': feconf.INVALID_PARAMETER_NAMES, 'NEW_STATE_TEMPLATE': NEW_STATE_TEMPLATE, 'SHOW_TRAINABLE_UNRESOLVED_ANSWERS': ( feconf.SHOW_TRAINABLE_UNRESOLVED_ANSWERS), 'TAG_REGEX': feconf.TAG_REGEX, }) self.render_template('exploration_editor/exploration_editor.html')