def test_different_groups_indexed_on_same_vertical_html_blocks(self):
        """
        Indexing course with different content groups assigned to each of multiple html units
        on same vertical

        """
        group_access_content_1 = {'group_access': {666: [1]}}
        group_access_content_2 = {'group_access': {666: [0]}}

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", self.html_unit2.location),
            data={'metadata': group_access_content_1}
        )
        self.client.ajax_post(
            reverse_usage_url("xblock_handler", self.html_unit3.location),
            data={'metadata': group_access_content_2}
        )

        self.publish_item(self.store, self.html_unit2.location)
        self.publish_item(self.store, self.html_unit3.location)

        with patch(settings.SEARCH_ENGINE + '.index') as mock_index:
            self.reindex_course(self.store)
            self.assertTrue(mock_index.called)
            self.assertIn(self._html_group_result(self.html_unit2, [1]), mock_index.mock_calls)
            self.assertIn(self._html_group_result(self.html_unit3, [0]), mock_index.mock_calls)
            mock_index.reset_mock()
    def test_content_group_not_indexed_on_delete(self):
        """ indexing course with content groups deleted test """

        group_access_content = {'group_access': {666: [1]}}

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", self.html_unit1.location),
            data={'metadata': group_access_content}
        )

        self.publish_item(self.store, self.html_unit1.location)

        # Checking group indexed correctly
        with patch(settings.SEARCH_ENGINE + '.index') as mock_index:
            self.reindex_course(self.store)
            self.assertTrue(mock_index.called)
            self.assertIn(self._html_group_result(self.html_unit1, [1]), mock_index.mock_calls)
            mock_index.reset_mock()

        empty_group_access = {'group_access': {}}

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", self.html_unit1.location),
            data={'metadata': empty_group_access}
        )

        self.publish_item(self.store, self.html_unit1.location)

        # Checking group removed and not indexed any more
        with patch(settings.SEARCH_ENGINE + '.index') as mock_index:
            self.reindex_course(self.store)
            self.assertTrue(mock_index.called)
            self.assertIn(self._html_nogroup_result(self.html_unit1), mock_index.mock_calls)
            mock_index.reset_mock()
Exemple #3
0
    def setUp(self):
        """
        Initial data setup
        """
        super(TestSubsectionGating, self).setUp()

        # Enable subsection gating for the test course
        self.course.enable_subsection_gating = True
        self.save_course()

        # create a chapter
        self.chapter = ItemFactory.create(parent_location=self.course.location,
                                          category='chapter',
                                          display_name='untitled chapter')

        # create 2 sequentials
        self.seq1 = ItemFactory.create(parent_location=self.chapter.location,
                                       category='sequential',
                                       display_name='untitled sequential 1')
        self.seq1_url = reverse_usage_url('xblock_handler', self.seq1.location)

        self.seq2 = ItemFactory.create(parent_location=self.chapter.location,
                                       category='sequential',
                                       display_name='untitled sequential 2')
        self.seq2_url = reverse_usage_url('xblock_handler', self.seq2.location)
Exemple #4
0
    def setUp(self):
        """ Creates the test course structure and a couple problems to 'edit'. """
        super(TestEditItem, self).setUp()
        # create a chapter
        display_name = 'chapter created'
        resp = self.create_xblock(display_name=display_name,
                                  category='chapter')
        chap_usage_key = self.response_usage_key(resp)
        resp = self.create_xblock(parent_usage_key=chap_usage_key,
                                  category='sequential')
        self.seq_usage_key = self.response_usage_key(resp)
        self.seq_update_url = reverse_usage_url("xblock_handler",
                                                self.seq_usage_key)

        # create problem w/ boilerplate
        template_id = 'multiplechoice.yaml'
        resp = self.create_xblock(parent_usage_key=self.seq_usage_key,
                                  category='problem',
                                  boilerplate=template_id)
        self.problem_usage_key = self.response_usage_key(resp)
        self.problem_update_url = reverse_usage_url("xblock_handler",
                                                    self.problem_usage_key)

        self.course_update_url = reverse_usage_url("xblock_handler",
                                                   self.usage_key)
    def setUp(self):
        """
        Initial data setup
        """
        super(TestSubsectionGating, self).setUp()

        # Enable subsection gating for the test course
        self.course.enable_subsection_gating = True
        self.save_course()

        # create a chapter
        self.chapter = ItemFactory.create(
            parent_location=self.course.location,
            category='chapter',
            display_name='untitled chapter'
        )

        # create 2 sequentials
        self.seq1 = ItemFactory.create(
            parent_location=self.chapter.location,
            category='sequential',
            display_name='untitled sequential 1'
        )
        self.seq1_url = reverse_usage_url('xblock_handler', self.seq1.location)

        self.seq2 = ItemFactory.create(
            parent_location=self.chapter.location,
            category='sequential',
            display_name='untitled sequential 2'
        )
        self.seq2_url = reverse_usage_url('xblock_handler', self.seq2.location)
    def _get_usage_dict(course, unit, item, scheme_name=None):
        """
        Get usage info for unit/module.
        """
        parent_unit = get_parent_unit(item)

        if unit == parent_unit and not item.has_children:
            # Display the topmost unit page if
            # the item is a child of the topmost unit and doesn't have its own children.
            unit_for_url = unit
        elif (not parent_unit and unit.get_parent()) or (unit == parent_unit and item.has_children):
            # Display the item's page rather than the unit page if
            # the item is one level below the topmost unit and has children, or
            # the item itself *is* the topmost unit (and thus does not have a parent unit, but is not an orphan).
            unit_for_url = item
        else:
            # If the item is nested deeper than two levels (the topmost unit > vertical > ... > item)
            # display the page for the nested vertical element.
            parent = item.get_parent()
            nested_vertical = item
            while parent != parent_unit:
                nested_vertical = parent
                parent = parent.get_parent()
            unit_for_url = nested_vertical

        unit_url = reverse_usage_url(
            'container_handler',
            course.location.course_key.make_usage_key(unit_for_url.location.block_type, unit_for_url.location.block_id)
        )

        usage_dict = {'label': u"{} / {}".format(unit.display_name, item.display_name), 'url': unit_url}
        if scheme_name == RANDOM_SCHEME:
            validation_summary = item.general_validation_message()
            usage_dict.update({'validation': validation_summary.to_json() if validation_summary else None})
        return usage_dict
    def test_can_get_usage_info_when_special_characters_are_used(self):
        """
        Test if group configurations json updated successfully when special
         characters are being used in content experiment
        """
        self._add_user_partitions(count=1)
        __, split_test, __ = self._create_content_experiment(cid=0, name_suffix='0', special_characters=u"JOSÉ ANDRÉS")

        actual = GroupConfiguration.get_split_test_partitions_with_usage(self.store, self.course, )

        expected = [{
            'id': 0,
            'name': 'Name 0',
            'scheme': 'random',
            'description': 'Description 0',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 0, 'name': 'Group A', 'version': 1},
                {'id': 1, 'name': 'Group B', 'version': 1},
                {'id': 2, 'name': 'Group C', 'version': 1},
            ],
            'usage': [{
                'url': reverse_usage_url("container_handler", split_test.location),
                'label': u"Test Unit 0 / Test Content Experiment 0JOSÉ ANDRÉS",
                'validation': None,
            }],
            'parameters': {},
            'active': True,
        }]

        self.assertEqual(actual, expected)
    def test_can_get_usage_info_when_special_characters_are_used(self):
        """
        Test if group configurations json updated successfully when special
         characters are being used in content experiment
        """
        self._add_user_partitions(count=1)
        __, split_test, __ = self._create_content_experiment(cid=0, name_suffix='0', special_characters=u"JOSÉ ANDRÉS")

        actual = GroupConfiguration.get_split_test_partitions_with_usage(self.store, self.course, )

        expected = [{
            'id': 0,
            'name': 'Name 0',
            'scheme': 'random',
            'description': 'Description 0',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 0, 'name': 'Group A', 'version': 1},
                {'id': 1, 'name': 'Group B', 'version': 1},
                {'id': 2, 'name': 'Group C', 'version': 1},
            ],
            'usage': [{
                'url': reverse_usage_url("container_handler", split_test.location),
                'label': u"Test Unit 0 / Test Content Experiment 0JOSÉ ANDRÉS",
                'validation': None,
            }],
            'parameters': {},
            'active': True,
        }]

        self.assertEqual(actual, expected)
 def _update_item(self, usage_key, metadata):
     """
     Helper method: Uses the REST API to update the fields of an XBlock.
     This will result in the XBlock's editor_saved() method being called.
     """
     update_url = reverse_usage_url("xblock_handler", usage_key)
     return self.client.ajax_post(update_url, data={"metadata": metadata})
