예제 #1
0
    def put(self, collection_id):
        """Updates properties of the given collection."""

        collection = collection_services.get_collection_by_id(collection_id)
        version = self.payload.get('version')
        self._require_valid_version(version, collection.version)

        commit_message = self.payload.get('commit_message')
        change_list = self.payload.get('change_list')

        try:
            collection_services.update_collection(
                self.user_id, collection_id, change_list, commit_message)
        except utils.ValidationError as e:
            raise self.InvalidInputException(e)

        collection_dict = (
            summary_services.get_learner_collection_dict_by_id(
                collection_id, self.user_id, allow_invalid_explorations=True))

        # Send the updated collection back to the frontend.
        self.values.update({
            'collection': collection_dict
        })

        self.render_json(self.values)
예제 #2
0
    def put(self, collection_id):
        """Updates properties of the given collection."""

        collection = collection_services.get_collection_by_id(collection_id)
        version = self.payload.get('version')
        _require_valid_version(version, collection.version)

        commit_message = self.payload.get('commit_message')

        if (commit_message is not None
                and len(commit_message) > constants.MAX_COMMIT_MESSAGE_LENGTH):
            raise self.InvalidInputException(
                'Commit messages must be at most %s characters long.' %
                constants.MAX_COMMIT_MESSAGE_LENGTH)

        change_list = self.payload.get('change_list')

        collection_services.update_collection(self.user_id, collection_id,
                                              change_list, commit_message)

        collection_dict = (summary_services.get_learner_collection_dict_by_id(
            collection_id, self.user, allow_invalid_explorations=True))

        # Send the updated collection back to the frontend.
        self.values.update({'collection': collection_dict})

        self.render_json(self.values)
예제 #3
0
    def map(item):
        if item.deleted:
            yield (CollectionMigrationJob._DELETED_KEY,
                   'Encountered deleted collection.')
            return

        # Note: the read will bring the collection up to the newest version.
        collection = collection_services.get_collection_by_id(item.id)
        try:
            collection.validate(strict=False)
        except Exception as e:
            logging.error(
                'Collection %s failed validation: %s' % (item.id, e))
            yield (CollectionMigrationJob._ERROR_KEY,
                   'Collection %s failed validation: %s' % (item.id, e))
            return

        # Write the new collection into the datastore if it's different from
        # the old version.
        if item.schema_version <= feconf.CURRENT_COLLECTION_SCHEMA_VERSION:
            commit_cmds = [{
                'cmd': collection_domain.CMD_MIGRATE_SCHEMA_TO_LATEST_VERSION,
                'from_version': item.schema_version,
                'to_version': str(
                    feconf.CURRENT_COLLECTION_SCHEMA_VERSION)
            }]
            collection_services.update_collection(
                feconf.MIGRATION_BOT_USERNAME, item.id, commit_cmds,
                'Update collection schema version to %d.' % (
                    feconf.CURRENT_COLLECTION_SCHEMA_VERSION))
            yield (CollectionMigrationJob._MIGRATED_KEY,
                   'Collection successfully migrated.')
예제 #4
0
    def test_basic_computation_with_an_update_after_collection_is_created(self):
        with self._get_test_context():
            self.save_new_default_collection(
                COLLECTION_ID, USER_ID, title=COLLECTION_TITLE)
            # Another user makes a commit; this, too, shows up in the
            # original user's dashboard.
            collection_services.update_collection(
                ANOTHER_USER_ID, COLLECTION_ID, [{
                    'cmd': 'edit_collection_property',
                    'property_name': 'title',
                    'new_value': 'A new title'
                }], 'Update collection')
            expected_last_updated_ms = (
                self._get_most_recent_collection_snapshot_created_on_ms(
                    COLLECTION_ID))

            ModifiedRecentUpdatesAggregator.start_computation()
            self.assertEqual(
                self.count_jobs_in_taskqueue(
                    queue_name=taskqueue_services.QUEUE_NAME_DEFAULT),
                1)
            self.process_and_flush_pending_tasks()

            recent_notifications = (
                ModifiedRecentUpdatesAggregator.get_recent_notifications(
                    USER_ID)[1])
            self.assertEqual([{
                'type': feconf.UPDATE_TYPE_COLLECTION_COMMIT,
                'last_updated_ms': expected_last_updated_ms,
                'activity_id': COLLECTION_ID,
                'activity_title': 'A new title',
                'author_id': ANOTHER_USER_ID,
                'subject': 'Update collection',
            }], recent_notifications)
    def map(item):
        if item.deleted:
            yield (CollectionMigrationJob._DELETED_KEY,
                   'Encountered deleted collection.')
            return

        # Note: the read will bring the collection up to the newest version.
        collection = collection_services.get_collection_by_id(item.id)
        try:
            collection.validate(strict=False)
        except Exception as e:
            logging.error('Collection %s failed validation: %s' % (item.id, e))
            yield (CollectionMigrationJob._ERROR_KEY,
                   'Collection %s failed validation: %s' % (item.id, e))
            return

        # Write the new collection into the datastore if it's different from
        # the old version.
        if item.schema_version <= feconf.CURRENT_COLLECTION_SCHEMA_VERSION:
            commit_cmds = [{
                'cmd':
                collection_domain.CMD_MIGRATE_SCHEMA_TO_LATEST_VERSION,
                'from_version':
                item.schema_version,
                'to_version':
                str(feconf.CURRENT_COLLECTION_SCHEMA_VERSION)
            }]
            collection_services.update_collection(
                feconf.MIGRATION_BOT_USERNAME, item.id, commit_cmds,
                'Update collection schema version to %d.' %
                (feconf.CURRENT_COLLECTION_SCHEMA_VERSION))
            yield (CollectionMigrationJob._MIGRATED_KEY,
                   'Collection successfully migrated.')
