Example #1
0
def test_cached_parent():
    class HasParent(XBlock):
        """
        Dummy empty class
        """
        pass

    runtime = TestRuntime(services={'field-data': DictFieldData({})})
    runtime.get_block = Mock()
    block = HasParent(runtime, scope_ids=Mock(spec=ScopeIds))

    # block has no parent yet, and we don't need to call the runtime to find
    # that out.
    assert_equals(block.get_parent(), None)
    assert not runtime.get_block.called

    # Set a parent id for the block.  Get the parent.  Now we have one, and we
    # used runtime.get_block to get it.
    block.parent = "some_parent_id"
    parent = block.get_parent()
    assert_not_equals(parent, None)
    assert runtime.get_block.called_with("some_parent_id")

    # Get the parent again.  It will be the same parent, and we didn't call the
    # runtime.
    runtime.get_block.reset_mock()
    parent2 = block.get_parent()
    assert parent2 is parent
    assert not runtime.get_block.called
Example #2
0
 def test_set_field_data(self):
     field_data = Mock(spec=FieldData)
     runtime = TestRuntime(Mock(spec=IdReader), None)
     with self.assertWarns(FieldDataDeprecationWarning):
         runtime.field_data = field_data
     with self.assertWarns(FieldDataDeprecationWarning):
         self.assertEquals(runtime.field_data, field_data)
Example #3
0
def test_mixin_field_access():
    field_data = DictFieldData({
        'field_a': 5,
        'field_x': [1, 2, 3],
    })
    runtime = TestRuntime(Mock(), mixins=[TestSimpleMixin], services={'field-data': field_data})

    field_tester = runtime.construct_xblock_from_class(FieldTester, Mock())

    assert_equals(5, field_tester.field_a)
    assert_equals(10, field_tester.field_b)
    assert_equals(42, field_tester.field_c)
    assert_equals([1, 2, 3], field_tester.field_x)
    assert_equals('default_value', field_tester.field_y)

    field_tester.field_x = ['a', 'b']
    field_tester.save()
    assert_equals(['a', 'b'], field_tester._field_data.get(field_tester, 'field_x'))

    del field_tester.field_x
    assert_equals([], field_tester.field_x)
    assert_equals([1, 2, 3], field_tester.field_x_with_default)

    with assert_raises(AttributeError):
        getattr(field_tester, 'field_z')
    with assert_raises(AttributeError):
        delattr(field_tester, 'field_z')

    field_tester.field_z = 'foo'
    assert_equals('foo', field_tester.field_z)
    assert_false(field_tester._field_data.has(field_tester, 'field_z'))
Example #4
0
    def test_lazy_translation(self):
        with warnings.catch_warnings(record=True) as caught_warnings:
            warnings.simplefilter('always', FailingEnforceTypeWarning)

            class XBlockTest(XBlock):
                """
                Set up a class that contains a single string field with a translated default.
                """
                STR_DEFAULT_ENG = 'ENG: String to be translated'
                str_field = String(scope=Scope.settings, default=_('ENG: String to be translated'))

        # No FailingEnforceTypeWarning should have been triggered
        assert not caught_warnings

        # Construct a runtime and an XBlock using it.
        key_store = DictKeyValueStore()
        field_data = KvsFieldData(key_store)
        runtime = TestRuntime(Mock(), services={'field-data': field_data})

        # Change language to 'de'.
        user_language = 'de'
        with translation.override(user_language):
            tester = runtime.construct_xblock_from_class(XBlockTest, ScopeIds('s0', 'XBlockTest', 'd0', 'u0'))

            # Assert instantiated XBlock str_field value is not yet evaluated.
            assert 'django.utils.functional.' in str(type(tester.str_field))

            # Assert str_field *is* translated when the value is used.
            assert text_type(tester.str_field) == 'DEU: Translated string'
Example #5
0
def test_mixin_field_access():
    field_data = DictFieldData({
        'field_a': 5,
        'field_x': [1, 2, 3],
    })
    runtime = TestRuntime(Mock(), mixins=[TestSimpleMixin], services={'field-data': field_data})

    field_tester = runtime.construct_xblock_from_class(FieldTester, Mock())

    assert field_tester.field_a == 5
    assert field_tester.field_b == 10
    assert field_tester.field_c == 42
    assert field_tester.field_x == [1, 2, 3]
    assert field_tester.field_y == 'default_value'

    field_tester.field_x = ['a', 'b']
    field_tester.save()
    assert ['a', 'b'] == field_tester._field_data.get(field_tester, 'field_x')

    del field_tester.field_x
    assert [] == field_tester.field_x
    assert [1, 2, 3] == field_tester.field_x_with_default

    with pytest.raises(AttributeError):
        getattr(field_tester, 'field_z')
    with pytest.raises(AttributeError):
        delattr(field_tester, 'field_z')

    field_tester.field_z = 'foo'
    assert field_tester.field_z == 'foo'
    assert not field_tester._field_data.has(field_tester, 'field_z')