def xblock_studio_url(xblock):
    """
    Returns the Studio editing URL for the specified xblock.
    """
    if not xblock_has_own_studio_page(xblock):
        return None
    category = xblock.category
    parent_xblock = get_parent_xblock(xblock)
    parent_category = parent_xblock.category if parent_xblock else None
    if category == 'course':
        return reverse_course_url('course_handler', xblock.location.course_key)
    elif category == 'vertical' and parent_category == 'sequential':
        # only show the unit page for verticals directly beneath a subsection
        return reverse_usage_url('unit_handler', xblock.location)
    else:
        return reverse_usage_url('container_handler', xblock.location)
    def _create_problem_with_content_group(self, cid, group_id, name_suffix='', special_characters=''):
        """
        Create a problem
        Assign content group to the problem.
        """
        vertical = ItemFactory.create(
            category='vertical',
            parent_location=self.course.location,
            display_name="Test Unit {}".format(name_suffix)
        )

        problem = ItemFactory.create(
            category='problem',
            parent_location=vertical.location,
            display_name=u"Test Problem {}{}".format(name_suffix, special_characters)
        )

        group_access_content = {'group_access': {cid: [group_id]}}

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", problem.location),
            data={'metadata': group_access_content}
        )

        self.save_course()

        return vertical, problem
Exemple #12
0
def xblock_studio_url(xblock):
    """
    Returns the Studio editing URL for the specified xblock.
    """
    if not xblock_has_own_studio_page(xblock):
        return None
    category = xblock.category
    parent_xblock = get_parent_xblock(xblock)
    parent_category = parent_xblock.category if parent_xblock else None
    if category == 'course':
        return reverse_course_url('course_handler', xblock.location.course_key)
    elif category == 'vertical' and parent_category == 'sequential':
        # only show the unit page for verticals directly beneath a subsection
        return reverse_usage_url('unit_handler', xblock.location)
    else:
        return reverse_usage_url('container_handler', xblock.location)
Exemple #13
0
    def test_preview_conditional_module_children_context(
            self, mock_is_condition_satisfied):
        """
        Testst that when empty context is pass to children of ConditionalModule it will not raise KeyError.
        """
        mock_is_condition_satisfied.return_value = True
        client = Client()
        client.login(username=self.user.username, password=self.user_password)

        with self.store.default_store(ModuleStoreEnum.Type.split):
            course = CourseFactory.create()

            conditional_block = ItemFactory.create(
                parent_location=course.location, category="conditional")

            # child conditional_block
            ItemFactory.create(parent_location=conditional_block.location,
                               category="conditional")

            url = reverse_usage_url(
                'preview_handler',
                conditional_block.location,
                kwargs={'handler': 'xmodule_handler/conditional_get'})
            response = client.post(url)
            self.assertEqual(response.status_code, 200)
    def _get_usage_info(course,
                        unit,
                        item,
                        usage_info,
                        group_id,
                        scheme_name=None):
        """
        Get usage info for unit/module.
        """
        unit_url = reverse_usage_url(
            'container_handler',
            course.location.course_key.make_usage_key(unit.location.block_type,
                                                      unit.location.name))

        usage_dict = {
            'label': u"{} / {}".format(unit.display_name, item.display_name),
            'url': unit_url
        }
        if scheme_name == RANDOM_SCHEME:
            validation_summary = item.general_validation_message()
            usage_dict.update({
                'validation':
                validation_summary.to_json() if validation_summary else None
            })

        usage_info[group_id].append(usage_dict)

        return usage_info
    def test_preview_conditional_module_children_context(self, mock_is_condition_satisfied):
        """
        Testst that when empty context is pass to children of ConditionalModule it will not raise KeyError.
        """
        mock_is_condition_satisfied.return_value = True
        client = Client()
        client.login(username=self.user.username, password=self.user_password)

        with self.store.default_store(ModuleStoreEnum.Type.split):
            course = CourseFactory.create()

            conditional_block = ItemFactory.create(
                parent_location=course.location,
                category="conditional"
            )

            # child conditional_block
            ItemFactory.create(
                parent_location=conditional_block.location,
                category="conditional"
            )

            url = reverse_usage_url(
                'preview_handler',
                conditional_block.location,
                kwargs={'handler': 'xmodule_handler/conditional_get'}
            )
            response = client.post(url)
            self.assertEqual(response.status_code, 200)
Exemple #16
0
    def test_post_course_update(self, mock_push_update):
        """
        Test that a user can successfully post on course updates and handouts of a course
        """
        self.post_course_update()

        # check that push notifications are not sent
        self.assertFalse(mock_push_update.called)

        updates_location = self.course.id.make_usage_key('course_info', 'updates')
        self.assertTrue(isinstance(updates_location, UsageKey))
        self.assertEqual(updates_location.name, u'updates')

        # check posting on handouts
        handouts_location = self.course.id.make_usage_key('course_info', 'handouts')
        course_handouts_url = reverse_usage_url('xblock_handler', handouts_location)

        content = u"Sample handout"
        payload = {'data': content}
        resp = self.client.ajax_post(course_handouts_url, payload)

        # check that response status is 200 not 500
        self.assertEqual(resp.status_code, 200)

        payload = json.loads(resp.content)
        self.assertHTMLEqual(payload['data'], content)