예제 #6
0
    def put(self, collection_id):
        """Updates properties of the given collection."""

        collection = collection_services.get_collection_by_id(collection_id)
        version = self.payload.get('version')
        self._require_valid_version(version, collection.version)

        commit_message = self.payload.get('commit_message')
        change_list = self.payload.get('change_list')

        try:
            collection_services.update_collection(
                self.user_id, collection_id, change_list, commit_message)
        except utils.ValidationError as e:
            raise self.InvalidInputException(e)

        collection_dict = (
            summary_services.get_learner_collection_dict_by_id(
                collection_id, self.user_id, allow_invalid_explorations=True))

        # Send the updated collection back to the frontend.
        self.values.update({
            'collection': collection_dict
        })

        self.render_json(self.values)
예제 #7
0
    def test_contribution_msec_updates_on_published_collections(self):
        self.save_new_valid_collection(
            self.COL_ID, self.admin_id, title=self.COLLECTION_TITLE,
            category=self.COLLECTION_CATEGORY,
            objective=self.COLLECTION_OBJECTIVE,
            exploration_id=self.EXP_ID)

        collection_services.publish_collection_and_update_user_profiles(
            self.admin_id, self.COL_ID)
        exp_services.publish_exploration_and_update_user_profiles(
            self.admin_id, self.EXP_ID)

        # Test all owners and editors of collection after publication have
        # updated first contribution times.
        self.assertIsNotNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)

        # Test editor of published collection has updated
        # first contribution time.
        rights_manager.release_ownership_of_collection(
            self.admin_id, self.COL_ID)

        collection_services.update_collection(
            self.editor_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'title',
                'new_value': 'Some new title'
            }], 'Changed the title')

        self.assertIsNotNone(user_services.get_user_settings(
            self.editor_id).first_contribution_msec)
    def test_basic_computation_with_an_update_after_collection_is_created(
            self):
        with self._get_test_context():
            self.save_new_default_collection(COLLECTION_ID,
                                             USER_ID,
                                             title=COLLECTION_TITLE)
            # Another user makes a commit; this, too, shows up in the
            # original user's dashboard.
            collection_services.update_collection(
                ANOTHER_USER_ID, COLLECTION_ID, [{
                    'cmd': 'edit_collection_property',
                    'property_name': 'title',
                    'new_value': 'A new title'
                }], 'Update collection')
            expected_last_updated_ms = (
                self._get_most_recent_collection_snapshot_created_on_ms(
                    COLLECTION_ID))

            ModifiedRecentUpdatesAggregator.start_computation()
            self.assertEqual(
                self.count_jobs_in_taskqueue(
                    queue_name=taskqueue_services.QUEUE_NAME_DEFAULT), 1)
            self.process_and_flush_pending_tasks()

            recent_notifications = (ModifiedRecentUpdatesAggregator.
                                    get_recent_notifications(USER_ID)[1])
            self.assertEqual([{
                'type': feconf.UPDATE_TYPE_COLLECTION_COMMIT,
                'last_updated_ms': expected_last_updated_ms,
                'activity_id': COLLECTION_ID,
                'activity_title': 'A new title',
                'author_id': ANOTHER_USER_ID,
                'subject': 'Update collection',
            }], recent_notifications)
예제 #9
0
    def test_adding_exploration_to_collection_does_not_create_subscription(
            self):
        self.save_new_default_collection(COLLECTION_ID, self.owner_id)

        # The author is subscribed to the collection but to no explorations.
        self.assertEqual(
            self._get_collection_ids_subscribed_to(self.owner_id),
            [COLLECTION_ID])
        self.assertEqual(
            self._get_exploration_ids_subscribed_to(self.owner_id), [])

        # Another author creates an exploration.
        self.save_new_valid_exploration(EXP_ID, self.owner_2_id)

        # If the collection author adds the exploration to his/her collection,
        # the collection author should not be subscribed to the exploration nor
        # should the exploration author be subscribed to the collection.
        collection_services.update_collection(self.owner_id, COLLECTION_ID, [{
            'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
            'exploration_id': EXP_ID
        }], 'Add new exploration to collection.')

        # Ensure subscriptions are as expected.
        self.assertEqual(
            self._get_collection_ids_subscribed_to(self.owner_id),
            [COLLECTION_ID])
        self.assertEqual(
            self._get_exploration_ids_subscribed_to(self.owner_2_id), [EXP_ID])
