Пример #1
0
def test_field_serialization():
    # Some Fields can define their own serialization mechanisms.
    # This test ensures that we are using them properly.

    class CustomField(Field):
        """
        Specifiy a custom field that defines its own serialization
        """
        def from_json(self, value):
            return value['value']

        def to_json(self, value):
            return {'value': value}

    class FieldTester(XBlock):
        """Test XBlock for field serialization testing"""
        field = CustomField()

    field_data = DictFieldData({
        'field': {'value': 4}
    })

    field_tester = FieldTester(
        TestRuntime(services={'field-data': field_data}),
        None,
        Mock(),
    )

    assert_equals(4, field_tester.field)
    field_tester.field = 5
    field_tester.save()
    assert_equals({'value': 5}, field_data.get(field_tester, 'field'))
Пример #2
0
def test_xblock_write_then_delete():
    # Tests that setting a field, then deleting it later, doesn't
    # cause an erroneous write of the originally set value after
    # a call to `XBlock.save`
    class FieldTester(XBlock):
        """Test XBlock with two fields"""

        field_a = Integer(scope=Scope.settings)
        field_b = Integer(scope=Scope.content, default=10)

    field_data = DictFieldData({"field_a": 5})
    field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock(spec=ScopeIds))

    # Verify that the fields have been set correctly
    assert_equals(5, field_tester.field_a)
    assert_equals(10, field_tester.field_b)

    # Set the fields to new values
    field_tester.field_a = 20
    field_tester.field_b = 20

    # Assert that we've correctly cached the value of both fields to the newly set values.
    assert_equals(20, field_tester.field_a)
    assert_equals(20, field_tester.field_b)

    # Before saving, delete all the fields. Deletes are performed immediately for now,
    # so the field should immediately not be present in the field_data after the delete.
    # However, we copy the default values into the cache, so after the delete we expect the
    # cached values to be the default values, but the fields to be removed from the field_data.
    del field_tester.field_a
    del field_tester.field_b

    # Assert that we're now finding the right cached values - these should be the default values
    # that the fields have from the class since we've performed a delete, and XBlock.__delete__
    # inserts the default values into the cache as an optimization.
    assert_equals(None, field_tester.field_a)
    assert_equals(10, field_tester.field_b)

    # Perform explicit save
    field_tester.save()

    # Now that we've done the save, double-check that we still have the correct cached values (the defaults)
    assert_equals(None, field_tester.field_a)
    assert_equals(10, field_tester.field_b)

    # Additionally assert that in the model data, we don't have any values actually set for these fields.
    # Basically, we want to ensure that the `save` didn't overwrite anything in the actual field_data
    # Note this test directly accessess field_data and is thus somewhat fragile.
    assert_false(field_data.has(field_tester, "field_a"))
    assert_false(field_data.has(field_tester, "field_b"))
Пример #3
0
def test_default_values():
    # Check that values that are deleted are restored to their default values
    class FieldTester(XBlock):
        """Test XBlock for field access testing"""

        dic1 = Dict(scope=Scope.settings)
        dic2 = Dict(scope=Scope.content, default={"a": 1, "b": 2, "c": 3})
        list1 = List(scope=Scope.settings)
        list2 = List(scope=Scope.content, default=[1, 2, 3])

    field_data = DictFieldData({"dic1": {"a": 200}, "list1": ["a", "b"]})
    field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock(spec=ScopeIds))

    assert_equals({"a": 200}, field_tester.dic1)
    assert_equals({"a": 1, "b": 2, "c": 3}, field_tester.dic2)
    assert_equals(["a", "b"], field_tester.list1)
    assert_equals([1, 2, 3], field_tester.list2)
    # Modify the fields & save
    field_tester.dic1.popitem()
    field_tester.dic2.clear()
    field_tester.list1.pop()
    field_tester.list2.remove(2)
    field_tester.save()

    # Test that after save, new values exist and fields are present in the underlying kvstore
    assert_equals({}, field_tester.dic1)
    assert_equals({}, field_tester.dic2)
    assert_equals(["a"], field_tester.list1)
    assert_equals([1, 3], field_tester.list2)
    for fname in ["dic1", "dic2", "list1", "list2"]:
        assert field_data.has(field_tester, fname)

    # Now delete each field
    del field_tester.dic1
    del field_tester.dic2
    del field_tester.list1
    del field_tester.list2

    # Test that default values return after a delete, but fields not actually
    # in the underlying kvstore

    # Defaults not explicitly set
    assert_equals({}, field_tester.dic1)
    assert_equals([], field_tester.list1)
    # Defaults explicitly set
    assert_equals({"a": 1, "b": 2, "c": 3}, field_tester.dic2)
    assert_equals([1, 2, 3], field_tester.list2)
    for fname in ["dic1", "dic2", "list1", "list2"]:
        assert_false(field_data.has(field_tester, fname))
Пример #4
0
def test_field_access():
    class FieldTester(XBlock):
        """Test XBlock for field access testing"""
        field_a = Integer(scope=Scope.settings)
        field_b = Integer(scope=Scope.content, default=10)
        field_c = Integer(scope=Scope.user_state, default=42)
        float_a = Float(scope=Scope.settings, default=5.8)
        float_b = Float(scope=Scope.settings)

    field_data = DictFieldData({'field_a': 5, 'float_a': 6.1, 'field_x': 15})

    field_tester = FieldTester(TestRuntime(services={'field-data': field_data}), scope_ids=Mock())
    # Verify that the fields have been set
    assert field_tester.field_a == 5
    assert field_tester.field_b == 10
    assert field_tester.field_c == 42
    assert field_tester.float_a == 6.1
    assert field_tester.float_b is None
    assert not hasattr(field_tester, 'field_x')

    # Set two of the fields.
    field_tester.field_a = 20
    field_tester.float_a = 20.5
    # field_a should be updated in the cache, but /not/ in the underlying db.
    assert field_tester.field_a == 20
    assert field_tester.float_a == 20.5
    assert field_data.get(field_tester, 'field_a') == 5
    assert field_data.get(field_tester, 'float_a') == 6.1
    # save the XBlock
    field_tester.save()
    # verify that the fields have been updated correctly
    assert field_tester.field_a == 20
    assert field_tester.float_a == 20.5
    # Now, field_a should be updated in the underlying db
    assert field_data.get(field_tester, 'field_a') == 20
    assert field_data.get(field_tester, 'float_a') == 20.5
    assert field_tester.field_b == 10
    assert field_tester.field_c == 42
    assert field_tester.float_b is None

    # Deletes happen immediately (do not require a save)
    del field_tester.field_a
    del field_tester.float_a

    # After delete, we should find default values in the cache
    assert field_tester.field_a is None
    assert field_tester.float_a == 5.8
    # But the fields should not actually be present in the underlying kvstore
    with pytest.raises(KeyError):
        field_data.get(field_tester, 'field_a')
    assert not field_data.has(field_tester, 'field_a')
    with pytest.raises(KeyError):
        field_data.get(field_tester, 'float_a')
    assert not field_data.has(field_tester, 'float_a')