Example #6
0
def test_db_model_keys():
    # Tests that updates to fields are properly recorded in the KeyValueStore,
    # and that the keys have been constructed correctly
    key_store = DictKeyValueStore()
    field_data = KvsFieldData(key_store)
    runtime = TestRuntime(Mock(), mixins=[TestMixin], services={'field-data': field_data})
    tester = runtime.construct_xblock_from_class(TestXBlock, ScopeIds('s0', 'TestXBlock', 'd0', 'u0'))

    assert not field_data.has(tester, 'not a field')

    for field in six.itervalues(tester.fields):
        new_value = 'new ' + field.name
        assert not field_data.has(tester, field.name)
        if isinstance(field, List):
            new_value = [new_value]
        setattr(tester, field.name, new_value)

    # Write out the values
    tester.save()

    # Make sure everything saved correctly
    for field in six.itervalues(tester.fields):
        assert field_data.has(tester, field.name)

    def get_key_value(scope, user_id, block_scope_id, field_name):
        """Gets the value, from `key_store`, of a Key with the given values."""
        new_key = KeyValueStore.Key(scope, user_id, block_scope_id, field_name)
        return key_store.db_dict[new_key]

    # Examine each value in the database and ensure that keys were constructed correctly
    assert get_key_value(Scope.content, None, 'd0', 'content') == 'new content'
    assert get_key_value(Scope.settings, None, 'u0', 'settings') == 'new settings'
    assert get_key_value(Scope.user_state, 's0', 'u0', 'user_state') == 'new user_state'
    assert get_key_value(Scope.preferences, 's0', 'TestXBlock', 'preferences') == 'new preferences'
    assert get_key_value(Scope.user_info, 's0', None, 'user_info') == 'new user_info'
    assert get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, 'TestXBlock', 'by_type') == 'new by_type'
    assert get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, 'for_all') == 'new for_all'
    assert get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), 's0', 'd0', 'user_def') == 'new user_def'
    assert get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, 'agg_global') == 'new agg_global'
    assert get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, 'TestXBlock', 'agg_type') == 'new agg_type'
    assert get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, 'd0', 'agg_def') == 'new agg_def'
    assert get_key_value(Scope.user_state_summary, None, 'u0', 'agg_usage') == 'new agg_usage'
    assert get_key_value(Scope.content, None, 'd0', 'mixin_content') == 'new mixin_content'
    assert get_key_value(Scope.settings, None, 'u0', 'mixin_settings') == 'new mixin_settings'
    assert get_key_value(Scope.user_state, 's0', 'u0', 'mixin_user_state') == 'new mixin_user_state'
    assert get_key_value(Scope.preferences, 's0', 'TestXBlock', 'mixin_preferences') == 'new mixin_preferences'
    assert get_key_value(Scope.user_info, 's0', None, 'mixin_user_info') == 'new mixin_user_info'
    assert get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, 'TestXBlock', 'mixin_by_type') == \
        'new mixin_by_type'
    assert get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, 'mixin_for_all') == \
        'new mixin_for_all'
    assert get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), 's0', 'd0', 'mixin_user_def') == \
        'new mixin_user_def'
    assert get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, 'mixin_agg_global') == \
        'new mixin_agg_global'
    assert get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, 'TestXBlock', 'mixin_agg_type') == \
        'new mixin_agg_type'
    assert get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, 'd0', 'mixin_agg_def') == \
        'new mixin_agg_def'
    assert get_key_value(Scope.user_state_summary, None, 'u0', 'mixin_agg_usage') == 'new mixin_agg_usage'
Example #7
0
def test_mixin_field_access():
    field_data = DictFieldData({"field_a": 5, "field_x": [1, 2, 3]})
    runtime = TestRuntime(Mock(), mixins=[TestSimpleMixin], services={"field-data": field_data})

    field_tester = runtime.construct_xblock_from_class(FieldTester, Mock())

    assert_equals(5, field_tester.field_a)
    assert_equals(10, field_tester.field_b)
    assert_equals(42, field_tester.field_c)
    assert_equals([1, 2, 3], field_tester.field_x)
    assert_equals("default_value", field_tester.field_y)

    field_tester.field_x = ["a", "b"]
    field_tester.save()
    assert_equals(["a", "b"], field_tester._field_data.get(field_tester, "field_x"))

    del field_tester.field_x
    assert_equals([], field_tester.field_x)
    assert_equals([1, 2, 3], field_tester.field_x_with_default)

    with assert_raises(AttributeError):
        getattr(field_tester, "field_z")
    with assert_raises(AttributeError):
        delattr(field_tester, "field_z")

    field_tester.field_z = "foo"
    assert_equals("foo", field_tester.field_z)
    assert_false(field_tester._field_data.has(field_tester, "field_z"))
Example #8
0
def test_sub_service():
    runtime = TestRuntime(id_reader=Mock(), services={
        'secret_service': 17,
        'field-data': DictFieldData({}),
    })
    tester = SubXBlockWithServices(runtime, scope_ids=Mock(spec=ScopeIds))

    # Call the student_view to run its assertions.
    runtime.render(tester, 'student_view')
