Hone logo
Hone
Problems

Jest Focus Management Testing

This challenge focuses on testing the behavior of elements within a web application that manage focus. Specifically, you will write Jest tests to ensure that focus is correctly managed when certain UI elements are rendered, removed, or interacted with. This is crucial for accessibility and a smooth user experience, especially for keyboard navigators.

Problem Description

Your task is to implement a series of Jest tests for a hypothetical JavaScript/TypeScript module responsible for focus management. This module will likely handle scenarios such as:

  • Initial Focus: Setting focus to a specific element when a component mounts or a modal opens.
  • Focus Trapping: Preventing focus from escaping a designated container (e.g., a modal).
  • Focus Restoration: Returning focus to the element that triggered an action (e.g., closing a modal) when that action is completed.

You will need to simulate DOM interactions and assertions using Jest and a DOM mocking library (like jsdom, which Jest includes by default).

Key Requirements:

  • Write tests in TypeScript.
  • Use Jest for testing.
  • Assume you have a FocusManager class or a set of utility functions that provide focus management capabilities. You will not implement the FocusManager itself, but rather test its behavior.
  • Your tests should cover the core functionalities of focus management as described above.
  • You should be able to mock DOM elements and their properties (like focus(), blur(), tabIndex, contains()).

Expected Behavior:

  • When a component requiring initial focus mounts, the specified element should receive focus.
  • When focus attempts to leave a trapped area, it should wrap around to the beginning or end of the trapped elements.
  • When a modal is closed, focus should return to the element that originally opened it.

Edge Cases to Consider:

  • What happens if the element intended to receive focus is not present in the DOM?
  • What happens if the focus trapping container is empty or has no focusable elements?
  • What happens if multiple modals are nested?

Examples

For these examples, assume we are testing a FocusManager that has methods like setInitialFocus(element), trapFocus(container), and restoreFocus(elementToReturnTo). We'll also assume helper functions to get focusable elements.

Example 1: Initial Focus

  • Scenario: A modal component mounts, and its primary input field should receive focus.
  • Input:
    • A DOM element representing the modal.
    • A DOM element representing the input field within the modal.
  • Expected Output (Assertions):
    • The input element's focus() method is called exactly once.
  • Explanation: We simulate the mounting of a modal and verify that the designated input field correctly receives focus.

Example 2: Focus Trapping (Forward)

  • Scenario: Focus is trapped within a modal. Pressing Tab when focus is on the last focusable element should move focus to the first focusable element.
  • Input:
    • A DOM element representing the modal container.
    • A list of focusable DOM elements within the container, in order.
    • The focus is currently on the last focusable element.
  • Expected Output (Assertions):
    • A keydown event with key: 'Tab' and shiftKey: false is dispatched.
    • The document.activeElement after the event is the first focusable element in the list.
  • Explanation: We simulate a Tab press and confirm that focus wraps around to the beginning of the trapped area.

Example 3: Focus Trapping (Backward)

  • Scenario: Focus is trapped within a modal. Pressing Shift+Tab when focus is on the first focusable element should move focus to the last focusable element.
  • Input:
    • A DOM element representing the modal container.
    • A list of focusable DOM elements within the container, in order.
    • The focus is currently on the first focusable element.
  • Expected Output (Assertions):
    • A keydown event with key: 'Tab' and shiftKey: true is dispatched.
    • The document.activeElement after the event is the last focusable element in the list.
  • Explanation: We simulate a Shift+Tab press and confirm that focus wraps around to the end of the trapped area.

Example 4: Focus Restoration

  • Scenario: A button is clicked, opening a modal. When the modal is closed, focus should return to the original button.
  • Input:
    • A DOM element representing the button that opened the modal.
    • A DOM element representing the modal.
  • Expected Output (Assertions):
    • When the modal is closed, the original button's focus() method is called.
  • Explanation: We verify that closing the modal correctly returns focus to the element that triggered its opening.

Constraints

  • All tests must be written in TypeScript.
  • You must use Jest for test execution.
  • You will be working with mocked DOM elements. Native browser APIs like document.createElement, element.focus(), element.addEventListener, etc., should be used in the context of jsdom.
  • Assume that the FocusManager (or equivalent utilities) is available and correctly imported.
  • Tests should be efficient and not rely on actual timers or asynchronous operations unless explicitly testing them (which is not the primary focus here).

Notes

  • You'll likely need to mock or create DOM elements for your tests. jsdom provides a good environment for this.
  • Pay close attention to how you simulate user interactions like keyboard events (keydown, keypress, keyup).
  • Consider how to identify focusable elements programmatically (e.g., by tag name, tabIndex attribute).
  • The goal is to test the behavior of focus management, not the implementation details of how you find focusable elements or apply styles. You can assume helper functions exist for these.
  • Think about the order of operations and how to assert the state of the DOM (specifically document.activeElement) at different points.
Loading editor...
typescript