Over a million developers have joined DZone.

Recording User Behavior: Testing Focus in JavaScript

This blog post is an overview for testing focus behavior in a web browser. Read on to learn more.

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

This blog post is an overview for testing focus behavior in a web browser.

During the work on Azure Portal, I spent quite a bit of time on ensuring rich keyboard support. This requires appropriate focus management. When a user presses some keyboard shortcut, the focus should move to the appropriate element. Focus behavior should also be tested very succinctly, as it is very easy to change (break) with even the smallest change in the HTML or JavaScript.

Standard test goes as follows:

  • Arrange: open some page
  • Act: execute some keyboard shortcut that should open a particular page and/or set focus on a particular element
  • Assert: check if the expected element is focused

How to Check if Element is Focused

The simplest way is to use jQuery:

expect($(element).is(':focus')).equals(true);

However, this may not always work, especially if you run your unit tests in parallel, because $element.is(‘:focus’) will not work when window does not have focus.

The better (right) way is to use document.activeElement:

expect(document.activeElement).equals(element);

This will work even when the browser window is not focused.

Testing Async Actions

Sometimes, the keyboard invokes asynchronous actions that eventually will change the focus. This can cause:

  • false negative tests: assertion was executed before focus was eventually set
  • false positives: finally focused element, got focus after assertion was executed

The simplest recipe for the first problem is to delay assertion:

setTimeout(() => {
    expect(document.activeElement).equals(element);
    done();
}, 100);

The problem with this approach is choosing the appropriate delay for the assertion. Therefore, it is better to avoid raw setTimeout, and usethe  polling approach that I described in my post setTimeout considered harmful:

poll(
    () => document.activeElement === element, 
    () => {
       assert(true);
       start();
  },
    () => {
       assert(false);
       start();
  }
    );

The polling function can be also used for the second solution (by changing assertion order in callback functions). However, for the false positives problem, simple setTimeout is good enough, because we do not have a choice other than waiting some particular period of time to execute assertion.

Invoking Keyboard Actions

There are 3 types of events that we can use to simulate keyboard actions:

  • keydown
  • keyup
  • keypress

The safest bet is to use keydown. Why? An example might be using special keys. While in the case of keypress – various browsers handle it differently (e.g., by not triggering the event), keydown is pretty consistent. I recommend you check out this article if you are interested in the details. It has not been updated for some time, but it will give you an idea.

In order to detect keyboard actions you may handle events on capture or bubbling phase. You should choose the model depending upon your needs, but in general bubbling phase is the optimal solution. Additionally, it is supported by jQuery, with browser inconsistencies taken care of for you.

To invoke a keydown event in your tests, you need to set focus on the element first:

$(element)
  .focus()
  .trigger("keydown", { which: keyCode });

You can find JavaScript key codes here.

Summary

  • Use document.activeElement to check which element is focused.
  • Use polling approach for testing async actions.
  • Use keydown event, and bubble phase to invoke/handle keyboard actions.

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

Topics:
javascript ,testing ,jquery

Published at DZone with permission of Jakub Jedryszek, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}