|
5 | 5 | * Use of this source code is governed by an MIT-style license that can be
|
6 | 6 | * found in the LICENSE file at https://angular.io/license
|
7 | 7 | */
|
8 |
| -import {describe, expect, it} from '@angular/core/testing/src/testing_internal'; |
9 |
| -import {HammerGestureConfig, HammerGesturesPlugin} from '@angular/platform-browser/src/dom/events/hammer_gestures'; |
| 8 | +import {NgZone} from '@angular/core'; |
| 9 | +import {fakeAsync, inject, tick} from '@angular/core/testing'; |
| 10 | +import {afterEach, beforeEach, describe, expect, it,} from '@angular/core/testing/src/testing_internal'; |
| 11 | +import {EventManager} from '@angular/platform-browser'; |
| 12 | +import {HammerGestureConfig, HammerGesturesPlugin,} from '@angular/platform-browser/src/dom/events/hammer_gestures'; |
10 | 13 |
|
11 | 14 | {
|
12 | 15 | describe('HammerGesturesPlugin', () => {
|
13 | 16 | let plugin: HammerGesturesPlugin;
|
14 |
| - let mockConsole: any; |
| 17 | + let fakeConsole: any; |
15 | 18 | if (isNode) return;
|
16 | 19 |
|
17 |
| - beforeEach(() => { |
18 |
| - mockConsole = {warn: () => {}}; |
19 |
| - plugin = new HammerGesturesPlugin(document, new HammerGestureConfig(), mockConsole); |
20 |
| - }); |
| 20 | + beforeEach(() => { fakeConsole = {warn: jasmine.createSpy('console.warn')}; }); |
| 21 | + |
| 22 | + describe('with no custom loader', () => { |
| 23 | + beforeEach(() => { |
| 24 | + plugin = new HammerGesturesPlugin(document, new HammerGestureConfig(), fakeConsole); |
| 25 | + }); |
21 | 26 |
|
22 |
| - it('should implement addGlobalEventListener', () => { |
23 |
| - spyOn(plugin, 'addEventListener').and.callFake(() => {}); |
| 27 | + it('should implement addGlobalEventListener', () => { |
| 28 | + spyOn(plugin, 'addEventListener').and.callFake(() => {}); |
24 | 29 |
|
25 |
| - expect(() => plugin.addGlobalEventListener('document', 'swipe', () => {})).not.toThrowError(); |
| 30 | + expect(() => { |
| 31 | + plugin.addGlobalEventListener('document', 'swipe', () => {}); |
| 32 | + }).not.toThrowError(); |
| 33 | + }); |
| 34 | + |
| 35 | + it('should warn user and do nothing when Hammer.js not loaded', () => { |
| 36 | + expect(plugin.supports('swipe')).toBe(false); |
| 37 | + expect(fakeConsole.warn) |
| 38 | + .toHaveBeenCalledWith( |
| 39 | + `The "swipe" event cannot be bound because Hammer.JS is not ` + |
| 40 | + `loaded and no custom loader has been specified.`); |
| 41 | + }); |
26 | 42 | });
|
27 | 43 |
|
28 |
| - it('should warn user and do nothing when Hammer.js not loaeded', () => { |
29 |
| - spyOn(mockConsole, 'warn'); |
| 44 | + describe('with a custom loader', () => { |
| 45 | + // Use a fake custom loader for tests, with helper functions to resolve or reject. |
| 46 | + let loader: () => Promise<void>; |
| 47 | + let resolveLoader: () => void; |
| 48 | + let failLoader: () => void; |
| 49 | + |
| 50 | + // Arbitrary element and listener for testing. |
| 51 | + let someElement: HTMLDivElement; |
| 52 | + let someListener: () => void; |
| 53 | + |
| 54 | + // Keep track of whatever value is in `window.Hammer` before the test so it can be |
| 55 | + // restored afterwards so that this test doesn't care whether Hammer is actually loaded. |
| 56 | + let originalHammerGlobal: any; |
| 57 | + |
| 58 | + // Fake Hammer instance ("mc") used to test the underlying event registration. |
| 59 | + let fakeHammerInstance: {on: () => void, off: () => void}; |
| 60 | + |
| 61 | + // Inject the NgZone so that we can make it available to the plugin through a fake |
| 62 | + // EventManager. |
| 63 | + let ngZone: NgZone; |
| 64 | + beforeEach(inject([NgZone], (z: NgZone) => { ngZone = z; })); |
| 65 | + |
| 66 | + beforeEach(() => { |
| 67 | + originalHammerGlobal = (window as any).Hammer; |
| 68 | + (window as any).Hammer = undefined; |
| 69 | + |
| 70 | + fakeHammerInstance = { |
| 71 | + on: jasmine.createSpy('mc.on'), |
| 72 | + off: jasmine.createSpy('mc.off'), |
| 73 | + }; |
| 74 | + |
| 75 | + loader = () => new Promise((resolve, reject) => { |
| 76 | + resolveLoader = resolve; |
| 77 | + failLoader = reject; |
| 78 | + }); |
| 79 | + |
| 80 | + // Make the hammer config return a fake hammer instance |
| 81 | + const hammerConfig = new HammerGestureConfig(); |
| 82 | + spyOn(hammerConfig, 'buildHammer').and.returnValue(fakeHammerInstance); |
| 83 | + |
| 84 | + plugin = new HammerGesturesPlugin(document, hammerConfig, fakeConsole, loader); |
| 85 | + |
| 86 | + // Use a fake EventManager that has access to the NgZone. |
| 87 | + plugin.manager = { getZone: () => ngZone } as EventManager; |
| 88 | + |
| 89 | + someElement = document.createElement('div'); |
| 90 | + someListener = () => {}; |
| 91 | + }); |
| 92 | + |
| 93 | + afterEach(() => { (window as any).Hammer = originalHammerGlobal; }); |
| 94 | + |
| 95 | + it('should not log a warning when HammerJS is not loaded', () => { |
| 96 | + plugin.addEventListener(someElement, 'swipe', () => {}); |
| 97 | + expect(fakeConsole.warn).not.toHaveBeenCalled(); |
| 98 | + }); |
| 99 | + |
| 100 | + it('should defer registering an event until Hammer is loaded', fakeAsync(() => { |
| 101 | + plugin.addEventListener(someElement, 'swipe', someListener); |
| 102 | + expect(fakeHammerInstance.on).not.toHaveBeenCalled(); |
| 103 | + |
| 104 | + (window as any).Hammer = {}; |
| 105 | + resolveLoader(); |
| 106 | + tick(); |
| 107 | + |
| 108 | + expect(fakeHammerInstance.on).toHaveBeenCalledWith('swipe', jasmine.any(Function)); |
| 109 | + })); |
| 110 | + |
| 111 | + it('should cancel registration if an event is removed before being added', fakeAsync(() => { |
| 112 | + const deregister = plugin.addEventListener(someElement, 'swipe', someListener); |
| 113 | + deregister(); |
| 114 | + |
| 115 | + (window as any).Hammer = {}; |
| 116 | + resolveLoader(); |
| 117 | + tick(); |
| 118 | + |
| 119 | + expect(fakeHammerInstance.on).not.toHaveBeenCalled(); |
| 120 | + })); |
| 121 | + |
| 122 | + it('should remove a listener after Hammer is loaded', fakeAsync(() => { |
| 123 | + const removeListener = plugin.addEventListener(someElement, 'swipe', someListener); |
| 124 | + |
| 125 | + (window as any).Hammer = {}; |
| 126 | + resolveLoader(); |
| 127 | + tick(); |
| 128 | + |
| 129 | + removeListener(); |
| 130 | + expect(fakeHammerInstance.off).toHaveBeenCalledWith('swipe', jasmine.any(Function)); |
| 131 | + })); |
| 132 | + |
| 133 | + it('should log a warning when the loader fails', fakeAsync(() => { |
| 134 | + plugin.addEventListener(someElement, 'swipe', () => {}); |
| 135 | + failLoader(); |
| 136 | + tick(); |
| 137 | + |
| 138 | + expect(fakeConsole.warn) |
| 139 | + .toHaveBeenCalledWith( |
| 140 | + `The "swipe" event cannot be bound because the custom Hammer.JS loader failed.`); |
| 141 | + })); |
| 142 | + |
| 143 | + it('should load a warning if the loader resolves and Hammer is not present', fakeAsync(() => { |
| 144 | + plugin.addEventListener(someElement, 'swipe', () => {}); |
| 145 | + resolveLoader(); |
| 146 | + tick(); |
30 | 147 |
|
31 |
| - expect(plugin.supports('swipe')).toBe(false); |
32 |
| - expect(mockConsole.warn) |
33 |
| - .toHaveBeenCalledWith(`Hammer.js is not loaded, can not bind 'swipe' event.`); |
| 148 | + expect(fakeConsole.warn) |
| 149 | + .toHaveBeenCalledWith( |
| 150 | + `The custom HAMMER_LOADER completed, but Hammer.JS is not present.`); |
| 151 | + })); |
34 | 152 | });
|
35 | 153 | });
|
36 | 154 | }
|
0 commit comments