Example #9
0
def test_service():
    runtime = TestRuntime(services={"secret_service": 17, "field-data": DictFieldData({})})
    block_type = "test"
    def_id = runtime.id_generator.create_definition(block_type)
    usage_id = runtime.id_generator.create_usage(def_id)
    tester = XBlockWithServices(runtime, scope_ids=ScopeIds("user", block_type, def_id, usage_id))

    # Call the student_view to run its assertions.
    runtime.render(tester, "student_view")
Example #10
0
def test_runtime_handle():
    # Test a simple handler and a fallback handler

    key_store = DictKeyValueStore()
    field_data = KvsFieldData(key_store)
    runtime = TestRuntime(services={"field-data": field_data})
    tester = TestXBlock(runtime, scope_ids=Mock(spec=ScopeIds))
    runtime = MockRuntimeForQuerying()
    # string we want to update using the handler
    update_string = "user state update"
    assert_equals(runtime.handle(tester, "existing_handler", update_string), "I am the existing test handler")
    assert_equals(tester.user_state, update_string)

    # when the handler needs to use the fallback as given name can't be found
    new_update_string = "new update"
    assert_equals(runtime.handle(tester, "test_fallback_handler", new_update_string), "I have been handled")
    assert_equals(tester.user_state, new_update_string)

    # request to use a handler which doesn't have XBlock.handler decoration
    # should use the fallback
    new_update_string = "new update"
    assert_equals(runtime.handle(tester, "handler_without_correct_decoration", new_update_string), "gone to fallback")
    assert_equals(tester.user_state, new_update_string)

    # handler can't be found & no fallback handler supplied, should throw an exception
    tester = TestXBlockNoFallback(runtime, scope_ids=Mock(spec=ScopeIds))
    ultimate_string = "ultimate update"
    with assert_raises(NoSuchHandlerError):
        runtime.handle(tester, "test_nonexistant_fallback_handler", ultimate_string)

    # request to use a handler which doesn't have XBlock.handler decoration
    # and no fallback should raise NoSuchHandlerError
    with assert_raises(NoSuchHandlerError):
        runtime.handle(tester, "handler_without_correct_decoration", "handled")
Example #11
0
def test_service():
    runtime = TestRuntime(services={
        'secret_service': 17,
        'field-data': DictFieldData({}),
    })
    block_type = 'test'
    def_id = runtime.id_generator.create_definition(block_type)
    usage_id = runtime.id_generator.create_usage(def_id)
    tester = XBlockWithServices(runtime, scope_ids=ScopeIds('user', block_type, def_id, usage_id))

    # Call the student_view to run its assertions.
    runtime.render(tester, 'student_view')
Example #12
0
 def setUp(self):
     key_store = DictKeyValueStore()
     field_data = KvsFieldData(key_store)
     self.runtime = TestRuntime(services={'field-data': field_data})
     block_type = 'test'
     def_id = self.runtime.id_generator.create_definition(block_type)
     usage_id = self.runtime.id_generator.create_usage(def_id)
     self.tester = TestXBlock(self.runtime, scope_ids=ScopeIds('user', block_type, def_id, usage_id))
Example #13
0
class TestAsides(TestCase):
    """
    Tests of XBlockAsides.
    """
    def setUp(self):
        key_store = DictKeyValueStore()
        field_data = KvsFieldData(key_store)
        self.runtime = TestRuntime(services={'field-data': field_data})
        block_type = 'test'
        def_id = self.runtime.id_generator.create_definition(block_type)
        usage_id = self.runtime.id_generator.create_usage(def_id)
        self.tester = TestXBlock(self.runtime, scope_ids=ScopeIds('user', block_type, def_id, usage_id))

    @XBlockAside.register_temp_plugin(TestAside)
    def test_render_aside(self):
        """
        Test that rendering the xblock renders its aside
        """

        frag = self.runtime.render(self.tester, 'student_view', [u"ignore"])
        self.assertIn(TestAside.FRAG_CONTENT, frag.body_html())

        frag = self.runtime.render(self.tester, 'author_view', [u"ignore"])
        self.assertNotIn(TestAside.FRAG_CONTENT, frag.body_html())

    @XBlockAside.register_temp_plugin(TestAside)
    @XBlockAside.register_temp_plugin(TestInheritedAside)
    def test_inherited_aside_view(self):
        """
        Test that rendering the xblock renders its aside (when the aside view is
        inherited).
        """
        frag = self.runtime.render(self.tester, 'student_view', [u"ignore"])
        self.assertIn(TestAside.FRAG_CONTENT, frag.body_html())
        self.assertIn(TestInheritedAside.FRAG_CONTENT, frag.body_html())

        frag = self.runtime.render(self.tester, 'author_view', [u"ignore"])
        self.assertNotIn(TestAside.FRAG_CONTENT, frag.body_html())
        self.assertNotIn(TestInheritedAside.FRAG_CONTENT, frag.body_html())
