2016-11-10 17:46:23 -05:00
|
|
|
/**
|
|
|
|
* @license
|
2020-05-19 15:08:49 -04:00
|
|
|
* Copyright Google LLC All Rights Reserved.
|
2016-11-10 17:46:23 -05:00
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
2018-05-14 21:39:15 -04:00
|
|
|
import {NgZone} from '@angular/core';
|
|
|
|
import {fakeAsync, inject, tick} from '@angular/core/testing';
|
|
|
|
import {afterEach, beforeEach, describe, expect, it,} from '@angular/core/testing/src/testing_internal';
|
|
|
|
import {EventManager} from '@angular/platform-browser';
|
|
|
|
import {HammerGestureConfig, HammerGesturesPlugin,} from '@angular/platform-browser/src/dom/events/hammer_gestures';
|
2016-11-10 17:46:23 -05:00
|
|
|
|
2017-12-16 17:42:55 -05:00
|
|
|
{
|
2016-11-10 17:46:23 -05:00
|
|
|
describe('HammerGesturesPlugin', () => {
|
2018-02-17 08:00:05 -05:00
|
|
|
let plugin: HammerGesturesPlugin;
|
2018-05-14 21:39:15 -04:00
|
|
|
let fakeConsole: any;
|
2017-12-18 01:18:50 -05:00
|
|
|
if (isNode) return;
|
2016-11-10 17:46:23 -05:00
|
|
|
|
2020-03-30 11:22:25 -04:00
|
|
|
beforeEach(() => {
|
|
|
|
fakeConsole = {warn: jasmine.createSpy('console.warn')};
|
|
|
|
});
|
2018-05-14 21:39:15 -04:00
|
|
|
|
|
|
|
describe('with no custom loader', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
plugin = new HammerGesturesPlugin(document, new HammerGestureConfig(), fakeConsole);
|
|
|
|
});
|
2016-11-10 17:46:23 -05:00
|
|
|
|
2018-05-14 21:39:15 -04:00
|
|
|
it('should implement addGlobalEventListener', () => {
|
2020-01-03 00:28:06 -05:00
|
|
|
spyOn(plugin, 'addEventListener').and.callFake(() => () => {});
|
2016-11-10 17:46:23 -05:00
|
|
|
|
2018-05-14 21:39:15 -04:00
|
|
|
expect(() => {
|
|
|
|
plugin.addGlobalEventListener('document', 'swipe', () => {});
|
|
|
|
}).not.toThrowError();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should warn user and do nothing when Hammer.js not loaded', () => {
|
|
|
|
expect(plugin.supports('swipe')).toBe(false);
|
|
|
|
expect(fakeConsole.warn)
|
|
|
|
.toHaveBeenCalledWith(
|
|
|
|
`The "swipe" event cannot be bound because Hammer.JS is not ` +
|
|
|
|
`loaded and no custom loader has been specified.`);
|
|
|
|
});
|
2016-11-10 17:46:23 -05:00
|
|
|
});
|
2018-02-17 08:00:05 -05:00
|
|
|
|
2018-05-14 21:39:15 -04:00
|
|
|
describe('with a custom loader', () => {
|
|
|
|
// Use a fake custom loader for tests, with helper functions to resolve or reject.
|
|
|
|
let loader: () => Promise<void>;
|
|
|
|
let resolveLoader: () => void;
|
|
|
|
let failLoader: () => void;
|
|
|
|
|
|
|
|
// Arbitrary element and listener for testing.
|
|
|
|
let someElement: HTMLDivElement;
|
|
|
|
let someListener: () => void;
|
|
|
|
|
|
|
|
// Keep track of whatever value is in `window.Hammer` before the test so it can be
|
|
|
|
// restored afterwards so that this test doesn't care whether Hammer is actually loaded.
|
|
|
|
let originalHammerGlobal: any;
|
|
|
|
|
|
|
|
// Fake Hammer instance ("mc") used to test the underlying event registration.
|
|
|
|
let fakeHammerInstance: {on: () => void, off: () => void};
|
|
|
|
|
|
|
|
// Inject the NgZone so that we can make it available to the plugin through a fake
|
|
|
|
// EventManager.
|
|
|
|
let ngZone: NgZone;
|
2020-03-30 11:22:25 -04:00
|
|
|
beforeEach(inject([NgZone], (z: NgZone) => {
|
|
|
|
ngZone = z;
|
|
|
|
}));
|
2018-05-14 21:39:15 -04:00
|
|
|
|
2021-02-18 13:53:57 -05:00
|
|
|
let loaderCalled = 0;
|
|
|
|
|
2018-05-14 21:39:15 -04:00
|
|
|
beforeEach(() => {
|
|
|
|
originalHammerGlobal = (window as any).Hammer;
|
|
|
|
(window as any).Hammer = undefined;
|
|
|
|
|
|
|
|
fakeHammerInstance = {
|
|
|
|
on: jasmine.createSpy('mc.on'),
|
|
|
|
off: jasmine.createSpy('mc.off'),
|
|
|
|
};
|
|
|
|
|
2021-02-18 13:53:57 -05:00
|
|
|
loader = () => {
|
|
|
|
loaderCalled++;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
resolveLoader = resolve;
|
|
|
|
failLoader = reject;
|
|
|
|
});
|
|
|
|
};
|
2018-05-14 21:39:15 -04:00
|
|
|
|
|
|
|
// Make the hammer config return a fake hammer instance
|
|
|
|
const hammerConfig = new HammerGestureConfig();
|
|
|
|
spyOn(hammerConfig, 'buildHammer').and.returnValue(fakeHammerInstance);
|
|
|
|
|
|
|
|
plugin = new HammerGesturesPlugin(document, hammerConfig, fakeConsole, loader);
|
|
|
|
|
|
|
|
// Use a fake EventManager that has access to the NgZone.
|
2020-03-30 11:22:25 -04:00
|
|
|
plugin.manager = {getZone: () => ngZone} as EventManager;
|
2018-05-14 21:39:15 -04:00
|
|
|
|
|
|
|
someElement = document.createElement('div');
|
|
|
|
someListener = () => {};
|
|
|
|
});
|
|
|
|
|
2020-03-30 11:22:25 -04:00
|
|
|
afterEach(() => {
|
2021-02-18 13:53:57 -05:00
|
|
|
loaderCalled = 0;
|
2020-03-30 11:22:25 -04:00
|
|
|
(window as any).Hammer = originalHammerGlobal;
|
|
|
|
});
|
2018-05-14 21:39:15 -04:00
|
|
|
|
2021-02-18 13:53:57 -05:00
|
|
|
it('should call the loader provider only once', () => {
|
|
|
|
plugin.addEventListener(someElement, 'swipe', () => {});
|
|
|
|
plugin.addEventListener(someElement, 'panleft', () => {});
|
|
|
|
plugin.addEventListener(someElement, 'panright', () => {});
|
|
|
|
// Ensure that the loader is called only once, because previouly
|
|
|
|
// it was called the same number of times as `addEventListener` was called.
|
|
|
|
expect(loaderCalled).toEqual(1);
|
|
|
|
});
|
|
|
|
|
2018-05-14 21:39:15 -04:00
|
|
|
it('should not log a warning when HammerJS is not loaded', () => {
|
|
|
|
plugin.addEventListener(someElement, 'swipe', () => {});
|
|
|
|
expect(fakeConsole.warn).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should defer registering an event until Hammer is loaded', fakeAsync(() => {
|
|
|
|
plugin.addEventListener(someElement, 'swipe', someListener);
|
|
|
|
expect(fakeHammerInstance.on).not.toHaveBeenCalled();
|
|
|
|
|
|
|
|
(window as any).Hammer = {};
|
|
|
|
resolveLoader();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
expect(fakeHammerInstance.on).toHaveBeenCalledWith('swipe', jasmine.any(Function));
|
|
|
|
}));
|
|
|
|
|
|
|
|
it('should cancel registration if an event is removed before being added', fakeAsync(() => {
|
|
|
|
const deregister = plugin.addEventListener(someElement, 'swipe', someListener);
|
|
|
|
deregister();
|
|
|
|
|
|
|
|
(window as any).Hammer = {};
|
|
|
|
resolveLoader();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
expect(fakeHammerInstance.on).not.toHaveBeenCalled();
|
|
|
|
}));
|
|
|
|
|
|
|
|
it('should remove a listener after Hammer is loaded', fakeAsync(() => {
|
|
|
|
const removeListener = plugin.addEventListener(someElement, 'swipe', someListener);
|
|
|
|
|
|
|
|
(window as any).Hammer = {};
|
|
|
|
resolveLoader();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
removeListener();
|
|
|
|
expect(fakeHammerInstance.off).toHaveBeenCalledWith('swipe', jasmine.any(Function));
|
|
|
|
}));
|
|
|
|
|
|
|
|
it('should log a warning when the loader fails', fakeAsync(() => {
|
|
|
|
plugin.addEventListener(someElement, 'swipe', () => {});
|
|
|
|
failLoader();
|
|
|
|
tick();
|
|
|
|
|
|
|
|
expect(fakeConsole.warn)
|
|
|
|
.toHaveBeenCalledWith(
|
|
|
|
`The "swipe" event cannot be bound because the custom Hammer.JS loader failed.`);
|
|
|
|
}));
|
|
|
|
|
|
|
|
it('should load a warning if the loader resolves and Hammer is not present', fakeAsync(() => {
|
|
|
|
plugin.addEventListener(someElement, 'swipe', () => {});
|
|
|
|
resolveLoader();
|
|
|
|
tick();
|
2018-02-17 08:00:05 -05:00
|
|
|
|
2018-05-14 21:39:15 -04:00
|
|
|
expect(fakeConsole.warn)
|
|
|
|
.toHaveBeenCalledWith(
|
|
|
|
`The custom HAMMER_LOADER completed, but Hammer.JS is not present.`);
|
|
|
|
}));
|
2018-02-17 08:00:05 -05:00
|
|
|
});
|
2016-11-10 17:46:23 -05:00
|
|
|
});
|
|
|
|
}
|