Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

test($parse): add tests for watching one-time array/object literals #16477

Merged
merged 1 commit into from
Apr 3, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions test/ng/parseSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2840,6 +2840,46 @@ describe('parser', function() {
expect(filterCalled).toBe(true);
});

it('should not be invoked unless the input/arguments change within literals', function() {
var filterCalls = [];
$filterProvider.register('foo', valueFn(function(input) {
filterCalls.push(input);
return input;
}));

scope.$watch('[(a | foo:b:1), undefined]');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of including the params b and 1 here?
Should you not also be checking what happens if b change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question... I have no idea why I added those. I guess I'll just delete them, or if I think of a reason maybe they deserve a separate test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I guess I added it because the tests above and below the new tests have it as well (which I wrote some time ago)!

I think the original reason was to ensure that constant/variables as filter arguments do not effect what is being tested. While it doesn't truely test that because it never assigns a value to the b variable, I think I'd vote to leave it anyway, partially just to be consistent with the other tests around it... WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am indifferent, it just stood out to me as something unexplained.

scope.a = 0;
scope.$digest();
expect(filterCalls).toEqual([0]);

scope.$digest();
expect(filterCalls).toEqual([0]);

scope.a++;
scope.$digest();
expect(filterCalls).toEqual([0, 1]);
});

it('should not be invoked unless the input/arguments change within literals (one-time)', function() {
var filterCalls = [];
$filterProvider.register('foo', valueFn(function(input) {
filterCalls.push(input);
return input;
}));

scope.$watch('::[(a | foo:b:1), undefined]');
scope.a = 0;
scope.$digest();
expect(filterCalls).toEqual([0]);

scope.$digest();
expect(filterCalls).toEqual([0]);

scope.a++;
scope.$digest();
expect(filterCalls).toEqual([0, 1]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unexpected. If this is a one-time binding, shouldn't we be ignoring the filter once the binding has a value?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or does the undefined in the second element of the array prevent the one time binding from stabilizing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly! For ::[ ] and ::{ }, all values must be defined before unwatching the whole expression.

});

it('should always be invoked if they are marked as having $stateful', function() {
var filterCalled = false;
$filterProvider.register('foo', valueFn(extend(function(input) {
Expand Down Expand Up @@ -2883,6 +2923,52 @@ describe('parser', function() {
expect(watcherCalls).toBe(1);
}));

it('should ignore changes within nested objects', function() {
var watchCalls = [];
scope.$watch('[a]', function(a) { watchCalls.push(a[0]); });
scope.a = 0;
scope.$digest();
expect(watchCalls).toEqual([0]);

scope.$digest();
expect(watchCalls).toEqual([0]);

scope.a++;
scope.$digest();
expect(watchCalls).toEqual([0, 1]);

scope.a = {};
scope.$digest();
expect(watchCalls).toEqual([0, 1, {}]);

scope.a.foo = 42;
scope.$digest();
expect(watchCalls).toEqual([0, 1, {foo: 42}]);
});

it('should ignore changes within nested objects (one-time)', function() {
var watchCalls = [];
scope.$watch('::[a, undefined]', function(a) { watchCalls.push(a[0]); });
scope.a = 0;
scope.$digest();
expect(watchCalls).toEqual([0]);

scope.$digest();
expect(watchCalls).toEqual([0]);

scope.a++;
scope.$digest();
expect(watchCalls).toEqual([0, 1]);

scope.a = {};
scope.$digest();
expect(watchCalls).toEqual([0, 1, {}]);

scope.a.foo = 42;
scope.$digest();
expect(watchCalls).toEqual([0, 1, {foo: 42}]);
});

describe('with non-primitive input', function() {

describe('that does NOT support valueOf()', function() {
Expand Down