Skip to content

Commit 9670589

Browse files
committed
chore(core): add unit tests for event listener identity
1 parent 412a988 commit 9670589

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

apps/automated/src/data/observable-tests.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,65 @@ export var test_Observable_removeEventListener_SingleEvent_MultipleCallbacks = f
273273
TKUnit.assert(receivedCount === 3, 'Observable.removeEventListener not working properly with multiple listeners.');
274274
};
275275

276-
export var test_Observable_removeEventListener_MutlipleEvents_SingleCallback = function () {
276+
export var test_Observable_identity = function () {
277+
const obj = new Observable();
278+
279+
let receivedCount = 0;
280+
const callback = () => receivedCount++;
281+
const eventName = Observable.propertyChangeEvent;
282+
283+
// The identity of an event listener is determined by the tuple of
284+
// [eventType, callback, thisArg], and influences addition and removal.
285+
286+
// If you try to add the same callback for a given event name twice, without
287+
// distinguishing by its thisArg, the second addition will no-op.
288+
obj.addEventListener(eventName, callback);
289+
obj.addEventListener(eventName, callback);
290+
obj.set('testName', 1);
291+
TKUnit.assert(receivedCount === 1, 'Expected Observable to fire exactly once upon a property change, having passed the same callback into addEventListener() twice');
292+
obj.removeEventListener(eventName, callback);
293+
TKUnit.assert(!obj.hasListeners(eventName), 'Expected removeEventListener(eventName, callback) to remove all matching callbacks regardless of thisArg');
294+
receivedCount = 0;
295+
296+
// All truthy thisArgs are distinct, so we have three distinct identities here
297+
// and they should all get added.
298+
obj.addEventListener(eventName, callback);
299+
obj.addEventListener(eventName, callback, 1);
300+
obj.addEventListener(eventName, callback, 2);
301+
obj.set('testName', 2);
302+
TKUnit.assert(receivedCount === 3, 'Expected Observable to fire exactly three times upon a property change, having passed the same callback into addEventListener() three times, with the latter two distinguished by each having a different truthy thisArg');
303+
obj.removeEventListener(eventName, callback);
304+
TKUnit.assert(!obj.hasListeners(eventName), 'Expected removeEventListener(eventName, callback) to remove all matching callbacks regardless of thisArg');
305+
receivedCount = 0;
306+
307+
// If you specify thisArg when removing an event listener, it should remove
308+
// just the event listener with the corresponding thisArg.
309+
obj.addEventListener(eventName, callback, 1);
310+
obj.addEventListener(eventName, callback, 2);
311+
obj.set('testName', 3);
312+
TKUnit.assert(receivedCount === 2, 'Expected Observable to fire exactly three times upon a property change, having passed the same callback into addEventListener() three times, with the latter two distinguished by each having a different truthy thisArg');
313+
obj.removeEventListener(eventName, callback, 2);
314+
TKUnit.assert(obj.hasListeners(eventName), 'Expected removeEventListener(eventName, callback, thisArg) to remove just the event listener that matched the callback and thisArg');
315+
obj.removeEventListener(eventName, callback, 1);
316+
TKUnit.assert(!obj.hasListeners(eventName), 'Expected removeEventListener(eventName, callback, thisArg) to remove the remaining event listener that matched the callback and thisArg');
317+
receivedCount = 0;
318+
319+
// All falsy thisArgs are treated alike, so these all have the same identity
320+
// and only the first should get added.
321+
obj.addEventListener(eventName, callback);
322+
obj.addEventListener(eventName, callback, 0);
323+
obj.addEventListener(eventName, callback, false);
324+
obj.addEventListener(eventName, callback, null);
325+
obj.addEventListener(eventName, callback, undefined);
326+
obj.addEventListener(eventName, callback, '');
327+
obj.set('testName', 4);
328+
TKUnit.assert(receivedCount === 1, 'Expected Observable to fire exactly once upon a property change, having passed the same callback into addEventListener() multiple times, each time with a different falsy (and therefore indistinct) thisArg');
329+
obj.removeEventListener(eventName, callback);
330+
TKUnit.assert(!obj.hasListeners(eventName), 'Expected removeEventListener(eventName, callback) to remove all matching callbacks regardless of thisArg');
331+
receivedCount = 0;
332+
};
333+
334+
export var test_Observable_removeEventListener_MultipleEvents_SingleCallback = function () {
277335
var obj = new TestObservable();
278336

279337
var receivedCount = 0;

packages/core/data/observable/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ export class Observable {
279279
continue;
280280
}
281281

282-
// If we have a `thisArg`, refine only on `callback`.
282+
// If we don't have a `thisArg`, refine only on `callback`.
283283
if (callback && entry.callback !== callback) {
284284
continue;
285285
}

0 commit comments

Comments
 (0)