예제 #10
0
    def map(item):
        if item.deleted:
            yield (CollectionMigrationOneOffJob._DELETED_KEY, 1)
            return

        # Note: the read will bring the collection up to the newest version.
        collection = collection_services.get_collection_by_id(item.id)
        try:
            collection.validate(strict=False)
        except Exception as e:
            logging.exception(
                'Collection %s failed validation: %s' % (item.id, e))
            yield (
                CollectionMigrationOneOffJob._ERROR_KEY,
                'Collection %s failed validation: %s' % (item.id, e))
            return

        # Write the new collection into the datastore if it's different from
        # the old version.
        #
        # Note: to_version really should be int, but left as str to conform
        # with legacy data.
        if item.schema_version <= feconf.CURRENT_COLLECTION_SCHEMA_VERSION:
            commit_cmds = [{
                'cmd': collection_domain.CMD_MIGRATE_SCHEMA_TO_LATEST_VERSION,
                'from_version': item.schema_version,
                'to_version': python_utils.UNICODE(
                    feconf.CURRENT_COLLECTION_SCHEMA_VERSION)
            }]
            collection_services.update_collection(
                feconf.MIGRATION_BOT_USERNAME, item.id, commit_cmds,
                'Update collection schema version to %d.' % (
                    feconf.CURRENT_COLLECTION_SCHEMA_VERSION))
            yield (CollectionMigrationOneOffJob._MIGRATED_KEY, 1)
예제 #11
0
    def test_contribution_msec_updates_on_published_collections(self):
        self.save_new_valid_collection(self.COL_ID,
                                       self.admin_id,
                                       title=self.COLLECTION_TITLE,
                                       category=self.COLLECTION_CATEGORY,
                                       objective=self.COLLECTION_OBJECTIVE,
                                       exploration_id=self.EXP_ID)

        collection_services.publish_collection_and_update_user_profiles(
            self.admin_id, self.COL_ID)
        exp_services.publish_exploration_and_update_user_profiles(
            self.admin_id, self.EXP_ID)

        # Test all owners and editors of collection after publication have
        # updated first contribution times.
        self.assertIsNotNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)

        # Test editor of published collection has updated
        # first contribution time.
        rights_manager.release_ownership_of_collection(self.admin_id,
                                                       self.COL_ID)

        collection_services.update_collection(
            self.editor_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'title',
                'new_value': 'Some new title'
            }], 'Changed the title')

        self.assertIsNotNone(
            user_services.get_user_settings(
                self.editor_id).first_contribution_msec)
예제 #12
0
    def setUp(self):
        super(QuestionsBatchHandlerTest, self).setUp()

        self.collection_id = 'coll_0'
        self.exp_id = 'exp_1'
        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)
        self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL)

        # Create a new collection and exploration.
        self.save_new_valid_collection(self.collection_id,
                                       self.owner_id,
                                       exploration_id=self.exp_id)

        # Add a skill.
        collection_services.update_collection(
            self.owner_id, self.collection_id, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_SKILL,
                'name': 'test'
            }], 'Add a new skill')
        collection = collection_services.get_collection_by_id(
            self.collection_id)
        self.skill_id = collection.get_skill_id_from_skill_name('test')
        collection_node = collection.get_node(self.exp_id)
        collection_node.update_acquired_skill_ids([self.skill_id])

        # Update the acquired skill IDs for the exploration.
        collection_services.update_collection(
            self.owner_id,
            self.collection_id,
            [{
                'cmd':
                collection_domain.CMD_EDIT_COLLECTION_NODE_PROPERTY,
                'property_name':
                (collection_domain.COLLECTION_NODE_PROPERTY_ACQUIRED_SKILL_IDS
                 ),  # pylint: disable=line-too-long
                'exploration_id':
                self.exp_id,
                'new_value': [self.skill_id]
            }],
            'Update skill')

        question = question_domain.Question(
            'dummy', 'A Question',
            exp_domain.State.create_default_state('ABC').to_dict(), 1,
            self.collection_id, 'en')

        question_id = question_services.add_question(self.owner_id, question)
        self.question = question_services.get_question_by_id(question_id)
        question_services.add_question_id_to_skill(self.question.question_id,
                                                   self.question.collection_id,
                                                   self.skill_id,
                                                   self.owner_id)

        self.signup(self.NEW_USER_EMAIL, self.NEW_USER_USERNAME)
        self.new_user_id = self.get_user_id_from_email(self.NEW_USER_EMAIL)
        collection_services.record_played_exploration_in_collection_context(
            self.new_user_id, self.collection_id, self.exp_id)
        self.payload = {}
예제 #13
0
    def test_contribution_msec_does_not_update_until_collection_is_published(
            self):
        self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
        self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)

        collection = self.save_new_valid_collection(
            self.COL_ID,
            self.admin_id,
            title=self.COLLECTION_TITLE,
            category=self.COLLECTION_CATEGORY,
            objective=self.COLLECTION_OBJECTIVE,
            exploration_id=self.EXP_ID)

        # Test that saving a collection does not update first contribution
        # time.
        self.assertIsNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)

        # Test that commit to unpublished collection does not update
        # contribution time.
        collection_services.update_collection(
            self.admin_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'title',
                'new_value': 'Some new title'
            }], '')
        self.assertIsNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)

        # Test that another user who commits to unpublished collection does not
        # have updated first contribution time.
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
        self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)
        rights_manager.assign_role_for_collection(self.admin_id, self.COL_ID,
                                                  self.editor_id, 'editor')
        collection_services.update_collection(
            self.editor_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'category',
                'new_value': 'Some new category'
            }], '')
        self.assertIsNone(
            user_services.get_user_settings(
                self.editor_id).first_contribution_msec)

        # Test that after an collection is published, all contributors have
        # updated first contribution times.
        collection_services.publish_collection_and_update_user_profiles(
            self.admin_id, self.COL_ID)
        self.assertIsNotNone(
            user_services.get_user_settings(
                self.admin_id).first_contribution_msec)
        self.assertIsNotNone(
            user_services.get_user_settings(
                self.editor_id).first_contribution_msec)
