def test_only_explorations_with_ratings_are_returned(self): """Note that only explorations with ratings will be included """ rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_2, 5) top_rated_exploration_summaries = ( summary_services.get_top_rated_exploration_summary_dicts( [feconf.DEFAULT_LANGUAGE_CODE], feconf.NUMBER_OF_TOP_RATED_EXPLORATIONS_FOR_LIBRARY_PAGE)) expected_summary = { 'status': u'public', 'thumbnail_bg_color': '#a33f40', 'community_owned': False, 'tags': [], 'thumbnail_icon_url': self.get_static_asset_url( '/images/subjects/Lightbulb.svg'), 'language_code': feconf.DEFAULT_LANGUAGE_CODE, 'id': self.EXP_ID_2, 'category': u'A category', 'ratings': {u'1': 0, u'3': 0, u'2': 0, u'5': 1, u'4': 0}, 'title': u'A title', 'num_views': 0, 'objective': u'An objective' } self.assertDictContainsSubset( expected_summary, top_rated_exploration_summaries[0]) expected_ordering = [self.EXP_ID_2] actual_ordering = [exploration['id'] for exploration in top_rated_exploration_summaries] self.assertEqual(expected_ordering, actual_ordering)
def put(self, exploration_id): """Handles PUT requests for submitting ratings at the end of an exploration. """ user_rating = self.payload.get('user_rating') rating_services.assign_rating_to_exploration( self.user_id, exploration_id, user_rating) self.render_json({})
def _rate_exploration(self, exp_id, num_ratings, rating): """Create num_ratings ratings for exploration with exp_id, of value rating. """ # Each user id needs to be unique since each user can only give an # exploration one rating. user_ids = ['user%d' % i for i in range(num_ratings)] for user_id in user_ids: rating_services.assign_rating_to_exploration( user_id, exp_id, rating)
def _rate_exploration(self, exp_id, ratings): """Create num_ratings ratings for exploration with exp_id, of values from ratings. """ # Generate unique user ids to rate an exploration. Each user id needs # to be unique since each user can only give an exploration one rating. user_ids = ['user%d' % i for i in range(len(ratings))] self.process_and_flush_pending_tasks() for ind, user_id in enumerate(user_ids): rating_services.assign_rating_to_exploration( user_id, exp_id, ratings[ind]) self.process_and_flush_pending_tasks()
def test_time_of_ratings_recorded(self): """Check that the time a rating is given is recorded correctly.""" time_allowed_for_computation = datetime.timedelta(seconds=10) exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 1) first_rating_time = rating_services.get_when_exploration_rated( self.USER_ID_1, self.EXP_ID) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) second_rating_time = rating_services.get_when_exploration_rated( self.USER_ID_1, self.EXP_ID) self.assertLess( datetime.datetime.utcnow(), first_rating_time + time_allowed_for_computation) self.assertLess(first_rating_time, second_rating_time) self.assertLess(second_rating_time, datetime.datetime.utcnow())
def test_time_of_ratings_recorded(self): """Check that the time a rating is given is recorded correctly.""" TIME_ALLOWED_FOR_COMPUTATION = datetime.timedelta(seconds=10) self.exploration = exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category') exp_services.save_new_exploration(self.EXP_ID, self.exploration) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 1) first_rating_time = rating_services.get_when_exploration_rated( self.USER_ID_1, self.EXP_ID) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) second_rating_time = rating_services.get_when_exploration_rated( self.USER_ID_1, self.EXP_ID) self.assertLess( datetime.datetime.utcnow(), first_rating_time + TIME_ALLOWED_FOR_COMPUTATION) self.assertLess(first_rating_time, second_rating_time) self.assertLess(second_rating_time, datetime.datetime.utcnow())
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration""" exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0}) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( exp_summary.scaled_average_rating, 0) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating_to_exploration( self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertAlmostEqual( exp_summary.scaled_average_rating, 1.5667471839848, places=4) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 1, '4': 1, '5': 0}) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 2, '5': 0})
def test_rating_assignations_do_not_conflict(self): """Check that ratings of different explorations are independant.""" exp_id_a = 'exp_id_A' exp_id_b = 'exp_id_B' exp_services.save_new_exploration( exp_id_a, exp_domain.Exploration.create_default_exploration( exp_id_a, 'A title', 'A category')) exp_services.save_new_exploration( exp_id_b, exp_domain.Exploration.create_default_exploration( exp_id_b, 'A title', 'A category')) rating_services.assign_rating_to_exploration( self.USER_ID_1, exp_id_a, 1) rating_services.assign_rating_to_exploration( self.USER_ID_1, exp_id_b, 3) rating_services.assign_rating_to_exploration( self.USER_ID_2, exp_id_a, 2) rating_services.assign_rating_to_exploration( self.USER_ID_2, exp_id_b, 5) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, exp_id_a), 1) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, exp_id_b), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, exp_id_a), 2) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, exp_id_b), 5) self.assertEqual( rating_services.get_overall_ratings_for_exploration(exp_id_a), {'1': 1, '2': 1, '3': 0, '4': 0, '5': 0}) self.assertEqual( rating_services.get_overall_ratings_for_exploration(exp_id_b), {'1': 0, '2': 0, '3': 1, '4': 0, '5': 1})
def test_rating_assignations_do_not_conflict(self): """Check that ratings of different explorations are independant.""" EXP_ID_A = 'exp_id_A' EXP_ID_B = 'exp_id_B' self.exploration = exp_domain.Exploration.create_default_exploration( EXP_ID_A, 'A title', 'A category') exp_services.save_new_exploration(EXP_ID_A, self.exploration) self.exploration = exp_domain.Exploration.create_default_exploration( EXP_ID_B, 'A title', 'A category') exp_services.save_new_exploration(EXP_ID_B, self.exploration) rating_services.assign_rating_to_exploration( self.USER_ID_1, EXP_ID_A, 1) rating_services.assign_rating_to_exploration( self.USER_ID_1, EXP_ID_B, 3) rating_services.assign_rating_to_exploration( self.USER_ID_2, EXP_ID_A, 2) rating_services.assign_rating_to_exploration( self.USER_ID_2, EXP_ID_B, 5) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, EXP_ID_A), 1) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, EXP_ID_B), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, EXP_ID_A), 2) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, EXP_ID_B), 5) self.assertEqual( rating_services.get_overall_ratings_for_exploration(EXP_ID_A), {'1': 1, '2': 1, '3': 0, '4': 0, '5': 0}) self.assertEqual( rating_services.get_overall_ratings_for_exploration(EXP_ID_B), {'1': 0, '2': 0, '3': 1, '4': 0, '5': 1})
def test_invalid_ratings_are_forbidden(self): with self.assertRaisesRegexp( ValueError, 'Expected a rating 1-5, received 0'): rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 0) with self.assertRaisesRegexp( ValueError, 'Expected a rating 1-5, received 7'): rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 7) with self.assertRaisesRegexp( ValueError, 'Expected the rating to be an integer, received 2'): rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, '2') with self.assertRaisesRegexp( ValueError, 'Expected the rating to be an integer, received aaa'): rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 'aaa')
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration""" exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration( self.EXP_ID, 'A title', 'A category')) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0}) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating_to_exploration( self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 1, '4': 1, '5': 0}) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 2, '5': 0})
def test_at_most_eight_top_rated_explorations(self): """Note that at most 8 explorations should be returned. """ rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_2, 5) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_3, 5) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_3, 4) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_4, 4) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_5, 4) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_5, 3) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_6, 3) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_6, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_8, 2) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_8, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_7, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_9, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_1, 1) top_rated_exploration_summaries = ( summary_services.get_top_rated_exploration_summary_dicts( [feconf.DEFAULT_LANGUAGE_CODE], feconf.NUMBER_OF_TOP_RATED_EXPLORATIONS_FOR_LIBRARY_PAGE)) expected_summary = { 'status': u'public', 'thumbnail_bg_color': '#a33f40', 'community_owned': False, 'tags': [], 'thumbnail_icon_url': self.get_static_asset_url( '/images/subjects/Lightbulb.svg'), 'language_code': feconf.DEFAULT_LANGUAGE_CODE, 'id': self.EXP_ID_3, 'category': u'A category', 'ratings': {u'1': 0, u'3': 0, u'2': 0, u'5': 1, u'4': 1}, 'title': u'A title', 'num_views': 0, 'objective': u'An objective' } self.assertDictContainsSubset( expected_summary, top_rated_exploration_summaries[0]) expected_ordering = [ self.EXP_ID_3, self.EXP_ID_2, self.EXP_ID_5, self.EXP_ID_4, self.EXP_ID_6, self.EXP_ID_8, self.EXP_ID_7, self.EXP_ID_9] actual_ordering = [exploration['id'] for exploration in top_rated_exploration_summaries] self.assertEqual(expected_ordering, actual_ordering)
def test_handler_for_top_rated_library_group_page(self): """Test library handler for top rated group page.""" # Load a public demo exploration. exp_services.load_demo('0') response_dict = self.get_json( feconf.LIBRARY_GROUP_DATA_URL, {'group_name': feconf.LIBRARY_GROUP_TOP_RATED}) self.assertDictContainsSubset({ 'is_admin': False, 'is_moderator': False, 'is_super_admin': False, 'activity_list': [], 'preferred_language_codes': ['en'], 'profile_picture_data_url': None, }, response_dict) # Assign rating to exploration to test handler for top rated # explorations page. rating_services.assign_rating_to_exploration('user', '0', 2) # Test whether the response contains the exploration we have rated. response_dict = self.get_json( feconf.LIBRARY_GROUP_DATA_URL, {'group_name': feconf.LIBRARY_GROUP_TOP_RATED}) self.assertDictContainsSubset({ 'header_i18n_id': 'I18N_LIBRARY_GROUPS_TOP_RATED_EXPLORATIONS', 'preferred_language_codes': ['en'], }, response_dict) self.assertEqual(len(response_dict['activity_list']), 1) self.assertDictContainsSubset({ 'id': '0', 'category': 'Welcome', 'title': 'Welcome to Oppia!', 'language_code': 'en', 'objective': 'become familiar with Oppia\'s capabilities', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][0]) # Load another public demo exploration. exp_services.load_demo('1') # Assign rating to exploration to test handler for top rated # explorations page. rating_services.assign_rating_to_exploration('user', '1', 4) # Test whether the response contains both the explorations we have # rated and they are returned in decending order of rating. response_dict = self.get_json( feconf.LIBRARY_GROUP_DATA_URL, {'group_name': feconf.LIBRARY_GROUP_TOP_RATED}) self.assertEqual(len(response_dict['activity_list']), 2) self.assertDictContainsSubset({ 'id': '1', 'category': 'Programming', 'title': 'Project Euler Problem 1', 'language_code': 'en', 'objective': 'solve Problem 1 on the Project Euler site', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][0]) self.assertDictContainsSubset({ 'id': '0', 'category': 'Welcome', 'title': 'Welcome to Oppia!', 'language_code': 'en', 'objective': 'become familiar with Oppia\'s capabilities', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][1])
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration.""" exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), { '1': 0, '2': 0, '3': 0, '4': 0, '5': 0 }) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual(exp_summary.scaled_average_rating, 0) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating_to_exploration(self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating_to_exploration(self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating_to_exploration(self.USER_ID_1, self.EXP_ID, 3) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertAlmostEqual(exp_summary.scaled_average_rating, 1.5667471839848, places=4) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), { '1': 0, '2': 0, '3': 1, '4': 1, '5': 0 }) rating_services.assign_rating_to_exploration(self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), { '1': 0, '2': 0, '3': 0, '4': 2, '5': 0 })
def test_invalid_exploration_ids_are_forbidden(self): with self.assertRaisesRegexp(Exception, 'Invalid exploration id invalid_id'): rating_services.assign_rating_to_exploration( self.USER_ID_1, 'invalid_id', 3)
def test_at_most_eight_top_rated_explorations(self): """Note that at most 8 explorations should be returned.""" rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_2, 5) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_3, 5) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_3, 4) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_4, 4) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_5, 4) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_5, 3) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_6, 3) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_6, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_8, 2) rating_services.assign_rating_to_exploration( self.alice_id, self.EXP_ID_8, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_7, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_9, 2) rating_services.assign_rating_to_exploration( self.bob_id, self.EXP_ID_1, 1) top_rated_exploration_summaries = ( summary_services.get_top_rated_exploration_summary_dicts( [constants.DEFAULT_LANGUAGE_CODE], feconf.NUMBER_OF_TOP_RATED_EXPLORATIONS_FOR_LIBRARY_PAGE)) expected_summary = { 'status': u'public', 'thumbnail_bg_color': '#a33f40', 'community_owned': False, 'tags': [], 'language_code': constants.DEFAULT_LANGUAGE_CODE, 'thumbnail_icon_url': '/subjects/Lightbulb.svg', 'id': self.EXP_ID_3, 'category': u'A category', 'ratings': {u'1': 0, u'3': 0, u'2': 0, u'5': 1, u'4': 1}, 'title': u'A title', 'num_views': 0, 'objective': u'An objective' } self.assertDictContainsSubset( expected_summary, top_rated_exploration_summaries[0]) expected_ordering = [ self.EXP_ID_3, self.EXP_ID_2, self.EXP_ID_5, self.EXP_ID_4, self.EXP_ID_6, self.EXP_ID_8, self.EXP_ID_7, self.EXP_ID_9] actual_ordering = [exploration['id'] for exploration in top_rated_exploration_summaries] self.assertEqual(expected_ordering, actual_ordering)
def _rate_exploration(self, user_id, exp_id, rating): rating_services.assign_rating_to_exploration(user_id, exp_id, rating)
def test_handler_for_top_rated_library_group_page(self): """Test library handler for top rated group page.""" # Load a public demo exploration. exp_services.load_demo('0') response_dict = self.get_json( feconf.LIBRARY_GROUP_DATA_URL, {'group_name': feconf.LIBRARY_GROUP_TOP_RATED}) self.assertDictContainsSubset( { 'is_admin': False, 'is_moderator': False, 'is_super_admin': False, 'activity_list': [], 'preferred_language_codes': ['en'], 'profile_picture_data_url': None, }, response_dict) # Assign rating to exploration to test handler for top rated # explorations page. rating_services.assign_rating_to_exploration('user', '0', 2) # Test whether the response contains the exploration we have rated. response_dict = self.get_json( feconf.LIBRARY_GROUP_DATA_URL, {'group_name': feconf.LIBRARY_GROUP_TOP_RATED}) self.assertDictContainsSubset( { 'header_i18n_id': 'I18N_LIBRARY_GROUPS_TOP_RATED_EXPLORATIONS', 'preferred_language_codes': ['en'], }, response_dict) self.assertEqual(len(response_dict['activity_list']), 1) self.assertDictContainsSubset( { 'id': '0', 'category': 'Welcome', 'title': 'Welcome to Oppia!', 'language_code': 'en', 'objective': 'become familiar with Oppia\'s capabilities', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][0]) # Load another public demo exploration. exp_services.load_demo('1') # Assign rating to exploration to test handler for top rated # explorations page. rating_services.assign_rating_to_exploration('user', '1', 4) # Test whether the response contains both the explorations we have # rated and they are returned in decending order of rating. response_dict = self.get_json( feconf.LIBRARY_GROUP_DATA_URL, {'group_name': feconf.LIBRARY_GROUP_TOP_RATED}) self.assertEqual(len(response_dict['activity_list']), 2) self.assertDictContainsSubset( { 'id': '1', 'category': 'Programming', 'title': 'Project Euler Problem 1', 'language_code': 'en', 'objective': 'solve Problem 1 on the Project Euler site', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][0]) self.assertDictContainsSubset( { 'id': '0', 'category': 'Welcome', 'title': 'Welcome to Oppia!', 'language_code': 'en', 'objective': 'become familiar with Oppia\'s capabilities', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['activity_list'][1])
def test_invalid_exploration_ids_are_forbidden(self) -> None: with self.assertRaisesRegex( # type: ignore[no-untyped-call] Exception, 'Invalid exploration id invalid_id'): rating_services.assign_rating_to_exploration( self.USER_ID_1, 'invalid_id', 3)
def test_invalid_exploration_ids_are_forbidden(self): with self.assertRaisesRegexp( Exception, 'Invalid exploration id invalid_id' ): rating_services.assign_rating_to_exploration( self.USER_ID_1, 'invalid_id', 3)