Пример #5
0
def test_default_values():
    # Check that values that are deleted are restored to their default values
    class FieldTester(XBlock):
        """Test XBlock for field access testing"""
        dic1 = Dict(scope=Scope.settings)
        dic2 = Dict(scope=Scope.content, default={'a': 1, 'b': 2, 'c': 3})
        list1 = List(scope=Scope.settings)
        list2 = List(scope=Scope.content, default=[1, 2, 3])

    field_data = DictFieldData({'dic1': {'a': 200}, 'list1': ['a', 'b']})
    field_tester = FieldTester(TestRuntime(services={'field-data': field_data}), scope_ids=Mock(spec=ScopeIds))

    assert {'a': 200} == field_tester.dic1
    assert {'a': 1, 'b': 2, 'c': 3} == field_tester.dic2
    assert ['a', 'b'] == field_tester.list1
    assert [1, 2, 3] == field_tester.list2
    # Modify the fields & save
    field_tester.dic1.popitem()
    field_tester.dic2.clear()
    field_tester.list1.pop()
    field_tester.list2.remove(2)
    field_tester.save()

    # Test that after save, new values exist and fields are present in the underlying kvstore
    assert {} == field_tester.dic1
    assert {} == field_tester.dic2
    assert ['a'] == field_tester.list1
    assert [1, 3] == field_tester.list2
    for fname in ['dic1', 'dic2', 'list1', 'list2']:
        assert field_data.has(field_tester, fname)

    # Now delete each field
    del field_tester.dic1
    del field_tester.dic2
    del field_tester.list1
    del field_tester.list2

    # Test that default values return after a delete, but fields not actually
    # in the underlying kvstore

    # Defaults not explicitly set
    assert {} == field_tester.dic1
    assert [] == field_tester.list1
    # Defaults explicitly set
    assert {'a': 1, 'b': 2, 'c': 3} == field_tester.dic2
    assert [1, 2, 3] == field_tester.list2
    for fname in ['dic1', 'dic2', 'list1', 'list2']:
        assert not field_data.has(field_tester, fname)
Пример #6
0
def test_change_mutable_default():
    """
    Ensure that mutating the default value for a field causes
    the changes to be saved, and doesn't corrupt other instances
    """

    class MutableTester(XBlock):
        """Test class with mutable fields."""
        list_field = List()

    field_data_a = DictFieldData({})
    mutable_test_a = MutableTester(TestRuntime(services={'field-data': field_data_a}), scope_ids=Mock(spec=ScopeIds))
    field_data_b = DictFieldData({})
    mutable_test_b = MutableTester(TestRuntime(services={'field-data': field_data_b}), scope_ids=Mock(spec=ScopeIds))

    # Saving without changing the default value shouldn't write to field_data
    mutable_test_a.list_field  # pylint: disable=W0104
    mutable_test_a.save()
    with assert_raises(KeyError):
        field_data_a.get(mutable_test_a, 'list_field')

    mutable_test_a.list_field.append(1)
    mutable_test_a.save()

    assert_equals([1], field_data_a.get(mutable_test_a, 'list_field'))
    with assert_raises(KeyError):
        field_data_b.get(mutable_test_b, 'list_field')
Пример #7
0
def test_dict_field_access():
    # Check that dicts are correctly saved when not directly set
    class FieldTester(XBlock):
        """Test XBlock for field access testing"""
        field_a = Dict(scope=Scope.settings)
        field_b = Dict(scope=Scope.content, default={'a': 1, 'b': 2, 'c': 3})
        field_c = Dict(scope=Scope.content, default={'a': 4, 'b': 5, 'c': 6})
        field_d = Dict(scope=Scope.settings)

    field_data = DictFieldData({
        'field_a': {'a': 200},
        'field_b': {'a': 11, 'b': 12, 'c': 13}
    })

    field_tester = FieldTester(
        TestRuntime(services={'field-data': field_data}),
        None,
        Mock()
    )

    # Check initial values have been set properly
    assert_equals({'a': 200}, field_tester.field_a)
    assert_equals({'a': 11, 'b': 12, 'c': 13}, field_tester.field_b)
    assert_equals({'a': 4, 'b': 5, 'c': 6}, field_tester.field_c)
    assert_equals({}, field_tester.field_d)

    # Update the fields
    field_tester.field_a['a'] = 250
    field_tester.field_b['d'] = 14
    field_tester.field_c['a'] = 0
    field_tester.field_d['new'] = 'value'

    # The fields should be update in the cache, but /not/ in the underlying kvstore.
    assert_equals({'a': 250}, field_tester.field_a)
    assert_equals({'a': 11, 'b': 12, 'c': 13, 'd': 14}, field_tester.field_b)
    assert_equals({'a': 0, 'b': 5, 'c': 6}, field_tester.field_c)
    assert_equals({'new': 'value'}, field_tester.field_d)

    # Examine model data directly
    #  Caveat: there's not a clean way to copy the originally provided values for `field_a` and `field_b`
    #  when we instantiate the XBlock. So, the values for those two in both `field_data` and `_field_data_cache`
    #  point at the same object. Thus, `field_a` and `field_b` actually have the correct values in
    #  `field_data` right now. `field_c` does not, because it has never been written to the `field_data`.
    assert_false(field_data.has(field_tester, 'field_c'))
    assert_false(field_data.has(field_tester, 'field_d'))

    field_tester.save()
    # verify that the fields have been updated correctly
    assert_equals({'a': 250}, field_tester.field_a)
    assert_equals({'a': 11, 'b': 12, 'c': 13, 'd': 14}, field_tester.field_b)
    assert_equals({'a': 0, 'b': 5, 'c': 6}, field_tester.field_c)
    assert_equals({'new': 'value'}, field_tester.field_d)

    # Now, the fields should be updated in the underlying kvstore
    assert_equals({'a': 250}, field_data.get(field_tester, 'field_a'))
    assert_equals({'a': 11, 'b': 12, 'c': 13, 'd': 14}, field_data.get(field_tester, 'field_b'))
    assert_equals({'a': 0, 'b': 5, 'c': 6}, field_data.get(field_tester, 'field_c'))
    assert_equals({'new': 'value'}, field_data.get(field_tester, 'field_d'))