예제 #14
0
파일: reader_test.py 프로젝트: gvirav/oppia
    def setUp(self):
        super(LearnerProgressTest, self).setUp()

        self.signup(self.USER_EMAIL, self.USER_USERNAME)
        self.user_id = self.get_user_id_from_email(self.USER_EMAIL)
        self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME)
        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        # Save and publish explorations.
        self.save_new_valid_exploration(
            self.EXP_ID_0, self.owner_id, title='Bridges in England',
            category='Architecture', language_code='en')

        self.save_new_valid_exploration(
            self.EXP_ID_1, self.owner_id, title='Welcome to Gadgets',
            category='Architecture', language_code='fi')

        self.save_new_valid_exploration(
            self.EXP_ID_1_0, self.owner_id, title='Sillat Suomi',
            category='Architecture', language_code='fi')

        self.save_new_valid_exploration(
            self.EXP_ID_1_1, self.owner_id,
            title='Introduce Interactions in Oppia',
            category='Welcome', language_code='en')

        rights_manager.publish_exploration(self.owner_id, self.EXP_ID_0)
        rights_manager.publish_exploration(self.owner_id, self.EXP_ID_1)
        rights_manager.publish_exploration(self.owner_id, self.EXP_ID_1_0)
        rights_manager.publish_exploration(self.owner_id, self.EXP_ID_1_1)

        # Save a new collection.
        self.save_new_default_collection(
            self.COL_ID_0, self.owner_id, title='Welcome',
            category='Architecture')

        self.save_new_default_collection(
            self.COL_ID_1, self.owner_id, title='Bridges in England',
            category='Architecture')

        # Add two explorations to the previously saved collection and publish
        # it.
        for exp_id in [self.EXP_ID_1_0, self.EXP_ID_1_1]:
            collection_services.update_collection(
                self.owner_id, self.COL_ID_1, [{
                    'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                    'exploration_id': exp_id
                }], 'Added new exploration')

        # Publish the collections.
        rights_manager.publish_collection(self.owner_id, self.COL_ID_0)
        rights_manager.publish_collection(self.owner_id, self.COL_ID_1)
예제 #15
0
    def test_get_question_batch(self):
        coll_id_0 = '0_collection_id'
        exp_id_0 = '0_exploration_id'
        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        # Create a new collection and exploration.
        self.save_new_valid_collection(coll_id_0,
                                       self.owner_id,
                                       exploration_id=exp_id_0)

        # Add a skill.
        collection_services.update_collection(
            self.owner_id, coll_id_0, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_SKILL,
                'name': 'skill0'
            }], 'Add a new skill')
        collection = collection_services.get_collection_by_id(coll_id_0)
        skill_id = collection.get_skill_id_from_skill_name('skill0')
        collection_node = collection.get_node(exp_id_0)
        collection_node.update_acquired_skill_ids([skill_id])
        # Update the acquired skill IDs for the exploration.
        collection_services.update_collection(
            self.owner_id,
            coll_id_0,
            [{
                'cmd':
                collection_domain.CMD_EDIT_COLLECTION_NODE_PROPERTY,
                'property_name':
                (collection_domain.COLLECTION_NODE_PROPERTY_ACQUIRED_SKILL_IDS
                 ),  # pylint: disable=line-too-long
                'exploration_id':
                exp_id_0,
                'new_value': [skill_id]
            }],
            'Update skill')

        question = question_domain.Question(
            'dummy', 'A Question',
            exp_domain.State.create_default_state('ABC').to_dict(), 1,
            coll_id_0, 'en')

        question_id = question_services.add_question(self.owner_id, question)
        question = question_services.get_question_by_id(question_id)
        question_services.add_question_id_to_skill(question.question_id,
                                                   coll_id_0, skill_id,
                                                   self.owner_id)
        collection_services.record_played_exploration_in_collection_context(
            self.owner_id, coll_id_0, exp_id_0)
        question_batch = question_services.get_questions_batch(
            coll_id_0, [skill_id], self.owner_id, 1)
        self.assertEqual(question_batch[0].title, question.title)
예제 #16
0
    def test_contribution_msec_does_not_update_until_collection_is_published(self):
        self.signup(self.ADMIN_EMAIL, self.ADMIN_USERNAME)
        self.admin_id = self.get_user_id_from_email(self.ADMIN_EMAIL)

        collection = self.save_new_valid_collection(
            self.COL_ID, self.admin_id, title=self.COLLECTION_TITLE,
            category=self.COLLECTION_CATEGORY,
            objective=self.COLLECTION_OBJECTIVE,
            exploration_id=self.EXP_ID)

        # Test that saving a collection does not update first contribution
        # time.
        self.assertIsNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)

        # Test that commit to unpublished collection does not update
        # contribution time.
        collection_services.update_collection(
            self.admin_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'title',
                'new_value': 'Some new title'
            }], '')
        self.assertIsNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)

        # Test that another user who commits to unpublished collection does not
        # have updated first contribution time.
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
        self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)
        rights_manager.assign_role_for_collection(
            self.admin_id, self.COL_ID, self.editor_id, 'editor')
        collection_services.update_collection(
                self.editor_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'category',
                'new_value': 'Some new category'
            }], '')
        self.assertIsNone(user_services.get_user_settings(
            self.editor_id).first_contribution_msec)

        # Test that after an collection is published, all contributors have
        # updated first contribution times.
        collection_services.publish_collection_and_update_user_profiles(
            self.admin_id, self.COL_ID)
        self.assertIsNotNone(user_services.get_user_settings(
            self.admin_id).first_contribution_msec)
        self.assertIsNotNone(user_services.get_user_settings(
            self.editor_id).first_contribution_msec)