Exemple #17
0
    def _get_usage_dict(course, unit, item, scheme_name=None):
        """
        Get usage info for unit/module.
        """
        parent_unit = get_parent_unit(item)

        if unit == parent_unit and not item.has_children:
            # Display the topmost unit page if
            # the item is a child of the topmost unit and doesn't have its own children.
            unit_for_url = unit
        elif (not parent_unit and unit.get_parent()) or (unit == parent_unit and item.has_children):
            # Display the item's page rather than the unit page if
            # the item is one level below the topmost unit and has children, or
            # the item itself *is* the topmost unit (and thus does not have a parent unit, but is not an orphan).
            unit_for_url = item
        else:
            # If the item is nested deeper than two levels (the topmost unit > vertical > ... > item)
            # display the page for the nested vertical element.
            parent = item.get_parent()
            nested_vertical = item
            while parent != parent_unit:
                nested_vertical = parent
                parent = parent.get_parent()
            unit_for_url = nested_vertical

        unit_url = reverse_usage_url(
            'container_handler',
            course.location.course_key.make_usage_key(unit_for_url.location.block_type, unit_for_url.location.block_id)
        )

        usage_dict = {'label': u"{} / {}".format(unit.display_name, item.display_name), 'url': unit_url}
        if scheme_name == RANDOM_SCHEME:
            validation_summary = item.general_validation_message()
            usage_dict.update({'validation': validation_summary.to_json() if validation_summary else None})
        return usage_dict
Exemple #18
0
    def _create_problem_with_content_group(self,
                                           cid,
                                           group_id,
                                           name_suffix='',
                                           special_characters=''):
        """
        Create a problem
        Assign content group to the problem.
        """
        vertical = ItemFactory.create(
            category='vertical',
            parent_location=self.course.location,
            display_name="Test Unit {}".format(name_suffix))

        problem = ItemFactory.create(category='problem',
                                     parent_location=vertical.location,
                                     display_name=u"Test Problem {}{}".format(
                                         name_suffix, special_characters))

        group_access_content = {'group_access': {cid: [group_id]}}

        self.client.ajax_post(reverse_usage_url("xblock_handler",
                                                problem.location),
                              data={'metadata': group_access_content})

        self.save_course()

        return vertical, problem
Exemple #19
0
def create_export_tarball(course_module, course_key, context, status=None):
    """
    Generates the export tarball, or returns None if there was an error.

    Updates the context with any error information if applicable.
    """
    name = course_module.url_name
    export_file = NamedTemporaryFile(prefix=name + '.', suffix=".tar.gz")
    root_dir = path(mkdtemp())

    try:
        if isinstance(course_key, LibraryLocator):
            export_library_to_xml(modulestore(), contentstore(), course_key, root_dir, name)
        else:
            export_course_to_xml(modulestore(), contentstore(), course_module.id, root_dir, name)

        if status:
            status.set_state(u'Compressing')
            status.increment_completed_steps()
        LOGGER.debug(u'tar file being generated at %s', export_file.name)
        with tarfile.open(name=export_file.name, mode='w:gz') as tar_file:
            tar_file.add(root_dir / name, arcname=name)

    except SerializationError as exc:
        LOGGER.exception(u'There was an error exporting %s', course_key, exc_info=True)
        parent = None
        try:
            failed_item = modulestore().get_item(exc.location)
            parent_loc = modulestore().get_parent_location(failed_item.location)

            if parent_loc is not None:
                parent = modulestore().get_item(parent_loc)
        except:  # pylint: disable=bare-except
            # if we have a nested exception, then we'll show the more generic error message
            pass

        context.update({
            'in_err': True,
            'raw_err_msg': str(exc),
            'edit_unit_url': reverse_usage_url("container_handler", parent.location) if parent else "",
        })
        if status:
            status.fail(json.dumps({'raw_error_msg': context['raw_err_msg'],
                                    'edit_unit_url': context['edit_unit_url']}))
        raise
    except Exception as exc:
        LOGGER.exception(u'There was an error exporting %s', course_key, exc_info=True)
        context.update({
            'in_err': True,
            'edit_unit_url': None,
            'raw_err_msg': str(exc)})
        if status:
            status.fail(json.dumps({'raw_error_msg': context['raw_err_msg']}))
        raise
    finally:
        if os.path.exists(root_dir / name):
            shutil.rmtree(root_dir / name)

    return export_file
Exemple #20
0
def create_export_tarball(course_module, course_key, context, status=None):
    """
    Generates the export tarball, or returns None if there was an error.

    Updates the context with any error information if applicable.
    """
    name = course_module.url_name
    export_file = NamedTemporaryFile(prefix=name + '.', suffix=".tar.gz")
    root_dir = path(mkdtemp())

    try:
        if isinstance(course_key, LibraryLocator):
            export_library_to_xml(modulestore(), contentstore(), course_key, root_dir, name)
        else:
            export_course_to_xml(modulestore(), contentstore(), course_module.id, root_dir, name)

        if status:
            status.set_state(u'Compressing')
            status.increment_completed_steps()
        LOGGER.debug(u'tar file being generated at %s', export_file.name)
        with tarfile.open(name=export_file.name, mode='w:gz') as tar_file:
            tar_file.add(root_dir / name, arcname=name)

    except SerializationError as exc:
        LOGGER.exception(u'There was an error exporting %s', course_key, exc_info=True)
        parent = None
        try:
            failed_item = modulestore().get_item(exc.location)
            parent_loc = modulestore().get_parent_location(failed_item.location)

            if parent_loc is not None:
                parent = modulestore().get_item(parent_loc)
        except:  # pylint: disable=bare-except
            # if we have a nested exception, then we'll show the more generic error message
            pass

        context.update({
            'in_err': True,
            'raw_err_msg': str(exc),
            'edit_unit_url': reverse_usage_url("container_handler", parent.location) if parent else "",
        })
        if status:
            status.fail(json.dumps({'raw_error_msg': context['raw_err_msg'],
                                    'edit_unit_url': context['edit_unit_url']}))
        raise
    except Exception as exc:
        LOGGER.exception('There was an error exporting %s', course_key, exc_info=True)
        context.update({
            'in_err': True,
            'edit_unit_url': None,
            'raw_err_msg': str(exc)})
        if status:
            status.fail(json.dumps({'raw_error_msg': context['raw_err_msg']}))
        raise
    finally:
        if os.path.exists(root_dir / name):
            shutil.rmtree(root_dir / name)

    return export_file
Exemple #21
0
    def test_delete_static_page(self):
        # Add static tab
        resp = self.create_xblock(category='static_tab')
        usage_key = self.response_usage_key(resp)

        # Now delete it. There was a bug that the delete was failing (static tabs do not exist in draft modulestore).
        resp = self.client.delete(reverse_usage_url('xblock_handler', usage_key))
        self.assertEqual(resp.status_code, 204)
