From 13a2e70950d544369d96cd15da6529492125449e Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Sat, 18 Feb 2017 12:46:21 +0100 Subject: [PATCH] Provide consistent testing API --- src/lib/core/ripple/ripple.spec.ts | 42 +++---------------- .../core/style/focus-origin-monitor.spec.ts | 6 +-- src/lib/core/testing/dispatch-events.ts | 6 +-- src/lib/core/testing/event-objects.ts | 8 ++-- src/lib/dialog/dialog.spec.ts | 17 ++------ src/lib/slider/slider.spec.ts | 30 ++++++------- src/lib/tabs/tab-header.spec.ts | 8 ++-- src/lib/tooltip/tooltip.spec.ts | 5 +-- 8 files changed, 41 insertions(+), 81 deletions(-) diff --git a/src/lib/core/ripple/ripple.spec.ts b/src/lib/core/ripple/ripple.spec.ts index 51937ec3cf0e..b6b7ebe3992c 100644 --- a/src/lib/core/ripple/ripple.spec.ts +++ b/src/lib/core/ripple/ripple.spec.ts @@ -5,33 +5,6 @@ import {ViewportRuler} from '../overlay/position/viewport-ruler'; import {RIPPLE_FADE_OUT_DURATION, RIPPLE_FADE_IN_DURATION} from './ripple-renderer'; import {dispatchMouseEvent} from '../testing/dispatch-events'; - -/** Creates a DOM mouse event. */ -const createMouseEvent = (eventType: string, dict: any = {}) => { - // Ideally this would just be "return new MouseEvent(eventType, dict)". But IE11 doesn't support - // the MouseEvent constructor, and Edge inexplicably divides clientX and clientY by 100 to get - // pageX and pageY. (Really. After "e = new MouseEvent('click', {clientX: 200, clientY: 300})", - // e.clientX is 200, e.pageX is 2, e.clientY is 300, and e.pageY is 3.) - // So instead we use the deprecated createEvent/initMouseEvent API, which works everywhere. - const event = document.createEvent('MouseEvents'); - event.initMouseEvent(eventType, - false, /* canBubble */ - false, /* cancelable */ - window, /* view */ - 0, /* detail */ - dict.screenX || 0, - dict.screenY || 0, - dict.clientX || 0, - dict.clientY || 0, - false, /* ctrlKey */ - false, /* altKey */ - false, /* shiftKey */ - false, /* metaKey */ - 0, /* button */ - null /* relatedTarget */); - return event; -}; - /** Extracts the numeric value of a pixel size string like '123px'. */ const pxStringToFloat = (s: string) => { return parseFloat(s.replace('px', '')); @@ -160,8 +133,8 @@ describe('MdRipple', () => { const spy = jasmine.createSpy('zone unstable callback'); const subscription = fixture.ngZone.onUnstable.subscribe(spy); - dispatchMouseEvent('mousedown'); - dispatchMouseEvent('mouseup'); + dispatchMouseEvent(rippleTarget, 'mousedown'); + dispatchMouseEvent(rippleTarget, 'mouseup'); expect(spy).not.toHaveBeenCalled(); subscription.unsubscribe(); @@ -298,11 +271,8 @@ describe('MdRipple', () => { let alternateTrigger = fixture.debugElement.nativeElement .querySelector('.alternateTrigger') as HTMLElement; - let mousedownEvent = createMouseEvent('mousedown'); - let mouseupEvent = createMouseEvent('mouseup'); - - alternateTrigger.dispatchEvent(mousedownEvent); - alternateTrigger.dispatchEvent(mouseupEvent); + dispatchMouseEvent(alternateTrigger, 'mousedown'); + dispatchMouseEvent(alternateTrigger, 'mouseup'); expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0); @@ -310,8 +280,8 @@ describe('MdRipple', () => { controller.trigger = alternateTrigger; fixture.detectChanges(); - alternateTrigger.dispatchEvent(mousedownEvent); - alternateTrigger.dispatchEvent(mouseupEvent); + dispatchMouseEvent(alternateTrigger, 'mousedown'); + dispatchMouseEvent(alternateTrigger, 'mouseup'); expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(1); }); diff --git a/src/lib/core/style/focus-origin-monitor.spec.ts b/src/lib/core/style/focus-origin-monitor.spec.ts index 4b0e3a7d6d94..7f17f3ea7cb6 100644 --- a/src/lib/core/style/focus-origin-monitor.spec.ts +++ b/src/lib/core/style/focus-origin-monitor.spec.ts @@ -57,7 +57,7 @@ describe('FocusOriginMonitor', () => { it('should detect focus via keyboard', async(() => { // Simulate focus via keyboard. - dispatchKeyboardEvent(document, TAB); + dispatchKeyboardEvent(document, 'keydown', TAB); buttonElement.focus(); fixture.detectChanges(); @@ -95,7 +95,7 @@ describe('FocusOriginMonitor', () => { it('should detect focus via touch', async(() => { // Simulate focus via touch. - dispatchTouchstartEvent(buttonElement); + dispatchMouseEvent(buttonElement, 'touchstart'); buttonElement.focus(); fixture.detectChanges(); @@ -272,7 +272,7 @@ describe('cdkMonitorFocus', () => { it('should detect focus via keyboard', async(() => { // Simulate focus via keyboard. - dispatchKeyboardEvent(document, TAB, 'keydown'); + dispatchKeyboardEvent(document, 'keydown', TAB); buttonElement.focus(); fixture.detectChanges(); diff --git a/src/lib/core/testing/dispatch-events.ts b/src/lib/core/testing/dispatch-events.ts index 78c973870155..3552301e0754 100644 --- a/src/lib/core/testing/dispatch-events.ts +++ b/src/lib/core/testing/dispatch-events.ts @@ -6,12 +6,12 @@ import { } from './event-objects'; /** Shorthand to dispatch a fake event on a specified node. */ -export function dispatchFakeEvent(node: Node, eventName: string) { - node.dispatchEvent(createFakeEvent(eventName)); +export function dispatchFakeEvent(node: Node, type: string) { + node.dispatchEvent(createFakeEvent(type)); } /** Shorthand to dispatch a keyboard event with a specified key code. */ -export function dispatchKeyboardEvent(node: Node, keyCode: number, type = 'keydown') { +export function dispatchKeyboardEvent(node: Node, type: string, keyCode: number) { node.dispatchEvent(createKeyboardEvent(type, keyCode)); } diff --git a/src/lib/core/testing/event-objects.ts b/src/lib/core/testing/event-objects.ts index f07782dd6245..bc13c3408a9c 100644 --- a/src/lib/core/testing/event-objects.ts +++ b/src/lib/core/testing/event-objects.ts @@ -22,12 +22,12 @@ export function createMouseEvent(type: string, x = 0, y = 0) { } /** Dispatches a keydown event from an element. */ -export function createKeyboardEvent(eventType: string, keyCode: number) { +export function createKeyboardEvent(type: string, keyCode: number) { let event = document.createEvent('KeyboardEvent') as any; // Firefox does not support `initKeyboardEvent`, but supports `initKeyEvent`. let initEventFn = (event.initKeyEvent || event.initKeyboardEvent).bind(event); - initEventFn(eventType, true, true, window, 0, 0, 0, 0, 0, keyCode); + initEventFn(type, true, true, window, 0, 0, 0, 0, 0, keyCode); // Webkit Browsers don't set the keyCode when calling the init function. // See related bug https://bugs.webkit.org/show_bug.cgi?id=16735 @@ -55,8 +55,8 @@ export function createTransitionEndEvent(propertyName: string, elapsedTime = 0) } /** Creates a fake event object with any desired event type. */ -export function createFakeEvent(eventName: string) { +export function createFakeEvent(type: string) { let event = document.createEvent('Event'); - event.initEvent(eventName, true, true); + event.initEvent(type, true, true); return event; } diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts index dbb02ac81aed..a15e24cd4ccf 100644 --- a/src/lib/dialog/dialog.spec.ts +++ b/src/lib/dialog/dialog.spec.ts @@ -21,6 +21,7 @@ import {OverlayContainer} from '../core'; import {MdDialogRef} from './dialog-ref'; import {MD_DIALOG_DATA} from './dialog-injector'; import {ESCAPE} from '../core/keyboard/keycodes'; +import {dispatchKeyboardEvent} from '../core/testing/dispatch-events'; describe('MdDialog', () => { @@ -135,7 +136,7 @@ describe('MdDialog', () => { viewContainerFixture.detectChanges(); - dispatchKeydownEvent(document, ESCAPE); + dispatchKeyboardEvent(document, 'keydown', ESCAPE); expect(overlayContainerElement.querySelector('md-dialog-container')).toBeNull(); }); @@ -319,7 +320,7 @@ describe('MdDialog', () => { viewContainerFixture.detectChanges(); - dispatchKeydownEvent(document, ESCAPE); + dispatchKeyboardEvent(document, 'keydown', ESCAPE); expect(overlayContainerElement.querySelector('md-dialog-container')).toBeTruthy(); }); @@ -556,15 +557,3 @@ const TEST_DIRECTIVES = [ ], }) class DialogTestModule { } - - -// TODO(crisbeto): switch to using function from common testing utils once #2943 is merged. -function dispatchKeydownEvent(element: Node, keyCode: number) { - let event: any = document.createEvent('KeyboardEvent'); - (event.initKeyEvent || event.initKeyboardEvent).bind(event)( - 'keydown', true, true, window, 0, 0, 0, 0, 0, keyCode); - Object.defineProperty(event, 'keyCode', { - get: function() { return keyCode; } - }); - element.dispatchEvent(event); -} diff --git a/src/lib/slider/slider.spec.ts b/src/lib/slider/slider.spec.ts index 60e4d2b95ad4..e029442694db 100644 --- a/src/lib/slider/slider.spec.ts +++ b/src/lib/slider/slider.spec.ts @@ -729,7 +729,7 @@ describe('MdSlider', () => { it('should update the model on keydown', () => { expect(testComponent.val).toBe(0); - dispatchKeyboardEvent(sliderNativeElement, UP_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', UP_ARROW); fixture.detectChanges(); expect(testComponent.val).toBe(1); @@ -949,14 +949,14 @@ describe('MdSlider', () => { }); it('should increment slider by 1 on up arrow pressed', () => { - dispatchKeyboardEvent(sliderNativeElement, UP_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', UP_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(1); }); it('should increment slider by 1 on right arrow pressed', () => { - dispatchKeyboardEvent(sliderNativeElement, RIGHT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', RIGHT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(1); @@ -965,7 +965,7 @@ describe('MdSlider', () => { it('should decrement slider by 1 on down arrow pressed', () => { sliderInstance.value = 100; - dispatchKeyboardEvent(sliderNativeElement, DOWN_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', DOWN_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(99); @@ -974,14 +974,14 @@ describe('MdSlider', () => { it('should decrement slider by 1 on left arrow pressed', () => { sliderInstance.value = 100; - dispatchKeyboardEvent(sliderNativeElement, LEFT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', LEFT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(99); }); it('should increment slider by 10 on page up pressed', () => { - dispatchKeyboardEvent(sliderNativeElement, PAGE_UP); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', PAGE_UP); fixture.detectChanges(); expect(sliderInstance.value).toBe(10); @@ -990,14 +990,14 @@ describe('MdSlider', () => { it('should decrement slider by 10 on page down pressed', () => { sliderInstance.value = 100; - dispatchKeyboardEvent(sliderNativeElement, PAGE_DOWN); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', PAGE_DOWN); fixture.detectChanges(); expect(sliderInstance.value).toBe(90); }); it('should set slider to max on end pressed', () => { - dispatchKeyboardEvent(sliderNativeElement, END); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', END); fixture.detectChanges(); expect(sliderInstance.value).toBe(100); @@ -1006,7 +1006,7 @@ describe('MdSlider', () => { it('should set slider to min on home pressed', () => { sliderInstance.value = 100; - dispatchKeyboardEvent(sliderNativeElement, HOME); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', HOME); fixture.detectChanges(); expect(sliderInstance.value).toBe(0); @@ -1067,7 +1067,7 @@ describe('MdSlider', () => { testComponent.invert = true; fixture.detectChanges(); - dispatchKeyboardEvent(sliderNativeElement, RIGHT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', RIGHT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(1); @@ -1078,7 +1078,7 @@ describe('MdSlider', () => { sliderInstance.value = 100; fixture.detectChanges(); - dispatchKeyboardEvent(sliderNativeElement, LEFT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', LEFT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(99); @@ -1089,7 +1089,7 @@ describe('MdSlider', () => { sliderInstance.value = 100; fixture.detectChanges(); - dispatchKeyboardEvent(sliderNativeElement, RIGHT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', RIGHT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(99); @@ -1099,7 +1099,7 @@ describe('MdSlider', () => { testComponent.dir = 'rtl'; fixture.detectChanges(); - dispatchKeyboardEvent(sliderNativeElement, LEFT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', LEFT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(1); @@ -1111,7 +1111,7 @@ describe('MdSlider', () => { sliderInstance.value = 100; fixture.detectChanges(); - dispatchKeyboardEvent(sliderNativeElement, RIGHT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', RIGHT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(99); @@ -1122,7 +1122,7 @@ describe('MdSlider', () => { testComponent.invert = true; fixture.detectChanges(); - dispatchKeyboardEvent(sliderNativeElement, LEFT_ARROW); + dispatchKeyboardEvent(sliderNativeElement, 'keydown', LEFT_ARROW); fixture.detectChanges(); expect(sliderInstance.value).toBe(1); diff --git a/src/lib/tabs/tab-header.spec.ts b/src/lib/tabs/tab-header.spec.ts index dc687f41f923..ef7bac7e39c4 100644 --- a/src/lib/tabs/tab-header.spec.ts +++ b/src/lib/tabs/tab-header.spec.ts @@ -106,19 +106,21 @@ describe('MdTabHeader', () => { fixture.detectChanges(); expect(appComponent.mdTabHeader.focusIndex).toBe(0); + let tabListContainer = appComponent.mdTabHeader._tabListContainer.nativeElement; + // Move focus right to 2 - dispatchKeyboardEvent(appComponent.mdTabHeader._tabListContainer.nativeElement, RIGHT_ARROW); + dispatchKeyboardEvent(tabListContainer, 'keydown', RIGHT_ARROW); fixture.detectChanges(); expect(appComponent.mdTabHeader.focusIndex).toBe(2); // Select the focused index 2 expect(appComponent.selectedIndex).toBe(0); - dispatchKeyboardEvent(appComponent.mdTabHeader._tabListContainer.nativeElement, ENTER); + dispatchKeyboardEvent(tabListContainer, 'keydown', ENTER); fixture.detectChanges(); expect(appComponent.selectedIndex).toBe(2); // Move focus right to 0 - dispatchKeyboardEvent(appComponent.mdTabHeader._tabListContainer.nativeElement, LEFT_ARROW); + dispatchKeyboardEvent(tabListContainer, 'keydown', LEFT_ARROW); fixture.detectChanges(); expect(appComponent.mdTabHeader.focusIndex).toBe(0); }); diff --git a/src/lib/tooltip/tooltip.spec.ts b/src/lib/tooltip/tooltip.spec.ts index 5873f340f0e6..268ef2e162e7 100644 --- a/src/lib/tooltip/tooltip.spec.ts +++ b/src/lib/tooltip/tooltip.spec.ts @@ -19,6 +19,7 @@ import {OverlayContainer} from '../core'; import {Dir, LayoutDirection} from '../core/rtl/dir'; import {OverlayModule} from '../core/overlay/overlay-directives'; import {Scrollable} from '../core/overlay/scroll/scrollable'; +import {dispatchFakeEvent} from '../core/testing/dispatch-events'; const initialTooltipMessage = 'initial tooltip message'; @@ -441,9 +442,7 @@ class ScrollableTooltipDemo { // Emit a scroll event from the scrolling element in our component. // This event should be picked up by the scrollable directive and notify. // The notification should be picked up by the service. - const scrollEvent = document.createEvent('UIEvents'); - scrollEvent.initUIEvent('scroll', true, true, window, 0); - scrollingContainerEl.dispatchEvent(scrollEvent); + dispatchFakeEvent(scrollingContainerEl, 'scroll'); } }