Ejemplo n.º 1
0
    def test_get_question_summaries_for_collection(self):
        """Tests to verify get_question_summaries_for_collection method."""
        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)
        question_summaries = (
            question_services.get_question_summaries_for_collection(coll_id_0))
        self.assertEqual(question_summaries[0].question_id, question_id)
        self.assertEqual(question_summaries[0].question_title, question.title)
        self.assertEqual(question_summaries[0].skill_names, ['skill0'])
Ejemplo n.º 2
0
    def get(self, entity_type, entity_id):
        """Handles the GET requests for learner answer info for an
        exploration state.
        """
        if not constants.ENABLE_SOLICIT_ANSWER_DETAILS_FEATURE:
            raise self.PageNotFoundException

        learner_answer_info_data = []

        if entity_type == feconf.ENTITY_TYPE_EXPLORATION:
            exp = exp_fetchers.get_exploration_by_id(entity_id)
            for state_name in exp.states:
                state_reference = (
                    stats_services.get_state_reference_for_exploration(
                        entity_id, state_name))
                learner_answer_details = (
                    stats_services.get_learner_answer_details(
                        feconf.ENTITY_TYPE_EXPLORATION, state_reference))
                if learner_answer_details is not None:
                    learner_answer_info_data.append({
                        'state_name': state_name,
                        'interaction_id': learner_answer_details.interaction_id,
                        'customization_args': exp.states[state_name].interaction
                                              .to_dict()['customization_args'],
                        'learner_answer_info_dicts': [
                            learner_answer_info.to_dict() for
                            learner_answer_info in
                            learner_answer_details.learner_answer_info_list]
                    })
        elif entity_type == feconf.ENTITY_TYPE_QUESTION:
            question = question_services.get_question_by_id(entity_id)
            state_reference = stats_services.get_state_reference_for_question(
                entity_id)
            learner_answer_details = stats_services.get_learner_answer_details(
                feconf.ENTITY_TYPE_QUESTION, state_reference)
            if learner_answer_details is not None:
                learner_answer_info_dicts = [
                    learner_answer_info.to_dict() for learner_answer_info in
                    learner_answer_details.learner_answer_info_list]
            learner_answer_info_data = {
                'interaction_id': learner_answer_details.interaction_id,
                'customization_args': question.question_state_data.interaction
                                      .to_dict()['customization_args'],
                'learner_answer_info_dicts': learner_answer_info_dicts
            }

        self.render_json({
            'learner_answer_info_data': learner_answer_info_data
        })
Ejemplo n.º 3
0
def get_state_reference_for_question(question_id):
    """Returns the generated state reference for the given question id.

    Args:
        question_id: str. ID of the question.

    Returns:
        str. The generated state reference.
    """
    question = question_services.get_question_by_id(question_id, strict=False)
    if question is None:
        raise utils.InvalidInputException(
            'No question with the given question id exists.')
    return (stats_models.LearnerAnswerDetailsModel.
            get_state_reference_for_question(question_id))
    def test_deleted_question_are_not_processed(self):
        """Tests that the job does not process deleted questions."""
        # Delete the question before migration occurs.
        question_services.delete_question(self.albert_id, self.QUESTION_ID)

        # Ensure the question is deleted.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            question_services.get_question_by_id(self.QUESTION_ID)

        # Start migration job on sample question.
        job_id = (question_jobs_one_off.FixQuestionImagesStorageOneOffJob.
                  create_new())
        question_jobs_one_off.FixQuestionImagesStorageOneOffJob.enqueue(job_id)
        self.process_and_flush_pending_mapreduce_tasks()

        # Ensure that the question is still deleted and the output is None.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            question_services.get_question_by_id(self.QUESTION_ID)

        output = (question_jobs_one_off.FixQuestionImagesStorageOneOffJob.
                  get_output(job_id))
        self.assertEqual(
            [[u'question_deleted', [u'Encountered 1 deleted questions.']]],
            [ast.literal_eval(x) for x in output])