Example #14
0
    def setUp(self):
        patcher = patch.object(TestRuntime, 'construct_xblock')
        self.construct_block = patcher.start()
        self.addCleanup(patcher.stop)

        self.id_reader = Mock(IdReader)
        self.user_id = Mock()
        self.field_data = Mock(FieldData)
        self.runtime = TestRuntime(self.id_reader, services={'field-data': self.field_data})
        self.runtime.user_id = self.user_id

        self.usage_id = 'usage_id'

        # Can only get a definition id from the id_reader
        self.def_id = self.id_reader.get_definition_id.return_value

        # Can only get a block type from the id_reader
        self.block_type = self.id_reader.get_block_type.return_value
Example #15
0
def test_runtime_handle():
    # Test a simple handler and a fallback handler

    key_store = DictKeyValueStore()
    field_data = KvsFieldData(key_store)
    test_runtime = TestRuntime(services={'field-data': field_data})
    basic_tester = TestXBlock(test_runtime, scope_ids=Mock(spec=ScopeIds))
    runtime = MockRuntimeForQuerying()
    # string we want to update using the handler
    update_string = "user state update"
    assert runtime.handle(basic_tester, 'existing_handler', update_string) == \
        'I am the existing test handler'
    assert basic_tester.user_state == update_string

    # when the handler needs to use the fallback as given name can't be found
    new_update_string = "new update"
    assert runtime.handle(basic_tester, 'test_fallback_handler', new_update_string) == \
        'I have been handled'
    assert basic_tester.user_state == new_update_string

    # request to use a handler which doesn't have XBlock.handler decoration
    # should use the fallback
    new_update_string = "new update"
    assert runtime.handle(basic_tester, 'handler_without_correct_decoration', new_update_string) == \
        'gone to fallback'
    assert basic_tester.user_state == new_update_string

    # handler can't be found & no fallback handler supplied, should throw an exception
    no_fallback_tester = TestXBlockNoFallback(runtime,
                                              scope_ids=Mock(spec=ScopeIds))
    ultimate_string = "ultimate update"
    with pytest.raises(NoSuchHandlerError):
        runtime.handle(no_fallback_tester, 'test_nonexistant_fallback_handler',
                       ultimate_string)

    # request to use a handler which doesn't have XBlock.handler decoration
    # and no fallback should raise NoSuchHandlerError
    with pytest.raises(NoSuchHandlerError):
        runtime.handle(no_fallback_tester,
                       'handler_without_correct_decoration', 'handled')
Example #16
0
class TestRuntimeGetBlock(TestCase):
    """
    Test the get_block default method on Runtime.
    """
    def setUp(self):
        patcher = patch.object(TestRuntime, 'construct_xblock')
        self.construct_block = patcher.start()
        self.addCleanup(patcher.stop)

        self.id_reader = Mock(IdReader)
        self.user_id = Mock()
        self.field_data = Mock(FieldData)
        self.runtime = TestRuntime(self.id_reader,
                                   services={'field-data': self.field_data})
        self.runtime.user_id = self.user_id

        self.usage_id = 'usage_id'

        # Can only get a definition id from the id_reader
        self.def_id = self.id_reader.get_definition_id.return_value

        # Can only get a block type from the id_reader
        self.block_type = self.id_reader.get_block_type.return_value

    def test_basic(self):
        self.runtime.get_block(self.usage_id)

        self.id_reader.get_definition_id.assert_called_with(self.usage_id)
        self.id_reader.get_block_type.assert_called_with(self.def_id)
        self.construct_block.assert_called_with(
            self.block_type,
            ScopeIds(self.user_id, self.block_type, self.def_id,
                     self.usage_id),
            for_parent=None,
        )

    def test_missing_usage(self):
        self.id_reader.get_definition_id.side_effect = NoSuchUsage
        with self.assertRaises(NoSuchUsage):
            self.runtime.get_block(self.usage_id)

    def test_missing_definition(self):
        self.id_reader.get_block_type.side_effect = NoSuchDefinition

        # If we don't have a definition, then the usage doesn't exist
        with self.assertRaises(NoSuchUsage):
            self.runtime.get_block(self.usage_id)
Example #17
0
def test_default_fn():
    key_store = SerialDefaultKVS()
    field_data = KvsFieldData(key_store)
    runtime = TestRuntime(services={'field-data': field_data})
    tester = TestIntegerXblock(runtime, scope_ids=Mock(spec=ScopeIds))
    tester2 = TestIntegerXblock(runtime, scope_ids=Mock(spec=ScopeIds))

    # ensure value is not in tester before any actions
    assert_false(field_data.has(tester, 'counter'))
    # ensure value is same over successive calls for same DbModel
    first_call = tester.counter
    assert_equals(first_call, 1)
    assert_equals(first_call, tester.counter)
    # ensure the value is not saved in the object
    assert_false(field_data.has(tester, 'counter'))
    # ensure save does not save the computed default back to the object
    tester.save()
    assert_false(field_data.has(tester, 'counter'))

    # ensure second object gets another value
    second_call = tester2.counter
    assert_equals(second_call, 2)