Пример #8
0
def test_list_field_access():
    # Check that lists are correctly saved when not directly set
    class FieldTester(XBlock):
        """Test XBlock for field access testing"""

        field_a = List(scope=Scope.settings)
        field_b = List(scope=Scope.content, default=[1, 2, 3])
        field_c = List(scope=Scope.content, default=[4, 5, 6])
        field_d = List(scope=Scope.settings)

    field_data = DictFieldData({"field_a": [200], "field_b": [11, 12, 13]})
    field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock(spec=ScopeIds))

    # Check initial values have been set properly
    assert_equals([200], field_tester.field_a)
    assert_equals([11, 12, 13], field_tester.field_b)
    assert_equals([4, 5, 6], field_tester.field_c)
    assert_equals([], field_tester.field_d)

    # Update the fields
    field_tester.field_a.append(1)
    field_tester.field_b.append(14)
    field_tester.field_c.append(7)
    field_tester.field_d.append(1)

    # The fields should be update in the cache, but /not/ in the underlying kvstore.
    assert_equals([200, 1], field_tester.field_a)
    assert_equals([11, 12, 13, 14], field_tester.field_b)
    assert_equals([4, 5, 6, 7], field_tester.field_c)
    assert_equals([1], field_tester.field_d)

    # Examine model data directly
    #  Caveat: there's not a clean way to copy the originally provided values for `field_a` and `field_b`
    #  when we instantiate the XBlock. So, the values for those two in both `field_data` and `_field_data_cache`
    #  point at the same object. Thus, `field_a` and `field_b` actually have the correct values in
    #  `field_data` right now. `field_c` does not, because it has never been written to the `field_data`.
    assert_false(field_data.has(field_tester, "field_c"))
    assert_false(field_data.has(field_tester, "field_d"))

    # save the XBlock
    field_tester.save()

    # verify that the fields have been updated correctly
    assert_equals([200, 1], field_tester.field_a)
    assert_equals([11, 12, 13, 14], field_tester.field_b)
    assert_equals([4, 5, 6, 7], field_tester.field_c)
    assert_equals([1], field_tester.field_d)
    # Now, the fields should be updated in the underlying kvstore

    assert_equals([200, 1], field_data.get(field_tester, "field_a"))
    assert_equals([11, 12, 13, 14], field_data.get(field_tester, "field_b"))
    assert_equals([4, 5, 6, 7], field_data.get(field_tester, "field_c"))
    assert_equals([1], field_data.get(field_tester, "field_d"))
Пример #9
0
    def setUp(self):
        """
            Makes sure that the Module is declared and mocked with the sample xml above.
        """

        # return anything except None to test LMS
        def test_real_user(useless):
            useless_user = Mock(email='*****@*****.**', id=useless)
            return useless_user

        # test to make sure that role is checked in LMS
        def test_user_role():
            return 'staff'

        self.system = get_test_system()
        self.system.get_real_user = test_real_user
        self.system.get_user_role = test_user_role
        self.system.anonymous_student_id = None

        self.mod = TextAnnotationModule(
            Mock(), self.system, DictFieldData({'data': self.sample_xml}),
            ScopeIds(None, None, None, None))
Пример #10
0
    def initialize_module(self, **kwargs):
        kwargs.update({
            'parent_location': self.section.location,
            'category': self.CATEGORY
        })

        self.item_descriptor = ItemFactory.create(**kwargs)

        self.runtime = self.new_descriptor_runtime()

        field_data = {}
        field_data.update(self.MODEL_DATA)
        student_data = DictFieldData(field_data)
        self.item_descriptor._field_data = LmsFieldData(
            self.item_descriptor._field_data, student_data)

        self.item_descriptor.xmodule_runtime = self.new_module_runtime()

        #self.item_module = self.item_descriptor.xmodule_runtime.xmodule_instance
        #self.item_module is None at this time

        self.item_url = self.item_descriptor.location.to_deprecated_string()
Пример #11
0
    def test_type_and_options(self):
        # test_display_name_field verifies that a String field is of type "Generic".
        # test_integer_field verifies that a Integer field is of type "Integer".

        descriptor = self.get_descriptor(DictFieldData({}))
        editable_fields = descriptor.editable_metadata_fields

        # Tests for select
        self.assert_field_values(
            editable_fields, 'string_select', TestFields.string_select,
            explicitly_set=False, value='default value', default_value='default value',
            type='Select', options=[{'display_name': 'first', 'value': 'value a JSON'},
                                    {'display_name': 'second', 'value': 'value b JSON'}]
        )

        self.assert_field_values(
            editable_fields, 'float_select', TestFields.float_select,
            explicitly_set=False, value=.999, default_value=.999,
            type='Select', options=[1.23, 0.98]
        )

        self.assert_field_values(
            editable_fields, 'boolean_select', TestFields.boolean_select,
            explicitly_set=False, value=None, default_value=None,
            type='Select', options=[{'display_name': "True", "value": True}, {'display_name': "False", "value": False}]
        )

        # Test for float
        self.assert_field_values(
            editable_fields, 'float_non_select', TestFields.float_non_select,
            explicitly_set=False, value=.999, default_value=.999,
            type='Float', options={'min': 0, 'step': .3}
        )

        self.assert_field_values(
            editable_fields, 'list_field', TestFields.list_field,
            explicitly_set=False, value=[], default_value=[],
            type='List'
        )
