Skip to content

Commit

Permalink
Refactor triggerKeyEvent functionality into util function.
Browse files Browse the repository at this point in the history
Moves the bulk of the actual event firing logic of `triggerKeyEvent`
into a separate function that can be used by our other helper functions
(e.g. `typeIn`) without incorporating `await settled()` directly.

Does **not** change the fundamental mechanism that makes `typeIn` work,
but does ensure that we do not wait for all settledness checks to fire
before continueing to fire typing events.
  • Loading branch information
rwjblue committed Oct 25, 2019
1 parent 18d1ba0 commit 1c365f3
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 38 deletions.
78 changes: 44 additions & 34 deletions addon-test-support/@ember/test-helpers/dom/trigger-key-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { assign } from '@ember/polyfills';
import getElement from './-get-element';
import fireEvent from './fire-event';
import settled from '../settled';
import { resolve } from 'rsvp';
import { KEYBOARD_EVENT_TYPES, KeyboardEventType, isKeyboardEventType } from './fire-event';
import { nextTickPromise, isNumeric } from '../-utils';
import Target from './-target';
Expand Down Expand Up @@ -114,6 +113,47 @@ function keyCodeFromKey(key: string) {
return keyCode !== undefined ? parseInt(keyCode) : undefined;
}

/**
@private
@param {Element | Document} element the element to trigger the key event on
@param {'keydown' | 'keyup' | 'keypress'} eventType the type of event to trigger
@param {number|string} key the `keyCode`(number) or `key`(string) of the event being triggered
@param {Object} [modifiers] the state of various modifier keys
*/
export function __triggerKeyEvent__(
element: Element | Document,
eventType: KeyboardEventType,
key: number | string,
modifiers: KeyModifiers = DEFAULT_MODIFIERS
) {
let props;
if (typeof key === 'number') {
props = { keyCode: key, which: key, key: keyFromKeyCodeAndModifiers(key, modifiers) };
} else if (typeof key === 'string' && key.length !== 0) {
let firstCharacter = key[0];
if (firstCharacter !== firstCharacter.toUpperCase()) {
throw new Error(
`Must provide a \`key\` to \`triggerKeyEvent\` that starts with an uppercase character but you passed \`${key}\`.`
);
}

if (isNumeric(key) && key.length > 1) {
throw new Error(
`Must provide a numeric \`keyCode\` to \`triggerKeyEvent\` but you passed \`${key}\` as a string.`
);
}

let keyCode = keyCodeFromKey(key);
props = { keyCode, which: keyCode, key };
} else {
throw new Error(`Must provide a \`key\` or \`keyCode\` to \`triggerKeyEvent\``);
}

let options = assign(props, modifiers);

fireEvent(element, eventType, options);
}

/**
Triggers a keyboard event of given type in the target element.
It also requires the developer to provide either a string with the [`key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
Expand All @@ -129,7 +169,6 @@ function keyCodeFromKey(key: string) {
@param {boolean} [modifiers.altKey=false] if true the generated event will indicate the alt key was pressed during the key event
@param {boolean} [modifiers.shiftKey=false] if true the generated event will indicate the shift key was pressed during the key event
@param {boolean} [modifiers.metaKey=false] if true the generated event will indicate the meta key was pressed during the key event
@param {boolean} awaitSettled if true the event will wait for promises to settle by returning settled()
@return {Promise<void>} resolves when the application is settled unless awaitSettled is false
@example
Expand All @@ -142,8 +181,7 @@ export default function triggerKeyEvent(
target: Target,
eventType: KeyboardEventType,
key: number | string,
modifiers: KeyModifiers = DEFAULT_MODIFIERS,
awaitSettled: boolean = true
modifiers: KeyModifiers = DEFAULT_MODIFIERS
): Promise<void> {
return nextTickPromise().then(() => {
if (!target) {
Expand All @@ -166,36 +204,8 @@ export default function triggerKeyEvent(
);
}

let props;
if (typeof key === 'number') {
props = { keyCode: key, which: key, key: keyFromKeyCodeAndModifiers(key, modifiers) };
} else if (typeof key === 'string' && key.length !== 0) {
let firstCharacter = key[0];
if (firstCharacter !== firstCharacter.toUpperCase()) {
throw new Error(
`Must provide a \`key\` to \`triggerKeyEvent\` that starts with an uppercase character but you passed \`${key}\`.`
);
}

if (isNumeric(key) && key.length > 1) {
throw new Error(
`Must provide a numeric \`keyCode\` to \`triggerKeyEvent\` but you passed \`${key}\` as a string.`
);
}

let keyCode = keyCodeFromKey(key);
props = { keyCode, which: keyCode, key };
} else {
throw new Error(`Must provide a \`key\` or \`keyCode\` to \`triggerKeyEvent\``);
}

let options = assign(props, modifiers);
__triggerKeyEvent__(element, eventType, key, modifiers);

fireEvent(element, eventType, options);
if (awaitSettled) {
return settled();
} else {
return resolve();
}
return settled();
});
}
9 changes: 5 additions & 4 deletions addon-test-support/@ember/test-helpers/dom/type-in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import isFocusable from './-is-focusable';
import { Promise } from 'rsvp';
import fireEvent from './fire-event';
import Target from './-target';
import triggerKeyEvent from './trigger-key-event';
import { __triggerKeyEvent__ } from './trigger-key-event';

export interface Options {
delay?: number;
Expand Down Expand Up @@ -82,13 +82,14 @@ function keyEntry(element: FormControl, character: string): () => void {
let characterKey = character.toUpperCase();

return function() {
return triggerKeyEvent(element, 'keydown', characterKey, options, false)
.then(() => triggerKeyEvent(element, 'keypress', characterKey, options, false))
return nextTickPromise()
.then(() => __triggerKeyEvent__(element, 'keydown', characterKey, options))
.then(() => __triggerKeyEvent__(element, 'keypress', characterKey, options))
.then(() => {
element.value = element.value + character;
fireEvent(element, 'input');
})
.then(() => triggerKeyEvent(element, 'keyup', characterKey, options, false));
.then(() => __triggerKeyEvent__(element, 'keyup', characterKey, options));
};
}

Expand Down

0 comments on commit 1c365f3

Please sign in to comment.