Exemple #22
0
    def test_get_vertical(self):
        # Add a vertical
        resp = self.create_xblock(category='vertical')
        usage_key = self.response_usage_key(resp)

        # Retrieve it
        resp = self.client.get(reverse_usage_url('xblock_handler', usage_key))
        self.assertEqual(resp.status_code, 200)
Exemple #23
0
    def test_get_vertical(self):
        # Add a vertical
        resp = self.create_xblock(category='vertical')
        usage_key = self.response_usage_key(resp)

        # Retrieve it
        resp = self.client.get(reverse_usage_url('xblock_handler', usage_key))
        self.assertEqual(resp.status_code, 200)
Exemple #24
0
    def test_delete_static_page(self):
        # Add static tab
        resp = self.create_xblock(category='static_tab')
        usage_key = self.response_usage_key(resp)

        # Now delete it. There was a bug that the delete was failing (static tabs do not exist in draft modulestore).
        resp = self.client.delete(reverse_usage_url('xblock_handler', usage_key))
        self.assertEqual(resp.status_code, 204)
 def _update_item(self, usage_key, metadata):
     """
     Helper method: Uses the REST API to update the fields of an XBlock.
     This will result in the XBlock's editor_saved() method being called.
     """
     update_url = reverse_usage_url("xblock_handler", usage_key)
     return self.client.ajax_post(update_url, data={
         'metadata': metadata,
     })
def i_click_on_error_dialog(step):
    world.click_link_by_text('Correct failed component')
    assert_true(world.css_html("span.inline-error").startswith("Problem i4x://MITx/999/problem"))
    course_key = SlashSeparatedCourseKey("MITx", "999", "Robot_Super_Course")
    # we don't know the actual ID of the vertical. So just check that we did go to a
    # vertical page in the course (there should only be one).
    vertical_usage_key = course_key.make_usage_key("vertical", "")
    vertical_url = reverse_usage_url('unit_handler', vertical_usage_key)
    assert_equal(1, world.browser.url.count(vertical_url))
 def test_delete_item_signal_handler_called(self, mock_remove_prereq, mock_set_required):
     seq3 = ItemFactory.create(
         parent_location=self.chapter.location,
         category='sequential',
         display_name='untitled sequential 3'
     )
     self.client.delete(reverse_usage_url('xblock_handler', seq3.location))
     mock_remove_prereq.assert_called_with(seq3.location)
     mock_set_required.assert_called_with(seq3.location.course_key, seq3.location, None, None, None)
Exemple #28
0
    def setUp(self):
        """ Creates the test course structure and a couple problems to 'edit'. """
        super(TestEditItem, self).setUp()
        # create a chapter
        display_name = 'chapter created'
        resp = self.create_xblock(display_name=display_name, category='chapter')
        chap_usage_key = self.response_usage_key(resp)
        resp = self.create_xblock(parent_usage_key=chap_usage_key, category='sequential')
        self.seq_usage_key = self.response_usage_key(resp)
        self.seq_update_url = reverse_usage_url("xblock_handler", self.seq_usage_key)

        # create problem w/ boilerplate
        template_id = 'multiplechoice.yaml'
        resp = self.create_xblock(parent_usage_key=self.seq_usage_key, category='problem', boilerplate=template_id)
        self.problem_usage_key = self.response_usage_key(resp)
        self.problem_update_url = reverse_usage_url("xblock_handler", self.problem_usage_key)

        self.course_update_url = reverse_usage_url("xblock_handler", self.usage_key)
Exemple #29
0
 def test_delete_item_signal_handler_called(self, mock_remove_prereq,
                                            mock_set_required):
     seq3 = ItemFactory.create(parent_location=self.chapter.location,
                               category='sequential',
                               display_name='untitled sequential 3')
     self.client.delete(reverse_usage_url('xblock_handler', seq3.location))
     mock_remove_prereq.assert_called_with(seq3.location)
     mock_set_required.assert_called_with(seq3.location.course_key,
                                          seq3.location, None, None, None)
Exemple #30
0
    def test_published_and_draft_contents_with_update(self):
        """ Create a draft and publish it then modify the draft and check that published content is not modified """

        # Make problem public.
        resp = self.client.ajax_post(self.problem_update_url,
                                     data={'publish': 'make_public'})
        self.assertIsNotNone(
            self.get_item_from_modulestore(self.problem_usage_key, False))

        # Now make a draft
        resp = self.client.ajax_post(self.problem_update_url,
                                     data={
                                         'id': unicode(self.problem_usage_key),
                                         'metadata': {},
                                         'data':
                                         "<p>Problem content draft.</p>",
                                         'publish': 'create_draft'
                                     })

        # Both published and draft content should be different
        published = self.get_item_from_modulestore(self.problem_usage_key,
                                                   False)
        draft = self.get_item_from_modulestore(self.problem_usage_key, True)
        self.assertNotEqual(draft.data, published.data)

        # Get problem by 'xblock_handler'
        view_url = reverse_usage_url("xblock_view_handler",
                                     self.problem_usage_key,
                                     {"view_name": "student_view"})
        resp = self.client.get(view_url, HTTP_ACCEPT='application/json')
        self.assertEqual(resp.status_code, 200)

        # Activate the editing view
        view_url = reverse_usage_url("xblock_view_handler",
                                     self.problem_usage_key,
                                     {"view_name": "studio_view"})
        resp = self.client.get(view_url, HTTP_ACCEPT='application/json')
        self.assertEqual(resp.status_code, 200)

        # Both published and draft content should still be different
        published = self.get_item_from_modulestore(self.problem_usage_key,
                                                   False)
        draft = self.get_item_from_modulestore(self.problem_usage_key, True)
        self.assertNotEqual(draft.data, published.data)
Exemple #31
0
def create_export_tarball(course_module, course_key, context):
    """
    Generates the export tarball, or returns None if there was an error.

    Updates the context with any error information if applicable.
    """
    name = course_module.url_name
    export_file = NamedTemporaryFile(prefix=name + '.', suffix=".tar.gz")
    root_dir = path(mkdtemp())

    try:
        if isinstance(course_key, LibraryLocator):
            export_library_to_xml(modulestore(), contentstore(), course_key, root_dir, name)
        else:
            export_course_to_xml(modulestore(), contentstore(), course_module.id, root_dir, name)

        logging.debug(u'tar file being generated at %s', export_file.name)
        with tarfile.open(name=export_file.name, mode='w:gz') as tar_file:
            tar_file.add(root_dir / name, arcname=name)

    except SerializationError as exc:
        log.exception(u'There was an error exporting %s', course_key)
        unit = None
        failed_item = None
        parent = None
        try:
            failed_item = modulestore().get_item(exc.location)
            parent_loc = modulestore().get_parent_location(failed_item.location)

            if parent_loc is not None:
                parent = modulestore().get_item(parent_loc)
                if parent.location.category == 'vertical':
                    unit = parent
        except:  # pylint: disable=bare-except
            # if we have a nested exception, then we'll show the more generic error message
            pass

        context.update({
            'in_err': True,
            'raw_err_msg': str(exc),
            'failed_module': failed_item,
            'unit': unit,
            'edit_unit_url': reverse_usage_url("container_handler", parent.location) if parent else "",
        })
        raise
    except Exception as exc:
        log.exception('There was an error exporting %s', course_key)
        context.update({
            'in_err': True,
            'unit': None,
            'raw_err_msg': str(exc)})
        raise
    finally:
        shutil.rmtree(root_dir / name)

    return export_file