Пример #12
0
    def setUp(self):
        self.runtime_mock = mock.Mock()
        self.activity_mock = mock.create_autospec(GroupActivityXBlock)
        self.activity_mock.content_id = '123456'
        # can't use create_autospec here, as most methods are wrapped in decorators and mock fails signature checks
        # with "Too many positional arguments" because of this
        self.project_api_mock = mock.Mock(spec_set=TypedProjectAPI)

        # pylint: disable=not-callable
        self.block = self.block_to_test(self.runtime_mock, field_data=DictFieldData({}), scope_ids=mock.Mock())
        self.make_patch(self.block_to_test, 'project_api', mock.PropertyMock(return_value=self.project_api_mock))
        self.make_patch(self.block_to_test, 'activity', mock.PropertyMock(return_value=self.activity_mock))
        self.real_user_id_mock = self.make_patch(self.block, 'real_user_id', mock.Mock(side_effect=lambda u_id: u_id))
        self.workgroup_mock = self.make_patch(
            self.block_to_test, 'workgroup', mock.PropertyMock(return_value=self.workgroup_data)
        )
        self.user_id_mock = self.make_patch(
            self.block_to_test, 'user_id', mock.PropertyMock(return_value=self.user_id)
        )

        self.runtime_mock.anonymous_student_id = self.user_id
        self.runtime_mock.get_real_user.side_effect = lambda uid: mock.Mock(id=uid)
Пример #13
0
    def setUp(self):
        super(TabsEditingDescriptorTestCase, self).setUp()
        system = get_test_descriptor_system()
        system.render_template = Mock(
            return_value="<div>Test Template HTML</div>")
        self.tabs = [{
            'name': "Test_css",
            'template': "tabs/codemirror-edit.html",
            'current': True,
            'css': {
                'scss': [
                    resource_string(
                        __name__,
                        '../../test_files/test_tabseditingdescriptor.scss')
                ],
                'css': [
                    resource_string(
                        __name__,
                        '../../test_files/test_tabseditingdescriptor.css')
                ]
            }
        }, {
            'name': "Subtitles",
            'template': "video/subtitles.html",
        }, {
            'name': "Settings",
            'template': "tabs/video-metadata-edit-tab.html"
        }]

        TabsEditingDescriptor.tabs = self.tabs
        self.descriptor = system.construct_xblock_from_class(
            TabsEditingDescriptor,
            scope_ids=ScopeIds(
                None, None, None,
                BlockUsageLocator(
                    CourseLocator('org', 'course', 'run', branch='revision'),
                    'category', 'name')),
            field_data=DictFieldData({}),
        )
Пример #14
0
def _section_send_email(course, access):
    """ Provide data for the corresponding bulk email section """
    course_key = course.id

    # Monkey-patch applicable_aside_types to return no asides for the duration of this render
    with patch.object(course.runtime, 'applicable_aside_types', null_applicable_aside_types):
        # This HtmlDescriptor is only being used to generate a nice text editor.
        html_module = HtmlDescriptor(
            course.system,
            DictFieldData({'data': ''}),
            ScopeIds(None, None, None, course_key.make_usage_key('html', 'fake'))
        )
        fragment = course.system.render(html_module, 'studio_view')
    fragment = wrap_xblock(
        'LmsRuntime', html_module, 'studio_view', fragment, None,
        extra_data={"course-id": unicode(course_key)},
        usage_id_serializer=lambda usage_id: quote_slashes(unicode(usage_id)),
        # Generate a new request_token here at random, because this module isn't connected to any other
        # xblock rendering.
        request_token=uuid.uuid1().get_hex()
    )
    email_editor = fragment.content
    section_data = {
        'section_key': 'send_email',
        'section_display_name': _('Email'),
        'access': access,
        'send_email': reverse('send_email', kwargs={'course_id': unicode(course_key)}),
        'editor': email_editor,
        'list_instructor_tasks_url': reverse(
            'list_instructor_tasks', kwargs={'course_id': unicode(course_key)}
        ),
        'email_background_tasks_url': reverse(
            'list_background_email_tasks', kwargs={'course_id': unicode(course_key)}
        ),
        'email_content_history_url': reverse(
            'list_email_content', kwargs={'course_id': unicode(course_key)}
        ),
    }
    return section_data
Пример #15
0
    def setUp(self):
        self.student = '*****@*****.**'
        self.instructor = '*****@*****.**'
        self.password = '******'
        self.create_account('u1', self.student, self.password)
        self.create_account('u2', self.instructor, self.password)
        self.activate_user(self.student)
        self.activate_user(self.instructor)

        self.course_id = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
        self.location_string = self.course_id.make_usage_key(
            'html', 'TestLocation').to_deprecated_string()
        self.toy = modulestore().get_course(self.course_id)
        location = "i4x://edX/toy/peergrading/init"
        field_data = DictFieldData({
            'data': "<peergrading/>",
            'location': location,
            'category': 'peergrading'
        })
        self.mock_service = peer_grading_service.MockPeerGradingService()
        self.system = LmsModuleSystem(
            static_url=settings.STATIC_URL,
            track_function=None,
            get_module=None,
            render_template=render_to_string,
            replace_urls=None,
            s3_interface=test_util_open_ended.S3_INTERFACE,
            open_ended_grading_interface=test_util_open_ended.
            OPEN_ENDED_GRADING_INTERFACE,
            mixins=settings.XBLOCK_MIXINS,
            error_descriptor_class=ErrorDescriptor,
            descriptor_runtime=None,
        )
        self.descriptor = peer_grading_module.PeerGradingDescriptor(
            self.system, field_data, ScopeIds(None, None, None, None))
        self.descriptor.xmodule_runtime = self.system
        self.peer_module = self.descriptor
        self.peer_module.peer_gs = self.mock_service
        self.logout()