Example #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)
Example #19
0
def test_object_identity():
    # Check that values that are modified are what is returned
    class FieldTester(ScopedStorageMixin):
        """Toy class for ModelMetaclass and field access testing"""
        field_a = List(scope=Scope.settings)

    def mock_default(block, name):  # pylint: disable=unused-argument
        """
        Raising KeyError emulates no attribute found, which causes
        proper default value to be used after field is deleted.
        """
        raise KeyError

    # Make sure that field_data always returns a different object
    # each time it's actually queried, so that the caching is
    # doing the work to maintain object identity.
    field_data = MagicMock(spec=FieldData)
    field_data.get = lambda block, name, default=None: [name]  # pylint: disable=C0322
    field_data.default = mock_default
    field_tester = FieldTester(
        runtime=TestRuntime(services={'field-data': field_data}),
        scope_ids=MagicMock(spec=ScopeIds)
    )
    value = field_tester.field_a
    assert_equals(value, field_tester.field_a)

    # Changing the field in place matches a previously fetched value
    field_tester.field_a.append(1)
    assert_equals(value, field_tester.field_a)

    # Changing the previously-fetched value also changes the value returned by the field:
    value.append(2)
    assert_equals(value, field_tester.field_a)

    # Deletion restores the default value.  In the case of a List with
    # no default defined, this is the empty list.
    del field_tester.field_a
    assert_equals([], field_tester.field_a)
Example #20
0
class TestRuntimeGetBlock(TestCase):
    """
    Test the get_block default method on Runtime.
    """
    def setUp(self):
        patcher = patch.object(TestRuntime, 'construct_xblock')
        self.construct_block = patcher.start()
        self.addCleanup(patcher.stop)

        self.id_reader = Mock(IdReader)
        self.user_id = Mock()
        self.field_data = Mock(FieldData)
        self.runtime = TestRuntime(self.id_reader, services={'field-data': self.field_data})
        self.runtime.user_id = self.user_id

        self.usage_id = 'usage_id'

        # Can only get a definition id from the id_reader
        self.def_id = self.id_reader.get_definition_id.return_value

        # Can only get a block type from the id_reader
        self.block_type = self.id_reader.get_block_type.return_value

    def test_basic(self):
        self.runtime.get_block(self.usage_id)

        self.id_reader.get_definition_id.assert_called_with(self.usage_id)
        self.id_reader.get_block_type.assert_called_with(self.def_id)
        self.construct_block.assert_called_with(
            self.block_type,
            ScopeIds(self.user_id, self.block_type, self.def_id, self.usage_id),
            for_parent=None,
        )

    def test_missing_usage(self):
        self.id_reader.get_definition_id.side_effect = NoSuchUsage
        with self.assertRaises(NoSuchUsage):
            self.runtime.get_block(self.usage_id)

    def test_missing_definition(self):
        self.id_reader.get_block_type.side_effect = NoSuchDefinition

        # If we don't have a definition, then the usage doesn't exist
        with self.assertRaises(NoSuchUsage):
            self.runtime.get_block(self.usage_id)
Example #21
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 = []
class TestUpgrade(unittest.TestCase):
    """
    Test upgrade from mentoring v1 (which uses xml_content even in Studio) to v2.

    We can't test the steps that depend on Studio, so we just test the XML conversion.
    """

    def setUp(self):
        self.runtime = TestRuntime(field_data=KvsFieldData(DictKeyValueStore()))

    @ddt.data(
        "v1_upgrade_a",
        "v1_upgrade_b",
        "v1_upgrade_c",
        "v1_upgrade_d",
    )
    @XBlock.register_temp_plugin(HtmlBlock, "html")
    @XBlock.register_temp_plugin(MentoringBlock, "mentoring")
    def test_xml_upgrade(self, file_name):
        """
        Convert a v1 mentoring block to v2 and then compare the resulting block to a pre-converted one.
        """
        with open("{}/{}_old.xml".format(xml_path, file_name)) as xmlfile:
            temp_node = etree.parse(xmlfile).getroot()
            old_block = self.create_block_from_node(temp_node)

        parser = etree.XMLParser(remove_blank_text=True)
        xml_root = etree.parse(StringIO(old_block.xml_content), parser=parser).getroot()
        convert_xml_to_v2(xml_root)
        converted_block = self.create_block_from_node(xml_root)

        with open("{}/{}_new.xml".format(xml_path, file_name)) as xmlfile:
            temp_node = etree.parse(xmlfile).getroot()
            new_block = self.create_block_from_node(temp_node)

        try:
            self.assertBlocksAreEquivalent(converted_block, new_block)
        except AssertionError:
            xml_result = etree.tostring(xml_root, pretty_print=True, encoding="UTF-8")
            print("Converted XML:\n{}".format(xml_result))
            raise

    def create_block_from_node(self, node):
        """
        Parse an XML node representing an XBlock (and children), and return the XBlock.
        """
        block_type = node.tag
        def_id = self.runtime.id_generator.create_definition(block_type)
        usage_id = self.runtime.id_generator.create_usage(def_id)
        keys = ScopeIds(None, block_type, def_id, usage_id)
        block_class = self.runtime.mixologist.mix(self.runtime.load_block_type(block_type))
        block = block_class.parse_xml(node, self.runtime, keys, self.runtime.id_generator)
        block.save()
        return block

    def assertBlocksAreEquivalent(self, block1, block2):
        """
        Compare two blocks for equivalence.
        Borrowed from xblock.test.tools.blocks_are_equivalent but modified to use assertions.
        """
        # The two blocks have to be the same class.
        self.assertEqual(block1.__class__, block2.__class__)
        # They have to have the same fields.
        self.assertEqual(set(block1.fields), set(block2.fields))
        # The data fields have to have the same values.
        for field_name in block1.fields:
            if field_name in ('parent', 'children'):
                continue
            if field_name == "content":
                # Inner HTML/XML content may have varying whitespace which we don't care about:
                self.assertEqual(
                    self.clean_html(getattr(block1, field_name)),
                    self.clean_html(getattr(block2, field_name))
                )
            else:
                self.assertEqual(getattr(block1, field_name), getattr(block2, field_name))
        # The children need to be equal.
        self.assertEqual(block1.has_children, block2.has_children)

        if block1.has_children:
            self.assertEqual(len(block1.children), len(block2.children))
            for child_id1, child_id2 in zip(block1.children, block2.children):
                # Load up the actual children to see if they are equal.
                child1 = block1.runtime.get_block(child_id1)
                child2 = block2.runtime.get_block(child_id2)
                self.assertBlocksAreEquivalent(child1, child2)

    def clean_html(self, html_str):
        """
        Standardize the given HTML string for a consistent comparison.
        Assumes the HTML is valid XML.
        """
        # We wrap it in <x></x> so that the given HTML string doesn't need a single root element.
        parser = etree.XMLParser(remove_blank_text=True)
        parsed = etree.parse(StringIO(u"<x>{}</x>".format(html_str)), parser=parser).getroot()
        return etree.tostring(parsed, pretty_print=False, encoding="UTF-8")[3:-3]