def create_export_tarball(course_module, course_key, context):
    """
    Generates the export tarball, or returns None if there was an error.

    Updates the context with any error information if applicable.
    """
    name = course_module.url_name
    export_file = NamedTemporaryFile(prefix=name + '.', suffix=".tar.gz")
    root_dir = path(mkdtemp())

    try:
        if isinstance(course_key, LibraryLocator):
            export_library_to_xml(modulestore(), contentstore(), course_key, root_dir, name)
        else:
            export_course_to_xml(modulestore(), contentstore(), course_module.id, root_dir, name)

        logging.debug(u'tar file being generated at %s', export_file.name)
        with tarfile.open(name=export_file.name, mode='w:gz') as tar_file:
            tar_file.add(root_dir / name, arcname=name)

    except SerializationError as exc:
        log.exception(u'There was an error exporting %s', course_key)
        unit = None
        failed_item = None
        parent = None
        try:
            failed_item = modulestore().get_item(exc.location)
            parent_loc = modulestore().get_parent_location(failed_item.location)

            if parent_loc is not None:
                parent = modulestore().get_item(parent_loc)
                if parent.location.category == 'vertical':
                    unit = parent
        except:  # pylint: disable=bare-except
            # if we have a nested exception, then we'll show the more generic error message
            pass

        context.update({
            'in_err': True,
            'raw_err_msg': str(exc),
            'failed_module': failed_item,
            'unit': unit,
            'edit_unit_url': reverse_usage_url("container_handler", parent.location) if parent else "",
        })
        raise
    except Exception as exc:
        log.exception('There was an error exporting %s', course_key)
        context.update({
            'in_err': True,
            'unit': None,
            'raw_err_msg': str(exc)})
        raise
    finally:
        shutil.rmtree(root_dir / name)

    return export_file
Exemple #33
0
    def _create_content_experiment(self,
                                   cid=-1,
                                   name_suffix='',
                                   special_characters=''):
        """
        Create content experiment.

        Assign Group Configuration to the experiment if cid is provided.
        """
        vertical = ItemFactory.create(
            category='vertical',
            parent_location=self.course.location,
            display_name='Test Unit {}'.format(name_suffix))
        c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0")
        c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1")
        c2_url = self.course.id.make_usage_key("vertical", "split_test_cond2")
        split_test = ItemFactory.create(
            category='split_test',
            parent_location=vertical.location,
            user_partition_id=cid,
            display_name=u"Test Content Experiment {}{}".format(
                name_suffix, special_characters),
            group_id_to_child={
                "0": c0_url,
                "1": c1_url,
                "2": c2_url
            })
        ItemFactory.create(
            parent_location=split_test.location,
            category="vertical",
            display_name="Condition 0 vertical",
            location=c0_url,
        )
        ItemFactory.create(
            parent_location=split_test.location,
            category="vertical",
            display_name="Condition 1 vertical",
            location=c1_url,
        )
        ItemFactory.create(
            parent_location=split_test.location,
            category="vertical",
            display_name="Condition 2 vertical",
            location=c2_url,
        )

        partitions_json = [p.to_json() for p in self.course.user_partitions]

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", split_test.location),
            data={'metadata': {
                'user_partitions': partitions_json
            }})

        self.save_course()
        return (vertical, split_test)
 def setup_test_set_get_section_grader_ajax(self):
     """
     Populate the course, grab a section, get the url for the assignment type access
     """
     self.populate_course()
     sections = modulestore().get_items(self.course.id, qualifiers={'category': "sequential"})
     # see if test makes sense
     self.assertGreater(len(sections), 0, "No sections found")
     section = sections[0]  # just take the first one
     return reverse_usage_url('xblock_handler', section.location)
 def setup_test_set_get_section_grader_ajax(self):
     """
     Populate the course, grab a section, get the url for the assignment type access
     """
     self.populate_course()
     sections = modulestore().get_items(self.course.id, qualifiers={'category': "sequential"})
     # see if test makes sense
     self.assertGreater(len(sections), 0, "No sections found")
     section = sections[0]  # just take the first one
     return reverse_usage_url('xblock_handler', section.location)
