Skip to content

Commit

Permalink
feat: add testing utilities for components
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
devversion committed Feb 5, 2017
1 parent 8d900e0 commit 3520f25
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 260 deletions.
67 changes: 26 additions & 41 deletions src/lib/autocomplete/autocomplete.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
import {FakeViewportRuler} from '../core/overlay/position/fake-viewport-ruler';
import {MdAutocomplete} from './autocomplete';
import {MdInputContainer} from '../input/input-container';
import {dispatchFakeEvent} from '../core/testing/dispatch-events';

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

dispatchEvent('focus', input);
dispatchFakeEvent(input, 'focus');
fixture.detectChanges();

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

it('should close the panel when blurred', async(() => {
dispatchEvent('focus', input);
dispatchFakeEvent(input, 'focus');
fixture.detectChanges();

fixture.whenStable().then(() => {
dispatchEvent('blur', input);
dispatchFakeEvent(input, 'blur');
fixture.detectChanges();

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

it('should close the panel when an option is clicked', async(() => {
dispatchEvent('focus', input);
dispatchFakeEvent(input, 'focus');
fixture.detectChanges();

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

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

fixture.whenStable().then(() => {
// Filter down the option list to a subset of original options ('Alabama', 'California')
input.value = 'al';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

fixture.whenStable().then(() => {
Expand Down Expand Up @@ -166,13 +167,13 @@ describe('MdAutocomplete', () => {
});

it('should close the panel when the options list is empty', async(() => {
dispatchEvent('focus', input);
dispatchFakeEvent(input, 'focus');
fixture.detectChanges();

fixture.whenStable().then(() => {
// Filter down the option list such that no options match the value
input.value = 'af';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

expect(fixture.componentInstance.trigger.panelOpen)
Expand Down Expand Up @@ -232,14 +233,14 @@ describe('MdAutocomplete', () => {
fixture.detectChanges();

input.value = 'a';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

input.value = 'al';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

expect(fixture.componentInstance.stateCtrl.value)
Expand Down Expand Up @@ -273,7 +274,7 @@ describe('MdAutocomplete', () => {
fixture.detectChanges();

input.value = 'Californi';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

it('should clear the text field if value is reset programmatically', async(() => {
input.value = 'Alabama';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

input.value = 'a';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

dispatchEvent('blur', input);
dispatchFakeEvent(input, 'blur');
fixture.detectChanges();

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

input = fixture.debugElement.query(By.css('input')).nativeElement;
DOWN_ARROW_EVENT = new FakeKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
ENTER_EVENT = new FakeKeyboardEvent(ENTER) as KeyboardEvent;
DOWN_ARROW_EVENT = new MockKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
ENTER_EVENT = new MockKeyboardEvent(ENTER) as KeyboardEvent;

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

const UP_ARROW_EVENT = new FakeKeyboardEvent(UP_ARROW) as KeyboardEvent;
const UP_ARROW_EVENT = new MockKeyboardEvent(UP_ARROW) as KeyboardEvent;
fixture.componentInstance.trigger._handleKeydown(UP_ARROW_EVENT);

fixture.whenStable().then(() => {
Expand Down Expand Up @@ -522,7 +523,7 @@ describe('MdAutocomplete', () => {

fixture.whenStable().then(() => {
input.value = 'o';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

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

input.value = 'Alabam';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

const DOWN_ARROW_EVENT = new FakeKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
const DOWN_ARROW_EVENT = new MockKeyboardEvent(DOWN_ARROW) as KeyboardEvent;
fixture.componentInstance.trigger._handleKeydown(DOWN_ARROW_EVENT);
fixture.detectChanges();

Expand Down Expand Up @@ -773,7 +774,7 @@ describe('MdAutocomplete', () => {

fixture.whenStable().then(() => {
input.value = 'f';
dispatchEvent('input', input);
dispatchFakeEvent(input, 'input');
fixture.detectChanges();

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

}



/**
* TODO: Move this to core testing utility until Angular has event faking
* support.
*
* Dispatches an event from an element.
* @param eventName Name of the event
* @param element The element from which the event will be dispatched.
*/
function dispatchEvent(eventName: string, element: HTMLElement): void {
let event = document.createEvent('Event');
event.initEvent(eventName, true, true);
element.dispatchEvent(event);
}

/** This is a mock keyboard event to test keyboard events in the autocomplete. */
class FakeKeyboardEvent {
class MockKeyboardEvent {
constructor(public keyCode: number) {}
preventDefault() {}
}
5 changes: 2 additions & 3 deletions src/lib/core/overlay/scroll/scroll-dispatcher.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {NgModule, Component, ViewChild, ElementRef, QueryList, ViewChildren} fro
import {ScrollDispatcher} from './scroll-dispatcher';
import {OverlayModule} from '../overlay-directives';
import {Scrollable} from './scrollable';
import {dispatchFakeEvent} from '../../testing/dispatch-events';

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

Expand Down Expand Up @@ -51,9 +52,7 @@ describe('Scroll Dispatcher', () => {
// 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);
fixture.componentInstance.scrollingElement.nativeElement.dispatchEvent(scrollEvent);
dispatchFakeEvent(fixture.componentInstance.scrollingElement.nativeElement, 'scroll');

expect(hasDirectiveScrollNotified).toBe(true);
expect(hasServiceScrollNotified).toBe(true);
Expand Down
Loading

0 comments on commit 3520f25

Please sign in to comment.