Example #23
0
def test_service():
    runtime = TestRuntime(services={'secret_service': 17})
    tester = XBlockWithServices(runtime, scope_ids=Mock(spec=ScopeIds))

    # Call the student_view to run its assertions.
    runtime.render(tester, 'student_view')
 def setUp(self):
     self.runtime = TestRuntime(field_data=KvsFieldData(DictKeyValueStore()))
Example #25
0
 def test_passed_field_data(self):
     field_data = Mock(spec=FieldData)
     with self.assertWarns(FieldDataDeprecationWarning):
         runtime = TestRuntime(Mock(spec=IdReader), field_data)
     with self.assertWarns(FieldDataDeprecationWarning):
         self.assertEquals(runtime.field_data, field_data)
Example #26
0
class TestUpgrade(unittest.TestCase):
    """
    Test upgrade from mentoring v1 (which uses xml_content even in Studio) to v2.

    We can't test the steps that depend on Studio, so we just test the XML conversion.
    """

    def setUp(self):
        self.runtime = TestRuntime(field_data=KvsFieldData(DictKeyValueStore()))

    @ddt.data(
        "v1_upgrade_a",
        "v1_upgrade_b",
        "v1_upgrade_c",
        "v1_upgrade_d",
    )
    @XBlock.register_temp_plugin(HtmlBlock, "html")
    @XBlock.register_temp_plugin(MentoringBlock, "mentoring")
    def test_xml_upgrade(self, file_name):
        """
        Convert a v1 mentoring block to v2 and then compare the resulting block to a pre-converted one.
        """
        with open("{}/{}_old.xml".format(xml_path, file_name)) as xmlfile:
            temp_node = etree.parse(xmlfile).getroot()
            old_block = self.create_block_from_node(temp_node)

        parser = etree.XMLParser(remove_blank_text=True)
        xml_root = etree.parse(StringIO(old_block.xml_content), parser=parser).getroot()
        convert_xml_to_v2(xml_root)
        converted_block = self.create_block_from_node(xml_root)

        with open("{}/{}_new.xml".format(xml_path, file_name)) as xmlfile:
            temp_node = etree.parse(xmlfile).getroot()
            new_block = self.create_block_from_node(temp_node)

        try:
            self.assertBlocksAreEquivalent(converted_block, new_block)
        except AssertionError:
            xml_result = etree.tostring(xml_root, pretty_print=True, encoding="UTF-8")
            print("Converted XML:\n{}".format(xml_result))
            raise

    def create_block_from_node(self, node):
        """
        Parse an XML node representing an XBlock (and children), and return the XBlock.
        """
        block_type = node.tag
        def_id = self.runtime.id_generator.create_definition(block_type)
        usage_id = self.runtime.id_generator.create_usage(def_id)
        keys = ScopeIds(None, block_type, def_id, usage_id)
        block_class = self.runtime.mixologist.mix(self.runtime.load_block_type(block_type))
        block = block_class.parse_xml(node, self.runtime, keys, self.runtime.id_generator)
        block.save()
        return block

    def assertBlocksAreEquivalent(self, block1, block2):
        """
        Compare two blocks for equivalence.
        Borrowed from xblock.test.tools.blocks_are_equivalent but modified to use assertions.
        """
        # The two blocks have to be the same class.
        self.assertEqual(block1.__class__, block2.__class__)
        # They have to have the same fields.
        self.assertEqual(set(block1.fields), set(block2.fields))
        # The data fields have to have the same values.
        for field_name in block1.fields:
            if field_name in ('parent', 'children'):
                continue
            if field_name == "content":
                # Inner HTML/XML content may have varying whitespace which we don't care about:
                self.assertEqual(
                    self.clean_html(getattr(block1, field_name)),
                    self.clean_html(getattr(block2, field_name))
                )
            else:
                self.assertEqual(getattr(block1, field_name), getattr(block2, field_name))
        # The children need to be equal.
        self.assertEqual(block1.has_children, block2.has_children)

        if block1.has_children:
            self.assertEqual(len(block1.children), len(block2.children))
            for child_id1, child_id2 in zip(block1.children, block2.children):
                # Load up the actual children to see if they are equal.
                child1 = block1.runtime.get_block(child_id1)
                child2 = block2.runtime.get_block(child_id2)
                self.assertBlocksAreEquivalent(child1, child2)

    def clean_html(self, html_str):
        """
        Standardize the given HTML string for a consistent comparison.
        Assumes the HTML is valid XML.
        """
        # We wrap it in <x></x> so that the given HTML string doesn't need a single root element.
        parser = etree.XMLParser(remove_blank_text=True)
        parsed = etree.parse(StringIO(u"<x>{}</x>".format(html_str)), parser=parser).getroot()
        return etree.tostring(parsed, pretty_print=False, encoding="UTF-8")[3:-3]