예제 #17
0
    def test_contributors_for_valid_nonrevert_contribution(self):
        # Let USER A make three commits.
        exploration = self.save_new_valid_exploration(self.EXP_ID,
                                                      self.user_a_id)
        collection = self.save_new_valid_collection(self.COL_ID,
                                                    self.user_a_id)

        exp_services.update_exploration(self.user_a_id, self.EXP_ID, [
            exp_domain.ExplorationChange({
                'cmd': 'edit_exploration_property',
                'property_name': 'title',
                'new_value': 'New Exploration Title'
            })
        ], 'Changed title.')
        exp_services.update_exploration(self.user_a_id, self.EXP_ID, [
            exp_domain.ExplorationChange({
                'cmd': 'edit_exploration_property',
                'property_name': 'objective',
                'new_value': 'New Objective'
            })
        ], 'Changed Objective.')
        collection_services.update_collection(
            self.user_a_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'title',
                'new_value': 'New Exploration Title'
            }], 'Changed title.')
        collection_services.update_collection(
            self.user_a_id, self.COL_ID, [{
                'cmd': 'edit_collection_property',
                'property_name': 'objective',
                'new_value': 'New Objective'
            }], 'Changed Objective.')

        output = self._run_one_off_job()
        self.assertEqual([['SUCCESS', 3]], output)

        exploration_summary = exp_fetchers.get_exploration_summary_by_id(
            exploration.id)
        self.assertEqual([self.user_a_id], exploration_summary.contributor_ids)
        self.assertEqual({self.user_a_id: 3},
                         exploration_summary.contributors_summary)

        collection_summary = collection_services.get_collection_summary_by_id(
            collection.id)
        self.assertEqual([self.user_a_id], collection_summary.contributor_ids)
        self.assertEqual({self.user_a_id: 3},
                         collection_summary.contributors_summary)
예제 #18
0
def add_question_id_to_skill(question_id, collection_id, skill_id, user_id):
    """Adds the question id to the question list of the appropriate skill.

    Args:
        question_id: str. The id of the question.
        collection_id: str. The id of the collection.
        skill_id: str. The id of the skill.
        user_id: str. The id of the user.
    """
    collection_services.update_collection(
        user_id, collection_id, [{
            'cmd': collection_domain.CMD_ADD_QUESTION_ID_TO_SKILL,
            'skill_id': skill_id,
            'question_id': question_id
        }], 'Add a new question with ID %s to skill with ID %s' %
        (question_id, skill_id))
예제 #19
0
def remove_question_id_from_skill(question_id, collection_id, skill_id,
                                  user_id):
    """Removes the question id from the question list of the appropriate
    skill.

    Args:
        skill_id: str. The id of the skill.
        user_id: str. The id of the user.
    """
    collection_services.update_collection(
        user_id, collection_id, [{
            'cmd': collection_domain.CMD_REMOVE_QUESTION_ID_FROM_SKILL,
            'skill_id': skill_id,
            'question_id': question_id
        }], 'Remove a question with ID %s from skill with ID: %s' %
        (question_id, skill_id))
예제 #20
0
    def test_remove_question_id_from_skill(self):
        """Tests to verify remove_question_id_from_skill method."""
        collection_id = 'col1'
        exp_id = '0_exploration_id'
        owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        # Create a new collection and exploration.
        self.save_new_valid_collection(collection_id,
                                       owner_id,
                                       exploration_id=exp_id)

        # Add a skill.
        collection_services.update_collection(
            owner_id, collection_id, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_SKILL,
                'name': 'skill0'
            }], 'Add a new skill')

        state = exp_domain.State.create_default_state('ABC')
        question_data = state.to_dict()

        question_dict = {
            'question_id': 'col1.random',
            'title': 'abc',
            'question_data': question_data,
            'question_data_schema_version': 1,
            'collection_id': 'col1',
            'language_code': 'en'
        }

        collection = collection_services.get_collection_by_id(collection_id)
        skill_id = collection.get_skill_id_from_skill_name('skill0')
        question = question_domain.Question.from_dict(question_dict)

        question_services.add_question_id_to_skill(question.question_id,
                                                   collection_id, skill_id,
                                                   owner_id)
        collection = collection_services.get_collection_by_id(collection_id)
        self.assertIn(question.question_id,
                      collection.skills[skill_id].question_ids)
        skill_id = collection.get_skill_id_from_skill_name('skill0')
        question_services.remove_question_id_from_skill(
            question.question_id, collection_id, skill_id, owner_id)
        collection = collection_services.get_collection_by_id(collection_id)
        self.assertEqual(len(collection.skills[skill_id].question_ids), 0)
