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'))
def test_mutation_without_save_doesnt_write(self): assert_false(self.field_data.has(self.block, 'field')) mutable = self.get() self.mutate(mutable) assert_false(self.field_data.has(self.block, 'field'))
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"))
def test_mixin_field_access(): field_data = DictFieldData({ 'field_a': 5, 'field_x': [1, 2, 3], }) runtime = TestRuntime(Mock(), field_data, [TestSimpleMixin]) 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('field c', 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'))
def test_set_field_access(): # Check that sets are correctly saved when not directly set class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = Set(scope=Scope.settings) field_b = Set(scope=Scope.content, default=[1, 2, 3]) field_c = Set(scope=Scope.content, default=[4, 5, 6]) field_d = Set(scope=Scope.settings) field_tester = FieldTester( MagicMock(), DictFieldData({ 'field_a': [200], 'field_b': [11, 12, 13] }), Mock()) # Check initial values have been set properly assert_equals(set([200]), field_tester.field_a) assert_equals(set([11, 12, 13]), field_tester.field_b) assert_equals(set([4, 5, 6]), field_tester.field_c) assert_equals(set(), field_tester.field_d) # Update the fields field_tester.field_a.add(1) field_tester.field_b.add(14) field_tester.field_c.remove(5) field_tester.field_d.add(1) # The fields should be update in the cache, but /not/ in the underlying kvstore. assert_equals(set([200, 1]), field_tester.field_a) assert_equals(set([11, 12, 13, 14]), field_tester.field_b) assert_equals(set([4, 6]), field_tester.field_c) assert_equals(set([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_tester._field_data.has(field_tester, 'field_c')) assert_false(field_tester._field_data.has(field_tester, 'field_d')) # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert_equals(set([200, 1]), field_tester.field_a) assert_equals(set([11, 12, 13, 14]), field_tester.field_b) assert_equals(set([4, 6]), field_tester.field_c) assert_equals(set([1]), field_tester.field_d) # Now, the fields should be updated in the underlying kvstore assert_equals(set([200, 1]), field_tester._field_data.get(field_tester, 'field_a')) assert_equals(set([11, 12, 13, 14]), field_tester._field_data.get(field_tester, 'field_b')) assert_equals(set([4, 6]), field_tester._field_data.get(field_tester, 'field_c')) assert_equals(set([1]), field_tester._field_data.get(field_tester, 'field_d'))
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'))
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_tester = FieldTester( MagicMock(), DictFieldData({ 'field_a': 5, 'float_a': 6.1, 'field_x': 15 }), 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_tester._field_data.get(field_tester, 'field_a')) assert_equals(6.1, field_tester._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_tester._field_data.get(field_tester, 'field_a')) assert_equals(20.5, field_tester._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_tester._field_data.get(field_tester, 'field_a') assert_false(field_tester._field_data.has(field_tester, 'field_a')) with assert_raises(KeyError): field_tester._field_data.get(field_tester, 'float_a') assert_false(field_tester._field_data.has(field_tester, 'float_a'))
def test_delete(self): assert_equals(1, self.agg.first) del self.agg.first assert_false(hasattr(self.first, 'first')) with assert_raises(AttributeError): self.agg.first # pylint: disable=W0104 with assert_raises(AttributeError): del self.agg.other
def test_set_after_get_doesnt_save(self): with patch.object(self.field_data, 'set_many') as patched_set_many: self.set(self.get()) self.block.save() assert_false(patched_set_many.called) self.set(self.new_value) self.block.save() assert_true(patched_set_many.called)
def test_set(self): assert_equals(1, self.agg.first) self.agg.first = 10 assert_equals(10, self.agg.first) assert_equals(10, self.first.first) # pylint: disable=E1101 with assert_raises(AttributeError): self.agg.other = 99 assert_false(hasattr(self.first, 'other')) assert_false(hasattr(self.second, 'other'))
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 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"))
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_tester = FieldTester( MagicMock(), DictFieldData({ 'dic1': { 'a': 200 }, 'list1': ['a', 'b'] }), Mock()) 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_tester._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_tester._field_data.has(field_tester, fname))
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() db_model = DbModel(key_store) runtime = Runtime(Mock(), db_model, [TestMixin]) tester = runtime.construct_xblock_from_class(TestXBlock, ScopeIds('s0', 'TestXBlock', 'd0', 'u0')) assert_false(db_model.has(tester, 'not a field')) for field in tester.fields.values(): new_value = 'new ' + field.name assert_false(db_model.has(tester, field.name)) 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(db_model.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'))
def test_validate_correct_inputs(self): xblock = self.make_xblock() for href in ('', 'https://foo.wistia.com/medias/bar', 'https://foo.wistia.com/embed/bar', 'https://foo.wi.st/embed/bar', 'https://foo.wi.st/medias/bar'): data = Mock(href=href) validation = Mock() validation.add = Mock() xblock.validate_field_data(validation, data) assert_false(validation.add.called)
def test_set_field_access(): # Check that sets are correctly saved when not directly set class FieldTester(XBlock): """Test XBlock for field access testing""" field_a = Set(scope=Scope.settings) field_b = Set(scope=Scope.content, default=[1, 2, 3]) field_c = Set(scope=Scope.content, default=[4, 5, 6]) field_d = Set(scope=Scope.settings) field_tester = FieldTester(MagicMock(), DictFieldData({'field_a': [200], 'field_b': [11, 12, 13]}), Mock()) # Check initial values have been set properly assert_equals(set([200]), field_tester.field_a) assert_equals(set([11, 12, 13]), field_tester.field_b) assert_equals(set([4, 5, 6]), field_tester.field_c) assert_equals(set(), field_tester.field_d) # Update the fields field_tester.field_a.add(1) field_tester.field_b.add(14) field_tester.field_c.remove(5) field_tester.field_d.add(1) # The fields should be update in the cache, but /not/ in the underlying kvstore. assert_equals(set([200, 1]), field_tester.field_a) assert_equals(set([11, 12, 13, 14]), field_tester.field_b) assert_equals(set([4, 6]), field_tester.field_c) assert_equals(set([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_tester._field_data.has(field_tester, 'field_c')) assert_false(field_tester._field_data.has(field_tester, 'field_d')) # save the XBlock field_tester.save() # verify that the fields have been updated correctly assert_equals(set([200, 1]), field_tester.field_a) assert_equals(set([11, 12, 13, 14]), field_tester.field_b) assert_equals(set([4, 6]), field_tester.field_c) assert_equals(set([1]), field_tester.field_d) # Now, the fields should be updated in the underlying kvstore assert_equals(set([200, 1]), field_tester._field_data.get(field_tester, 'field_a')) assert_equals(set([11, 12, 13, 14]), field_tester._field_data.get(field_tester, 'field_b')) assert_equals(set([4, 6]), field_tester._field_data.get(field_tester, 'field_c')) assert_equals(set([1]), field_tester._field_data.get(field_tester, 'field_d'))
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'))
def test_dummy_user_service_current_user(): """ Tests that get_current_user() works on a dummy user service. """ user = XBlockUser(full_name="tester") user_service = SingleUserService(user) current_user = user_service.get_current_user() assert_equals(current_user, user) assert_equals(current_user.full_name, "tester") # assert that emails is an Iterable but not a string assert_is_instance(current_user.emails, collections.Iterable) assert_false(isinstance(current_user.emails, basestring)) # assert that opt_attrs is a Mapping assert_is_instance(current_user.opt_attrs, collections.Mapping)
def test_kv_store(): # Simple test to makes sure we can get things in and out kvs = WorkbenchDjangoKeyValueStore() key = KeyValueStore.Key(scope=Scope.content, user_id="rusty", block_scope_id="my_scenario.my_block.d0", field_name="age") assert_false(kvs.has(key)) kvs.set(key, 7) assert_true(kvs.has(key)) assert_equals(kvs.get(key), 7) kvs.delete(key) assert_false(kvs.has(key))
def test_dummy_user_service_current_user(): """ Tests that get_current_user() works on a dummy user service. """ user = XBlockUser(full_name="tester") user_service = SingleUserService(user) current_user = user_service.get_current_user() assert_equals(current_user, user) assert_equals(current_user.full_name, "tester") # assert that emails is an Iterable but not a string assert_is_instance(current_user.emails, collections.Iterable) assert_false(isinstance(current_user.emails, (six.text_type, six.binary_type))) # assert that opt_attrs is a Mapping assert_is_instance(current_user.opt_attrs, collections.Mapping)
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"))
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))
def test_mutation_with_save_writes(self): assert_false(self.field_data.has(self.block, 'field')) mutable = self.get() reference_copy = copy.deepcopy(mutable) self.mutate(reference_copy) # Verify that the test isn't vacuously true assert_not_equals(mutable, reference_copy) self.mutate(mutable) self.block.save() final_value = self.field_data.get(self.block, 'field') assert_equals(reference_copy, final_value)
def test_kv_store(): # Simple test to makes sure we can get things in and out kvs = WorkbenchDjangoKeyValueStore() key = KeyValueStore.Key( scope=Scope.content, user_id="rusty", block_scope_id="my_scenario.my_block.d0", field_name="age" ) assert_false(kvs.has(key)) kvs.set(key, 7) assert_true(kvs.has(key)) assert_equals(kvs.get(key), 7) kvs.delete(key) assert_false(kvs.has(key))
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_tester = FieldTester(MagicMock(), DictFieldData({'dic1': {'a': 200}, 'list1': ['a', 'b']}), Mock()) 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_tester._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_tester._field_data.has(field_tester, fname))
def test_setting_the_same_value_marks_field_as_dirty(): """ Check that setting field to the same value does not mark mutable fields as dirty. This might be an unexpected behavior though """ class FieldTester(XBlock): """Test block for set - get test.""" non_mutable = String(scope=Scope.settings) list_field = List(scope=Scope.settings) dict_field = Dict(scope=Scope.settings) runtime = TestRuntime(services={'field-data': DictFieldData({})}) field_tester = FieldTester(runtime, scope_ids=Mock(spec=ScopeIds)) # precondition checks assert_equals(len(field_tester._dirty_fields), 0) assert_false(field_tester.fields['list_field'].is_set_on(field_tester)) assert_false(field_tester.fields['dict_field'].is_set_on(field_tester)) assert_false(field_tester.fields['non_mutable'].is_set_on(field_tester)) field_tester.non_mutable = field_tester.non_mutable field_tester.list_field = field_tester.list_field field_tester.dict_field = field_tester.dict_field assert_in(field_tester.fields['non_mutable'], field_tester._dirty_fields) assert_in(field_tester.fields['list_field'], field_tester._dirty_fields) assert_in(field_tester.fields['dict_field'], field_tester._dirty_fields) assert_true(field_tester.fields['non_mutable'].is_set_on(field_tester)) assert_true(field_tester.fields['list_field'].is_set_on(field_tester)) assert_true(field_tester.fields['dict_field'].is_set_on(field_tester))
def test_default_fn(): key_store = SerialDefaultKVS() db_model = KvsFieldData(key_store) tester = TestIntegerXblock(Mock(), db_model, Mock()) tester2 = TestIntegerXblock(Mock(), db_model, Mock()) # ensure value is not in tester before any actions assert_false(db_model.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(db_model.has(tester, 'counter')) # ensure save does not save the computed default back to the object tester.save() assert_false(db_model.has(tester, 'counter')) # ensure second object gets another value second_call = tester2.counter assert_equals(second_call, 2)
def test_default_fn(): key_store = SerialDefaultKVS() db_model = DbModel(key_store) tester = TestIntegerXblock(Mock(), db_model, Mock()) tester2 = TestIntegerXblock(Mock(), db_model, Mock()) # ensure value is not in tester before any actions assert_false(db_model.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(db_model.has(tester, 'counter')) # ensure save does not save the computed default back to the object tester.save() assert_false(db_model.has(tester, 'counter')) # ensure second object gets another value second_call = tester2.counter assert_equals(second_call, 2)
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)
def test_delete_with_save_succeeds(self): self.delete() self.block.save() assert_false(self.field_data.has(self.block, 'field'))
def test_default(self): self.split.default(self.block, 'content') self.content.default.assert_called_once_with(self.block, 'content') assert_false(self.settings.default.called)
def test_get(self): assert_equals(1, self.agg.first) assert_equals(2, self.agg.second) assert_false(hasattr(self.agg, 'other')) with assert_raises(AttributeError): self.agg.other # pylint: disable=W0104
def test_player_token_is_disabled_by_default(): field_data = DictFieldData({}) player = OoyalaPlayerBlock(runtime, field_data, None) assert_false(player.enable_player_token)
def test_mutation_without_save_makes_non_default(self): self.mutate(self.get()) assert_false(self.is_default())
def test_get_with_save_doesnt_write(self): assert_false(self.field_data.has(self.block, 'field')) self.get() self.block.save() assert_false(self.field_data.has(self.block, 'field'))
def test_set_with_save_writes(self): assert_false(self.field_data.has(self.block, 'field')) self.set(self.new_value) self.block.save() assert_equals(self.new_value, self.field_data.get(self.block, 'field'))
def test_delete_with_save_writes(self): self.delete() self.block.save() assert_false(self.field_data.has(self.block, 'field')) assert_true(self.is_default())
def test_setting_the_same_value_marks_field_as_dirty(): """ Check that setting field to the same value marks mutable fields as dirty. However, since the value hasn't changed, these fields won't be saved. """ class FieldTester(XBlock): """Test block for set - get test.""" non_mutable = String(scope=Scope.settings) list_field = List(scope=Scope.settings) dict_field = Dict(scope=Scope.settings) runtime = TestRuntime(services={'field-data': DictFieldData({})}) field_tester = FieldTester(runtime, scope_ids=Mock(spec=ScopeIds)) # precondition checks assert_equals(len(field_tester._dirty_fields), 0) assert_false(field_tester.fields['list_field'].is_set_on(field_tester)) assert_false(field_tester.fields['dict_field'].is_set_on(field_tester)) assert_false(field_tester.fields['non_mutable'].is_set_on(field_tester)) field_tester.non_mutable = field_tester.non_mutable field_tester.list_field = field_tester.list_field field_tester.dict_field = field_tester.dict_field assert_not_in(field_tester.fields['non_mutable'], field_tester._dirty_fields) assert_in(field_tester.fields['list_field'], field_tester._dirty_fields) assert_in(field_tester.fields['dict_field'], field_tester._dirty_fields) assert_false(field_tester.fields['non_mutable'].is_set_on(field_tester)) assert_false(field_tester.fields['list_field'].is_set_on(field_tester)) assert_false(field_tester.fields['dict_field'].is_set_on(field_tester))
def test_mutation_with_save_makes_non_default(self): self.mutate(self.get()) self.block.save() assert_false(self.is_default())
def test_set_with_save_makes_non_default(self): self.set(self.new_value) self.block.save() assert_false(self.is_default())
def test_set_without_save_makes_non_default(self): self.set(self.new_value) assert_false(self.is_default())