Example #27
0
 def setUp(self):
     key_store = DictKeyValueStore()
     field_data = KvsFieldData(key_store)
     self.runtime = TestRuntime(services={'field-data': field_data})
Example #28
0
 def setUp(self):
     self.runtime = TestRuntime(field_data=KvsFieldData(DictKeyValueStore()))
Example #29
0
def test_db_model_keys():
    # Tests that updates to fields are properly recorded in the KeyValueStore,
    # and that the keys have been constructed correctly
    key_store = DictKeyValueStore()
    field_data = KvsFieldData(key_store)
    runtime = TestRuntime(Mock(), mixins=[TestMixin], services={'field-data': field_data})
    tester = runtime.construct_xblock_from_class(TestXBlock, ScopeIds('s0', 'TestXBlock', 'd0', 'u0'))

    assert_false(field_data.has(tester, 'not a field'))

    for field in tester.fields.values():
        new_value = 'new ' + field.name
        assert_false(field_data.has(tester, field.name))
        if isinstance(field, List):
            new_value = [new_value]
        setattr(tester, field.name, new_value)

    # Write out the values
    tester.save()

    # Make sure everything saved correctly
    for field in tester.fields.values():
        assert_true(field_data.has(tester, field.name))

    def get_key_value(scope, user_id, block_scope_id, field_name):
        """Gets the value, from `key_store`, of a Key with the given values."""
        new_key = KeyValueStore.Key(scope, user_id, block_scope_id, field_name)
        return key_store.db_dict[new_key]

    # Examine each value in the database and ensure that keys were constructed correctly
    assert_equals('new content', get_key_value(Scope.content, None, 'd0', 'content'))
    assert_equals('new settings', get_key_value(Scope.settings, None, 'u0', 'settings'))
    assert_equals('new user_state', get_key_value(Scope.user_state, 's0', 'u0', 'user_state'))
    assert_equals('new preferences', get_key_value(Scope.preferences, 's0', 'TestXBlock', 'preferences'))
    assert_equals('new user_info', get_key_value(Scope.user_info, 's0', None, 'user_info'))
    assert_equals('new by_type', get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, 'TestXBlock', 'by_type'))
    assert_equals('new for_all', get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, 'for_all'))
    assert_equals('new user_def', get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), 's0', 'd0', 'user_def'))
    assert_equals('new agg_global', get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, 'agg_global'))
    assert_equals('new agg_type', get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, 'TestXBlock', 'agg_type'))
    assert_equals('new agg_def', get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, 'd0', 'agg_def'))
    assert_equals('new agg_usage', get_key_value(Scope.user_state_summary, None, 'u0', 'agg_usage'))
    assert_equals('new mixin_content', get_key_value(Scope.content, None, 'd0', 'mixin_content'))
    assert_equals('new mixin_settings', get_key_value(Scope.settings, None, 'u0', 'mixin_settings'))
    assert_equals('new mixin_user_state', get_key_value(Scope.user_state, 's0', 'u0', 'mixin_user_state'))
    assert_equals('new mixin_preferences', get_key_value(Scope.preferences, 's0', 'TestXBlock', 'mixin_preferences'))
    assert_equals('new mixin_user_info', get_key_value(Scope.user_info, 's0', None, 'mixin_user_info'))
    assert_equals(
        'new mixin_by_type',
        get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, 'TestXBlock', 'mixin_by_type')
    )
    assert_equals(
        'new mixin_for_all',
        get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, 'mixin_for_all')
    )
    assert_equals(
        'new mixin_user_def',
        get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), 's0', 'd0', 'mixin_user_def')
    )
    assert_equals(
        'new mixin_agg_global',
        get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, 'mixin_agg_global')
    )
    assert_equals(
        'new mixin_agg_type',
        get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, 'TestXBlock', 'mixin_agg_type')
    )
    assert_equals(
        'new mixin_agg_def',
        get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, 'd0', 'mixin_agg_def')
    )
    assert_equals('new mixin_agg_usage', get_key_value(Scope.user_state_summary, None, 'u0', 'mixin_agg_usage'))
