def test_create_and_get_question_skill_link(self): question_id_2 = question_services.get_new_question_id() self.save_new_question(question_id_2, self.editor_id, self._create_valid_question_data('ABC')) question_id_3 = question_services.get_new_question_id() self.save_new_question(question_id_3, self.editor_id, self._create_valid_question_data('ABC')) question_services.create_new_question_skill_link( self.question_id, 'skill_1', 0.5) question_services.create_new_question_skill_link( question_id_2, 'skill_1', 0.3) question_services.create_new_question_skill_link( question_id_3, 'skill_2', 0.2) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, ['skill_1', 'skill_2', 'skill_3'], '')) with self.assertRaisesRegexp( Exception, 'Querying linked question summaries for more than 3 ' 'skills at a time is not supported currently.'): question_services.get_question_summaries_and_skill_descriptions( 5, ['skill_1', 'skill_2', 'skill_3', 'skill_4'], '') question_ids = [summary.id for summary in question_summaries] skill_descriptions = [ description for description in skill_descriptions ] self.assertEqual(len(question_ids), 3) self.assertEqual(len(skill_descriptions), 3) self.assertItemsEqual(question_ids, [self.question_id, question_id_2, question_id_3]) # Make sure the correct skill description corresponds to respective # question summaries. for index, description in enumerate(skill_descriptions): if (question_ids[index] == self.question_id or question_ids[index] == question_id_2): self.assertEqual('Skill Description 1', description) else: self.assertEqual('Skill Description 2', description) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, ['skill_1', 'skill_3'], '')) question_ids = [summary.id for summary in question_summaries] self.assertEqual(len(question_ids), 2) self.assertItemsEqual(question_ids, [self.question_id, question_id_2]) with self.assertRaisesRegexp( Exception, 'The given question is already linked to given skill'): question_services.create_new_question_skill_link( self.question_id, 'skill_1', 0.3)
def test_post(self): with self.swap(constants, 'ENABLE_NEW_STRUCTURE_EDITORS', True): self.login(self.NEW_USER_EMAIL) response = self.get_html_response(feconf.CREATOR_DASHBOARD_URL) csrf_token = self.get_csrf_token_from_response(response) self.post_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id ), {}, csrf_token=csrf_token, expected_status_int=401) self.logout() self.login(self.ADMIN_EMAIL) response = self.get_html_response(feconf.CREATOR_DASHBOARD_URL) csrf_token = self.get_csrf_token_from_response(response) self.post_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id ), {}, csrf_token=csrf_token) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual( question_summaries[0].id, self.question_id) self.assertEqual( skill_descriptions[0], 'Skill Description') self.logout() self.login(self.TOPIC_MANAGER_EMAIL) response = self.get_html_response(feconf.CREATOR_DASHBOARD_URL) csrf_token = self.get_csrf_token_from_response(response) self.post_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id_2, self.skill_id ), {}, csrf_token=csrf_token) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 2) question_ids = [ summary.id for summary in question_summaries ] self.assertItemsEqual( question_ids, [self.question_id, self.question_id_2]) self.logout()
def get(self, comma_separated_skill_ids): """Handles GET requests.""" start_cursor = self.request.get('cursor') skill_ids = comma_separated_skill_ids.split(',') for skill_id in skill_ids: try: skill_domain.Skill.require_valid_skill_id(skill_id) except Exception: raise self.PageNotFoundException(Exception('Invalid skill id')) try: skill_services.get_multi_skills(skill_ids) except Exception as e: raise self.PageNotFoundException(e) question_summaries, skill_descriptions_list, next_start_cursor = ( question_services.get_question_summaries_and_skill_descriptions( constants.NUM_QUESTIONS_PER_PAGE, skill_ids, start_cursor)) return_dicts = [] for index, summary in enumerate(question_summaries): return_dicts.append({ 'summary': summary.to_dict(), 'skill_descriptions': skill_descriptions_list[index] }) self.values.update({ 'question_summary_dicts': return_dicts, 'next_start_cursor': next_start_cursor }) self.render_json(self.values)
def get(self, topic_id): """Handles GET requests.""" if not constants.ENABLE_NEW_STRUCTURE_EDITORS: raise self.PageNotFoundException topic_domain.Topic.require_valid_topic_id(topic_id) start_cursor = self.request.get('cursor') topic = topic_services.get_topic_by_id(topic_id) skill_ids = topic.get_all_skill_ids() question_summaries, skill_descriptions, next_start_cursor = ( question_services.get_question_summaries_and_skill_descriptions( constants.NUM_QUESTIONS_PER_PAGE, skill_ids, start_cursor)) return_dicts = [] for index, summary in enumerate(question_summaries): return_dicts.append({ 'summary': summary.to_dict(), 'skill_description': skill_descriptions[index] }) self.values.update({ 'question_summary_dicts': return_dicts, 'next_start_cursor': next_start_cursor }) self.render_json(self.values)
def test_delete(self): question_services.create_new_question_skill_link( self.question_id, self.skill_id) question_services.create_new_question_skill_link( self.question_id_2, self.skill_id) with self.swap(constants, 'ENABLE_NEW_STRUCTURE_EDITORS', True): self.login(self.NEW_USER_EMAIL) self.delete_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id ), expected_status_int=401) self.logout() self.login(self.ADMIN_EMAIL) self.delete_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id )) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual( question_summaries[0].id, self.question_id_2) self.assertEqual( skill_descriptions[0], 'Skill Description') self.logout() self.login(self.TOPIC_MANAGER_EMAIL) self.delete_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id_2, self.skill_id )) question_summaries, _, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 0) self.logout()
def test_post_with_topic_manager_email_allows_question_linking(self): self.login(self.TOPIC_MANAGER_EMAIL) csrf_token = self.get_new_csrf_token() self.post_json('%s/%s/%s' % (feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id), {}, csrf_token=csrf_token) question_summaries, grouped_skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual(question_summaries[0].id, self.question_id) self.assertEqual(grouped_skill_descriptions[0], ['Skill Description']) self.logout()
def test_post_with_topic_manager_email_allows_question_linking(self): self.login(self.TOPIC_MANAGER_EMAIL) response = self.get_html_response(feconf.CREATOR_DASHBOARD_URL) csrf_token = self.get_csrf_token_from_response(response) self.post_json('%s/%s/%s' % (feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id), {}, csrf_token=csrf_token) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual(question_summaries[0].id, self.question_id) self.assertEqual(skill_descriptions[0], 'Skill Description') self.logout()
def test_delete_with_topic_manager_email_allows_question_deletion(self): question_services.create_new_question_skill_link( self.editor_id, self.question_id, self.skill_id, 0.5) question_services.create_new_question_skill_link( self.editor_id, self.question_id_2, self.skill_id, 0.5) self.login(self.TOPIC_MANAGER_EMAIL) self.delete_json('%s/%s/%s' % (feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id)) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual(question_summaries[0].id, self.question_id_2) self.assertEqual(skill_descriptions[0], 'Skill Description') self.logout()
def test_get_question_summaries_and_skill_descriptions_with_no_skill_ids( self): question_id = question_services.get_new_question_id() self.save_new_question(question_id, self.editor_id, self._create_valid_question_data('ABC')) question_services.create_new_question_skill_link( question_id, 'skill_1', 0.5) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 2, [], '')) self.assertEqual(question_summaries, []) self.assertEqual(skill_descriptions, [])
def test_delete_with_admin_email_allows_question_deletion(self): question_services.create_new_question_skill_link( self.editor_id, self.question_id, self.skill_id, 0.3) question_services.create_new_question_skill_link( self.editor_id, self.question_id_2, self.skill_id, 0.3) self.login(self.ADMIN_EMAIL) self.delete_json('%s/%s/%s' % (feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id)) question_summaries, grouped_skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual(question_summaries[0].id, self.question_id_2) self.assertEqual(grouped_skill_descriptions[0], ['Skill Description']) self.logout()
def test_accept_question_suggestion(self): suggestion_to_accept = self.get_json( '%s?suggestion_type=%s' % ( feconf.SUGGESTION_LIST_URL_PREFIX, suggestion_models.SUGGESTION_TYPE_ADD_QUESTION) )['suggestions'][0] self.login(self.ADMIN_EMAIL) csrf_token = self.get_new_csrf_token() with self.swap(constants, 'ENABLE_NEW_STRUCTURE_PLAYERS', True): self.put_json('%s/topic/%s/%s' % ( feconf.SUGGESTION_ACTION_URL_PREFIX, suggestion_to_accept['target_id'], suggestion_to_accept['suggestion_id']), { 'action': u'accept', 'commit_message': u'commit message', 'review_message': u'This looks good!', 'skill_id': self.SKILL_ID }, csrf_token=csrf_token) suggestion_post_accept = self.get_json( '%s?suggestion_type=%s' % ( feconf.SUGGESTION_LIST_URL_PREFIX, suggestion_models.SUGGESTION_TYPE_ADD_QUESTION) )['suggestions'][0] self.assertEqual( suggestion_post_accept['status'], suggestion_models.STATUS_ACCEPTED) questions, grouped_skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 1, [self.SKILL_ID], '')) self.assertEqual(len(questions), 1) self.assertEqual(questions[0].creator_id, self.author_id) self.assertEqual( grouped_skill_descriptions[0], [self.SKILL_DESCRIPTION]) self.assertEqual( questions[0].question_content, self.question_dict['question_state_data']['content']['html'] ) thread_messages = feedback_services.get_messages( suggestion_to_accept['suggestion_id']) last_message = thread_messages[len(thread_messages) - 1] self.assertEqual(last_message.text, 'This looks good!')
def test_post_with_admin_email_allows_question_linking(self): with self.swap(constants, 'ENABLE_NEW_STRUCTURE_EDITORS', True): self.login(self.ADMIN_EMAIL) response = self.get_html_response(feconf.CREATOR_DASHBOARD_URL) csrf_token = self.get_csrf_token_from_response(response) self.post_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id ), {}, csrf_token=csrf_token) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual( question_summaries[0].id, self.question_id) self.assertEqual( skill_descriptions[0], 'Skill Description') self.logout()
def get(self, topic_id): """Handles GET requests.""" start_cursor = self.request.get('cursor') topic = topic_services.get_topic_by_id(topic_id) skill_ids = topic.get_all_skill_ids() question_summaries, skill_descriptions, next_start_cursor = ( question_services.get_question_summaries_and_skill_descriptions( constants.NUM_QUESTIONS_PER_PAGE, skill_ids, start_cursor)) return_dicts = [] for index, summary in enumerate(question_summaries): return_dicts.append({ 'summary': summary.to_dict(), 'skill_description': skill_descriptions[index] }) self.values.update({ 'question_summary_dicts': return_dicts, 'next_start_cursor': next_start_cursor }) self.render_json(self.values)
def test_delete_with_admin_email_allows_question_deletion(self): question_services.create_new_question_skill_link( self.question_id, self.skill_id, 0.3) question_services.create_new_question_skill_link( self.question_id_2, self.skill_id, 0.3) with self.swap(constants, 'ENABLE_NEW_STRUCTURE_EDITORS', True): self.login(self.ADMIN_EMAIL) self.delete_json( '%s/%s/%s' % ( feconf.QUESTION_SKILL_LINK_URL_PREFIX, self.question_id, self.skill_id )) question_summaries, skill_descriptions, _ = ( question_services.get_question_summaries_and_skill_descriptions( 5, [self.skill_id], '')) self.assertEqual(len(question_summaries), 1) self.assertEqual( question_summaries[0].id, self.question_id_2) self.assertEqual( skill_descriptions[0], 'Skill Description') self.logout()
class QuestionsListHandler(base.BaseHandler): """Manages receiving of all question summaries for display in topic editor and skill editor page. """ GET_HANDLER_ERROR_RETURN_TYPE = feconf.HANDLER_TYPE_JSON @acl_decorators.open_access def get(self, comma_separated_skill_ids): """Handles GET requests.""" start_cursor = self.request.get('cursor') skill_ids = comma_separated_skill_ids.split(',') for skill_id in skill_ids: try: skill_domain.Skill.require_valid_skill_id(skill_id) except Exception: raise self.PageNotFoundException(Exception('Invalid skill id')) try: skill_services.get_multi_skills(skill_ids) except Exception, e: raise self.PageNotFoundException(e) question_summaries, skill_descriptions_list, next_start_cursor = ( question_services.get_question_summaries_and_skill_descriptions( constants.NUM_QUESTIONS_PER_PAGE, skill_ids, start_cursor)) return_dicts = [] for index, summary in enumerate(question_summaries): return_dicts.append({ 'summary': summary.to_dict(), 'skill_descriptions': skill_descriptions_list[index] }) self.values.update({ 'question_summary_dicts': return_dicts, 'next_start_cursor': next_start_cursor }) self.render_json(self.values)