Ejemplo n.º 5
0
    def get(self, question_id):
        """Gets the data for the question overview page."""

        if not constants.ENABLE_NEW_STRUCTURES:
            raise self.PageNotFoundException

        question = question_services.get_question_by_id(question_id,
                                                        strict=False)

        if question is None:
            raise self.PageNotFoundException(
                'The question with the given id doesn\'t exist.')

        self.values.update({'question_dict': question.to_dict()})
        self.render_json(self.values)
Ejemplo n.º 6
0
    def get(self, question_id):
        """Gets the data for the question overview page."""
        question = question_services.get_question_by_id(question_id,
                                                        strict=False)

        associated_skill_dicts = [
            skill.to_dict() for skill in skill_fetchers.get_multi_skills(
                question.linked_skill_ids)
        ]

        self.values.update({
            'question_dict': question.to_dict(),
            'associated_skill_dicts': associated_skill_dicts
        })
        self.render_json(self.values)
Ejemplo n.º 7
0
    def test_audit_job_skips_deleted_question(self):
        """Tests that the snapshot migration audit job skips deleted questions
        and does not attempt to migrate.
        """
        self.save_new_question(
            self.QUESTION_ID, self.albert_id,
            self._create_valid_question_data('ABC'), [self.skill_id])

        # Delete the question before migration occurs.
        question_services.delete_question(self.albert_id, self.QUESTION_ID)

        # Ensure the question is deleted.
        with self.assertRaisesRegexp(Exception, 'Entity .* not found'):
            question_services.get_question_by_id(self.QUESTION_ID)

        # Start migration job on sample question.
        job_id = (
            question_jobs_one_off.QuestionSnapshotsMigrationAuditJob.
            create_new())
        question_jobs_one_off.QuestionSnapshotsMigrationAuditJob.enqueue(job_id)

        # This running without errors indicates the deleted question is
        # being ignored.
        self.process_and_flush_pending_mapreduce_tasks()

        actual_output = (
            question_jobs_one_off.QuestionSnapshotsMigrationAuditJob.get_output(
                job_id))
        expected_output_choices = [
            '[u\'INFO - Question does not exist\', [u\'%s-1\', u\'%s-2\']]' %
            (self.QUESTION_ID, self.QUESTION_ID),
            '[u\'INFO - Exploration does not exist\', [u\'%s-2\', u\'%s-1\']]' %
            (self.QUESTION_ID, self.QUESTION_ID)
        ]
        self.assertEqual(len(actual_output), 1)
        self.assertIn(actual_output[0], expected_output_choices)
Ejemplo n.º 8
0
    def map(item):
        question_id = item.get_unversioned_instance_id()

        latest_question = question_services.get_question_by_id(question_id,
                                                               strict=False)
        if latest_question is None:
            yield ('INFO - Question does not exist', item.id)
            return

        question_model = question_models.QuestionModel.get(question_id)
        if (question_model.question_state_data_schema_version !=
                feconf.CURRENT_STATE_SCHEMA_VERSION):
            yield ('FAILURE - Question is not at latest schema version',
                   question_id)
            return

        try:
            latest_question.validate()
        except Exception as e:
            yield ('INFO - Question %s failed validation' % item.id, e)

        target_state_schema_version = feconf.CURRENT_STATE_SCHEMA_VERSION
        current_state_schema_version = item.content[
            'question_state_data_schema_version']
        if current_state_schema_version == target_state_schema_version:
            yield ('SUCCESS - Snapshot is already at latest schema version',
                   item.id)
            return

        versioned_question_state = {
            'states_schema_version': current_state_schema_version,
            'state': item.content['question_state_data']
        }
        while current_state_schema_version < target_state_schema_version:
            try:
                question_domain.Question.update_state_from_model(
                    versioned_question_state, current_state_schema_version)
                current_state_schema_version += 1
            except Exception as e:
                error_message = (
                    'Question snapshot %s failed migration to state '
                    'v%s: %s' % (item.id, current_state_schema_version + 1, e))
                logging.exception(error_message)
                yield ('MIGRATION_ERROR', error_message.encode('utf-8'))
                break

            if target_state_schema_version == current_state_schema_version:
                yield ('SUCCESS', 1)