Exemple #36
0
    def test_handle_requests(self, aside_key_class):
        """
        Checks that handler to save tags in StructuredTagsAside works properly
        """
        handler_url = reverse_usage_url(
            'preview_handler',
            unicode(aside_key_class(self.problem.location, self.aside_name)),
            kwargs={'handler': 'save_tags'}
        )

        client = AjaxEnabledTestClient()
        client.login(username=self.user.username, password=self.user_password)

        response = client.post(handler_url, json.dumps({}), content_type="application/json")
        self.assertEqual(response.status_code, 400)

        response = client.post(handler_url, json.dumps({'undefined_tag': ['undefined1', 'undefined2']}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 400)

        response = client.post(handler_url, json.dumps({self.aside_tag_dif: ['undefined1', 'undefined2']}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 400)

        def _test_helper_func(problem_location):
            """
            Helper function
            """
            problem = modulestore().get_item(problem_location)
            asides = problem.runtime.get_asides(problem)
            tag_aside = None
            for aside in asides:
                if isinstance(aside, StructuredTagsAside):
                    tag_aside = aside
                    break
            return tag_aside

        response = client.post(handler_url, json.dumps({self.aside_tag_dif: [self.aside_tag_dif_value]}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 200)

        tag_aside = _test_helper_func(self.problem.location)
        self.assertIsNotNone(tag_aside, "Necessary StructuredTagsAside object isn't found")
        self.assertEqual(tag_aside.saved_tags[self.aside_tag_dif], [self.aside_tag_dif_value])

        response = client.post(handler_url, json.dumps({self.aside_tag_dif: [self.aside_tag_dif_value,
                                                                             self.aside_tag_dif_value2]}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 200)

        tag_aside = _test_helper_func(self.problem.location)
        self.assertIsNotNone(tag_aside, "Necessary StructuredTagsAside object isn't found")
        self.assertEqual(tag_aside.saved_tags[self.aside_tag_dif], [self.aside_tag_dif_value,
                                                                    self.aside_tag_dif_value2])
Exemple #37
0
def i_click_on_error_dialog(step):
    world.click_link_by_text('Correct failed component')
    assert_true(
        world.css_html("span.inline-error").startswith(
            "Problem i4x://MITx/999/problem"))
    course_key = SlashSeparatedCourseKey("MITx", "999", "Robot_Super_Course")
    # we don't know the actual ID of the vertical. So just check that we did go to a
    # vertical page in the course (there should only be one).
    vertical_usage_key = course_key.make_usage_key("vertical", "")
    vertical_url = reverse_usage_url('unit_handler', vertical_usage_key)
    assert_equal(1, world.browser.url.count(vertical_url))
        def _get_settings_html():
            """
            Helper function to get block settings HTML
            Used to check the available libraries.
            """
            edit_view_url = reverse_usage_url("xblock_view_handler", lib_block.location, {"view_name": STUDIO_VIEW})

            resp = self.client.get_json(edit_view_url)
            self.assertEquals(resp.status_code, 200)

            return parse_json(resp)['html']
        def _get_settings_html():
            """
            Helper function to get block settings HTML
            Used to check the available libraries.
            """
            edit_view_url = reverse_usage_url("xblock_view_handler", lib_block.location, {"view_name": STUDIO_VIEW})

            resp = self.client.get_json(edit_view_url)
            self.assertEquals(resp.status_code, 200)

            return parse_json(resp)['html']
Exemple #40
0
    def test_handle_requests(self, aside_key_class):
        """
        Checks that handler to save tags in StructuredTagsAside works properly
        """
        handler_url = reverse_usage_url(
            'component_handler',
            unicode(aside_key_class(self.problem.location, self.aside_name)),
            kwargs={'handler': 'save_tags'}
        )

        client = AjaxEnabledTestClient()
        client.login(username=self.user.username, password=self.user_password)

        response = client.post(handler_url, json.dumps({}), content_type="application/json")
        self.assertEqual(response.status_code, 400)

        response = client.post(handler_url, json.dumps({'undefined_tag': ['undefined1', 'undefined2']}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 400)

        response = client.post(handler_url, json.dumps({self.aside_tag_dif: ['undefined1', 'undefined2']}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 400)

        def _test_helper_func(problem_location):
            """
            Helper function
            """
            problem = modulestore().get_item(problem_location)
            asides = problem.runtime.get_asides(problem)
            tag_aside = None
            for aside in asides:
                if isinstance(aside, StructuredTagsAside):
                    tag_aside = aside
                    break
            return tag_aside

        response = client.post(handler_url, json.dumps({self.aside_tag_dif: [self.aside_tag_dif_value]}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 200)

        tag_aside = _test_helper_func(self.problem.location)
        self.assertIsNotNone(tag_aside, "Necessary StructuredTagsAside object isn't found")
        self.assertEqual(tag_aside.saved_tags[self.aside_tag_dif], [self.aside_tag_dif_value])

        response = client.post(handler_url, json.dumps({self.aside_tag_dif: [self.aside_tag_dif_value,
                                                                             self.aside_tag_dif_value2]}),
                               content_type="application/json")
        self.assertEqual(response.status_code, 200)

        tag_aside = _test_helper_func(self.problem.location)
        self.assertIsNotNone(tag_aside, "Necessary StructuredTagsAside object isn't found")
        self.assertEqual(tag_aside.saved_tags[self.aside_tag_dif], [self.aside_tag_dif_value,
                                                                    self.aside_tag_dif_value2])
    def test_can_get_correct_usage_info_for_unit(self):
        """
        When group access is set on the unit level, the usage info should return a url to the unit, not
        the sequential parent of the unit.
        """
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='User Partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='User Partition',
                groups=[
                    Group(id=0, name="Group")
                ],
            ),
        ]
        vertical, __ = self._create_problem_with_content_group(
            cid=0, group_id=0, name_suffix='0'
        )

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", vertical.location),
            data={'metadata': {'group_access': {0: [0]}}}
        )

        actual = self._get_user_partition('cohort')
        # order of usage list is arbitrary, sort for reliable comparison
        actual['groups'][0]['usage'].sort(key=itemgetter('label'))
        expected = {
            'id': 0,
            'name': 'User Partition',
            'scheme': 'cohort',
            'description': 'User Partition',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 0, 'name': 'Group', 'version': 1, 'usage': [
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Subsection 0 / Test Unit 0"
                    },
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Unit 0 / Test Problem 0"
                    }
                ]},
            ],
            u'parameters': {},
            u'active': True,
        }

        self.maxDiff = None

        assert actual == expected
Exemple #42
0
    def test_published_and_draft_contents_with_update(self):
        """ Create a draft and publish it then modify the draft and check that published content is not modified """

        # Make problem public.
        resp = self.client.ajax_post(
            self.problem_update_url,
            data={'publish': 'make_public'}
        )
        self.assertIsNotNone(self.get_item_from_modulestore(self.problem_usage_key, False))

        # Now make a draft
        resp = self.client.ajax_post(
            self.problem_update_url,
            data={
                'id': unicode(self.problem_usage_key),
                'metadata': {},
                'data': "<p>Problem content draft.</p>",
                'publish': 'create_draft'
            }
        )

        # Both published and draft content should be different
        published = self.get_item_from_modulestore(self.problem_usage_key, False)
        draft = self.get_item_from_modulestore(self.problem_usage_key, True)
        self.assertNotEqual(draft.data, published.data)

        # Get problem by 'xblock_handler'
        view_url = reverse_usage_url("xblock_view_handler", self.problem_usage_key, {"view_name": STUDENT_VIEW})
        resp = self.client.get(view_url, HTTP_ACCEPT='application/json')
        self.assertEqual(resp.status_code, 200)

        # Activate the editing view
        view_url = reverse_usage_url("xblock_view_handler", self.problem_usage_key, {"view_name": STUDIO_VIEW})
        resp = self.client.get(view_url, HTTP_ACCEPT='application/json')
        self.assertEqual(resp.status_code, 200)

        # Both published and draft content should still be different
        published = self.get_item_from_modulestore(self.problem_usage_key, False)
        draft = self.get_item_from_modulestore(self.problem_usage_key, True)
        self.assertNotEqual(draft.data, published.data)
Exemple #43
0
 def _get_container_preview(self, usage_key):
     """
     Returns the HTML and resources required for the xblock at the specified UsageKey
     """
     preview_url = reverse_usage_url("xblock_view_handler", usage_key, {'view_name': 'container_preview'})
     resp = self.client.get(preview_url, HTTP_ACCEPT='application/json')
     self.assertEqual(resp.status_code, 200)
     resp_content = json.loads(resp.content)
     html = resp_content['html']
     self.assertTrue(html)
     resources = resp_content['resources']
     self.assertIsNotNone(resources)
     return html, resources
Exemple #44
0
 def _get_container_preview(self, usage_key):
     """
     Returns the HTML and resources required for the xblock at the specified UsageKey
     """
     preview_url = reverse_usage_url("xblock_view_handler", usage_key, {'view_name': 'container_preview'})
     resp = self.client.get(preview_url, HTTP_ACCEPT='application/json')
     self.assertEqual(resp.status_code, 200)
     resp_content = json.loads(resp.content)
     html = resp_content['html']
     self.assertTrue(html)
     resources = resp_content['resources']
     self.assertIsNotNone(resources)
     return html, resources