Пример #16
0
    def make_one(self, display_name=None, **kw):
        """
        Creates a XBlock SGA for testing purpose.
        """
        field_data = DictFieldData(kw)
        block = StaffAssignmentXBlock(self.runtime, field_data, self.scope_ids)
        block.location = Location('foo', 'bar', 'baz', 'category', 'name',
                                  'revision')

        block.xmodule_runtime = self.runtime
        block.course_id = self.course_id
        block.category = 'problem'

        if display_name:
            block.display_name = display_name

        block.start = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=pytz.utc)
        modulestore().create_item(self.staff.username,
                                  block.location.course_key,
                                  block.location.block_type,
                                  block.location.block_id)
        return block
 def test_student_view_data(self):
     def get_mock_components():
         child_a = Mock(spec=['student_view_data'])
         child_a.block_id = 'child_a'
         child_a.category = 'text'
         child_a.student_view_data.return_value = 'child_a_json'
         child_b = Mock(spec=[])
         child_b.block_id = 'child_b'
         child_b.category = 'html'
         return [child_a, child_b]
     shared_data = {
         'max_attempts': 3,
         'extended_feedback': True,
         'feedback_label': 'Feedback label',
     }
     children = get_mock_components()
     children_by_id = {child.block_id: child for child in children}
     display_name = "I'm problem builder"
     block_data = {'display_name': display_name, 'children': children}
     block_data.update(shared_data)
     block = MentoringBlock(Mock(usage_id=1), DictFieldData(block_data), Mock(usage_id=1))
     block.runtime = Mock(
         get_block=lambda block: children_by_id[block.block_id],
         load_block_type=lambda block: Mock,
         id_reader=Mock(get_definition_id=lambda block: block, get_block_type=lambda block: block),
     )
     expected = {
         'block_id': '1',
         'display_name': display_name,
         'components': ['child_a_json'],
         'messages': {
             'completed': None,
             'incomplete': None,
             'max_attempts_reached': None,
         }
     }
     expected.update(shared_data)
     self.assertEqual(block.student_view_data(), expected)
Пример #18
0
def test_json_field_access():
    # Check that values are correctly converted to and from json in accessors.

    class Date(Field):
        """Date needs to convert between JSON-compatible persistence and a datetime object"""
        def from_json(self, field):
            """Convert a string representation of a date to a datetime object"""
            return datetime.strptime(field, "%m/%d/%Y")

        def to_json(self, value):
            """Convert a datetime object to a string"""
            return value.strftime("%m/%d/%Y")

    class FieldTester(ScopedStorageMixin):
        """Toy class for ModelMetaclass and field access testing"""

        field_a = Date(scope=Scope.settings)
        field_b = Date(scope=Scope.content, default=datetime(2013, 4, 1))

    field_tester = FieldTester(
        runtime=TestRuntime(services={'field-data': DictFieldData({})}),
        scope_ids=MagicMock(spec=ScopeIds))

    # Check initial values
    assert_equals(None, field_tester.field_a)
    assert_equals(datetime(2013, 4, 1), field_tester.field_b)

    # Test no default specified
    field_tester.field_a = datetime(2013, 1, 2)
    assert_equals(datetime(2013, 1, 2), field_tester.field_a)
    del field_tester.field_a
    assert_equals(None, field_tester.field_a)

    # Test default explicitly specified
    field_tester.field_b = datetime(2013, 1, 2)
    assert_equals(datetime(2013, 1, 2), field_tester.field_b)
    del field_tester.field_b
    assert_equals(datetime(2013, 4, 1), field_tester.field_b)
Пример #19
0
def make_an_xblock(**kwargs):
    """
    Helper method that creates a Free-text Response XBlock
    """
    course_id = SlashSeparatedCourseKey('foo', 'bar', 'baz')
    services = {
        'i18n':
        Mock(ugettext=lambda string: string),
        'user':
        Mock(get_current_user=lambda: Mock(
            emails=['*****@*****.**'],
            opt_attrs={},
        ), )
    }
    runtime = Mock(
        course_id=course_id,
        service=lambda _, service: services.get(service),
    )
    scope_ids = Mock()
    field_data = DictFieldData(kwargs)
    xblock = GradeMeButton(runtime, field_data, scope_ids)
    xblock.xmodule_runtime = runtime
    return xblock
 def test_conditional_module_parse_sources(self):
     dummy_system = Mock()
     dummy_location = Location("edX", "conditional_test", "test_run",
                               "conditional", "SampleConditional", None)
     dummy_scope_ids = ScopeIds(None, None, dummy_location, dummy_location)
     dummy_field_data = DictFieldData({
         'data': '<conditional/>',
         'xml_attributes': {
             'sources':
             'i4x://HarvardX/ER22x/poll_question/T15_poll;i4x://HarvardX/ER22x/poll_question/T16_poll'
         },
         'children': None,
     })
     conditional = ConditionalDescriptor(
         dummy_system,
         dummy_field_data,
         dummy_scope_ids,
     )
     self.assertEqual(conditional.parse_sources(conditional.xml_attributes),
                      [
                          'i4x://HarvardX/ER22x/poll_question/T15_poll',
                          'i4x://HarvardX/ER22x/poll_question/T16_poll'
                      ])
Пример #21
0
 def test_conditional_module_parse_sources(self):
     dummy_system = Mock()
     dummy_location = BlockUsageLocator(
         CourseLocator("edX", "conditional_test", "test_run"),
         "conditional", "SampleConditional")
     dummy_scope_ids = ScopeIds(None, None, dummy_location, dummy_location)
     dummy_field_data = DictFieldData({
         'data': '<conditional/>',
         'xml_attributes': {
             'sources':
             'i4x://HarvardX/ER22x/poll_question/T15_poll;i4x://HarvardX/ER22x/poll_question/T16_poll'
         },  # lint-amnesty, pylint: disable=line-too-long
         'children': None,
     })
     conditional = ConditionalBlock(
         dummy_system,
         dummy_field_data,
         dummy_scope_ids,
     )
     assert conditional.parse_sources(conditional.xml_attributes) == [
         'i4x://HarvardX/ER22x/poll_question/T15_poll',
         'i4x://HarvardX/ER22x/poll_question/T16_poll'
     ]
Пример #22
0
    def test_conditional_module_with_empty_sources_list(self):
        """
        If a ConditionalBlock is initialized with an empty sources_list, we assert that the sources_list is set
        via generating UsageKeys from the values in xml_attributes['sources']
        """
        dummy_system = Mock()
        dummy_location = BlockUsageLocator(CourseLocator("edX", "conditional_test", "test_run"),
                                           "conditional", "SampleConditional")
        dummy_scope_ids = ScopeIds(None, None, dummy_location, dummy_location)
        dummy_field_data = DictFieldData({
            'data': '<conditional/>',
            'xml_attributes': {'sources': 'i4x://HarvardX/ER22x/poll_question/T15_poll'},
            'children': None,
        })
        conditional = ConditionalBlock(
            dummy_system,
            dummy_field_data,
            dummy_scope_ids,
        )

        new_run = conditional.location.course_key.run  # lint-amnesty, pylint: disable=unused-variable
        assert conditional.sources_list[0] == BlockUsageLocator.from_string(conditional.xml_attributes['sources'])\
            .replace(run=dummy_location.course_key.run)
