Skip to content

Commit 235120c

Browse files
committed
feat: add testing utilities for components
* Moves existing testing helpers to a testing folder in the core package. * The testing utilities currently consist of functions to create dom events and shorthands to dispatch them. * Also fixes that **releases** include components `spec.d.ts` files. The `core/testing` utilities are not includes in releases for now. It could be possible to expose them as part of the Component Toolkit. Closes #2902
1 parent 4b830d3 commit 235120c

File tree

14 files changed

+180
-260
lines changed

14 files changed

+180
-260
lines changed

src/lib/autocomplete/autocomplete.spec.ts

+26-41
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
1313
import {FakeViewportRuler} from '../core/overlay/position/fake-viewport-ruler';
1414
import {MdAutocomplete} from './autocomplete';
1515
import {MdInputContainer} from '../input/input-container';
16+
import {dispatchFakeEvent} from '../core/testing/dispatch-events';
1617

1718
describe('MdAutocomplete', () => {
1819
let overlayContainerElement: HTMLElement;
@@ -61,7 +62,7 @@ describe('MdAutocomplete', () => {
6162
expect(fixture.componentInstance.trigger.panelOpen)
6263
.toBe(false, `Expected panel state to start out closed.`);
6364

64-
dispatchEvent('focus', input);
65+
dispatchFakeEvent(input, 'focus');
6566
fixture.detectChanges();
6667

6768
expect(fixture.componentInstance.trigger.panelOpen)
@@ -88,11 +89,11 @@ describe('MdAutocomplete', () => {
8889
});
8990

9091
it('should close the panel when blurred', async(() => {
91-
dispatchEvent('focus', input);
92+
dispatchFakeEvent(input, 'focus');
9293
fixture.detectChanges();
9394

9495
fixture.whenStable().then(() => {
95-
dispatchEvent('blur', input);
96+
dispatchFakeEvent(input, 'blur');
9697
fixture.detectChanges();
9798

9899
expect(fixture.componentInstance.trigger.panelOpen)
@@ -103,7 +104,7 @@ describe('MdAutocomplete', () => {
103104
}));
104105

105106
it('should close the panel when an option is clicked', async(() => {
106-
dispatchEvent('focus', input);
107+
dispatchFakeEvent(input, 'focus');
107108
fixture.detectChanges();
108109

109110
fixture.whenStable().then(() => {
@@ -119,13 +120,13 @@ describe('MdAutocomplete', () => {
119120
}));
120121

121122
it('should close the panel when a newly created option is clicked', async(() => {
122-
dispatchEvent('focus', input);
123+
dispatchFakeEvent(input, 'focus');
123124
fixture.detectChanges();
124125

125126
fixture.whenStable().then(() => {
126127
// Filter down the option list to a subset of original options ('Alabama', 'California')
127128
input.value = 'al';
128-
dispatchEvent('input', input);
129+
dispatchFakeEvent(input, 'input');
129130
fixture.detectChanges();
130131

131132
let options =
@@ -135,7 +136,7 @@ describe('MdAutocomplete', () => {
135136
// Changing value from 'Alabama' to 'al' to re-populate the option list,
136137
// ensuring that 'California' is created new.
137138
input.value = 'al';
138-
dispatchEvent('input', input);
139+
dispatchFakeEvent(input, 'input');
139140
fixture.detectChanges();
140141

141142
fixture.whenStable().then(() => {
@@ -166,13 +167,13 @@ describe('MdAutocomplete', () => {
166167
});
167168

168169
it('should close the panel when the options list is empty', async(() => {
169-
dispatchEvent('focus', input);
170+
dispatchFakeEvent(input, 'focus');
170171
fixture.detectChanges();
171172

172173
fixture.whenStable().then(() => {
173174
// Filter down the option list such that no options match the value
174175
input.value = 'af';
175-
dispatchEvent('input', input);
176+
dispatchFakeEvent(input, 'input');
176177
fixture.detectChanges();
177178

178179
expect(fixture.componentInstance.trigger.panelOpen)
@@ -232,14 +233,14 @@ describe('MdAutocomplete', () => {
232233
fixture.detectChanges();
233234

234235
input.value = 'a';
235-
dispatchEvent('input', input);
236+
dispatchFakeEvent(input, 'input');
236237
fixture.detectChanges();
237238

238239
expect(fixture.componentInstance.stateCtrl.value)
239240
.toEqual('a', 'Expected control value to be updated as user types.');
240241

241242
input.value = 'al';
242-
dispatchEvent('input', input);
243+
dispatchFakeEvent(input, 'input');
243244
fixture.detectChanges();
244245

245246
expect(fixture.componentInstance.stateCtrl.value)
@@ -273,7 +274,7 @@ describe('MdAutocomplete', () => {
273274
fixture.detectChanges();
274275

275276
input.value = 'Californi';
276-
dispatchEvent('input', input);
277+
dispatchFakeEvent(input, 'input');
277278
fixture.detectChanges();
278279

279280
expect(fixture.componentInstance.stateCtrl.value)
@@ -330,7 +331,7 @@ describe('MdAutocomplete', () => {
330331

331332
it('should clear the text field if value is reset programmatically', async(() => {
332333
input.value = 'Alabama';
333-
dispatchEvent('input', input);
334+
dispatchFakeEvent(input, 'input');
334335
fixture.detectChanges();
335336

336337
fixture.whenStable().then(() => {
@@ -367,7 +368,7 @@ describe('MdAutocomplete', () => {
367368
.toBe(false, `Expected control to start out pristine.`);
368369

369370
input.value = 'a';
370-
dispatchEvent('input', input);
371+
dispatchFakeEvent(input, 'input');
371372
fixture.detectChanges();
372373

373374
expect(fixture.componentInstance.stateCtrl.dirty)
@@ -409,7 +410,7 @@ describe('MdAutocomplete', () => {
409410
expect(fixture.componentInstance.stateCtrl.touched)
410411
.toBe(false, `Expected control to start out untouched.`);
411412

412-
dispatchEvent('blur', input);
413+
dispatchFakeEvent(input, 'blur');
413414
fixture.detectChanges();
414415

415416
expect(fixture.componentInstance.stateCtrl.touched)
@@ -429,8 +430,8 @@ describe('MdAutocomplete', () => {
429430
fixture.detectChanges();
430431

431432
input = fixture.debugElement.query(By.css('input')).nativeElement;
432-
DOWN_ARROW_EVENT = new FakeKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
433-
ENTER_EVENT = new FakeKeyboardEvent(ENTER) as KeyboardEvent;
433+
DOWN_ARROW_EVENT = new MockKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
434+
ENTER_EVENT = new MockKeyboardEvent(ENTER) as KeyboardEvent;
434435

435436
fixture.componentInstance.trigger.openPanel();
436437
fixture.detectChanges();
@@ -491,7 +492,7 @@ describe('MdAutocomplete', () => {
491492
const optionEls =
492493
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
493494

494-
const UP_ARROW_EVENT = new FakeKeyboardEvent(UP_ARROW) as KeyboardEvent;
495+
const UP_ARROW_EVENT = new MockKeyboardEvent(UP_ARROW) as KeyboardEvent;
495496
fixture.componentInstance.trigger._handleKeydown(UP_ARROW_EVENT);
496497

497498
fixture.whenStable().then(() => {
@@ -522,7 +523,7 @@ describe('MdAutocomplete', () => {
522523

523524
fixture.whenStable().then(() => {
524525
input.value = 'o';
525-
dispatchEvent('input', input);
526+
dispatchFakeEvent(input, 'input');
526527
fixture.detectChanges();
527528

528529
fixture.componentInstance.trigger._handleKeydown(DOWN_ARROW_EVENT);
@@ -556,10 +557,10 @@ describe('MdAutocomplete', () => {
556557
it('should fill the text field, not select an option, when SPACE is entered', async(() => {
557558
fixture.whenStable().then(() => {
558559
input.value = 'New';
559-
dispatchEvent('input', input);
560+
dispatchFakeEvent(input, 'input');
560561
fixture.detectChanges();
561562

562-
const SPACE_EVENT = new FakeKeyboardEvent(SPACE) as KeyboardEvent;
563+
const SPACE_EVENT = new MockKeyboardEvent(SPACE) as KeyboardEvent;
563564
fixture.componentInstance.trigger._handleKeydown(DOWN_ARROW_EVENT);
564565
fixture.componentInstance.trigger._handleKeydown(SPACE_EVENT);
565566
fixture.detectChanges();
@@ -595,7 +596,7 @@ describe('MdAutocomplete', () => {
595596
.toEqual('', `Expected panel to close after ENTER key.`);
596597

597598
input.value = 'Alabam';
598-
dispatchEvent('input', input);
599+
dispatchFakeEvent(input, 'input');
599600
fixture.detectChanges();
600601

601602
expect(fixture.componentInstance.trigger.panelOpen)
@@ -669,7 +670,7 @@ describe('MdAutocomplete', () => {
669670
expect(input.hasAttribute('aria-activedescendant'))
670671
.toBe(false, 'Expected aria-activedescendant to be absent if no active item.');
671672

672-
const DOWN_ARROW_EVENT = new FakeKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
673+
const DOWN_ARROW_EVENT = new MockKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
673674
fixture.componentInstance.trigger._handleKeydown(DOWN_ARROW_EVENT);
674675
fixture.detectChanges();
675676

@@ -773,7 +774,7 @@ describe('MdAutocomplete', () => {
773774

774775
fixture.whenStable().then(() => {
775776
input.value = 'f';
776-
dispatchEvent('input', input);
777+
dispatchFakeEvent(input, 'input');
777778
fixture.detectChanges();
778779

779780
const inputTop = input.getBoundingClientRect().top;
@@ -848,24 +849,8 @@ class SimpleAutocomplete implements OnDestroy {
848849

849850
}
850851

851-
852-
853-
/**
854-
* TODO: Move this to core testing utility until Angular has event faking
855-
* support.
856-
*
857-
* Dispatches an event from an element.
858-
* @param eventName Name of the event
859-
* @param element The element from which the event will be dispatched.
860-
*/
861-
function dispatchEvent(eventName: string, element: HTMLElement): void {
862-
let event = document.createEvent('Event');
863-
event.initEvent(eventName, true, true);
864-
element.dispatchEvent(event);
865-
}
866-
867852
/** This is a mock keyboard event to test keyboard events in the autocomplete. */
868-
class FakeKeyboardEvent {
853+
class MockKeyboardEvent {
869854
constructor(public keyCode: number) {}
870855
preventDefault() {}
871856
}

src/lib/core/overlay/scroll/scroll-dispatcher.spec.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {NgModule, Component, ViewChild, ElementRef, QueryList, ViewChildren} fro
33
import {ScrollDispatcher} from './scroll-dispatcher';
44
import {OverlayModule} from '../overlay-directives';
55
import {Scrollable} from './scrollable';
6+
import {dispatchFakeEvent} from '../../testing/dispatch-events';
67

78
describe('Scroll Dispatcher', () => {
89

@@ -51,9 +52,7 @@ describe('Scroll Dispatcher', () => {
5152
// Emit a scroll event from the scrolling element in our component.
5253
// This event should be picked up by the scrollable directive and notify.
5354
// The notification should be picked up by the service.
54-
const scrollEvent = document.createEvent('UIEvents');
55-
scrollEvent.initUIEvent('scroll', true, true, window, 0);
56-
fixture.componentInstance.scrollingElement.nativeElement.dispatchEvent(scrollEvent);
55+
dispatchFakeEvent(fixture.componentInstance.scrollingElement.nativeElement, 'scroll');
5756

5857
expect(hasDirectiveScrollNotified).toBe(true);
5958
expect(hasServiceScrollNotified).toBe(true);

0 commit comments

Comments
 (0)