Ejemplo n.º 9
0
    def test_update_question_language_code(self):
        self.assertEqual(self.question.language_code, 'en')
        change_dict = {
            'cmd': 'update_question_property',
            'property_name': 'language_code',
            'new_value': 'bn',
            'old_value': 'en'
        }
        change_list = [question_domain.QuestionChange(change_dict)]

        question_services.update_question(
            self.editor_id, self.question_id, change_list,
            'updated question language code')

        question = question_services.get_question_by_id(self.question_id)
        self.assertEqual(question.language_code, 'bn')
        self.assertEqual(question.version, 2)
Ejemplo n.º 10
0
    def test_update_question(self):
        new_question_data = self._create_valid_question_data('DEF')
        change_dict = {
            'cmd': 'update_question_property',
            'property_name': 'question_state_data',
            'new_value': new_question_data.to_dict(),
            'old_value': self.question.question_state_data.to_dict()
        }
        change_list = [question_domain.QuestionChange(change_dict)]

        question_services.update_question(self.editor_id, self.question_id,
                                          change_list, 'updated question data')

        question = question_services.get_question_by_id(self.question_id)
        self.assertEqual(question.question_state_data.to_dict(),
                         new_question_data.to_dict())
        self.assertEqual(question.version, 2)
Ejemplo n.º 11
0
    def test_delete_question_skill_link(self):
        question_services.create_new_question_skill_link(
            self.editor_id, self.question_id, 'skill_1', 0.3)
        question_services.create_new_question_skill_link(
            self.editor_id, self.question_id, 'skill_2', 0.3)
        question_services.delete_question_skill_link(
            self.editor_id, self.question_id, 'skill_1')
        skill_ids = [skill.id for skill in
                     question_services.get_skills_linked_to_question(
                         self.question_id)]
        self.assertItemsEqual(skill_ids, ['skill_2'])

        question_services.delete_question_skill_link(
            self.editor_id, self.question_id, 'skill_2')

        question = question_services.get_question_by_id(
            self.question_id, strict=False)
        self.assertIsNone(question)
Ejemplo n.º 12
0
    def get(self, question_id):
        """Gets the data for the question overview page."""
        question = question_services.get_question_by_id(question_id,
                                                        strict=False)

        if question is None:
            raise self.PageNotFoundException(
                'The question with the given id doesn\'t exist.')

        associated_skill_dicts = [
            skill.to_dict() for skill in skill_services.get_multi_skills(
                question.linked_skill_ids)
        ]

        self.values.update({
            'question_dict': question.to_dict(),
            'associated_skill_dicts': associated_skill_dicts
        })
        self.render_json(self.values)
Ejemplo n.º 13
0
    def test_batch_get(self):
        """Tests get method of questions batch handler."""
        question_id = question_services.add_question(
            self.owner_id, self.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)

        collection_services.record_played_exploration_in_collection_context(
            self.new_user_id, self.collection_id, self.exp_id)

        payload = {}
        payload['collection_id'] = self.collection_id
        payload['stringified_skill_ids'] = json.dumps(
            [self.skill_id, 'test'])

        self.login(self.NEW_USER_EMAIL)
        response_json = self.get_json(
            '%s/batch' % feconf.QUESTION_DATA_URL, payload,
            expect_errors=False)
        self.assertIn(self.question.to_dict(), response_json['questions_dict'])
        self.assertEqual(len(response_json['questions_dict']), 1)

        response = self.testapp.get(
            '%s/batch' % feconf.QUESTION_DATA_URL,
            expect_errors=True)
        self.assertEqual(response.status_int, 404)

        del payload['stringified_skill_ids']
        response = self.testapp.get(
            '%s/batch' % feconf.QUESTION_DATA_URL, payload,
            expect_errors=True)
        self.assertEqual(response.status_int, 404)

        self.logout()
        self.login(self.random_email)
        response_json = self.testapp.get(
            '%s/batch' % feconf.QUESTION_DATA_URL, payload,
            expect_errors=True)
        self.assertEqual(response.status_int, 404)