Пример #23
0
    def _create_peer_grading_with_linked_problem(self,
                                                 location,
                                                 valid_linked_descriptor=True):
        """
        Create a peer grading problem with a linked location.
        """

        # Mock the linked problem descriptor.
        linked_descriptor = Mock()
        linked_descriptor.location = location

        # Mock the peer grading descriptor.
        pg_descriptor = Mock()
        pg_descriptor.location = self.problem_location

        if valid_linked_descriptor:
            pg_descriptor.get_required_module_descriptors = lambda: [
                linked_descriptor,
            ]
        else:
            pg_descriptor.get_required_module_descriptors = lambda: []

        # Setup the proper field data for the peer grading module.
        field_data = DictFieldData({
            'data': '<peergrading/>',
            'location': self.problem_location,
            'use_for_single_location': True,
            'link_to_location': self.coe_location.url(),
            'graded': True,
        })

        # Initialize the peer grading module.
        peer_grading = PeerGradingModule(
            pg_descriptor, self.test_system, field_data,
            ScopeIds(None, None, self.problem_location, self.problem_location))

        return peer_grading
Пример #24
0
    def test_export_default_discussion_id(self):
        """
        Test that default discussion_id values are not exported.

        Historically, the OLX format allowed omitting discussion ID values; in such case, the IDs are generated
        deterministically based on the course ID and the usage ID. Moreover, Studio does not allow course authors
        to edit discussion_id, so all courses authored in Studio have discussion_id omitted in OLX.

        Forcing Studio to always export discussion_id can cause data loss when switching between an older and newer
        export,  in a course with a course ID different from the one from which the export was created - because the
        discussion ID would be different.
        """
        target_node = etree.Element('dummy')

        block = DiscussionXBlock(self.runtime_mock, scope_ids=self.keys, field_data=DictFieldData({}))
        discussion_id_field = block.fields['discussion_id']  # pylint: disable=unsubscriptable-object

        # precondition checks - discussion_id does not have a value and uses UNIQUE_ID
        assert discussion_id_field._get_cached_value(block) == NO_CACHE_VALUE  # pylint: disable=W0212
        assert discussion_id_field.default == UNIQUE_ID

        block.add_xml_to_node(target_node)
        assert target_node.tag == 'discussion'  # pylint: disable=W0212
        assert 'discussion_id' not in target_node.attrib
Пример #25
0
 def test_constructor(self):
     sample_xml = '''
         <video display_name="Test Video"
                youtube="1.0:p2Q6BrNhdh8,0.75:izygArpw-Qo,1.25:1EeWXzPdhSA,1.5:rABDYkeK0x8"
                show_captions="false"
                download_track="true"
                download_video="true"
                start_time="00:00:01"
                end_time="00:01:00">
           <source src="http://www.example.com/source.mp4"/>
           <source src="http://www.example.com/source.ogg"/>
           <track src="http://www.example.com/track"/>
         </video>
     '''
     location = Location(["i4x", "edX", "video", "default",
                          "SampleProblem1"])
     field_data = DictFieldData({
         'data': sample_xml,
         'location': location
     })
     system = DummySystem(load_error_modules=True)
     descriptor = VideoDescriptor(system, field_data, Mock())
     self.assert_attributes_equal(descriptor, {
         'youtube_id_0_75': 'izygArpw-Qo',
         'youtube_id_1_0': 'p2Q6BrNhdh8',
         'youtube_id_1_25': '1EeWXzPdhSA',
         'youtube_id_1_5': 'rABDYkeK0x8',
         'download_video': True,
         'show_captions': False,
         'start_time': datetime.timedelta(seconds=1),
         'end_time': datetime.timedelta(seconds=60),
         'track': 'http://www.example.com/track',
         'download_track': True,
         'html5_sources': ['http://www.example.com/source.mp4', 'http://www.example.com/source.ogg'],
         'data': ''
     })
Пример #26
0
    def setUp(self):
        self.student = '*****@*****.**'
        self.instructor = '*****@*****.**'
        self.password = '******'
        self.location = 'TestLocation'
        self.create_account('u1', self.student, self.password)
        self.create_account('u2', self.instructor, self.password)
        self.activate_user(self.student)
        self.activate_user(self.instructor)

        self.course_id = "edX/toy/2012_Fall"
        self.toy = modulestore().get_course(self.course_id)
        location = "i4x://edX/toy/peergrading/init"
        field_data = DictFieldData({
            'data': "<peergrading/>",
            'location': location,
            'category': 'peergrading'
        })
        self.mock_service = peer_grading_service.MockPeerGradingService()
        self.system = ModuleSystem(
            ajax_url=location,
            track_function=None,
            get_module=None,
            render_template=render_to_string,
            replace_urls=None,
            xmodule_field_data=lambda d: d._field_data,
            s3_interface=test_util_open_ended.S3_INTERFACE,
            open_ended_grading_interface=test_util_open_ended.
            OPEN_ENDED_GRADING_INTERFACE,
            mixins=settings.XBLOCK_MIXINS,
        )
        self.descriptor = peer_grading_module.PeerGradingDescriptor(
            self.system, field_data, ScopeIds(None, None, None, None))
        self.peer_module = self.descriptor.xmodule(self.system)
        self.peer_module.peer_gs = self.mock_service
        self.logout()
Пример #27
0
    def test_partial_completion_status_migration(self):
        """
        Changed `completed` to `status` in `self.student_results` to accomodate partial responses
        """
        # Instantiate a mentoring block with the old format
        student_results = [
            [
                u'goal', {
                    u'completed': True,
                    u'score': 1,
                    u'student_input': u'test',
                    u'weight': 1
                }
            ],
            [
                u'mcq_1_1', {
                    u'completed': False,
                    u'score': 0,
                    u'submission': u'maybenot',
                    u'weight': 1
                }
            ],
        ]
        mentoring = MentoringBlock(
            MagicMock(), DictFieldData({'student_results': student_results}),
            Mock())
        self.assertEqual(copy.deepcopy(student_results),
                         mentoring.student_results)

        migrated_student_results = copy.deepcopy(student_results)
        migrated_student_results[0][1]['status'] = 'correct'
        migrated_student_results[1][1]['status'] = 'incorrect'
        del migrated_student_results[0][1]['completed']
        del migrated_student_results[1][1]['completed']
        mentoring.migrate_fields()
        self.assertEqual(migrated_student_results, mentoring.student_results)
