Skip to content

Commit bde7e95

Browse files
committed
test($interpolate): add a test to address Igor's first concern
which is point angular#1 in this PR comment angular#4556 (comment) also merged Igor's first code review IgorMinar@784dd4e
1 parent 33de609 commit bde7e95

File tree

3 files changed

+56
-18
lines changed

3 files changed

+56
-18
lines changed

src/ng/interpolate.js

+18-13
Original file line numberDiff line numberDiff line change
@@ -169,57 +169,62 @@ function $InterpolateProvider() {
169169
if (!mustHaveExpression || hasInterpolation) {
170170
var concat = new Array(parts.length),
171171
expressions = {};
172-
forEach(parts, function (value, index) {
172+
173+
forEach(parts, function(value, index) {
173174
if (isFunction(value)) {
174175
expressions[index] = value;
175176
concat[index] = '';
176177
} else {
177178
concat[index] = value;
178179
}
179180
});
181+
180182
// computes all the interpolations and returns the resulting string
181-
// a specific index might already be computed (cz of the scope's dirty-checking),
183+
// a specific index might already be computed (thanks to the scope's dirty-checking),
182184
// and so its expression shouldn't be executed a 2nd time
183185
// also populates the lastValues of custom watchers for internal dirty-checking
184-
var getTextValue = function (scope, computedIndex, computedValue, lastValues) {
186+
var getConcatValue = function(scope, computedIndex, computedValue, lastValues) {
185187
try {
186-
forEach(expressions, function (expression, index) {
187-
concat[index] = index == computedIndex
188+
189+
forEach(expressions, function(expression, index) {
190+
concat[index] = (index === computedIndex)
188191
? computedValue
189192
: getStringValue(expression(scope));
190193

191194
if (lastValues) lastValues[index] = concat[index];
192195
});
193196
return concat.join('');
194-
}
195-
catch(err) {
197+
198+
} catch(err) {
196199
var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
197200
err.toString());
198201
$exceptionHandler(newErr);
199202
}
200203
};
201-
var getStringValue = function (value) {
204+
205+
var getStringValue = function(value) {
202206
value = trustedContext
203207
? $sce.getTrusted(trustedContext, value)
204208
: $sce.valueOf(value);
205209

206-
if (value === null || isUndefined(value)) {
210+
if (value == null) {
207211
return '';
208212
}
209213
return isString(value) ? value : toJson(value);
210214
};
211215

212216
fn = function(scope) {
213-
return getTextValue(scope);
217+
// we don't want others to be able to pass more than the first argument
218+
return getConcatValue(scope);
214219
};
215220
fn.exp = text;
216221
fn.parts = parts;
217222

218223
// watches each interpolation separately for performance
219-
fn.$$beWatched = function (scope, origListener, objectEquality) {
224+
fn.$$beWatched = function(scope, origListener, objectEquality) {
220225
var lastTextValue, lastValues = {}, watchersRm = [];
221226

222-
forEach(expressions, function (expression, index) {
227+
forEach(expressions, function(expression, index) {
223228
watchersRm.push(scope.$watch(function watchInterpolatedExpr(scope) {
224229
try {
225230
return getStringValue(expression(scope));
@@ -241,7 +246,7 @@ function $InterpolateProvider() {
241246
// and ignore it when the listener of `b` gets triggered
242247
// (unless the value of `b` changes again since the last computation)
243248
if (value !== lastValues[index]) {
244-
var textValue = getTextValue(scope, index, value, lastValues);
249+
var textValue = getConcatValue(scope, index, value, lastValues);
245250
origListener.call(this, textValue,
246251
value === oldValue ? textValue : lastTextValue, scope);
247252
lastTextValue = textValue;

src/ng/rootScope.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ function $RootScopeProvider(){
315315
* @returns {function()} Returns a deregistration function for this listener.
316316
*/
317317
$watch: function(watchExp, listener, objectEquality) {
318-
if (isFunction(watchExp.$$beWatched)) {
318+
if (watchExp.$$beWatched) {
319319
return watchExp.$$beWatched(this, listener, objectEquality, watchExp);
320320
}
321321
var scope = this,

test/ng/interpolateSpec.js

+37-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
describe('$interpolate', function() {
44

5-
it('should return a function when there are no bindings and textOnly is undefined',
5+
it('should return a function when there are no bindings and mustHaveExpression is undefined',
66
inject(function($interpolate) {
77
expect(typeof $interpolate('some text')).toBe('function');
88
}));
99

10-
11-
it('should return undefined when there are no bindings and textOnly is set to true',
10+
it('should return null when there are no bindings and mustHaveExpression is set to true',
1211
inject(function($interpolate) {
1312
expect($interpolate('some text', true)).toBeNull();
1413
}));
@@ -318,6 +317,40 @@ describe('$interpolate', function() {
318317
});
319318
expect(nbCalls).toBe(4);
320319
}));
321-
})
322320

321+
it('should call the listener only once per whole text change', inject(function ($rootScope, $interpolate) {
322+
var nbCalls = 0, value;
323+
$rootScope.$watch($interpolate("{{a}}-{{b}}"), function (_value){
324+
nbCalls++;
325+
value = _value;
326+
});
327+
328+
$rootScope.$apply();
329+
expect(nbCalls).toBe(1);
330+
expect(value).toBe('-');
331+
332+
$rootScope.$apply('a=1;b=1');
333+
expect(nbCalls).toBe(2);
334+
expect(value).toBe('1-1');
335+
336+
// one changes
337+
$rootScope.$apply('a=2');
338+
expect(nbCalls).toBe(3);
339+
expect(value).toBe('2-1');
340+
341+
$rootScope.$apply('b=2');
342+
expect(nbCalls).toBe(4);
343+
expect(value).toBe('2-2');
344+
345+
// both change
346+
$rootScope.$apply('a=3;b=3');
347+
expect(nbCalls).toBe(5);
348+
expect(value).toBe('3-3');
349+
350+
// nothing changes
351+
$rootScope.$apply();
352+
expect(nbCalls).toBe(5);
353+
expect(value).toBe('3-3');
354+
}));
355+
});
323356
});

0 commit comments

Comments
 (0)