def i_click_on_error_dialog(step):
    world.click_link_by_text('Correct failed component')
    assert_true(world.css_html("span.inline-error").startswith("Problem i4x://MITx/999/problem"))
    course_key = SlashSeparatedCourseKey("MITx", "999", "Robot_Super_Course")
    # we don't know the actual ID of the vertical. So just check that we did go to a
    # vertical page in the course (there should only be one).
    vertical_usage_key = course_key.make_usage_key("vertical", None)
    vertical_url = reverse_usage_url('container_handler', vertical_usage_key)
    # Remove the trailing "/None" from the URL - we don't know the course ID, so we just want to
    # check that we visited a vertical URL.
    if vertical_url.endswith("/None"):
        vertical_url = vertical_url[:-5]
    assert_equal(1, world.browser.url.count(vertical_url))
    def test_can_get_correct_usage_info_for_unit(self):
        """
        When group access is set on the unit level, the usage info should return a url to the unit, not
        the sequential parent of the unit.
        """
        self.course.user_partitions = [
            UserPartition(
                id=0,
                name='User Partition',
                scheme=UserPartition.get_scheme('cohort'),
                description='User Partition',
                groups=[
                    Group(id=0, name="Group")
                ],
            ),
        ]
        vertical, __ = self._create_problem_with_content_group(
            cid=0, group_id=0, name_suffix='0'
        )

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", vertical.location),
            data={'metadata': {'group_access': {0: [0]}}}
        )

        actual = self._get_user_partition('cohort')
        expected = {
            'id': 0,
            'name': 'User Partition',
            'scheme': 'cohort',
            'description': 'User Partition',
            'version': UserPartition.VERSION,
            'groups': [
                {'id': 0, 'name': 'Group', 'version': 1, 'usage': [
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Subsection 0 / Test Unit 0"
                    },
                    {
                        'url': u"/container/{}".format(vertical.location),
                        'label': u"Test Unit 0 / Test Problem 0"
                    }
                ]},
            ],
            u'parameters': {},
            u'active': True,
        }

        self.maxDiff = None

        self.assertEqual(actual, expected)
Exemple #47
0
 def _refresh_children(self, lib_content_block, status_code_expected=200):
     """
     Helper method: Uses the REST API to call the 'refresh_children' handler
     of a LibraryContent block
     """
     if 'user' not in lib_content_block.runtime._services:  # pylint: disable=protected-access
         lib_content_block.runtime._services['user'] = Mock(
             user_id=self.user.id)  # pylint: disable=protected-access
     handler_url = reverse_usage_url('component_handler',
                                     lib_content_block.location,
                                     kwargs={'handler': 'refresh_children'})
     response = self.client.ajax_post(handler_url)
     self.assertEqual(response.status_code, status_code_expected)
     return modulestore().get_item(lib_content_block.location)
    def _create_content_experiment(self, cid=-1, name_suffix=''):
        """
        Create content experiment.

        Assign Group Configuration to the experiment if cid is provided.
        """
        vertical = ItemFactory.create(
            category='vertical',
            parent_location=self.course.location,
            display_name='Test Unit {}'.format(name_suffix)
        )
        c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0")
        c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1")
        c2_url = self.course.id.make_usage_key("vertical", "split_test_cond2")
        split_test = ItemFactory.create(
            category='split_test',
            parent_location=vertical.location,
            user_partition_id=cid,
            display_name='Test Content Experiment {}'.format(name_suffix),
            group_id_to_child={"0": c0_url, "1": c1_url, "2": c2_url}
        )
        ItemFactory.create(
            parent_location=split_test.location,
            category="vertical",
            display_name="Condition 0 vertical",
            location=c0_url,
        )
        ItemFactory.create(
            parent_location=split_test.location,
            category="vertical",
            display_name="Condition 1 vertical",
            location=c1_url,
        )
        ItemFactory.create(
            parent_location=split_test.location,
            category="vertical",
            display_name="Condition 2 vertical",
            location=c2_url,
        )

        partitions_json = [p.to_json() for p in self.course.user_partitions]

        self.client.ajax_post(
            reverse_usage_url("xblock_handler", split_test.location),
            data={'metadata': {'user_partitions': partitions_json}}
        )

        self.save_course()
        return (vertical, split_test)
def i_click_on_error_dialog(step):
    world.click_link_by_text('Correct failed component')
    assert_true(
        world.css_html("span.inline-error").startswith(
            "Problem i4x://MITx/999/problem"))
    course_key = SlashSeparatedCourseKey("MITx", "999", "Robot_Super_Course")
    # we don't know the actual ID of the vertical. So just check that we did go to a
    # vertical page in the course (there should only be one).
    vertical_usage_key = course_key.make_usage_key("vertical", None)
    vertical_url = reverse_usage_url('container_handler', vertical_usage_key)
    # Remove the trailing "/None" from the URL - we don't know the course ID, so we just want to
    # check that we visited a vertical URL.
    if vertical_url.endswith("/None"):
        vertical_url = vertical_url[:-5]
    assert_equal(1, world.browser.url.count(vertical_url))
Exemple #50
0
 def _refresh_children(self, lib_content_block, status_code_expected=200):
     """
     Helper method: Uses the REST API to call the 'refresh_children' handler
     of a LibraryContent block
     """
     if 'user' not in lib_content_block.runtime._services:  # pylint: disable=protected-access
         lib_content_block.runtime._services['user'] = Mock(user_id=self.user.id)  # pylint: disable=protected-access
     handler_url = reverse_usage_url(
         'component_handler',
         lib_content_block.location,
         kwargs={'handler': 'refresh_children'}
     )
     response = self.client.ajax_post(handler_url)
     self.assertEqual(response.status_code, status_code_expected)
     return modulestore().get_item(lib_content_block.location)
Exemple #51
0
def xblock_studio_url(xblock, parent_xblock=None):
    """
    Returns the Studio editing URL for the specified xblock.
    """
    if not xblock_has_own_studio_page(xblock, parent_xblock):
        return None
    category = xblock.category
    if category == 'course':
        return reverse_course_url('course_handler', xblock.location.course_key)
    elif category in ('chapter', 'sequential'):
        return u'{url}?show={usage_key}'.format(
            url=reverse_course_url('course_handler',
                                   xblock.location.course_key),
            usage_key=urllib.quote(unicode(xblock.location)))
    else:
        return reverse_usage_url('container_handler', xblock.location)
Exemple #52
0
def xblock_studio_url(xblock, parent_xblock=None):
    """
    Returns the Studio editing URL for the specified xblock.
    """
    if not xblock_has_own_studio_page(xblock, parent_xblock):
        return None
    category = xblock.category
    if category == "course":
        return reverse_course_url("course_handler", xblock.location.course_key)
    elif category in ("chapter", "sequential"):
        return u"{url}?show={usage_key}".format(
            url=reverse_course_url("course_handler", xblock.location.course_key),
            usage_key=urllib.quote(unicode(xblock.location)),
        )
    else:
        return reverse_usage_url("container_handler", xblock.location)
