/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ /** @class Siesta.Test.UserAgent.Keyboard This is a mixin, providing the keyboard events simulation functionality. */ Role('Siesta.Test.UserAgent.Keyboard', { requires : [ 'normalizeElement', 'runPromiseAsync', 'activeElement' ], does : [ Siesta.Util.Role.CanFormatStrings, Siesta.Test.Browser.Role.CanWorkWithKeyboard ], has : { }, methods: { /** * This method will simulate keyboard typing on either a provided DOM element, or, if omitted, on the currently focuced DOM element. * Simulation of certain special keys such as ENTER, ESC, LEFT etc is supported. * You can type these special keys by using the all uppercase name the key inside square brackets: `[ENTER]`, `[BACKSPACE]`. * See {@link Siesta.Test.UserAgent.KeyCodes} for a list of key names. * * For example: * t.type(el, 'Foo bar[ENTER]', function () { ... }) * * To type the `[ENTER]` as plain text and not as a special character - use double square brackets: `[[ENTER]]` * * To specify a control key like "shift/control/alt" of to be pressed during typing, use the `options` argument, for example: t.type(el, 'Foo bar[ENTER]', callback, scope, { shiftKey : true, ctrlKey : true, altKey : true }); * * This method returns a `Promise` which is resolved once the click has completed: * * t.type('#someEl', 'someText').then(function () { * return t.type('#anotherEl', 'someText') * }).then(function () { * return t.type('#yetAnotherEl', 'someText') * }) * * See also {@link Siesta.Test#chain chain} method for slimer chaining notation. * * @param {Siesta.Test.ActionTarget} el The element to type into. If not provided, currently focused element will be used as target. * @param {String} text The text to type, including any names of special keys in square brackets. * @param {Function} callback A function to be called after the type operation is completed. * @param {Object} scope The scope for the callback * @param {Object} options (optional) any extra options used to configure the DOM key events (like holding shiftKey, ctrlKey, altKey etc). * @param {Boolean} clearExisting (optional) true to clear existing text in the target before typing * * @return {Promise} Returns a promise resolved once the action has completed */ type : function (el, text, callback, scope, options, clearExisting, performTargetCheck) { if (text == null) throw 'Must supply a string to type'; // Skip target check if user is simply targeting whatever is focused if (!el) performTargetCheck = false; el = el || this.activeElement(); var targetCheckPromise = performTargetCheck !== false ? this.waitForTargetAndSyncMousePosition(el, null, 'Type: ' + text, [], false, false) : Promise.resolve() var me = this return me.runPromiseAsync(targetCheckPromise.then(function () { el = me.normalizeElement(el); if (!el || el.disabled) { return; } if (clearExisting) { if ('value' in el) { el.value = '' } // IE11 reports true for input´s `isContentEditable`, need to check this after 'value' check else if (el.isContentEditable) { el.innerHTML = '' } else { // What's up here...? } } var queue = new Siesta.Util.Queue({ deferer : me.originalSetTimeout, deferClearer : me.originalClearTimeout, interval : me.simulator.actionDelay, callbackDelay : me.simulator.afterActionDelay, observeTest : me }) // Manually focus the element to type into first queue.addStep({ processor : function () { me.focus(el) } }) // focus the element one more time for IE - me seems to fix the weird sporadic failures in 042_keyevent_simulation3.t.js // failures are caused by the field "blur" immediately after 1st focus // no Ext "focus/blur" methods seems to be called, so it can be a browser behavior bowser.msie && queue.addStep({ processor : function () { me.focus(el) } }) queue.addStep({ isAsync : true, processor : function (stepData) { var promise = me.simulator.simulateType(text, options, { el : el }) me.runPromiseAsync(promise, '', stepData.next) } }) return new Promise(function (resolve, reject) { queue.run(function () { resolve() }) }) }), 'type : `' + text + '`', callback, scope) }, /** * @param {Siesta.Test.ActionTarget} el * @param {String} key * @param {Object} options any extra options used to configure the DOM event. This argument can be omitted. * @param {Function} callback A function to be called after the type operation is completed. * @param {Object} scope The scope for the callback * * @return {Promise} Returns a promise resolved once the action has completed * * This method will simluate the key press, translated to the specified DOM element. It is generally exactly equivalent of * typing a single character, special characters are supported in the same way as in {@link #type} method. */ keyPress: function (el, key, options, callback, scope) { if (typeof options === 'function') { callback = options; options = undefined; } return this.type(el, key, callback, scope, options) } } });