예제 #21
0
    def test_adding_exploration_to_collection(self):
        with self.swap(
            subscription_services, 'subscribe_to_thread', self._null_fn
            ), self.swap(
                subscription_services, 'subscribe_to_collection', self._null_fn
            ):
            # User B creates and saves a new collection.
            self.save_new_default_collection(
                self.COLLECTION_ID_1, self.user_b_id)

            # User B adds the exploration created by user A to the collection.
            collection_services.update_collection(
                self.user_b_id, self.COLLECTION_ID_1, [{
                    'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                    'exploration_id': self.EXP_ID_1
                }], 'Add new exploration to collection.')

        # Users A and B have no subscriptions (to either explorations or
        # collections).
        user_a_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_a_id, strict=False)
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id, strict=False)
        self.assertEqual(user_a_subscriptions_model, None)
        self.assertEqual(user_b_subscriptions_model, None)

        self._run_one_off_job()

        user_a_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_a_id)
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id)

        # User B should be subscribed to the collection and user A to the
        # exploration.
        self.assertEqual(
            user_a_subscriptions_model.activity_ids, [self.EXP_ID_1])
        self.assertEqual(
            user_a_subscriptions_model.collection_ids, [])
        self.assertEqual(
            user_b_subscriptions_model.activity_ids, [])
        self.assertEqual(
            user_b_subscriptions_model.collection_ids, [self.COLLECTION_ID_1])
    def test_nonhuman_committers_not_counted(self):
        # Create a commit with the system user id.
        exploration = self.save_new_valid_exploration(
            self.EXP_ID, feconf.SYSTEM_COMMITTER_ID, title='Original Title')
        collection = self.save_new_valid_collection(self.COL_ID, self.user_a_id)

        # Create commits with all the system user ids.
        for system_id in constants.SYSTEM_USER_IDS:
            exp_services.update_exploration(
                system_id, self.EXP_ID, [exp_domain.ExplorationChange({
                    'cmd': 'edit_exploration_property',
                    'property_name': 'title',
                    'new_value': 'Title changed by %s' % system_id
                })], 'Changed title.')
            collection_services.update_collection(
                system_id, self.COL_ID, [{
                    'cmd': 'edit_collection_property',
                    'property_name': 'title',
                    'new_value': 'New Exploration Title'
                }], 'Changed title.')

        output = self._run_one_off_job()
        self.assertEqual([['SUCCESS', 3]], output)

        # Check that no system id was added to the exploration's
        # contributor's summary.
        exploration_summary = exp_fetchers.get_exploration_summary_by_id(
            exploration.id)
        collection_summary = collection_services.get_collection_summary_by_id(
            collection.id)
        for system_id in constants.SYSTEM_USER_IDS:
            self.assertNotIn(
                system_id,
                exploration_summary.contributors_summary)
            self.assertNotIn(
                system_id,
                exploration_summary.contributor_ids)
            self.assertNotIn(
                system_id,
                collection_summary.contributors_summary)
            self.assertNotIn(
                system_id,
                collection_summary.contributor_ids)
예제 #23
0
    def test_adding_exploration_to_collection(self):
        with self.swap(
                subscription_services, 'subscribe_to_thread', self._null_fn
            ), self.swap(
                subscription_services, 'subscribe_to_collection',
                self._null_fn):
            # User B creates and saves a new collection.
            self.save_new_default_collection(
                self.COLLECTION_ID_1, self.user_b_id)

            # User B adds the exploration created by user A to the collection.
            collection_services.update_collection(
                self.user_b_id, self.COLLECTION_ID_1, [{
                    'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                    'exploration_id': self.EXP_ID_1
                }], 'Add new exploration to collection.')

        # Users A and B have no subscriptions (to either explorations or
        # collections).
        user_a_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_a_id, strict=False)
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id, strict=False)
        self.assertEqual(user_a_subscriptions_model, None)
        self.assertEqual(user_b_subscriptions_model, None)

        self._run_one_off_job()

        user_a_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_a_id)
        user_b_subscriptions_model = user_models.UserSubscriptionsModel.get(
            self.user_b_id)

        # User B should be subscribed to the collection and user A to the
        # exploration.
        self.assertEqual(
            user_a_subscriptions_model.activity_ids, [self.EXP_ID_1])
        self.assertEqual(
            user_a_subscriptions_model.collection_ids, [])
        self.assertEqual(
            user_b_subscriptions_model.activity_ids, [])
        self.assertEqual(
            user_b_subscriptions_model.collection_ids, [self.COLLECTION_ID_1])
예제 #24
0
    def put(self, collection_id):
        """Updates properties of the given collection."""

        collection = collection_services.get_collection_by_id(collection_id)
        version = self.normalized_payload.get('version')
        _require_valid_version(version, collection.version)

        commit_message = self.normalized_payload.get('commit_message')
        change_list = self.normalized_payload.get('change_list')

        collection_services.update_collection(
            self.user_id, collection_id,
            [change.to_dict() for change in change_list], commit_message)

        collection_dict = (summary_services.get_learner_collection_dict_by_id(
            collection_id, self.user, allow_invalid_explorations=True))

        # Send the updated collection back to the frontend.
        self.values.update({'collection': collection_dict})

        self.render_json(self.values)
