Last Updated: February 25, 2016
·
2.568K
· alexindigo

typeKey() for modern browsers (w/ jQuery)

With new versions of Firefox Selenium's typeKey method stopped working,
and most people had downgrade back to Firefox 7.

Especially in our case where we need to test weird autocomplete plugin with lazy loaded components.

So I decided to create temporally workaround until we get new version of Selenium.

Since we're using jQuery everywhere, it was pretty easy just solution – just to call all keyboard related triggers in a loop.

Here is function:

function typeKey(glob, field, sequence, callback)
{
  var nextChar = 0;

  // make glob optional
  if (!callback && (typeof glob == 'string' || glob.jquery))
  {
    callback = sequence;
    sequence = field;
    field    = glob;
    glob     = window;
  }

  if (!callback) callback = function(){};

  // --- start with actual stuff

  // jquerytize field
  if (typeof field == 'string') field = glob.jQuery(field);

  // make it an array
  sequence = sequence.split('');

  // trigger the whole thing
  setTimeout(function()
  {
    // focus
    field.focus();
    // and start looping
    looping();
  }, 0);

  // --- subroutines

  // do looping
  function looping()
  {
    // check if we done
    if (!sequence[nextChar]) return callback(null);

    // type and continue looping
    type(field, sequence[nextChar], looping);
    // increment pointer
    nextChar++;
  }

  // do typing
  function type($field, char, cb)
  {
    var nextEvent = 0
      , fireSquad =
        [
          // 1. keydown
          function() { $field.trigger(keyEvent('keydown', char)); },
          // 2. enter char
          function() { $field.val($field.val() + char); },
          // 3. keyup
          function() { $field.trigger(keyEvent('keyup', char)); },
          // 4. keypress
          function() { $field.trigger(keyEvent('keypress', char)); },
          // 5. done – callback
          function() { if (typeof callback == 'function') cb(); }
        ]
      ;

    // start firing events in 300ms
    setTimeout(fire, 300);

    // -- sub-subroutines
    function fire()
    {
      fireSquad[nextEvent]();
      nextEvent++;
      // look for next and fire on next tick
      if (fireSquad[nextEvent]) setTimeout(fire, 0);
    }
  }

  // create keyEvent
  function keyEvent(event, key)
  {
    var code = key.charCodeAt(0);
    return glob.jQuery.Event(event, {which: code, keyCode: code});
  }
};

And that's how you use it:

typeKey('#search_location', 'Palo Alto, CA');

There are two optional params:

– callback, which get called after last character is typed.

– glob, window object, used when called from Selenium.

typeKey([window], field_obj_or_selector, sequence, [callback]);

1 Response
Add your response

Cheers! :)

over 1 year ago ·