Пример #28
0
 def setUp(self):
     """
     Test case setup
     """
     super(TestPollBlock, self).setUp()
     self.runtime = MockRuntime()
     self.poll_data = {
         'display_name':
         'My Poll',
         'question':
         'What is your favorite color?',
         'answers': [
             ['R', {
                 'label': 'Red'
             }],
             ['B', {
                 'label': 'Blue'
             }],
             ['G', {
                 'label': 'Green'
             }],
             ['O', {
                 'label': 'Other'
             }],
         ],
         'submissions_count':
         5,
         'max_submissions':
         1,
         'private_results':
         False,
         'feedback':
         'My Feedback',
     }
     self.poll_block = PollBlock(self.runtime,
                                 DictFieldData(self.poll_data), None)
Пример #29
0
    def make_one(self, display_name=None, **kw):
        """
        Creates a XBlock SGA for testing purpose.
        """
        from edx_sga.sga import StaffGradedXBlock as cls
        field_data = DictFieldData(kw)
        block = cls(self.runtime, field_data, self.scope_ids)
        block.location = Location('foo', 'bar', 'baz', 'category', 'name',
                                  'revision')

        block.xmodule_runtime = self.runtime
        block.course_id = self.course_id
        block.scope_ids.usage_id = "i4x://foo/bar/category/name"
        block.category = 'problem'

        if display_name:
            block.display_name = display_name

        block.start = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=pytz.utc)
        modulestore().create_item(self.staff.username,
                                  block.location.course_key,
                                  block.location.block_type,
                                  block.location.block_id)
        return block
Пример #30
0
    def setUp(self):
        """
        Create a XBlock VideoXBlock for testing purpose.
        """
        super(VideoXBlockTestBase, self).setUp()
        runtime = TestRuntime()  # pylint: disable=abstract-class-instantiated
        self.xblock = VideoXBlock(runtime,
                                  DictFieldData({
                                      'account_id': 'account_id',
                                      'metadata': {
                                          'client_id': 'api_key',
                                          'client_secret': 'api_secret'
                                      }
                                  }),
                                  scope_ids=mock.Mock(spec=[]))

        # Mocked objects is a list containing info about mocked entities.
        # Example:
        # self.mocked_objects.append({
        #    'obj': requests,                      # object that contains entity to be mocked
        #    'attrs': ['get', ],                   # list of methods/fields to be mocked
        #    'value': [copy.copy(requests.get), ]  # save here original values
        # })
        self.mocked_objects = []
Пример #31
0
def _section_send_email(course_key, access, course):
    """ Provide data for the corresponding bulk email section """
    html_module = HtmlDescriptor(
        course.system, DictFieldData({'data': ''}),
        ScopeIds(None, None, None, course_key.make_usage_key('html', 'fake')))
    fragment = course.system.render(html_module, 'studio_view')
    fragment = wrap_xblock(
        'LmsRuntime',
        html_module,
        'studio_view',
        fragment,
        None,
        extra_data={"course-id": course_key.to_deprecated_string()},
        usage_id_serializer=lambda usage_id: quote_slashes(
            usage_id.to_deprecated_string()))
    email_editor = fragment.content
    section_data = {
        'section_key':
        'send_email',
        'section_display_name':
        _('Email'),
        'access':
        access,
        'send_email':
        reverse('send_email',
                kwargs={'course_id': course_key.to_deprecated_string()}),
        'editor':
        email_editor,
        'list_instructor_tasks_url':
        reverse('list_instructor_tasks',
                kwargs={'course_id': course_key.to_deprecated_string()}),
        'email_background_tasks_url':
        reverse('list_background_email_tasks',
                kwargs={'course_id': course_key.to_deprecated_string()}),
    }
    return section_data
Пример #32
0
    def _load_extra_content(self, system, course_descriptor, category,
                            content_path, course_dir):
        """
        Import fields data content from files
        """
        for filepath in glob.glob(content_path / '*'):
            if not os.path.isfile(filepath):
                continue

            if filepath.endswith('~'):  # skip *~ files
                continue

            with open(filepath) as f:
                try:
                    if filepath.find('.json') != -1:
                        # json file with json data content
                        slug, loc, data_content = self._import_field_content(
                            course_descriptor, category, filepath)
                        if data_content is None:
                            continue
                        else:
                            try:
                                # get and update data field in xblock runtime
                                module = system.load_item(loc)
                                for key, value in data_content.items():
                                    setattr(module, key, value)
                                module.save()
                            except ItemNotFoundError:
                                module = None
                                data_content['location'] = loc
                                data_content['category'] = category
                    else:
                        slug = os.path.splitext(os.path.basename(filepath))[0]
                        loc = course_descriptor.scope_ids.usage_id.replace(
                            category=category, name=slug)
                        # html file with html data content
                        html = f.read()
                        try:
                            module = system.load_item(loc)
                            module.data = html
                            module.save()
                        except ItemNotFoundError:
                            module = None
                            data_content = {
                                'data': html,
                                'location': loc,
                                'category': category
                            }

                    if module is None:
                        module = system.construct_xblock(
                            category,
                            # We're loading a descriptor, so student_id is meaningless
                            # We also don't have separate notions of definition and usage ids yet,
                            # so we use the location for both
                            ScopeIds(None, category, loc, loc),
                            DictFieldData(data_content),
                        )
                        # VS[compat]:
                        # Hack because we need to pull in the 'display_name' for static tabs (because we need to edit them)  # lint-amnesty, pylint: disable=line-too-long
                        # from the course policy
                        if category == "static_tab":
                            tab = CourseTabList.get_tab_by_slug(
                                tab_list=course_descriptor.tabs, url_slug=slug)
                            if tab:
                                module.display_name = tab.name
                                module.course_staff_only = tab.course_staff_only
                        module.data_dir = course_dir
                        module.save()

                        self.modules[course_descriptor.id][
                            module.scope_ids.usage_id] = module
                except Exception as exc:  # pylint: disable=broad-except
                    logging.exception(
                        "Failed to load %s. Skipping... \
                            Exception: %s", filepath, str(exc))
                    system.error_tracker("ERROR: " + str(exc))