예제 #25
0
    def test_get_learner_dict_when_referencing_inaccessible_explorations(self):
        self.save_new_default_collection(self.COLLECTION_ID, self.owner_id)
        self.save_new_valid_exploration(self.EXP_ID, self.editor_id)
        collection_services.update_collection(
            self.owner_id, self.COLLECTION_ID, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                'exploration_id': self.EXP_ID
            }], 'Added another creator\'s private exploration')

        # A collection cannot access someone else's private exploration.
        rights_manager.publish_collection(self.owner, self.COLLECTION_ID)
        with self.assertRaisesRegex(
            utils.ValidationError,
            'Expected collection to only reference valid explorations, but '
            'found an exploration with ID: exploration_id'):
            summary_services.get_learner_collection_dict_by_id(
                self.COLLECTION_ID, self.owner)

        # After the exploration is published, the dict can now be created.
        rights_manager.publish_exploration(self.editor, self.EXP_ID)
        summary_services.get_learner_collection_dict_by_id(
            self.COLLECTION_ID, self.owner)
예제 #26
0
    def test_get_learner_dict_when_referencing_inaccessible_explorations(self):
        self.save_new_default_collection(self.COLLECTION_ID, self.owner_id)
        self.save_new_valid_exploration(self.EXP_ID, self.editor_id)
        collection_services.update_collection(
            self.owner_id, self.COLLECTION_ID, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                'exploration_id': self.EXP_ID
            }], 'Added another creator\'s private exploration')

        # A collection cannot access someone else's private exploration.
        rights_manager.publish_collection(self.owner_id, self.COLLECTION_ID)
        with self.assertRaisesRegexp(
            utils.ValidationError,
            'Expected collection to only reference valid explorations, but '
            'found an exploration with ID: exploration_id'):
            summary_services.get_learner_collection_dict_by_id(
                self.COLLECTION_ID, self.owner_id)

        # After the exploration is published, the dict can now be created.
        rights_manager.publish_exploration(self.editor_id, self.EXP_ID)
        summary_services.get_learner_collection_dict_by_id(
            self.COLLECTION_ID, self.owner_id)
예제 #27
0
    def test_get_learner_dict_with_allowed_private_exps(self):
        self.save_new_valid_collection(
            self.COLLECTION_ID, self.owner_id, exploration_id=self.EXP_ID)
        self.save_new_valid_exploration(self.EXP_ID_1, self.editor_id)
        collection_services.update_collection(
            self.owner_id, self.COLLECTION_ID, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                'exploration_id': self.EXP_ID_1
            }], 'Added another creator\'s private exploration')

        rights_manager.publish_collection(self.owner_id, self.COLLECTION_ID)

        collection_dict = summary_services.get_learner_collection_dict_by_id(
            self.COLLECTION_ID, self.owner_id, allow_invalid_explorations=True)

        # The author's private exploration will be contained in the public
        # collection since invalid explorations are being allowed, but the
        # private exploration of another author will not.
        collection_node_dicts = collection_dict['nodes']
        self.assertEqual(
            collection_node_dicts[0]['exploration_summary']['id'],
            self.EXP_ID)
        self.assertIsNone(collection_node_dicts[1]['exploration_summary'])
예제 #28
0
    def test_get_learner_dict_with_allowed_private_exps(self):
        self.save_new_valid_collection(self.COLLECTION_ID,
                                       self.owner_id,
                                       exploration_id=self.EXP_ID)
        self.save_new_valid_exploration(self.EXP_ID_1, self.editor_id)
        collection_services.update_collection(
            self.owner_id, self.COLLECTION_ID, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                'exploration_id': self.EXP_ID_1
            }], 'Added another creator\'s private exploration')

        rights_manager.publish_collection(self.owner, self.COLLECTION_ID)

        collection_dict = summary_services.get_learner_collection_dict_by_id(
            self.COLLECTION_ID, self.owner, allow_invalid_explorations=True)

        # The author's private exploration will be contained in the public
        # collection since invalid explorations are being allowed, but the
        # private exploration of another author will not.
        collection_node_dicts = collection_dict['nodes']
        self.assertEqual(collection_node_dicts[0]['exploration_summary']['id'],
                         self.EXP_ID)
        self.assertIsNone(collection_node_dicts[1]['exploration_summary'])