Exemple #53
0
    def _refresh_children(self, lib_content_block, status_code_expected=200):
        """
        Helper method: Uses the REST API to call the 'refresh_children' handler
        of a LibraryContent block
        """
        if "user" not in lib_content_block.runtime._services:  # pylint: disable=protected-access
            mocked_user_service = Mock(user_id=self.user.id)
            mocked_user_service.get_current_user.return_value = XBlockUser(is_current_user=True)
            lib_content_block.runtime._services["user"] = mocked_user_service  # pylint: disable=protected-access

        handler_url = reverse_usage_url(
            "component_handler", lib_content_block.location, kwargs={"handler": "refresh_children"}
        )
        response = self.client.ajax_post(handler_url)
        self.assertEqual(response.status_code, status_code_expected)
        return modulestore().get_item(lib_content_block.location)
    def test_group_indexed_only_on_assigned_html_block(self):
        """ indexing course with content groups assigned to one of multiple html units """
        group_access_content = {'group_access': {666: [1]}}
        self.client.ajax_post(
            reverse_usage_url("xblock_handler", self.html_unit1.location),
            data={'metadata': group_access_content}
        )

        self.publish_item(self.store, self.html_unit1.location)

        with patch(settings.SEARCH_ENGINE + '.index') as mock_index:
            self.reindex_course(self.store)
            self.assertTrue(mock_index.called)
            self.assertIn(self._html_group_result(self.html_unit1, [1]), mock_index.mock_calls)
            self.assertIn(self._html_nogroup_result(self.html_unit2), mock_index.mock_calls)
            mock_index.reset_mock()
Exemple #55
0
 def setUp(self):
     super(TestEditSplitModule, self).setUp()
     self.course.user_partitions = [
         UserPartition(
             0, 'first_partition', 'First Partition',
             [Group("0", 'alpha'), Group("1", 'beta')]
         ),
         UserPartition(
             1, 'second_partition', 'Second Partition',
             [Group("0", 'Group 0'), Group("1", 'Group 1'), Group("2", 'Group 2')]
         )
     ]
     self.store.update_item(self.course, self.user.id)
     root_usage_key = self._create_vertical()
     resp = self.create_xblock(category='split_test', parent_usage_key=root_usage_key)
     self.split_test_usage_key = self.response_usage_key(resp)
     self.split_test_update_url = reverse_usage_url("xblock_handler", self.split_test_usage_key)
Exemple #56
0
 def setUp(self):
     super(TestEditSplitModule, self).setUp()
     self.course.user_partitions = [
         UserPartition(
             0, 'first_partition', 'First Partition',
             [Group("0", 'alpha'), Group("1", 'beta')]
         ),
         UserPartition(
             1, 'second_partition', 'Second Partition',
             [Group("0", 'Group 0'), Group("1", 'Group 1'), Group("2", 'Group 2')]
         )
     ]
     self.store.update_item(self.course, self.user.id)
     root_usage_key = self._create_vertical()
     resp = self.create_xblock(category='split_test', parent_usage_key=root_usage_key)
     self.split_test_usage_key = self.response_usage_key(resp)
     self.split_test_update_url = reverse_usage_url("xblock_handler", self.split_test_usage_key)
Exemple #57
0
def i_click_on_error_dialog(step):
    world.css_click("button.action-primary")

    problem_string = unicode(world.scenario_dict['COURSE'].id.make_usage_key("problem", 'ignore'))
    problem_string = u"Problem {}".format(problem_string[:problem_string.rfind('ignore')])
    assert_true(
        world.css_html("span.inline-error").startswith(problem_string),
        u"{} does not start with {}".format(
            world.css_html("span.inline-error"), problem_string
        ))
    # we don't know the actual ID of the vertical. So just check that we did go to a
    # vertical page in the course (there should only be one).
    vertical_usage_key = world.scenario_dict['COURSE'].id.make_usage_key("vertical", "test")
    vertical_url = reverse_usage_url('container_handler', vertical_usage_key)
    # Remove the trailing "/None" from the URL - we don't know the course ID, so we just want to
    # check that we visited a vertical URL.
    if vertical_url.endswith("/test") or vertical_url.endswith("@test"):
        vertical_url = vertical_url[:-5]
    assert_equal(1, world.browser.url.count(vertical_url))
Exemple #58
0
    def test_publish_states_of_nested_xblocks(self):
        """ Test publishing of a unit page containing a nested xblock  """

        resp = self.create_xblock(parent_usage_key=self.seq_usage_key,
                                  display_name='Test Unit',
                                  category='vertical')
        unit_usage_key = self.response_usage_key(resp)
        resp = self.create_xblock(parent_usage_key=unit_usage_key,
                                  category='wrapper')
        wrapper_usage_key = self.response_usage_key(resp)
        resp = self.create_xblock(parent_usage_key=wrapper_usage_key,
                                  category='html')
        html_usage_key = self.response_usage_key(resp)

        # The unit and its children should be private initially
        unit_update_url = reverse_usage_url('xblock_handler', unit_usage_key)
        unit = self.get_item_from_modulestore(unit_usage_key, True)
        html = self.get_item_from_modulestore(html_usage_key, True)
        self.assertEqual(compute_publish_state(unit), PublishState.private)
        self.assertEqual(compute_publish_state(html), PublishState.private)

        # Make the unit public and verify that the problem is also made public
        resp = self.client.ajax_post(unit_update_url,
                                     data={'publish': 'make_public'})
        self.assertEqual(resp.status_code, 200)
        unit = self.get_item_from_modulestore(unit_usage_key, True)
        html = self.get_item_from_modulestore(html_usage_key, True)
        self.assertEqual(compute_publish_state(unit), PublishState.public)
        self.assertEqual(compute_publish_state(html), PublishState.public)

        # Make a draft for the unit and verify that the problem also has a draft
        resp = self.client.ajax_post(unit_update_url,
                                     data={
                                         'id': unicode(unit_usage_key),
                                         'metadata': {},
                                         'publish': 'create_draft'
                                     })
        self.assertEqual(resp.status_code, 200)
        unit = self.get_item_from_modulestore(unit_usage_key, True)
        html = self.get_item_from_modulestore(html_usage_key, True)
        self.assertEqual(compute_publish_state(unit), PublishState.draft)
        self.assertEqual(compute_publish_state(html), PublishState.draft)
    def _verify_deprecated_info(self, course_id, advanced_modules, info,
                                deprecated_block_types):
        """
        Verify deprecated info.
        """
        expected_blocks = []
        for block_type in deprecated_block_types:
            expected_blocks.append([
                reverse_usage_url('container_handler', self.vertical.location),
                '{} Problem'.format(block_type)
            ])

        self.assertEqual(info['deprecated_enabled_block_types'], [
            component for component in advanced_modules
            if component in deprecated_block_types
        ])

        self.assertItemsEqual(info['blocks'], expected_blocks)
        self.assertEqual(
            info['advance_settings_url'],
            reverse_course_url('advanced_settings_handler', course_id))