Пример #33
0
 def setUp(self):
     self.runtime_mock = mock.Mock(spec=Runtime)
     self.block = ActiveTableXBlock(self.runtime_mock, DictFieldData({}),
                                    mock.Mock())
Пример #34
0
 def _make_block(self, block_type=None):
     """ Creates a test block """
     block_type = block_type if block_type else self.TestXBlock
     runtime_mock = mock.Mock(spec=Runtime)
     scope_ids = ScopeIds("user_id", block_type.etree_node_tag, "def_id", "usage_id")
     return block_type(runtime=runtime_mock, field_data=DictFieldData({}), scope_ids=scope_ids)
    def create(system, source_is_error_module=False):
        """
        return a dict of modules: the conditional with a single source and a single child.
        Keys are 'cond_module', 'source_module', and 'child_module'.

        if the source_is_error_module flag is set, create a real ErrorModule for the source.
        """
        descriptor_system = get_test_descriptor_system()

        # construct source descriptor and module:
        source_location = Location("edX", "conditional_test", "test_run",
                                   "problem", "SampleProblem", None)
        if source_is_error_module:
            # Make an error descriptor and module
            source_descriptor = NonStaffErrorDescriptor.from_xml(
                'some random xml data',
                system,
                id_generator=CourseLocationManager(source_location.course_key),
                error_msg='random error message')
        else:
            source_descriptor = Mock(name='source_descriptor')
            source_descriptor.location = source_location

        source_descriptor.runtime = descriptor_system
        source_descriptor.render = lambda view, context=None: descriptor_system.render(
            source_descriptor, view, context)

        # construct other descriptors:
        child_descriptor = Mock(name='child_descriptor')
        child_descriptor._xmodule.student_view.return_value.content = u'<p>This is a secret</p>'
        child_descriptor.student_view = child_descriptor._xmodule.student_view
        child_descriptor.displayable_items.return_value = [child_descriptor]
        child_descriptor.runtime = descriptor_system
        child_descriptor.xmodule_runtime = get_test_system()
        child_descriptor.render = lambda view, context=None: descriptor_system.render(
            child_descriptor, view, context)
        child_descriptor.location = source_location.replace(category='html',
                                                            name='child')

        descriptor_system.load_item = {
            child_descriptor.location: child_descriptor,
            source_location: source_descriptor
        }.get

        system.descriptor_runtime = descriptor_system

        # construct conditional module:
        cond_location = Location("edX", "conditional_test", "test_run",
                                 "conditional", "SampleConditional", None)
        field_data = DictFieldData({
            'data': '<conditional/>',
            'xml_attributes': {
                'attempted': 'true'
            },
            'children': [child_descriptor.location],
        })

        cond_descriptor = ConditionalDescriptor(
            descriptor_system, field_data,
            ScopeIds(None, None, cond_location, cond_location))
        cond_descriptor.xmodule_runtime = system
        system.get_module = lambda desc: desc
        cond_descriptor.get_required_module_descriptors = Mock(
            return_value=[source_descriptor])

        # return dict:
        return {
            'cond_module': cond_descriptor,
            'source_module': source_descriptor,
            'child_module': child_descriptor
        }
Пример #36
0
def test_field_access():
    class FieldTester(XBlock):
        """Test XBlock for field access testing"""

        field_a = Integer(scope=Scope.settings)
        field_b = Integer(scope=Scope.content, default=10)
        field_c = Integer(scope=Scope.user_state, default=42)
        float_a = Float(scope=Scope.settings, default=5.8)
        float_b = Float(scope=Scope.settings)

    field_data = DictFieldData({"field_a": 5, "float_a": 6.1, "field_x": 15})

    field_tester = FieldTester(TestRuntime(services={"field-data": field_data}), scope_ids=Mock())
    # Verify that the fields have been set
    assert_equals(5, field_tester.field_a)
    assert_equals(10, field_tester.field_b)
    assert_equals(42, field_tester.field_c)
    assert_equals(6.1, field_tester.float_a)
    assert_equals(None, field_tester.float_b)
    assert not hasattr(field_tester, "field_x")

    # Set two of the fields.
    field_tester.field_a = 20
    field_tester.float_a = 20.5
    # field_a should be updated in the cache, but /not/ in the underlying db.
    assert_equals(20, field_tester.field_a)
    assert_equals(20.5, field_tester.float_a)
    assert_equals(5, field_data.get(field_tester, "field_a"))
    assert_equals(6.1, field_data.get(field_tester, "float_a"))
    # save the XBlock
    field_tester.save()
    # verify that the fields have been updated correctly
    assert_equals(20, field_tester.field_a)
    assert_equals(20.5, field_tester.float_a)
    # Now, field_a should be updated in the underlying db
    assert_equals(20, field_data.get(field_tester, "field_a"))
    assert_equals(20.5, field_data.get(field_tester, "float_a"))
    assert_equals(10, field_tester.field_b)
    assert_equals(42, field_tester.field_c)
    assert_equals(None, field_tester.float_b)

    # Deletes happen immediately (do not require a save)
    del field_tester.field_a
    del field_tester.float_a

    # After delete, we should find default values in the cache
    assert_equals(None, field_tester.field_a)
    assert_equals(5.8, field_tester.float_a)
    # But the fields should not actually be present in the underlying kvstore
    with assert_raises(KeyError):
        field_data.get(field_tester, "field_a")
    assert_false(field_data.has(field_tester, "field_a"))
    with assert_raises(KeyError):
        field_data.get(field_tester, "float_a")
    assert_false(field_data.has(field_tester, "float_a"))
 def make_one(self):
     return OverrideModulestoreFieldData.wrap(
         self.course, DictFieldData({
             'foo': 'bar',
             'bees': 'knees',
         }))
Пример #38
0
 def test_get_tip_content(self):
     self.mcq_block = MCQBlock(self.runtime_mock,
                               DictFieldData({'name': 'test_mcq'}), Mock())
     self.mcq_block.get_review_tip = Mock()
     self.mcq_block.get_review_tip.return_value = self.message_block.content
     self.assertEqual(self.block.review_tips, [])
Пример #39
0
 def setUp(self):
     self.service_mock = Mock()
     self.runtime_mock = Mock()
     self.runtime_mock.service = Mock(return_value=self.service_mock)
     self.block = MentoringBlock(self.runtime_mock, DictFieldData({}),
                                 Mock())