Skip to content

Commit

Permalink
test: add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaLiPassion committed May 18, 2019
1 parent 4a50eef commit 92692ec
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
18 changes: 13 additions & 5 deletions packages/core/src/zone/ng_zone.ts
Expand Up @@ -115,6 +115,8 @@ export class NgZone {
*/
readonly onError: EventEmitter<any> = new EventEmitter(false);

readonly shouldCoalesceEventChangeDetection: boolean = true;

constructor({enableLongStackTrace = false, shouldCoalesceEventChangeDetection = true}) {
if (typeof Zone == 'undefined') {
throw new Error(`In this configuration Angular requires Zone.js`);
Expand All @@ -138,6 +140,7 @@ export class NgZone {
self._inner = self._inner.fork((Zone as any)['longStackTraceZoneSpec']);
}

self.shouldCoalesceEventChangeDetection = shouldCoalesceEventChangeDetection;
forkInnerZoneWithAngularBehavior(self, shouldCoalesceEventChangeDetection);
}

Expand Down Expand Up @@ -231,6 +234,7 @@ interface NgZonePrivate extends NgZone {
hasPendingMicrotasks: boolean;
hasPendingMacrotasks: boolean;
isStable: boolean;
shouldCoalesceEventChangeDetection: boolean;
}

function checkStable(zone: NgZonePrivate) {
Expand All @@ -240,7 +244,9 @@ function checkStable(zone: NgZonePrivate) {
zone.onMicrotaskEmpty.emit(null);
} finally {
zone._nesting--;
if (!zone.hasPendingMicrotasks && lastRequestAnimationFrameId === -1) {
if (!zone.hasPendingMicrotasks &&
((zone.shouldCoalesceEventChangeDetection && lastRequestAnimationFrameId === -1)) ||
!zone.shouldCoalesceEventChangeDetection) {
try {
zone.runOutsideAngular(() => zone.onStable.emit(null));
} finally {
Expand All @@ -262,16 +268,16 @@ let nativeCancelAnimationFrame: any;
function initNativeRequestAnimationFrame() {
nativeRequestAnimationFrame = _global['requestAnimationFrame'];
nativeCancelAnimationFrame = _global['cancelAnimationFrame'];
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame) {
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
// use unpatched version of requestAnimationFrame if possible
// to avoid another Change detection
const unpatchedRequestAnimationFrame =
(requestAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];
(nativeRequestAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];
if (unpatchedRequestAnimationFrame) {
nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
}
const unpatchedCancelAnimationFrame =
(cancelAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];
(nativeCancelAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];
if (unpatchedCancelAnimationFrame) {
nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
}
Expand Down Expand Up @@ -305,7 +311,8 @@ function forkInnerZoneWithAngularBehavior(
properties: <any>{
'isAngularZone': true,
'maybeDelayChangeDetection': !!shouldCoalesceEventChangeDetection &&
nativeRequestAnimationFrame && delayChangeDetectionForEventsDelegate
nativeRequestAnimationFrame && nativeCancelAnimationFrame &&
delayChangeDetectionForEventsDelegate
},
onInvokeTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task, applyThis: any,
applyArgs: any): any => {
Expand Down Expand Up @@ -376,6 +383,7 @@ export class NoopNgZone implements NgZone {
readonly onMicrotaskEmpty: EventEmitter<any> = new EventEmitter();
readonly onStable: EventEmitter<any> = new EventEmitter();
readonly onError: EventEmitter<any> = new EventEmitter();
readonly shouldCoalesceEventChangeDetection: boolean = false;

run(fn: () => any): any { return fn(); }

Expand Down
25 changes: 24 additions & 1 deletion packages/platform-browser/test/dom/events/event_manager_spec.ts
Expand Up @@ -319,6 +319,29 @@ import {el} from '../../../testing/src/browser_util';
getDOM().dispatchEvent(element, dispatchedEvent);
expect(receivedEvent).toBe(null);
});

it('should only trigger one Change detection when bubbling', () => {
const element = el('<div></div>');
const child = el('<div></div>');
getDOM().appendChild(element, child);
getDOM().appendChild(doc.body, element);
const dispatchedEvent = getDOM().createMouseEvent('click');
let receivedEvents: any = [];
let stables: any = [];
const handler = (e: any) => { receivedEvents.push(e); };
const zone = new FakeNgZone();
const manager = new EventManager([domEventPlugin], zone);

const removerChild = manager.addEventListener(child, 'click', handler);
const removerParent = manager.addEventListener(element, 'click', handler);
zone.onStable.subscribe((isStable: any) => { stables.push(isStable); });
getDOM().dispatchEvent(child, dispatchedEvent);
expect(receivedEvents.length).toBe(2);
expect(stables.length).toBe(1);

removerChild && removerChild();
removerParent && removerParent();
});
});
})();

Expand All @@ -337,7 +360,7 @@ class FakeEventManagerPlugin extends EventManagerPlugin {
}

class FakeNgZone extends NgZone {
constructor() { super({enableLongStackTrace: false}); }
constructor() { super({enableLongStackTrace: false, shouldCoalesceEventChangeDetection: true}); }
run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T { return fn(); }
runOutsideAngular(fn: Function) { return fn(); }
}

0 comments on commit 92692ec

Please sign in to comment.