test($rootScope): add $watch/$watchCollection/$watchGroup tests
Closes #15949
This commit is contained in:
+569
-244
@@ -146,16 +146,6 @@ describe('Scope', function() {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should not keep constant expressions on watch queue', inject(function($rootScope) {
|
||||
$rootScope.$watch('1 + 1', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
expect($rootScope.$$watchersCount).toEqual(1);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
expect($rootScope.$$watchersCount).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should decrement the watcherCount when destroying a child scope', inject(function($rootScope) {
|
||||
var child1 = $rootScope.$new(),
|
||||
child2 = $rootScope.$new(),
|
||||
@@ -212,54 +202,136 @@ describe('Scope', function() {
|
||||
expect($rootScope.$$watchersCount).toBe(2);
|
||||
}));
|
||||
|
||||
it('should not keep constant literals on the watch queue', inject(function($rootScope) {
|
||||
$rootScope.$watch('[]', function() {});
|
||||
$rootScope.$watch('{}', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(2);
|
||||
$rootScope.$digest();
|
||||
describe('constants cleanup', function() {
|
||||
it('should remove $watch of constant literals after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watch('[]', function() {});
|
||||
$rootScope.$watch('{}', function() {});
|
||||
$rootScope.$watch('1', function() {});
|
||||
$rootScope.$watch('"foo"', function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should clean up stable watches on the watch queue', inject(function($rootScope) {
|
||||
$rootScope.$watch('::foo', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
it('should remove $watchCollection of constant literals after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watchCollection('[]', function() {});
|
||||
$rootScope.$watchCollection('{}', function() {});
|
||||
$rootScope.$watchCollection('1', function() {});
|
||||
$rootScope.$watchCollection('"foo"', function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
$rootScope.foo = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
it('should remove $watchGroup of constant literals after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watchGroup(['[]', '{}', '1', '"foo"'], function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
it('should clean up stable watches from $watchCollection', inject(function($rootScope) {
|
||||
$rootScope.$watchCollection('::foo', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
it('should remove $watch of filtered constant literals after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watch('[1] | filter:"x"', function() {});
|
||||
$rootScope.$watch('1 | number:2', function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
$rootScope.foo = [];
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should clean up stable watches from $watchGroup', inject(function($rootScope) {
|
||||
$rootScope.$watchGroup(['::foo', '::bar'], function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(2);
|
||||
it('should remove $watchCollection of filtered constant literals after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watchCollection('[1] | filter:"x"', function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(2);
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
$rootScope.foo = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
it('should remove $watchGroup of filtered constant literals after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watchGroup(['[1] | filter:"x"', '1 | number:2'], function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
$rootScope.bar = 'bar';
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should remove $watch of constant expressions after initial digest', inject(function($rootScope) {
|
||||
$rootScope.$watch('1 + 1', function() {});
|
||||
$rootScope.$watch('"a" + "b"', function() {});
|
||||
$rootScope.$watch('"ab".length', function() {});
|
||||
$rootScope.$watch('[].length', function() {});
|
||||
$rootScope.$watch('(1 + 1) | number:2', function() {});
|
||||
expect($rootScope.$$watchers.length).not.toEqual(0);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('onetime cleanup', function() {
|
||||
it('should clean up stable watches on the watch queue', inject(function($rootScope) {
|
||||
$rootScope.$watch('::foo', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.foo = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should clean up stable watches from $watchCollection', inject(function($rootScope) {
|
||||
$rootScope.$watchCollection('::foo', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.foo = [];
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should clean up stable watches from $watchCollection literals', inject(function($rootScope) {
|
||||
$rootScope.$watchCollection('::[foo, bar]', function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.foo = 1;
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.foo = 2;
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.bar = 3;
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
|
||||
it('should clean up stable watches from $watchGroup', inject(function($rootScope) {
|
||||
$rootScope.$watchGroup(['::foo', '::bar'], function() {});
|
||||
expect($rootScope.$$watchers.length).toEqual(2);
|
||||
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(2);
|
||||
|
||||
$rootScope.foo = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(1);
|
||||
|
||||
$rootScope.bar = 'bar';
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.$$watchers.length).toEqual(0);
|
||||
}));
|
||||
});
|
||||
|
||||
it('should delegate exceptions', function() {
|
||||
module(function($exceptionHandlerProvider) {
|
||||
@@ -689,249 +761,500 @@ describe('Scope', function() {
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
describe('$watchCollection', function() {
|
||||
var log, $rootScope, deregister;
|
||||
describe('variable', function() {
|
||||
var log, $rootScope, deregister;
|
||||
|
||||
beforeEach(inject(function(_$rootScope_, _log_) {
|
||||
$rootScope = _$rootScope_;
|
||||
log = _log_;
|
||||
deregister = $rootScope.$watchCollection('obj', function logger(newVal, oldVal) {
|
||||
var msg = {newVal: newVal, oldVal: oldVal};
|
||||
beforeEach(inject(function(_$rootScope_, _log_) {
|
||||
$rootScope = _$rootScope_;
|
||||
log = _log_;
|
||||
deregister = $rootScope.$watchCollection('obj', function logger(newVal, oldVal) {
|
||||
var msg = {newVal: newVal, oldVal: oldVal};
|
||||
|
||||
if (newVal === oldVal) {
|
||||
msg.identical = true;
|
||||
}
|
||||
if (newVal === oldVal) {
|
||||
msg.identical = true;
|
||||
}
|
||||
|
||||
log(msg);
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
it('should not trigger if nothing change', inject(function($rootScope) {
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{ newVal: undefined, oldVal: undefined, identical: true }]);
|
||||
log.reset();
|
||||
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([]);
|
||||
}));
|
||||
|
||||
|
||||
it('should allow deregistration', function() {
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.toArray().length).toBe(1);
|
||||
log.reset();
|
||||
|
||||
$rootScope.obj.push('a');
|
||||
deregister();
|
||||
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
describe('array', function() {
|
||||
|
||||
it('should return oldCollection === newCollection only on the first listener call',
|
||||
inject(function($rootScope, log) {
|
||||
|
||||
// first time should be identical
|
||||
$rootScope.obj = ['a', 'b'];
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: ['a', 'b'], oldVal: ['a', 'b'], identical: true}]);
|
||||
log.reset();
|
||||
|
||||
// second time should be different
|
||||
$rootScope.obj[1] = 'c';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: ['a', 'c'], oldVal: ['a', 'b']}]);
|
||||
log(msg);
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
it('should trigger when property changes into array', function() {
|
||||
$rootScope.obj = 'test';
|
||||
it('should not trigger if nothing change', function() {
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: 'test', oldVal: 'test', identical: true}]);
|
||||
expect(log).toEqual([{ newVal: undefined, oldVal: undefined, identical: true }]);
|
||||
log.reset();
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [], oldVal: 'test'}]);
|
||||
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {}, oldVal: []}]);
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [], oldVal: {}}]);
|
||||
|
||||
$rootScope.obj = undefined;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: undefined, oldVal: []}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.obj = [{}];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [{}], oldVal: [{}], identical: true}]);
|
||||
|
||||
$rootScope.obj[0].name = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should watch array properties', function() {
|
||||
it('should allow deregistration', function() {
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [], oldVal: [], identical: true}]);
|
||||
expect(log.toArray().length).toBe(1);
|
||||
log.reset();
|
||||
|
||||
$rootScope.obj.push('a');
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['a'], oldVal: []}]);
|
||||
deregister();
|
||||
|
||||
$rootScope.obj[0] = 'b';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['b'], oldVal: ['a']}]);
|
||||
|
||||
$rootScope.obj.push([]);
|
||||
$rootScope.obj.push({});
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['b', [], {}], oldVal: ['b']}]);
|
||||
|
||||
var temp = $rootScope.obj[1];
|
||||
$rootScope.obj[1] = $rootScope.obj[2];
|
||||
$rootScope.obj[2] = temp;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['b', {}, []], oldVal: ['b', [], {}]}]);
|
||||
|
||||
$rootScope.obj.shift();
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [{}, []], oldVal: ['b', {}, []]}]);
|
||||
expect(log).toEqual([]);
|
||||
});
|
||||
|
||||
it('should not infinitely digest when current value is NaN', function() {
|
||||
$rootScope.obj = [NaN];
|
||||
expect(function() {
|
||||
|
||||
describe('array', function() {
|
||||
|
||||
it('should return oldCollection === newCollection only on the first listener call',
|
||||
inject(function($rootScope, log) {
|
||||
|
||||
// first time should be identical
|
||||
$rootScope.obj = ['a', 'b'];
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
});
|
||||
expect(log).toEqual([{newVal: ['a', 'b'], oldVal: ['a', 'b'], identical: true}]);
|
||||
log.reset();
|
||||
|
||||
it('should watch array-like objects like arrays', function() {
|
||||
var arrayLikelog = [];
|
||||
$rootScope.$watchCollection('arrayLikeObject', function logger(obj) {
|
||||
forEach(obj, function(element) {
|
||||
// second time should be different
|
||||
$rootScope.obj[1] = 'c';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: ['a', 'c'], oldVal: ['a', 'b']}]);
|
||||
}));
|
||||
|
||||
|
||||
it('should trigger when property changes into array', function() {
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: 'test', oldVal: 'test', identical: true}]);
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [], oldVal: 'test'}]);
|
||||
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {}, oldVal: []}]);
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [], oldVal: {}}]);
|
||||
|
||||
$rootScope.obj = undefined;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: undefined, oldVal: []}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.obj = [{}];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [{}], oldVal: [{}], identical: true}]);
|
||||
|
||||
$rootScope.obj[0].name = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should watch array properties', function() {
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [], oldVal: [], identical: true}]);
|
||||
|
||||
$rootScope.obj.push('a');
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['a'], oldVal: []}]);
|
||||
|
||||
$rootScope.obj[0] = 'b';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['b'], oldVal: ['a']}]);
|
||||
|
||||
$rootScope.obj.push([]);
|
||||
$rootScope.obj.push({});
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['b', [], {}], oldVal: ['b']}]);
|
||||
|
||||
var temp = $rootScope.obj[1];
|
||||
$rootScope.obj[1] = $rootScope.obj[2];
|
||||
$rootScope.obj[2] = temp;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['b', {}, []], oldVal: ['b', [], {}]}]);
|
||||
|
||||
$rootScope.obj.shift();
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [{}, []], oldVal: ['b', {}, []]}]);
|
||||
});
|
||||
|
||||
it('should not infinitely digest when current value is NaN', function() {
|
||||
$rootScope.obj = [NaN];
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should watch array-like objects like arrays', function() {
|
||||
window.document.body.innerHTML = '<p>' +
|
||||
'<a name=\'x\'>a</a>' +
|
||||
'<a name=\'y\'>b</a>' +
|
||||
'</p>';
|
||||
|
||||
$rootScope.obj = window.document.getElementsByTagName('a');
|
||||
$rootScope.$digest();
|
||||
|
||||
var arrayLikelog = [];
|
||||
forEach(log.empty()[0].newVal, function(element) {
|
||||
arrayLikelog.push(element.name);
|
||||
});
|
||||
expect(arrayLikelog).toEqual(['x', 'y']);
|
||||
});
|
||||
window.document.body.innerHTML = '<p>' +
|
||||
'<a name=\'x\'>a</a>' +
|
||||
'<a name=\'y\'>b</a>' +
|
||||
'</p>';
|
||||
});
|
||||
|
||||
$rootScope.arrayLikeObject = window.document.getElementsByTagName('a');
|
||||
$rootScope.$digest();
|
||||
expect(arrayLikelog).toEqual(['x', 'y']);
|
||||
|
||||
describe('object', function() {
|
||||
|
||||
it('should return oldCollection === newCollection only on the first listener call', function() {
|
||||
|
||||
$rootScope.obj = {'a': 'b'};
|
||||
// first time should be identical
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': 'b'}, oldVal: {'a': 'b'}, identical: true}]);
|
||||
|
||||
// second time not identical
|
||||
$rootScope.obj.a = 'c';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: {'a': 'c'}, oldVal: {'a': 'b'}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should trigger when property changes into object', function() {
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: 'test', oldVal: 'test', identical: true}]);
|
||||
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {}, oldVal: 'test'}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.obj = {name: {}};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {name: {}}, oldVal: {name: {}}, identical: true}]);
|
||||
|
||||
$rootScope.obj.name.bar = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should watch object properties', function() {
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {}, oldVal: {}, identical: true}]);
|
||||
|
||||
$rootScope.obj.a = 'A';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'A'}, oldVal: {}}]);
|
||||
|
||||
$rootScope.obj.a = 'B';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'B'}, oldVal: {a: 'A'}}]);
|
||||
|
||||
$rootScope.obj.b = [];
|
||||
$rootScope.obj.c = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'B', b: [], c: {}}, oldVal: {a: 'B'}}]);
|
||||
|
||||
var temp = $rootScope.obj.a;
|
||||
$rootScope.obj.a = $rootScope.obj.b;
|
||||
$rootScope.obj.c = temp;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).
|
||||
toEqual([{newVal: {a: [], b: [], c: 'B'}, oldVal: {a: 'B', b: [], c: {}}}]);
|
||||
|
||||
delete $rootScope.obj.a;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {b: [], c: 'B'}, oldVal: {a: [], b: [], c: 'B'}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not infinitely digest when current value is NaN', function() {
|
||||
$rootScope.obj = {a: NaN};
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
|
||||
it('should handle objects created using `Object.create(null)`', function() {
|
||||
$rootScope.obj = Object.create(null);
|
||||
$rootScope.obj.a = 'a';
|
||||
$rootScope.obj.b = 'b';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()[0].newVal).toEqual(extend(Object.create(null), {a: 'a', b: 'b'}));
|
||||
|
||||
delete $rootScope.obj.b;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()[0].newVal).toEqual(extend(Object.create(null), {a: 'a'}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('literal', function() {
|
||||
describe('array', function() {
|
||||
var log, $rootScope;
|
||||
|
||||
describe('object', function() {
|
||||
beforeEach(inject(function(_$rootScope_, _log_) {
|
||||
$rootScope = _$rootScope_;
|
||||
log = _log_;
|
||||
$rootScope.$watchCollection('[obj]', function logger(newVal, oldVal) {
|
||||
var msg = {newVal: newVal, oldVal: oldVal};
|
||||
|
||||
it('should return oldCollection === newCollection only on the first listener call',
|
||||
inject(function($rootScope, log) {
|
||||
if (newVal === oldVal) {
|
||||
msg.identical = true;
|
||||
}
|
||||
|
||||
$rootScope.obj = {'a': 'b'};
|
||||
// first time should be identical
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': 'b'}, oldVal: {'a': 'b'}, identical: true}]);
|
||||
|
||||
// second time not identical
|
||||
$rootScope.obj.a = 'c';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: {'a': 'c'}, oldVal: {'a': 'b'}}]);
|
||||
}));
|
||||
log(msg);
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
it('should trigger when property changes into object', function() {
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: 'test', oldVal: 'test', identical: true}]);
|
||||
it('should return oldCollection === newCollection only on the first listener call', function() {
|
||||
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {}, oldVal: 'test'}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.obj = {name: {}};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {name: {}}, oldVal: {name: {}}, identical: true}]);
|
||||
|
||||
$rootScope.obj.name.bar = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should watch object properties', function() {
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {}, oldVal: {}, identical: true}]);
|
||||
|
||||
$rootScope.obj.a = 'A';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'A'}, oldVal: {}}]);
|
||||
|
||||
$rootScope.obj.a = 'B';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'B'}, oldVal: {a: 'A'}}]);
|
||||
|
||||
$rootScope.obj.b = [];
|
||||
$rootScope.obj.c = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'B', b: [], c: {}}, oldVal: {a: 'B'}}]);
|
||||
|
||||
var temp = $rootScope.obj.a;
|
||||
$rootScope.obj.a = $rootScope.obj.b;
|
||||
$rootScope.obj.c = temp;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).
|
||||
toEqual([{newVal: {a: [], b: [], c: 'B'}, oldVal: {a: 'B', b: [], c: {}}}]);
|
||||
|
||||
delete $rootScope.obj.a;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {b: [], c: 'B'}, oldVal: {a: [], b: [], c: 'B'}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not infinitely digest when current value is NaN', function() {
|
||||
$rootScope.obj = {a: NaN};
|
||||
expect(function() {
|
||||
// first time should be identical
|
||||
$rootScope.obj = 'a';
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
expect(log).toEqual([{newVal: ['a'], oldVal: ['a'], identical: true}]);
|
||||
log.reset();
|
||||
|
||||
// second time should be different
|
||||
$rootScope.obj = 'b';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: ['b'], oldVal: ['a']}]);
|
||||
});
|
||||
|
||||
|
||||
it('should trigger when property changes into array', function() {
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: ['test'], oldVal: ['test'], identical: true}]);
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [[]], oldVal: ['test']}]);
|
||||
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [{}], oldVal: [[]]}]);
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [[]], oldVal: [{}]}]);
|
||||
|
||||
$rootScope.obj = undefined;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [undefined], oldVal: [[]]}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: [{}], oldVal: [{}], identical: true}]);
|
||||
|
||||
$rootScope.obj.name = 'foo';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should not infinitely digest when current value is NaN', function() {
|
||||
$rootScope.obj = NaN;
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should handle objects created using `Object.create(null)`', function() {
|
||||
$rootScope.obj = Object.create(null);
|
||||
$rootScope.obj.a = 'a';
|
||||
$rootScope.obj.b = 'b';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()[0].newVal).toEqual(extend(Object.create(null), {a: 'a', b: 'b'}));
|
||||
describe('object', function() {
|
||||
var log, $rootScope;
|
||||
|
||||
delete $rootScope.obj.b;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()[0].newVal).toEqual(extend(Object.create(null), {a: 'a'}));
|
||||
beforeEach(inject(function(_$rootScope_, _log_) {
|
||||
$rootScope = _$rootScope_;
|
||||
log = _log_;
|
||||
$rootScope.$watchCollection('{a: obj}', function logger(newVal, oldVal) {
|
||||
var msg = {newVal: newVal, oldVal: oldVal};
|
||||
|
||||
if (newVal === oldVal) {
|
||||
msg.identical = true;
|
||||
}
|
||||
|
||||
log(msg);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return oldCollection === newCollection only on the first listener call', function() {
|
||||
|
||||
$rootScope.obj = 'b';
|
||||
// first time should be identical
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': 'b'}, oldVal: {'a': 'b'}, identical: true}]);
|
||||
|
||||
// second time not identical
|
||||
$rootScope.obj = 'c';
|
||||
$rootScope.$digest();
|
||||
expect(log).toEqual([{newVal: {'a': 'c'}, oldVal: {'a': 'b'}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should trigger when property changes into object', function() {
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': 'test'}, oldVal: {'a': 'test'}, identical: true}]);
|
||||
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': {}}, oldVal: {'a': 'test'}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.obj = {name: 'foo'};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': {name: 'foo'}}, oldVal: {'a': {name: 'foo'}}, identical: true}]);
|
||||
|
||||
$rootScope.obj.name = 'bar';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should watch object properties', function() {
|
||||
$rootScope.obj = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': {}}, oldVal: {'a': {}}, identical: true}]);
|
||||
|
||||
$rootScope.obj = 'A';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': 'A'}, oldVal: {'a': {}}}]);
|
||||
|
||||
$rootScope.obj = 'B';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: 'B'}, oldVal: {a: 'A'}}]);
|
||||
|
||||
$rootScope.obj = [];
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: []}, oldVal: {a: 'B'}}]);
|
||||
|
||||
delete $rootScope.obj;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {a: undefined}, oldVal: {a: []}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not infinitely digest when current value is NaN', function() {
|
||||
$rootScope.obj = NaN;
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('object computed property', function() {
|
||||
var log, $rootScope;
|
||||
|
||||
beforeEach(inject(function(_$rootScope_, _log_) {
|
||||
$rootScope = _$rootScope_;
|
||||
log = _log_;
|
||||
$rootScope.$watchCollection('{[key]: obj}', function logger(newVal, oldVal) {
|
||||
var msg = {newVal: newVal, oldVal: oldVal};
|
||||
|
||||
if (newVal === oldVal) {
|
||||
msg.identical = true;
|
||||
}
|
||||
|
||||
log(msg);
|
||||
});
|
||||
}));
|
||||
|
||||
|
||||
it('should default to "undefined" key', function() {
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'undefined': 'test'}, oldVal: {'undefined': 'test'}, identical: true}]);
|
||||
});
|
||||
|
||||
|
||||
it('should trigger when key changes', function() {
|
||||
$rootScope.key = 'a';
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': 'test'}, oldVal: {'a': 'test'}, identical: true}]);
|
||||
|
||||
$rootScope.key = 'b';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'b': 'test'}, oldVal: {'a': 'test'}}]);
|
||||
|
||||
$rootScope.key = true;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'true': 'test'}, oldVal: {'b': 'test'}}]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger when key changes but stringified key does not', function() {
|
||||
$rootScope.key = 1;
|
||||
$rootScope.obj = 'test';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'1': 'test'}, oldVal: {'1': 'test'}, identical: true}]);
|
||||
|
||||
$rootScope.key = '1';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
|
||||
$rootScope.key = true;
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'true': 'test'}, oldVal: {'1': 'test'}}]);
|
||||
|
||||
$rootScope.key = 'true';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
|
||||
$rootScope.key = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'[object Object]': 'test'}, oldVal: {'true': 'test'}}]);
|
||||
|
||||
$rootScope.key = {};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should not trigger change when object in collection changes', function() {
|
||||
$rootScope.key = 'a';
|
||||
$rootScope.obj = {name: 'foo'};
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([{newVal: {'a': {name: 'foo'}}, oldVal: {'a': {name: 'foo'}}, identical: true}]);
|
||||
|
||||
$rootScope.obj.name = 'bar';
|
||||
$rootScope.$digest();
|
||||
expect(log.empty()).toEqual([]);
|
||||
});
|
||||
|
||||
|
||||
it('should not infinitely digest when key value is NaN', function() {
|
||||
$rootScope.key = NaN;
|
||||
$rootScope.obj = NaN;
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('optimizations', function() {
|
||||
|
||||
function setupWatches(scope, log) {
|
||||
@@ -1108,6 +1431,8 @@ describe('Scope', function() {
|
||||
scope.$watchGroup(['1'], noop);
|
||||
//multi constant
|
||||
scope.$watchGroup(['1', '2'], noop);
|
||||
//multi one-time/constant
|
||||
scope.$watchGroup(['::a', '1'], noop);
|
||||
|
||||
expect(scope.$$watchersCount).not.toBe(0);
|
||||
scope.$apply('a = b = 1');
|
||||
|
||||
Reference in New Issue
Block a user