def test_state_class(self): """Test State Class.""" state = State(id='The exploration hash id') # A new state should have a default name property. self.assertEqual(state.name, feconf.DEFAULT_STATE_NAME) state.put()
def add_state(self, state_name, state_id=None): """Adds a new state, and returns it. Commits changes.""" if self._has_state_named(state_name): raise Exception('Duplicate state name %s' % state_name) state_id = state_id or State.get_new_id(state_name) new_state = State(id=state_id, name=state_name) new_state.put() self.state_ids.append(new_state.id) self.put() return new_state
def test_get_id_from_name(self): """Test converting state names to ids.""" id_1 = '123' name_1 = 'State 1' self.exploration.add_state(name_1, state_id=id_1) self.assertEqual( State._get_id_from_name(name_1, self.exploration), id_1) with self.assertRaises(Exception): State._get_id_from_name('fake_name', self.exploration) self.assertEqual( State._get_id_from_name(feconf.END_DEST, self.exploration), feconf.END_DEST)
def create_from_yaml( yaml_content, user_id, title, category, exploration_id=None, image_id=None): """Creates an exploration from a YAML text string.""" exploration_dict = utils.dict_from_yaml(yaml_content) init_state_name = exploration_dict['states'][0]['name'] exploration = Exploration.get(create_new( user_id, title, category, exploration_id=exploration_id, init_state_name=init_state_name, image_id=image_id)) init_state = State.get_by_name(init_state_name, exploration) try: exploration.parameters = [Parameter( name=param['name'], obj_type=param['obj_type'], values=param['values'] ) for param in exploration_dict['parameters']] state_list = [] for state_description in exploration_dict['states']: state_name = state_description['name'] state = (init_state if state_name == init_state_name else exploration.add_state(state_name)) state_list.append({'state': state, 'desc': state_description}) for index, state in enumerate(state_list): modify_using_dict(exploration.id, state['state'].id, state['desc']) except Exception: exploration.delete() raise return exploration.id
def get_state_by_id(self, state_id, strict=True): """Returns a state of the exploration, given its id.""" if state_id not in self.state_ids: raise Exception( 'Invalid state id %s for exploration %s' % (state_id, self.id)) return State.get(state_id, strict=strict)
def test_init_state_property(self): """Test the init_state property.""" INIT_STATE_ID = 'init_state_id' INIT_STATE_NAME = 'init_state_name' init_state = State(id=INIT_STATE_ID, name=INIT_STATE_NAME) init_state.put() exploration = FakeExploration(owner_id='*****@*****.**') exploration.state_ids = ['init_state_id'] self.assertEqual(exploration.init_state_id, INIT_STATE_ID) self.assertEqual(exploration.init_state.name, INIT_STATE_NAME) exploration.add_state('b') self.assertEqual(exploration.init_state_id, INIT_STATE_ID) self.assertEqual(exploration.init_state.name, INIT_STATE_NAME)
def test_state_operations(self): """Test adding, renaming and checking existence of states.""" exploration = FakeExploration(owner_id='*****@*****.**') exploration.add_state('Initial state') self.assertEqual(len(exploration.state_ids), 1) default_state = State.get(exploration.state_ids[0]) default_state_name = default_state.name exploration.rename_state(default_state.id, 'Renamed state') self.assertEqual(len(exploration.state_ids), 1) self.assertEqual(default_state.name, 'Renamed state') # Add a new state. second_state = exploration.add_state('State 2') self.assertEqual(len(exploration.state_ids), 2) # It is OK to rename a state to itself. exploration.rename_state(second_state.id, second_state.name) self.assertEqual(second_state.name, 'State 2') # But it is not OK to add or rename a state using a name that already # exists. with self.assertRaises(Exception): exploration.add_state('State 2') with self.assertRaises(Exception): exploration.rename_state(second_state.id, 'Renamed state') # The exploration now has exactly two states. self.assertFalse(exploration._has_state_named(default_state_name)) self.assertTrue(exploration._has_state_named('Renamed state')) self.assertTrue(exploration._has_state_named('State 2'))
def add_state(self, state_name): """Adds a new state, and returns it.""" if self._has_state_named(state_name): raise Exception('Duplicate state name %s' % state_name) state = State.create(self, state_name) self.states.append(state.key) self.put() return state
def create_new( user_id, title, category, exploration_id=None, init_state_name=feconf.DEFAULT_STATE_NAME, image_id=None): """Creates, saves and returns a new exploration id.""" # Generate a new exploration id, if one wasn't passed in. exploration_id = exploration_id or ExplorationModel.get_new_id(title) state_id = State.get_new_id(init_state_name) new_state = State(id=state_id, name=init_state_name) new_state.put() # Note that demo explorations do not have owners, so user_id may be None. exploration = ExplorationModel( id=exploration_id, title=title, category=category, image_id=image_id, state_ids=[state_id], editor_ids=[user_id] if user_id else []) exploration.put() return exploration.id
def test_create_and_get_state(self): """Test creation and retrieval of states.""" id_1 = '123' name_1 = 'State 1' state_1 = self.exploration.add_state(name_1, state_id=id_1) fetched_state_1 = self.exploration.get_state_by_id(id_1) self.assertEqual(fetched_state_1, state_1) fetched_state_by_name_1 = State.get_by_name(name_1, self.exploration) self.assertEqual(fetched_state_by_name_1, state_1) # Test the failure cases. id_2 = 'fake_id' name_2 = 'fake_name' with self.assertRaises(Exception): self.exploration.get(id_2) fetched_state_by_name_2 = State.get_by_name( name_2, self.exploration, strict=False) self.assertIsNone(fetched_state_by_name_2) with self.assertRaises(Exception): State.get_by_name(name_2, self.exploration, strict=True) # The default behavior is to fail noisily. with self.assertRaises(Exception): State.get_by_name(name_2, self.exploration)
def create(cls, user, title, category, exploration_id=None, init_state_name=feconf.DEFAULT_STATE_NAME, image_id=None): """Creates and returns a new exploration.""" # Generate a new exploration id, if one wasn't passed in. exploration_id = exploration_id or cls.get_new_id(title) # Temporarily create a fake initial state key. state_id = State.get_new_id(init_state_name) fake_state_key = ndb.Key(Exploration, exploration_id, State, state_id) # Note that demo explorations do not have owners, so user may be None. exploration = cls( id=exploration_id, title=title, init_state=fake_state_key, category=category, image_id=image_id, states=[fake_state_key], editors=[user] if user else []) exploration.put() # Finally, create the initial state and check that it has the right key. new_init_state = State.create( exploration, init_state_name, state_id=state_id) assert fake_state_key == new_init_state.key return exploration
def create_from_yaml( cls, yaml_file, user, title, category, exploration_id=None, image_id=None): """Creates an exploration from a YAML file.""" exploration_dict = utils.dict_from_yaml(yaml_file) init_state_name = exploration_dict['states'][0]['name'] exploration = cls.create( user, title, category, exploration_id=exploration_id, init_state_name=init_state_name, image_id=image_id) init_state = State.get_by_name(init_state_name, exploration) try: for param in exploration_dict['parameters']: exploration.parameters.append(Parameter( name=param['name'], obj_type=param['obj_type'], values=param['values']) ) state_list = [] exploration_states = exploration_dict['states'] for state_description in exploration_states: state_name = state_description['name'] state = (init_state if state_name == init_state_name else exploration.add_state(state_name)) state_list.append({'state': state, 'desc': state_description}) for index, state in enumerate(state_list): State.modify_using_dict( exploration, state['state'], state['desc']) except Exception: exploration.delete() raise return exploration
def modify_using_dict(exploration_id, state_id, sdict): """Modifies the properties of a state using values from a dict.""" exploration = Exploration.get(exploration_id) state = exploration.get_state_by_id(state_id) state.content = [ Content(type=item['type'], value=item['value']) for item in sdict['content'] ] state.param_changes = [] for pc in sdict['param_changes']: instance = get_or_create_param( exploration_id, pc['name'], obj_type=pc['obj_type']) instance.values = pc['values'] state.param_changes.append(instance) wdict = sdict['widget'] state.widget = WidgetInstance( widget_id=wdict['widget_id'], sticky=wdict['sticky'], params=wdict['params'], handlers=[]) # Augment the list of parameters in state.widget with the default widget # params. for wp in InteractiveWidget.get(wdict['widget_id']).params: if wp.name not in wdict['params']: state.widget.params[wp.name] = wp.value for handler in wdict['handlers']: handler_rules = [Rule( name=rule['name'], inputs=rule['inputs'], dest=State._get_id_from_name(rule['dest'], exploration), feedback=rule['feedback'] ) for rule in handler['rules']] state.widget.handlers.append(AnswerHandlerInstance( name=handler['name'], rules=handler_rules)) state.put() return state
def _has_state_named(self, state_name): """Checks if a state with the given name exists in this exploration.""" state = State.query(ancestor=self.key).filter( State.name == state_name).count(limit=1) return bool(state)
def test_exploration_class(self): """Test the Exploration model class.""" exploration = ExplorationModel(id='The exploration hash id') # A new exploration should have a default title property. self.assertEqual(exploration.title, 'New exploration') # A new exploration should have a default is_public property. self.assertEqual(exploration.is_public, False) state = State(id='The state hash id') state.put() # The 'state_ids' property must be a list of strings. with self.assertRaises(SyntaxError): exploration.state_ids = 'A string' exploration.put() with self.assertRaises(ValidationError): exploration.state_ids = [state] exploration.put() exploration.state_ids = [state.id] # An Exploration must have a category. with self.assertRaises(ValidationError): exploration.put() exploration.category = 'The category' # The 'parameters' property must be a list of Parameter objects. with self.assertRaises(ValidationError): exploration.parameters = 'A string' exploration.put() exploration.parameters = [] parameter = Parameter(name='theParameter', obj_type='Int') with self.assertRaises(AttributeError): exploration.parameters = [parameter.key] exploration.parameters = [parameter] # The 'is_public' property must be a boolean. with self.assertRaises(ValidationError): exploration.is_public = 'true' exploration.put() exploration.is_public = True # The 'image_id' property must be a string. # TODO: This fails now because of the behaviour of CharField image = Image(id='The image') with self.assertRaises(ValidationError): exploration.image_id = image exploration.put() exploration.image_id = 'A string' exploration.editor_ids = ['A user id'] # Put and retrieve the exploration. exploration.put() retrieved_exploration = Exploration.get('The exploration hash id') self.assertEqual(retrieved_exploration.category, 'The category') self.assertEqual(retrieved_exploration.title, 'New exploration') self.assertEqual(retrieved_exploration.state_ids, [state.id]) self.assertEqual(retrieved_exploration.parameters, [parameter]) self.assertEqual(retrieved_exploration.is_public, True) self.assertEqual(retrieved_exploration.image_id, 'A string') self.assertEqual(retrieved_exploration.editor_ids, ['A user id'])