def test_managers_can_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) self.set_admins([self.OWNER_USERNAME]) self.login(self.OWNER_EMAIL) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PRIVATE) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLIC) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLICIZED) self.logout()
def test_collaborators_can_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration( self.owner_id, self.EXP_ID, self.collaborator_id, rights_manager.ROLE_EDITOR) self.set_admins([self.OWNER_USERNAME]) self.login(self.COLLABORATOR_EMAIL) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PRIVATE) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLIC) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLICIZED) self.logout()
def test_for_featured_explorations(self): """Note that EXP_ID_1 is public, and EXP_ID_2 is publicized. The call to get_featured_explorations() should only return [EXP_ID_2]. """ rights_manager.publicize_exploration(self.admin_id, self.EXP_ID_2) featured_exploration_summaries = ( summary_services.get_featured_exploration_summary_dicts( [feconf.DEFAULT_LANGUAGE_CODE])) expected_summary = { 'status': u'publicized', 'thumbnail_bg_color': '#a33f40', 'community_owned': False, 'tags': [], 'thumbnail_icon_url': '/images/subjects/Lightbulb.svg', 'language_code': feconf.DEFAULT_LANGUAGE_CODE, 'id': self.EXP_ID_2, 'category': u'A category', 'ratings': feconf.get_empty_ratings(), 'title': u'A title', 'num_views': 0, 'objective': u'An objective' } self.assertDictContainsSubset(expected_summary, featured_exploration_summaries[0])
def test_managers_can_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) self.set_admins([self.OWNER_EMAIL]) self.login(self.OWNER_EMAIL) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PRIVATE) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLIC) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(self.MY_EXPLORATIONS_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual( response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLICIZED) self.logout()
def test_collaborators_can_see_explorations_on_dashboard(self): self.save_new_default_exploration( self.EXP_ID, self.OWNER_ID, title=self.EXP_TITLE) rights_manager.assign_role( self.OWNER_ID, self.EXP_ID, self.COLLABORATOR_ID, rights_manager.ROLE_EDITOR) self.set_admins([self.OWNER_EMAIL]) self.login(self.COLLABORATOR_EMAIL) response = self.get_json('/dashboardhandler/data') self.assertEqual(len(response['explorations']), 1) self.assertIn(self.EXP_ID, response['explorations']) self.assertEqual( response['explorations'][self.EXP_ID]['rights']['status'], rights_manager.EXPLORATION_STATUS_PRIVATE) rights_manager.publish_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(len(response['explorations']), 1) self.assertIn(self.EXP_ID, response['explorations']) self.assertEqual( response['explorations'][self.EXP_ID]['rights']['status'], rights_manager.EXPLORATION_STATUS_PUBLIC) rights_manager.publicize_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(len(response['explorations']), 1) self.assertIn(self.EXP_ID, response['explorations']) self.assertEqual( response['explorations'][self.EXP_ID]['rights']['status'], rights_manager.EXPLORATION_STATUS_PUBLICIZED) self.logout()
def test_publish_or_publicize_activity_does_not_affect_featured_list(self): self._compare_lists( activity_services.get_featured_activity_references(), []) rights_manager.publish_exploration(self.owner_id, self.EXP_ID_0) self._compare_lists( activity_services.get_featured_activity_references(), []) rights_manager.publicize_exploration(self.moderator_id, self.EXP_ID_0) self._compare_lists( activity_services.get_featured_activity_references(), []) rights_manager.unpublicize_exploration( self.moderator_id, self.EXP_ID_0) self._compare_lists( activity_services.get_featured_activity_references(), []) rights_manager.publish_collection(self.owner_id, self.COL_ID_2) self._compare_lists( activity_services.get_featured_activity_references(), []) rights_manager.publicize_collection(self.moderator_id, self.COL_ID_2) self._compare_lists( activity_services.get_featured_activity_references(), []) rights_manager.unpublicize_collection( self.moderator_id, self.COL_ID_2) self._compare_lists( activity_services.get_featured_activity_references(), [])
def test_collaborators_can_see_explorations(self): self.save_new_default_exploration(self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration(self.owner_id, self.EXP_ID, self.collaborator_id, rights_manager.ROLE_EDITOR) self.set_admins([self.OWNER_USERNAME]) self.login(self.COLLABORATOR_EMAIL) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual(response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PRIVATE) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual(response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLIC) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(len(response['explorations_list']), 1) self.assertEqual(response['explorations_list'][0]['status'], rights_manager.ACTIVITY_STATUS_PUBLICIZED) self.logout()
def test_collaborators_can_see_explorations_on_dashboard(self): self.save_new_default_exploration(self.EXP_ID, self.OWNER_ID, title=self.EXP_TITLE) rights_manager.assign_role(self.OWNER_ID, self.EXP_ID, self.COLLABORATOR_ID, rights_manager.ROLE_EDITOR) self.set_admins([self.OWNER_EMAIL]) self.login(self.COLLABORATOR_EMAIL) response = self.get_json('/dashboardhandler/data') self.assertEqual(len(response['explorations']), 1) self.assertIn(self.EXP_ID, response['explorations']) self.assertEqual( response['explorations'][self.EXP_ID]['rights']['status'], rights_manager.EXPLORATION_STATUS_PRIVATE) rights_manager.publish_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(len(response['explorations']), 1) self.assertIn(self.EXP_ID, response['explorations']) self.assertEqual( response['explorations'][self.EXP_ID]['rights']['status'], rights_manager.EXPLORATION_STATUS_PUBLIC) rights_manager.publicize_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(len(response['explorations']), 1) self.assertIn(self.EXP_ID, response['explorations']) self.assertEqual( response['explorations'][self.EXP_ID]['rights']['status'], rights_manager.EXPLORATION_STATUS_PUBLICIZED) self.logout()
def test_for_featured_explorations(self): """Note that EXP_ID_1 is public, and EXP_ID_2 is publicized. The call to get_featured_explorations() should only return [EXP_ID_2]. """ rights_manager.publicize_exploration(self.admin_id, self.EXP_ID_2) featured_exploration_summaries = ( summary_services.get_featured_exploration_summary_dicts([ feconf.DEFAULT_LANGUAGE_CODE])) expected_summary = { 'status': u'publicized', 'thumbnail_bg_color': '#a33f40', 'community_owned': False, 'tags': [], 'thumbnail_icon_url': '/images/subjects/Lightbulb.svg', 'language_code': feconf.DEFAULT_LANGUAGE_CODE, 'id': self.EXP_ID_2, 'category': u'A category', 'ratings': feconf.get_empty_ratings(), 'title': u'A title', 'num_views': 0, 'objective': u'An objective' } self.assertDictContainsSubset( expected_summary, featured_exploration_summaries[0])
def put(self, exploration_id): """Updates the publication status of the given exploration, and sends an email to all its owners. """ exploration = exp_services.get_exploration_by_id(exploration_id) action = self.payload.get('action') email_body = self.payload.get('email_body') version = self.payload.get('version') _require_valid_version(version, exploration.version) if action not in feconf.VALID_MODERATOR_ACTIONS: raise self.InvalidInputException('Invalid moderator action.') # If moderator emails can be sent, check that all the prerequisites are # satisfied, otherwise do nothing. if feconf.REQUIRE_EMAIL_ON_MODERATOR_ACTION: if not email_body: raise self.InvalidInputException( 'Moderator actions should include an email to the ' 'recipient.') email_manager.require_moderator_email_prereqs_are_satisfied() # Perform the moderator action. if action == 'unpublish_exploration': rights_manager.unpublish_exploration( self.user_id, exploration_id) exp_services.delete_documents_from_search_index([ exploration_id]) elif action == 'publicize_exploration': try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.publicize_exploration( self.user_id, exploration_id) else: raise self.InvalidInputException( 'No change was made to this exploration.') exp_rights = rights_manager.get_exploration_rights(exploration_id) # If moderator emails can be sent, send an email to the all owners of # the exploration notifying them of the change. if feconf.REQUIRE_EMAIL_ON_MODERATOR_ACTION: for owner_id in exp_rights.owner_ids: email_manager.send_moderator_action_email( self.user_id, owner_id, feconf.VALID_MODERATOR_ACTIONS[action]['email_intent'], exploration.title, email_body) self.render_json({ 'rights': exp_rights.to_dict(), })
def test_get_item_similarity(self): exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual( recommendations_services.get_item_similarity( exp_summaries['exp_id_1'].category, exp_summaries['exp_id_1'].language_code, exp_summaries['exp_id_1'].owner_ids, exp_summaries['exp_id_2'].category, exp_summaries['exp_id_2'].language_code, exp_summaries['exp_id_2'].exploration_model_last_updated, exp_summaries['exp_id_2'].owner_ids, exp_summaries['exp_id_2'].status), 4.5) self.assertEqual( recommendations_services.get_item_similarity( exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].exploration_model_last_updated, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].status), 9.0) rights_manager.publicize_exploration(self.admin_id, 'exp_id_4') exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual( recommendations_services.get_item_similarity( exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].exploration_model_last_updated, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].status), 10.0) rights_manager.unpublish_exploration(self.admin_id, 'exp_id_2') exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual( recommendations_services.get_item_similarity( exp_summaries['exp_id_1'].category, exp_summaries['exp_id_1'].language_code, exp_summaries['exp_id_1'].owner_ids, exp_summaries['exp_id_2'].category, exp_summaries['exp_id_2'].language_code, exp_summaries['exp_id_2'].exploration_model_last_updated, exp_summaries['exp_id_2'].owner_ids, exp_summaries['exp_id_2'].status), 0.0)
def test_get_item_similarity(self): exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual(recommendations_services.get_item_similarity( exp_summaries['exp_id_1'].category, exp_summaries['exp_id_1'].language_code, exp_summaries['exp_id_1'].owner_ids, exp_summaries['exp_id_2'].category, exp_summaries['exp_id_2'].language_code, exp_summaries['exp_id_2'].exploration_model_last_updated, exp_summaries['exp_id_2'].owner_ids, exp_summaries['exp_id_2'].status), 4.5) self.assertEqual(recommendations_services.get_item_similarity( exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].exploration_model_last_updated, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].status), 9.0) rights_manager.publicize_exploration(self.admin_id, 'exp_id_4') exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual(recommendations_services.get_item_similarity( exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].category, exp_summaries['exp_id_4'].language_code, exp_summaries['exp_id_4'].exploration_model_last_updated, exp_summaries['exp_id_4'].owner_ids, exp_summaries['exp_id_4'].status), 10.0) rights_manager.unpublish_exploration(self.admin_id, 'exp_id_2') exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual(recommendations_services.get_item_similarity( exp_summaries['exp_id_1'].category, exp_summaries['exp_id_1'].language_code, exp_summaries['exp_id_1'].owner_ids, exp_summaries['exp_id_2'].category, exp_summaries['exp_id_2'].language_code, exp_summaries['exp_id_2'].exploration_model_last_updated, exp_summaries['exp_id_2'].owner_ids, exp_summaries['exp_id_2'].status), 0.0)
def test_get_item_similarity(self): with self.assertRaisesRegexp( Exception, 'Invalid reference_exp_id fake_exp_id'): recommendations_services.get_item_similarity( 'fake_exp_id', 'fake_exp_id_2') self.assertEqual(recommendations_services.get_item_similarity( 'exp_id_1', 'exp_id_2'), 4.5) self.assertEqual(recommendations_services.get_item_similarity( 'exp_id_4', 'exp_id_4'), 9.0) rights_manager.publicize_exploration(self.ADMIN_ID, 'exp_id_4') self.assertEqual(recommendations_services.get_item_similarity( 'exp_id_4', 'exp_id_4'), 10.0) rights_manager.unpublish_exploration(self.ADMIN_ID, 'exp_id_2') self.assertEqual(recommendations_services.get_item_similarity( 'exp_id_1', 'exp_id_2'), 0.0)
def test_viewer_cannot_see_explorations(self): self.save_new_default_exploration( self.EXP_ID, self.owner_id, title=self.EXP_TITLE) rights_manager.assign_role_for_exploration( self.owner_id, self.EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER) self.set_admins([self.OWNER_USERNAME]) self.login(self.VIEWER_EMAIL) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publish_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) rights_manager.publicize_exploration(self.owner_id, self.EXP_ID) response = self.get_json(feconf.DASHBOARD_DATA_URL) self.assertEqual(response['explorations_list'], []) self.logout()
def test_viewer_cannot_see_explorations_on_dashboard(self): self.save_new_default_exploration( self.EXP_ID, self.OWNER_ID, title=self.EXP_TITLE) rights_manager.assign_role( self.OWNER_ID, self.EXP_ID, self.VIEWER_ID, rights_manager.ROLE_VIEWER) self.login(self.VIEWER_EMAIL) response = self.get_json('/dashboardhandler/data') self.assertEqual(response['explorations'], {}) rights_manager.publish_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(response['explorations'], {}) self.set_admins([self.OWNER_EMAIL]) rights_manager.publicize_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(response['explorations'], {}) self.logout()
def test_viewer_cannot_see_explorations_on_dashboard(self): self.save_new_default_exploration(self.EXP_ID, self.OWNER_ID, title=self.EXP_TITLE) rights_manager.assign_role(self.OWNER_ID, self.EXP_ID, self.VIEWER_ID, rights_manager.ROLE_VIEWER) self.login(self.VIEWER_EMAIL) response = self.get_json('/dashboardhandler/data') self.assertEqual(response['explorations'], {}) rights_manager.publish_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(response['explorations'], {}) self.set_admins([self.OWNER_EMAIL]) rights_manager.publicize_exploration(self.OWNER_ID, self.EXP_ID) response = self.get_json('/dashboardhandler/data') self.assertEqual(response['explorations'], {}) self.logout()
def test_get_non_private_explorations_summary_dict(self): self.save_new_default_exploration(self.EXP_ID) self.assertEqual( exp_services.get_non_private_explorations_summary_dict(), {}) rights_manager.publish_exploration(self.OWNER_ID, self.EXP_ID) self.assertEqual( exp_services.get_non_private_explorations_summary_dict(), { self.EXP_ID: { 'title': 'A title', 'category': 'A category', 'rights': { 'owner_names': [self.OWNER_NAME], 'editor_names': [], 'viewer_names': [], 'community_owned': False, 'cloned_from': None, 'status': rights_manager.EXPLORATION_STATUS_PUBLIC } } } ) rights_manager.publicize_exploration(self.user_id_admin, self.EXP_ID) self.assertEqual( exp_services.get_non_private_explorations_summary_dict(), { self.EXP_ID: { 'title': 'A title', 'category': 'A category', 'rights': { 'owner_names': [self.OWNER_NAME], 'editor_names': [], 'viewer_names': [], 'community_owned': False, 'cloned_from': None, 'status': rights_manager.EXPLORATION_STATUS_PUBLICIZED } } } )
def put(self, exploration_id): """Updates the editing rights for the given exploration.""" exploration = exp_services.get_exploration_by_id(exploration_id) version = self.payload.get('version') _require_valid_version(version, exploration.version) is_public = self.payload.get('is_public') is_publicized = self.payload.get('is_publicized') is_community_owned = self.payload.get('is_community_owned') new_member_username = self.payload.get('new_member_username') new_member_role = self.payload.get('new_member_role') viewable_if_private = self.payload.get('viewable_if_private') if new_member_username: if not rights_manager.Actor(self.user_id).can_modify_roles( rights_manager.ACTIVITY_TYPE_EXPLORATION, exploration_id): raise self.UnauthorizedUserException( 'Only an owner of this exploration can add or change ' 'roles.') new_member_id = user_services.get_user_id_from_username( new_member_username) if new_member_id is None: raise Exception('Sorry, we could not find the specified user.') rights_manager.assign_role_for_exploration(self.user_id, exploration_id, new_member_id, new_member_role) elif is_public is not None: exploration = exp_services.get_exploration_by_id(exploration_id) if is_public: try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) exp_services.publish_exploration_and_update_user_profiles( self.user_id, exploration_id) exp_services.index_explorations_given_ids([exploration_id]) else: rights_manager.unpublish_exploration(self.user_id, exploration_id) exp_services.delete_documents_from_search_index( [exploration_id]) elif is_publicized is not None: exploration = exp_services.get_exploration_by_id(exploration_id) if is_publicized: try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.publicize_exploration(self.user_id, exploration_id) else: rights_manager.unpublicize_exploration(self.user_id, exploration_id) elif is_community_owned: exploration = exp_services.get_exploration_by_id(exploration_id) try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.release_ownership_of_exploration( self.user_id, exploration_id) elif viewable_if_private is not None: rights_manager.set_private_viewability_of_exploration( self.user_id, exploration_id, viewable_if_private) else: raise self.InvalidInputException( 'No change was made to this exploration.') self.render_json({ 'rights': rights_manager.get_exploration_rights(exploration_id).to_dict() })
def put(self, exploration_id): """Updates the editing rights for the given exploration.""" exploration = exp_services.get_exploration_by_id(exploration_id) version = self.payload.get('version') _require_valid_version(version, exploration.version) is_public = self.payload.get('is_public') is_publicized = self.payload.get('is_publicized') is_community_owned = self.payload.get('is_community_owned') new_member_email = self.payload.get('new_member_email') new_member_role = self.payload.get('new_member_role') if new_member_email: if not rights_manager.Actor(self.user_id).can_modify_roles( exploration_id): raise self.UnauthorizedUserException( 'Only an owner of this exploration can add or change ' 'roles.') new_member_id = user_services.get_user_id_from_email( new_member_email) if new_member_id is None: raise Exception( 'Sorry, we could not find a user with this email address.') user_services.get_or_create_user(new_member_id, new_member_email) rights_manager.assign_role( self.user_id, exploration_id, new_member_id, new_member_role) elif is_public is not None: exploration = exp_services.get_exploration_by_id(exploration_id) if is_public: try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.publish_exploration( self.user_id, exploration_id) else: rights_manager.unpublish_exploration( self.user_id, exploration_id) elif is_publicized is not None: exploration = exp_services.get_exploration_by_id(exploration_id) if is_publicized: try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.publicize_exploration( self.user_id, exploration_id) else: rights_manager.unpublicize_exploration( self.user_id, exploration_id) elif is_community_owned: exploration = exp_services.get_exploration_by_id(exploration_id) try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.release_ownership(self.user_id, exploration_id) else: raise self.InvalidInputException( 'No change was made to this exploration.') self.render_json({ 'rights': rights_manager.get_exploration_rights( exploration_id).to_dict() })
def test_get_item_similarity(self): exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual( recommendations_services.get_item_similarity( exp_summaries["exp_id_1"].category, exp_summaries["exp_id_1"].language_code, exp_summaries["exp_id_1"].owner_ids, exp_summaries["exp_id_2"].category, exp_summaries["exp_id_2"].language_code, exp_summaries["exp_id_2"].exploration_model_last_updated, exp_summaries["exp_id_2"].owner_ids, exp_summaries["exp_id_2"].status, ), 4.5, ) self.assertEqual( recommendations_services.get_item_similarity( exp_summaries["exp_id_4"].category, exp_summaries["exp_id_4"].language_code, exp_summaries["exp_id_4"].owner_ids, exp_summaries["exp_id_4"].category, exp_summaries["exp_id_4"].language_code, exp_summaries["exp_id_4"].exploration_model_last_updated, exp_summaries["exp_id_4"].owner_ids, exp_summaries["exp_id_4"].status, ), 9.0, ) rights_manager.publicize_exploration(self.ADMIN_ID, "exp_id_4") exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual( recommendations_services.get_item_similarity( exp_summaries["exp_id_4"].category, exp_summaries["exp_id_4"].language_code, exp_summaries["exp_id_4"].owner_ids, exp_summaries["exp_id_4"].category, exp_summaries["exp_id_4"].language_code, exp_summaries["exp_id_4"].exploration_model_last_updated, exp_summaries["exp_id_4"].owner_ids, exp_summaries["exp_id_4"].status, ), 10.0, ) rights_manager.unpublish_exploration(self.ADMIN_ID, "exp_id_2") exp_summaries = exp_services.get_all_exploration_summaries() self.assertEqual( recommendations_services.get_item_similarity( exp_summaries["exp_id_1"].category, exp_summaries["exp_id_1"].language_code, exp_summaries["exp_id_1"].owner_ids, exp_summaries["exp_id_2"].category, exp_summaries["exp_id_2"].language_code, exp_summaries["exp_id_2"].exploration_model_last_updated, exp_summaries["exp_id_2"].owner_ids, exp_summaries["exp_id_2"].status, ), 0.0, )
def put(self, exploration_id): """Updates the editing rights for the given exploration.""" exploration = exp_services.get_exploration_by_id(exploration_id) version = self.payload.get('version') _require_valid_version(version, exploration.version) is_public = self.payload.get('is_public') is_publicized = self.payload.get('is_publicized') is_community_owned = self.payload.get('is_community_owned') new_member_username = self.payload.get('new_member_username') new_member_role = self.payload.get('new_member_role') viewable_if_private = self.payload.get('viewable_if_private') if new_member_username: if not rights_manager.Actor( self.user_id).can_modify_roles( rights_manager.ACTIVITY_TYPE_EXPLORATION, exploration_id): raise self.UnauthorizedUserException( 'Only an owner of this exploration can add or change ' 'roles.') new_member_id = user_services.get_user_id_from_username( new_member_username) if new_member_id is None: raise Exception( 'Sorry, we could not find the specified user.') rights_manager.assign_role_for_exploration( self.user_id, exploration_id, new_member_id, new_member_role) elif is_public is not None: exploration = exp_services.get_exploration_by_id(exploration_id) if is_public: try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) exp_services.publish_exploration_and_update_user_profiles( self.user_id, exploration_id) exp_services.index_explorations_given_ids([exploration_id]) else: rights_manager.unpublish_exploration( self.user_id, exploration_id) exp_services.delete_documents_from_search_index([ exploration_id]) elif is_publicized is not None: exploration = exp_services.get_exploration_by_id(exploration_id) if is_publicized: try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.publicize_exploration( self.user_id, exploration_id) else: rights_manager.unpublicize_exploration( self.user_id, exploration_id) elif is_community_owned: exploration = exp_services.get_exploration_by_id(exploration_id) try: exploration.validate(strict=True) except utils.ValidationError as e: raise self.InvalidInputException(e) rights_manager.release_ownership_of_exploration( self.user_id, exploration_id) elif viewable_if_private is not None: rights_manager.set_private_viewability_of_exploration( self.user_id, exploration_id, viewable_if_private) else: raise self.InvalidInputException( 'No change was made to this exploration.') self.render_json({ 'rights': rights_manager.get_exploration_rights( exploration_id).to_dict() })
def _run_batch_job_once_and_verify_output( self, exp_specs, default_title='A title', default_category='A category', default_status=rights_manager.ACTIVITY_STATUS_PUBLICIZED): """Run batch job for creating exploration summaries once and verify its output. exp_specs is a list of dicts with exploration specifications. Allowed keys are category, status, title. If a key is not specified, the default value is used. """ with self.swap( jobs_registry, 'ONE_OFF_JOB_MANAGERS', self.ONE_OFF_JOB_MANAGERS_FOR_TESTS ): default_spec = { 'title': default_title, 'category': default_category, 'status': default_status } self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.login(self.ADMIN_EMAIL) admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL) self.set_admins([self.ADMIN_USERNAME]) # Create and delete an exploration (to make sure job handles # deleted explorations correctly). exp_id = '100' self.save_new_valid_exploration( exp_id, admin_id, title=default_spec['title'], category=default_spec['category']) exploration = exp_services.get_exploration_by_id(exp_id) exp_services.delete_exploration(admin_id, exp_id) # Get dummy explorations. num_exps = len(exp_specs) expected_job_output = {} for ind in range(num_exps): exp_id = str(ind) spec = default_spec spec.update(exp_specs[ind]) self.save_new_valid_exploration( exp_id, admin_id, title=spec['title'], category=spec['category']) exploration = exp_services.get_exploration_by_id(exp_id) # Publish or publicize exploration. if spec['status'] == rights_manager.ACTIVITY_STATUS_PUBLIC: rights_manager.publish_exploration(admin_id, exp_id) elif ( spec['status'] == rights_manager.ACTIVITY_STATUS_PUBLICIZED): rights_manager.publish_exploration(admin_id, exp_id) rights_manager.publicize_exploration(admin_id, exp_id) # Do not include user_id here, so all explorations are not # editable for now (will be updated depending on user_id # in galleries) exp_rights_model = exp_models.ExplorationRightsModel.get( exp_id) exploration = exp_services.get_exploration_by_id(exp_id) exploration_model_last_updated = exploration.last_updated exploration_model_created_on = exploration.created_on # Manually create the expected summary specifying title, # category, etc. expected_job_output[exp_id] = exp_domain.ExplorationSummary( exp_id, spec['title'], spec['category'], exploration.objective, exploration.language_code, exploration.tags, feconf.get_empty_ratings(), spec['status'], exp_rights_model.community_owned, exp_rights_model.owner_ids, exp_rights_model.editor_ids, exp_rights_model.viewer_ids, [admin_id], {admin_id: 1}, exploration.version, exploration_model_created_on, exploration_model_last_updated) # Note: Calling constructor for fields that are not required # and have no default value does not work, because # unspecified fields will be empty list in # expected_job_output but will be unspecified in # actual_job_output. if exploration.tags: expected_job_output[exp_id].tags = exploration.tags if exp_rights_model.owner_ids: expected_job_output[exp_id].owner_ids = ( exp_rights_model.owner_ids) if exp_rights_model.editor_ids: expected_job_output[exp_id].editor_ids = ( exp_rights_model.editor_ids) if exp_rights_model.viewer_ids: expected_job_output[exp_id].viewer_ids = ( exp_rights_model.viewer_ids) if exploration.version: expected_job_output[exp_id].version = ( exploration.version) # Run batch job. job_id = ( exp_jobs_one_off.ExpSummariesCreationOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesCreationOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Get and check job output. actual_job_output = exp_services.get_all_exploration_summaries() self.assertEqual( actual_job_output.keys(), expected_job_output.keys()) # Note: 'exploration_model_last_updated' is not expected to be the # same, because it is now read from the version model representing # the exploration's history snapshot, and not the ExplorationModel. simple_props = ['id', 'title', 'category', 'objective', 'language_code', 'tags', 'ratings', 'status', 'community_owned', 'owner_ids', 'editor_ids', 'viewer_ids', 'contributor_ids', 'contributors_summary', 'version', 'exploration_model_created_on'] for exp_id in actual_job_output: for prop in simple_props: self.assertEqual( getattr(actual_job_output[exp_id], prop), getattr(expected_job_output[exp_id], prop))
def test_library_handler_demo_exploration(self): """Test the library data handler on demo explorations.""" response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual( { 'is_admin': False, 'is_moderator': False, 'is_super_admin': False, 'explorations_list': [], 'search_cursor': None, 'profile_picture_data_url': None, }, response_dict) # Load a public demo exploration. exp_services.load_demo('0') # Load the search results with an empty query. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(len(response_dict['explorations_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['explorations_list'][0]) # Publicize the demo exploration. self.set_admins([self.ADMIN_USERNAME]) rights_manager.publicize_exploration(self.admin_id, '0') # Run migration job to create exploration summaries. # This is not necessary, but serves as additional check that # the migration job works well and gives correct results. self.process_and_flush_pending_tasks() job_id = (exp_jobs_one_off.ExpSummariesCreationOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesCreationOneOffJob.enqueue(job_id) self.assertGreaterEqual(self.count_jobs_in_taskqueue(), 1) self.process_and_flush_pending_tasks() self.assertEqual(self.count_jobs_in_taskqueue(), 0) # change title and category exp_services.update_exploration(self.editor_id, '0', [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'A new title!' }, { 'cmd': 'edit_exploration_property', 'property_name': 'category', 'new_value': 'A new category' }], 'Change title and category') # Load the search results with an empty query. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset( { 'id': '0', 'category': 'A new category', 'title': 'A new title!', 'language_code': 'en', 'objective': 'become familiar with Oppia\'s capabilities', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def test_library_handler_for_created_explorations(self): """Test the library data handler for manually created explirations.""" self.set_admins([self.ADMIN_USERNAME]) self.login(self.ADMIN_EMAIL) response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertDictContainsSubset( { 'is_admin': True, 'is_moderator': True, 'is_super_admin': False, 'explorations_list': [], 'user_email': self.ADMIN_EMAIL, 'username': self.ADMIN_USERNAME, 'search_cursor': None, }, response_dict) # Create exploration A exploration = self.save_new_valid_exploration('A', self.admin_id, title='Title A', category='Category A', objective='Objective A') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration A', []) # Test that the private exploration isn't displayed. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(response_dict['explorations_list'], []) # Create exploration B exploration = self.save_new_valid_exploration('B', self.admin_id, title='Title B', category='Category B', objective='Objective B') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration B', []) rights_manager.publish_exploration(self.admin_id, 'B') rights_manager.publicize_exploration(self.admin_id, 'B') # Publish exploration A rights_manager.publish_exploration(self.admin_id, 'A') exp_services.index_explorations_given_ids(['A', 'B']) # Load the search results with an empty query. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 2) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0]) self.assertDictContainsSubset( { 'id': 'A', 'category': 'Category A', 'title': 'Title A', 'language_code': 'en', 'objective': 'Objective A', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['explorations_list'][1]) # Delete exploration A exp_services.delete_exploration(self.admin_id, 'A') # Load the search results with an empty query. response_dict = self.get_json(feconf.LIBRARY_SEARCH_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def test_gallery_handler_for_created_explorations(self): """Test the gallery data handler for manually created explirations.""" self.set_admins([self.ADMIN_USERNAME]) self.login(self.ADMIN_EMAIL) response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual({ 'is_admin': True, 'is_moderator': True, 'is_super_admin': False, 'explorations_list': [], 'user_email': self.ADMIN_EMAIL, 'username': self.ADMIN_USERNAME, 'search_cursor': None, 'profile_picture_data_url': None, 'preferred_language_codes': [feconf.DEFAULT_LANGUAGE_CODE], }, response_dict) # Create exploration A exploration = self.save_new_valid_exploration( 'A', self.admin_id, title='Title A', category='Category A', objective='Objective A') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration A', []) # Test that the private exploration isn't displayed. response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(response_dict['explorations_list'], []) # Create exploration B exploration = self.save_new_valid_exploration( 'B', self.admin_id, title='Title B', category='Category B', objective='Objective B') exp_services._save_exploration( # pylint: disable=protected-access self.admin_id, exploration, 'Exploration B', []) rights_manager.publish_exploration(self.admin_id, 'B') rights_manager.publicize_exploration(self.admin_id, 'B') # Publish exploration A rights_manager.publish_exploration(self.admin_id, 'A') exp_services.index_explorations_given_ids(['A', 'B']) # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 2) self.assertDictContainsSubset({ 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0]) self.assertDictContainsSubset({ 'id': 'A', 'category': 'Category A', 'title': 'Title A', 'language_code': 'en', 'objective': 'Objective A', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['explorations_list'][1]) # Delete exploration A exp_services.delete_exploration(self.admin_id, 'A') # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset({ 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def test_gallery_handler_for_created_explorations(self): """Test the gallery data handler for manually created explirations.""" self.set_admins([self.ADMIN_EMAIL]) self.login(self.ADMIN_EMAIL) response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual( { 'is_admin': True, 'is_moderator': True, 'is_super_admin': False, 'explorations_list': [], 'user_email': self.ADMIN_EMAIL, 'username': self.ADMIN_USERNAME, 'search_cursor': None, 'profile_picture_data_url': None, 'preferred_language_codes': [feconf.DEFAULT_LANGUAGE_CODE], }, response_dict) # Create exploration A exploration = self.save_new_valid_exploration('A', self.ADMIN_ID, title='Title A', category='Category A', objective='Objective A') exp_services._save_exploration(self.ADMIN_ID, exploration, 'Exploration A', []) # Test that the private exploration isn't displayed. response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(response_dict['explorations_list'], []) # Create exploration B exploration = self.save_new_valid_exploration('B', self.ADMIN_ID, title='Title B', category='Category B', objective='Objective B') exp_services._save_exploration(self.ADMIN_ID, exploration, 'Exploration B', []) rights_manager.publish_exploration(self.ADMIN_ID, 'B') rights_manager.publicize_exploration(self.ADMIN_ID, 'B') # Publish exploration A rights_manager.publish_exploration(self.ADMIN_ID, 'A') exp_services.index_explorations_given_ids(['A', 'B']) # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 2) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0]) self.assertDictContainsSubset( { 'id': 'A', 'category': 'Category A', 'title': 'Title A', 'language_code': 'en', 'objective': 'Objective A', 'status': rights_manager.ACTIVITY_STATUS_PUBLIC, }, response_dict['explorations_list'][1]) # Delete exploration A exp_services.delete_exploration(self.ADMIN_ID, 'A') # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset( { 'id': 'B', 'category': 'Category B', 'title': 'Title B', 'language_code': 'en', 'objective': 'Objective B', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def test_gallery_handler_demo_exploration(self): """Test the gallery data handler on demo explorations.""" response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual({ 'is_admin': False, 'is_moderator': False, 'is_super_admin': False, 'explorations_list': [], 'search_cursor': None, 'profile_picture_data_url': None, 'preferred_language_codes': [feconf.DEFAULT_LANGUAGE_CODE], }, response_dict) # Load a public demo exploration. exp_services.load_demo('0') # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_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['explorations_list'][0]) # Publicize the demo exploration. self.set_admins([self.ADMIN_USERNAME]) rights_manager.publicize_exploration(self.admin_id, '0') # Run migration job to create exploration summaries. # This is not necessary, but serves as additional check that # the migration job works well and gives correct galleries. self.process_and_flush_pending_tasks() job_id = (exp_jobs_one_off.ExpSummariesCreationOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesCreationOneOffJob.enqueue(job_id) self.assertGreaterEqual(self.count_jobs_in_taskqueue(), 1) self.process_and_flush_pending_tasks() self.assertEqual(self.count_jobs_in_taskqueue(), 0) # change title and category exp_services.update_exploration( self.editor_id, '0', [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'A new title!' }, { 'cmd': 'edit_exploration_property', 'property_name': 'category', 'new_value': 'A new category' }], 'Change title and category') # Test gallery response_dict = self.get_json(feconf.GALLERY_DATA_URL) self.assertEqual(len(response_dict['explorations_list']), 1) self.assertDictContainsSubset({ 'id': '0', 'category': 'A new category', 'title': 'A new title!', 'language_code': 'en', 'objective': 'become familiar with Oppia\'s capabilities', 'status': rights_manager.ACTIVITY_STATUS_PUBLICIZED, }, response_dict['explorations_list'][0])
def _run_batch_job_once_and_verify_output( self, exp_specs, default_title='A title', default_category='A category', default_status=rights_manager.EXPLORATION_STATUS_PUBLICIZED): """Run batch job for creating exploration summaries once and verify its output. exp_specs is a list of dicts with exploration specifications. Allowed keys are category, status, title. If a key is not specified, the default value is taken. """ from core.domain import exp_services with self.swap( jobs_registry, 'ONE_OFF_JOB_MANAGERS', self.ONE_OFF_JOB_MANAGERS_FOR_TESTS): # default specs default_specs = {'title': default_title, 'category': default_category, 'status': default_status} self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME) self.login(self.ADMIN_EMAIL) self.ADMIN_ID = self.get_user_id_from_email(self.ADMIN_EMAIL) self.set_admins([self.ADMIN_EMAIL]) # create and delete an exploration (to make sure job handles # deleted explorations correctly) exp_id = '100' self.save_new_valid_exploration( exp_id, self.ADMIN_ID, title=default_specs['title'], category=default_specs['category']) exploration = exp_services.get_exploration_by_id(exp_id) exp_services.delete_exploration(self.ADMIN_ID, exp_id) # get dummy explorations num_exps = len(exp_specs) expected_job_output = {} for ind in range(num_exps): exp_id = str(ind) spec = default_specs spec.update(exp_specs[ind]) self.save_new_valid_exploration( exp_id, self.ADMIN_ID, title=spec['title'], category=spec['category']) exploration = exp_services.get_exploration_by_id(exp_id) # publish or publicize exploration if spec['status'] == rights_manager.EXPLORATION_STATUS_PUBLIC: rights_manager.publish_exploration(self.ADMIN_ID, exp_id) elif (spec['status'] == rights_manager.EXPLORATION_STATUS_PUBLICIZED): rights_manager.publish_exploration(self.ADMIN_ID, exp_id) rights_manager.publicize_exploration(self.ADMIN_ID, exp_id) # do not include user_id here, so all explorations are not # editable for now (will be updated depending on user_id # in galleries) exp_rights_model = exp_models.ExplorationRightsModel.get( exp_id) exploration = exp_services.get_exploration_by_id(exp_id) exploration_model_last_updated = exploration.last_updated exploration_model_created_on = exploration.created_on # manually create the expectated summary specifying title, # category, etc expected_job_output[exp_id] = exp_domain.ExplorationSummary( exp_id, spec['title'], spec['category'], exploration.objective, exploration.language_code, exploration.skill_tags, spec['status'], exp_rights_model.community_owned, exp_rights_model.owner_ids, exp_rights_model.editor_ids, exp_rights_model.viewer_ids, exploration.version, exploration_model_created_on, exploration_model_last_updated) # calling constructor for fields that are not required # and have no default value does not work b/c # unspecified fields will be empty list in # expected_job_output but will be unspecified in # actual_job_output if exploration.skill_tags: expected_job_output[exp_id].skill_tags = ( exploration.skill_tags) if exp_rights_model.owner_ids: expected_job_output[exp_id].owner_ids = ( exp_rights_model.owner_ids) if exp_rights_model.editor_ids: expected_job_output[exp_id].editor_ids = ( exp_rights_model.editor_ids) if exp_rights_model.viewer_ids: expected_job_output[exp_id].viewer_ids = ( exp_rights_model.viewer_ids) if exploration.version: expected_job_output[exp_id].version = ( exploration.version) # run batch job job_id = exp_jobs.ExpSummariesCreationOneOffJob.create_new() exp_jobs.ExpSummariesCreationOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # get job output actual_job_output = exp_services.get_all_exploration_summaries() # check job output self.assertEqual(actual_job_output.keys(), expected_job_output.keys()) simple_props = ['id', 'title', 'category', 'objective', 'language_code', 'skill_tags', 'status', 'community_owned', 'owner_ids', 'editor_ids', 'viewer_ids', 'version', 'exploration_model_created_on', 'exploration_model_last_updated'] for exp_id in actual_job_output: for prop in simple_props: self.assertEqual( getattr(actual_job_output[exp_id], prop), getattr(expected_job_output[exp_id], prop))