def reload_widgets(): """Reload the default classifiers and widgets.""" Classifier.delete_all_classifiers() Classifier.load_default_classifiers() Widget.delete_all_widgets() InteractiveWidget.load_default_widgets() NonInteractiveWidget.load_default_widgets()
def test_parameterized_widget(self): """Test that parameterized widgets are correctly handled.""" self.assertEqual(InteractiveWidget.objects.count(), 0) Classifier.load_default_classifiers() InteractiveWidget.load_default_widgets() MUSIC_STAFF_ID = 'interactive-MusicStaff' widget = InteractiveWidget.get(MUSIC_STAFF_ID) self.assertEqual(widget.id, MUSIC_STAFF_ID) self.assertEqual(widget.name, 'Music staff') code = InteractiveWidget.get_raw_code(MUSIC_STAFF_ID) self.assertIn('GLOBALS.noteToGuess = JSON.parse(\'\\"', code) code = InteractiveWidget.get_raw_code(MUSIC_STAFF_ID, {'noteToGuess': 'abc'}) self.assertIn('GLOBALS.noteToGuess = JSON.parse(\'abc\');', code) # The get_with_params() method cannot be called directly on Widget. # It must be called on a subclass. with self.assertRaises(AttributeError): parameterized_widget_dict = Widget.get_with_params( MUSIC_STAFF_ID, {'noteToGuess': 'abc'}) with self.assertRaises(NotImplementedError): parameterized_widget_dict = Widget._get_with_params( MUSIC_STAFF_ID, {'noteToGuess': 'abc'}) parameterized_widget_dict = InteractiveWidget.get_with_params( MUSIC_STAFF_ID, {'noteToGuess': 'abc'}) self.assertItemsEqual(parameterized_widget_dict.keys(), [ 'id', 'name', 'category', 'description', 'template', 'static_template', 'params', 'handlers', 'raw']) self.assertEqual(parameterized_widget_dict['id'], MUSIC_STAFF_ID) self.assertIn('GLOBALS.noteToGuess = JSON.parse(\'abc\');', parameterized_widget_dict['raw']) self.assertEqual(parameterized_widget_dict['params'], {'noteToGuess': 'abc'}) InteractiveWidget.delete_all_widgets()
def test_put_method(self): """Test that put() only works when called on a Widget subclass.""" widget = Widget( id='WidgetName', name='Widget Name', category='Category', template='Template') with self.assertRaises(NotImplementedError): widget.put() widget = InteractiveWidget( id='WidgetName', name='Widget Name', category='Category', template='Template', handlers=[AnswerHandler()]) widget.put() InteractiveWidget.delete_all_widgets()
def verify_state_dict(self, state_dict, state_name_list): """Verifies a state dictionary.""" STATE_DICT_SCHEMA = [ ('name', basestring), ('content', list), ('param_changes', list), ('widget', dict)] self.verify_dict_keys_and_types(state_dict, STATE_DICT_SCHEMA) curr_state = state_dict['name'] # TODO(sll): Change the following verification once we move 'content' # to become a typed object. CONTENT_ITEM_SCHEMA = [('type', basestring), ('value', basestring)] for content_item in state_dict['content']: self.verify_dict_keys_and_types(content_item, CONTENT_ITEM_SCHEMA) self.assertIn(content_item['type'], ['text', 'image', 'video']) PARAM_CHANGES_SCHEMA = [ ('name', basestring), ('values', list), ('obj_type', basestring)] for param_change in state_dict['param_changes']: self.verify_dict_keys_and_types(param_change, PARAM_CHANGES_SCHEMA) # TODO(sll): Test that the elements of 'values' are of the correct # type. WIDGET_SCHEMA = [ ('widget_id', basestring), ('params', dict), ('handlers', list), ('sticky', bool)] self.verify_dict_keys_and_types(state_dict['widget'], WIDGET_SCHEMA) for handler in state_dict['widget']['handlers']: HANDLER_SCHEMA = [('name', basestring), ('rules', list)] self.verify_dict_keys_and_types(handler, HANDLER_SCHEMA) # Check that the list of rules is non-empty. self.assertTrue(handler['rules']) for rule in handler['rules']: RULE_SCHEMA = [ ('dest', basestring), ('feedback', list), ('inputs', dict), ('name', basestring), ('param_changes', list) ] self.verify_dict_keys_and_types(rule, RULE_SCHEMA) # Check that the destination is a valid one. if rule['dest'] != feconf.END_DEST: self.assertIn(rule['dest'], state_name_list) # Check that there are no feedback-less self-loops. self.assertFalse( rule['dest'] == curr_state and not rule['feedback'] and not state_dict['widget']['sticky'], msg='State %s has a self-loop with no feedback. This is ' 'likely to frustrate the reader.' % curr_state) # TODO(sll): Does 'inputs' need any tests? # TODO(sll): Check that the name corresponds to a valid one # from the relevant exploration -- maybe. (Need to decide if # we allow initialization of parameters midway through states.) for param_change in state_dict['param_changes']: self.verify_dict_keys_and_types( param_change, PARAM_CHANGES_SCHEMA) # TODO(sll): Test that the elements of 'values' are of the # correct type. for wp_name, wp_value in state_dict['widget']['params'].iteritems(): self.assertTrue(isinstance(wp_name, basestring)) # Check that the parameter name is valid. widget_params = Widget.get(state_dict['widget']['widget_id']).params widget_param_names = [wp.name for wp in widget_params] self.assertIn( wp_name, widget_param_names, msg='Parameter %s is not a valid parameter for widget %s' % ( wp_name, state_dict['widget']['widget_id'])) # Get the object class used to normalize the value for this param. for wp in widget_params: if wp.name == wp_name: obj_class = get_object_class(wp.obj_type) self.assertIsNotNone(obj_class) break # Check that the parameter value has the correct type. obj_class.normalize(wp_value)