in src/cdk/testing/testbed/fake-events/type-in-element.ts [60:116]
export function typeInElement(element: HTMLElement, ...modifiersAndKeys: any) {
const first = modifiersAndKeys[0];
let modifiers: ModifierKeys;
let rest: (string | {keyCode?: number; key?: string})[];
if (typeof first !== 'string' && first.keyCode === undefined && first.key === undefined) {
modifiers = first;
rest = modifiersAndKeys.slice(1);
} else {
modifiers = {};
rest = modifiersAndKeys;
}
const isInput = isTextInput(element);
const inputType = element.getAttribute('type') || 'text';
const keys: {keyCode?: number; key?: string}[] = rest
.map(k =>
typeof k === 'string'
? k.split('').map(c => ({keyCode: c.toUpperCase().charCodeAt(0), key: c}))
: [k],
)
.reduce((arr, k) => arr.concat(k), []);
// We simulate the user typing in a value by incrementally assigning the value below. The problem
// is that for some input types, the browser won't allow for an invalid value to be set via the
// `value` property which will always be the case when going character-by-character. If we detect
// such an input, we have to set the value all at once or listeners to the `input` event (e.g.
// the `ReactiveFormsModule` uses such an approach) won't receive the correct value.
const enterValueIncrementally =
inputType === 'number' && keys.length > 0
? // The value can be set character by character in number inputs if it doesn't have any decimals.
keys.every(key => key.key !== '.' && key.keyCode !== PERIOD)
: incrementalInputTypes.has(inputType);
triggerFocus(element);
// When we aren't entering the value incrementally, assign it all at once ahead
// of time so that any listeners to the key events below will have access to it.
if (!enterValueIncrementally) {
(element as HTMLInputElement).value = keys.reduce((value, key) => value + (key.key || ''), '');
}
for (const key of keys) {
dispatchKeyboardEvent(element, 'keydown', key.keyCode, key.key, modifiers);
dispatchKeyboardEvent(element, 'keypress', key.keyCode, key.key, modifiers);
if (isInput && key.key && key.key.length === 1) {
if (enterValueIncrementally) {
(element as HTMLInputElement | HTMLTextAreaElement).value += key.key;
dispatchFakeEvent(element, 'input');
}
}
dispatchKeyboardEvent(element, 'keyup', key.keyCode, key.key, modifiers);
}
// Since we weren't dispatching `input` events while sending the keys, we have to do it now.
if (!enterValueIncrementally) {
dispatchFakeEvent(element, 'input');
}
}