예제 #29
0
    def test_delete_question(self):
        collection_id = 'col1'
        exp_id = '0_exploration_id'
        owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)

        # Create a new collection and exploration.
        self.save_new_valid_collection(collection_id,
                                       owner_id,
                                       exploration_id=exp_id)

        # Add a skill.
        collection_services.update_collection(
            owner_id, collection_id, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_SKILL,
                'name': 'skill0'
            }], 'Add a new skill')

        question = question_domain.Question(
            'dummy', 'A Question',
            exp_domain.State.create_default_state('ABC').to_dict(), 1,
            collection_id, 'en')

        question_id = question_services.add_question(self.owner_id, question)
        with self.assertRaisesRegexp(
                Exception, ('The question with ID %s is not present'
                            ' in the given collection' % question_id)):
            question_services.delete_question(self.owner_id, 'random',
                                              question_id)
        question_services.delete_question(self.owner_id, collection_id,
                                          question_id)

        with self.assertRaisesRegexp(
                Exception,
            ('Entity for class QuestionModel with id %s not found' %
             (question_id))):
            question_models.QuestionModel.get(question_id)
    def test_get_activity_progress(self):
        # Add activities to the completed section.
        learner_progress_services.mark_exploration_as_completed(
            self.user_id, self.EXP_ID_0)
        learner_progress_services.mark_collection_as_completed(
            self.user_id, self.COL_ID_0)

        # Add activities to the incomplete section.
        state_name = 'state name'
        version = 1
        learner_progress_services.mark_exploration_as_incomplete(
            self.user_id, self.EXP_ID_1, state_name, version)
        learner_progress_services.mark_collection_as_incomplete(
            self.user_id, self.COL_ID_1)

        # Add activities to the playlist section.
        learner_progress_services.add_exp_to_learner_playlist(
            self.user_id, self.EXP_ID_3)
        learner_progress_services.add_collection_to_learner_playlist(
            self.user_id, self.COL_ID_3)

        # Get the progress of the user.
        activity_progress = learner_progress_services.get_activity_progress(
            self.user_id)

        incomplete_exp_summaries = (
            activity_progress[0].incomplete_exp_summaries)
        incomplete_collection_summaries = (
            activity_progress[0].incomplete_collection_summaries)
        completed_exp_summaries = (
            activity_progress[0].completed_exp_summaries)
        completed_collection_summaries = (
            activity_progress[0].completed_collection_summaries)
        exploration_playlist_summaries = (
            activity_progress[0].exploration_playlist_summaries)
        collection_playlist_summaries = (
            activity_progress[0].collection_playlist_summaries)

        self.assertEqual(len(incomplete_exp_summaries), 1)
        self.assertEqual(len(incomplete_collection_summaries), 1)
        self.assertEqual(len(completed_exp_summaries), 1)
        self.assertEqual(len(completed_collection_summaries), 1)
        self.assertEqual(len(exploration_playlist_summaries), 1)
        self.assertEqual(len(collection_playlist_summaries), 1)

        self.assertEqual(incomplete_exp_summaries[0].title, 'Sillat Suomi')
        self.assertEqual(incomplete_collection_summaries[0].title,
                         'Introduce Oppia')
        self.assertEqual(completed_exp_summaries[0].title,
                         'Bridges in England')
        self.assertEqual(completed_collection_summaries[0].title, 'Bridges')
        self.assertEqual(exploration_playlist_summaries[0].title,
                         'Welcome Oppia')
        self.assertEqual(collection_playlist_summaries[0].title,
                         'Welcome Oppia Collection')

        # Delete an exploration in the completed section.
        exp_services.delete_exploration(self.owner_id, self.EXP_ID_0)
        # Delete an exploration in the incomplete section.
        exp_services.delete_exploration(self.owner_id, self.EXP_ID_1)
        # Delete an exploration in the playlist section.
        exp_services.delete_exploration(self.owner_id, self.EXP_ID_3)
        # Add an exploration to a collection that has already been completed.
        collection_services.update_collection(
            self.owner_id, self.COL_ID_0, [{
                'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,
                'exploration_id': self.EXP_ID_2
            }], 'Add new exploration')

        # Get the progress of the user.
        activity_progress = learner_progress_services.get_activity_progress(
            self.user_id)

        # Check that the exploration is no longer present in the incomplete
        # section.
        self.assertEqual(len(activity_progress[0].incomplete_exp_summaries), 0)
        # Check that the dashboard records the exploration deleted in the
        # completed section.
        self.assertEqual(activity_progress[1]['completed_explorations'], 1)
        # Check that the dashboard records the exploration deleted in the
        # incomplete section.
        self.assertEqual(activity_progress[1]['incomplete_explorations'], 1)
        # Check that the dashboard records the exploration deleted in the
        # playlist section.
        self.assertEqual(activity_progress[1]['exploration_playlist'], 1)

        incomplete_collection_summaries = (
            activity_progress[0].incomplete_collection_summaries)

        # Check that the collection to which a new exploration has been added
        # has been moved to the incomplete section.
        self.assertEqual(len(incomplete_collection_summaries), 2)
        self.assertEqual(incomplete_collection_summaries[1].title, 'Bridges')
        # Check that the dashboard has recorded the change in the collection.
        self.assertEqual(activity_progress[2], ['Bridges'])

        # Now suppose the user has completed the collection. It should be added
        # back to the completed section.
        learner_progress_services.mark_collection_as_completed(
            self.user_id, self.COL_ID_0)

        # Delete a collection in the completed section.
        collection_services.delete_collection(self.owner_id, self.COL_ID_0)
        # Delete a collection in the incomplete section.
        collection_services.delete_collection(self.owner_id, self.COL_ID_1)
        # Delete a collection in the playlist section.
        collection_services.delete_collection(self.owner_id, self.COL_ID_3)

        # Get the progress of the user.
        activity_progress = learner_progress_services.get_activity_progress(
            self.user_id)

        # Check that the dashboard records the collection deleted in the
        # completed section.
        self.assertEqual(activity_progress[1]['completed_collections'], 1)
        # Check that the dashboard records the collection deleted in the
        # incomplete section.
        self.assertEqual(activity_progress[1]['incomplete_collections'], 1)
        # Check that the dashboard records the collection deleted in the
        # playlist section.
        self.assertEqual(activity_progress[1]['collection_playlist'], 1)