Ejemplo n.º 14
0
    def test_manager_get(self):
        """Tests get method of question manager handler."""
        question_id = question_services.add_question(
            self.owner_id, self.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.login(self.NEW_USER_EMAIL)
        payload = {}
        payload['collection_id'] = self.collection_id
        response_json = self.get_json(
            '%s' % feconf.QUESTION_MANAGER_URL, payload,
            expect_errors=False)
        expected_question_summary = question_domain.QuestionSummary(
            self.question.question_id, self.question.title, ['test'])
        self.assertIn(
            expected_question_summary.to_dict(),
            response_json['question_summary_dicts'])

        response = self.testapp.get(
            '%s/batch' % feconf.QUESTION_MANAGER_URL,
            expect_errors=True)
        self.assertEqual(response.status_int, 404)

        del payload['collection_id']
        response = self.testapp.get(
            '%s/batch' % feconf.QUESTION_MANAGER_URL, payload,
            expect_errors=True)
        self.assertEqual(response.status_int, 404)

        self.logout()
        self.login(self.random_email)
        payload['collection_id'] = self.collection_id
        response = self.testapp.get(
            '%s' % feconf.QUESTION_MANAGER_URL, payload,
            expect_errors=True)
        self.assertEqual(response.status_int, 401)
Ejemplo n.º 15
0
    def get(self, question_id):
        """Gets the data for the question overview page."""

        if not constants.ENABLE_NEW_STRUCTURE_EDITORS:
            raise self.PageNotFoundException

        question = question_services.get_question_by_id(
            question_id, strict=False)

        if question is None:
            raise self.PageNotFoundException(
                'The question with the given id doesn\'t exist.')

        associated_skills = question_services.get_skills_linked_to_question(
            question_id)
        associated_skill_dicts = [
            skill.to_dict() for skill in associated_skills]

        self.values.update({
            'question_dict': question.to_dict(),
            'associated_skill_dicts': associated_skill_dicts
        })
        self.render_json(self.values)
Ejemplo n.º 16
0
    def put(self, question_id):
        """Updates properties of the given question."""
        commit_message = self.payload.get('commit_message')

        if not commit_message:
            raise self.PageNotFoundException
        if not self.payload.get('change_list'):
            raise self.PageNotFoundException
        change_list = [
            question_domain.QuestionChange(change)
            for change in self.payload.get('change_list')
        ]

        for change in change_list:
            if (change.cmd ==
                    question_domain.CMD_CREATE_NEW_FULLY_SPECIFIED_QUESTION):
                raise self.InvalidInputException

        question_services.update_question(self.user_id, question_id,
                                          change_list, commit_message)

        question_dict = question_services.get_question_by_id(
            question_id).to_dict()
        self.render_json({'question_dict': question_dict})
Ejemplo n.º 17
0
    def map(item):
        if item.deleted:
            return
        question = question_services.get_question_by_id(item.id)
        html_string = ''.join(
            question.question_state_data.get_all_html_content_strings())
        list_of_latex_strings_without_svg = (
            html_validation_service.get_latex_strings_without_svg_from_html(
                html_string))
        latex_string_to_filename_mapping = (
            html_validation_service.
            extract_svg_filename_latex_mapping_in_math_rte_components(
                html_string))
        if len(latex_string_to_filename_mapping) > 0:
            latex_strings_with_svg = [
                latex_string_to_filename[1] for latex_string_to_filename in (
                    latex_string_to_filename_mapping)
            ]
            yield (QuestionsMathRteAuditOneOffJob._LATEX_STRINGS_HAVING_SVG,
                   (item.id, latex_strings_with_svg))

        if len(list_of_latex_strings_without_svg) > 0:
            yield (QuestionsMathRteAuditOneOffJob._LATEX_STRINGS_WITHOUT_SVG,
                   (item.id, list_of_latex_strings_without_svg))