Example #30
0
def createVimeoXBlockTestInstance():
    field_data = DictFieldData({'data': 'Safe <b>html</b>'})
    runtime = TestRuntime(field_data=field_data)

    return VimeoBlock(runtime, scope_ids=None)
Example #31
0
def test_db_model_keys():
    # Tests that updates to fields are properly recorded in the KeyValueStore,
    # and that the keys have been constructed correctly
    key_store = DictKeyValueStore()
    field_data = KvsFieldData(key_store)
    runtime = TestRuntime(Mock(), mixins=[TestMixin], services={"field-data": field_data})
    tester = runtime.construct_xblock_from_class(TestXBlock, ScopeIds("s0", "TestXBlock", "d0", "u0"))

    assert_false(field_data.has(tester, "not a field"))

    for field in tester.fields.values():
        new_value = "new " + field.name
        assert_false(field_data.has(tester, field.name))
        if isinstance(field, List):
            new_value = [new_value]
        setattr(tester, field.name, new_value)

    # Write out the values
    tester.save()

    # Make sure everything saved correctly
    for field in tester.fields.values():
        assert_true(field_data.has(tester, field.name))

    def get_key_value(scope, user_id, block_scope_id, field_name):
        """Gets the value, from `key_store`, of a Key with the given values."""
        new_key = KeyValueStore.Key(scope, user_id, block_scope_id, field_name)
        return key_store.db_dict[new_key]

    # Examine each value in the database and ensure that keys were constructed correctly
    assert_equals("new content", get_key_value(Scope.content, None, "d0", "content"))
    assert_equals("new settings", get_key_value(Scope.settings, None, "u0", "settings"))
    assert_equals("new user_state", get_key_value(Scope.user_state, "s0", "u0", "user_state"))
    assert_equals("new preferences", get_key_value(Scope.preferences, "s0", "TestXBlock", "preferences"))
    assert_equals("new user_info", get_key_value(Scope.user_info, "s0", None, "user_info"))
    assert_equals("new by_type", get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, "TestXBlock", "by_type"))
    assert_equals("new for_all", get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, "for_all"))
    assert_equals("new user_def", get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), "s0", "d0", "user_def"))
    assert_equals("new agg_global", get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, "agg_global"))
    assert_equals("new agg_type", get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, "TestXBlock", "agg_type"))
    assert_equals("new agg_def", get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, "d0", "agg_def"))
    assert_equals("new agg_usage", get_key_value(Scope.user_state_summary, None, "u0", "agg_usage"))
    assert_equals("new mixin_content", get_key_value(Scope.content, None, "d0", "mixin_content"))
    assert_equals("new mixin_settings", get_key_value(Scope.settings, None, "u0", "mixin_settings"))
    assert_equals("new mixin_user_state", get_key_value(Scope.user_state, "s0", "u0", "mixin_user_state"))
    assert_equals("new mixin_preferences", get_key_value(Scope.preferences, "s0", "TestXBlock", "mixin_preferences"))
    assert_equals("new mixin_user_info", get_key_value(Scope.user_info, "s0", None, "mixin_user_info"))
    assert_equals(
        "new mixin_by_type", get_key_value(Scope(UserScope.NONE, BlockScope.TYPE), None, "TestXBlock", "mixin_by_type")
    )
    assert_equals(
        "new mixin_for_all", get_key_value(Scope(UserScope.NONE, BlockScope.ALL), None, None, "mixin_for_all")
    )
    assert_equals(
        "new mixin_user_def", get_key_value(Scope(UserScope.ONE, BlockScope.DEFINITION), "s0", "d0", "mixin_user_def")
    )
    assert_equals(
        "new mixin_agg_global", get_key_value(Scope(UserScope.ALL, BlockScope.ALL), None, None, "mixin_agg_global")
    )
    assert_equals(
        "new mixin_agg_type", get_key_value(Scope(UserScope.ALL, BlockScope.TYPE), None, "TestXBlock", "mixin_agg_type")
    )
    assert_equals(
        "new mixin_agg_def", get_key_value(Scope(UserScope.ALL, BlockScope.DEFINITION), None, "d0", "mixin_agg_def")
    )
    assert_equals("new mixin_agg_usage", get_key_value(Scope.user_state_summary, None, "u0", "mixin_agg_usage"))
Example #32
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'))
Example #33
0
 def setUp(self):
     self.runtime = TestRuntime()
Example #34
0
 def make_xblock(self):
     key_store = DictKeyValueStore()
     field_data = KvsFieldData(key_store)
     runtime = TestRuntime(services={'field-data': field_data})
     xblock = WistiaVideoXBlock(runtime, scope_ids=Mock())
     return xblock