Hone logo
Hone
Problems

Mocking User Interactions with Jest's fireEvent

This challenge focuses on simulating user interactions with DOM elements within a testing environment. Understanding how to effectively use Jest's fireEvent is crucial for writing robust and realistic tests for front-end applications, ensuring that your components behave as expected when users click buttons, type into input fields, or perform other common actions.

Problem Description

Your task is to implement a custom fireEvent function in TypeScript that mimics the behavior of Jest's built-in fireEvent utility for specific DOM event types. This custom function will allow you to trigger events on DOM elements programmatically within your tests.

You need to create a function that accepts a DOM element and an event type as arguments. Based on the event type, it should create and dispatch the appropriate DOM event. For this challenge, you should focus on implementing support for the following event types:

  • click: Simulates a mouse click.
  • change: Simulates a change event, typically on form elements like inputs or selects.
  • keydown: Simulates a key press.

Key Requirements:

  1. Function Signature: The function should have a signature similar to fireEvent(element: HTMLElement, eventType: string, eventProperties?: object): void.
  2. Event Creation: Dynamically create the correct type of Event or CustomEvent based on the eventType argument.
  3. Event Dispatching: Dispatch the created event on the provided element.
  4. Property Propagation: Allow optional eventProperties to be passed and applied to the dispatched event. This is particularly useful for keydown events where you might want to specify the key or keyCode.
  5. Type Safety: Implement the solution using TypeScript, ensuring type safety.

Expected Behavior:

When fireEvent is called with a specific element, event type, and optional properties, the corresponding event should be triggered on that element. Test assertions should be able to verify that event handlers attached to the element have been called.

Edge Cases to Consider:

  • What happens if an unsupported eventType is provided? (For this challenge, you can choose to throw an error or do nothing gracefully).
  • How are properties for specific events, like key for keydown, handled?

Examples

Example 1: Simulating a Click

// Assume this is your component's render output in a test
const button = document.createElement('button');
button.textContent = 'Click Me';
document.body.appendChild(button);

let clickCount = 0;
button.addEventListener('click', () => {
  clickCount++;
});

// --- Your fireEvent implementation will be used here ---
// fireEvent(button, 'click');

// Assertion (in a test file):
// expect(clickCount).toBe(1);

Example 2: Simulating a Change Event on an Input

// Assume this is your component's render output in a test
const input = document.createElement('input');
input.type = 'text';
input.value = 'initial';
document.body.appendChild(input);

let changeValue = '';
input.addEventListener('change', (event: Event) => {
  changeValue = (event.target as HTMLInputElement).value;
});

// --- Your fireEvent implementation will be used here ---
// fireEvent(input, 'change', { target: { value: 'new value' } });

// Assertion (in a test file):
// expect(changeValue).toBe('new value');

Example 3: Simulating a Keydown Event

// Assume this is your component's render output in a test
const inputField = document.createElement('input');
document.body.appendChild(inputField);

let keyPressed = '';
inputField.addEventListener('keydown', (event: KeyboardEvent) => {
  keyPressed = event.key;
});

// --- Your fireEvent implementation will be used here ---
// fireEvent(inputField, 'keydown', { key: 'Enter' });

// Assertion (in a test file):
// expect(keyPressed).toBe('Enter');

Constraints

  • The implementation should be in TypeScript.
  • The solution should focus on the three specified event types (click, change, keydown).
  • The eventProperties object should allow for arbitrary properties to be passed, which will be merged into the event object.
  • The solution should not rely on external libraries other than standard DOM APIs and TypeScript.

Notes

  • Consider using document.createEvent and element.dispatchEvent or the more modern new Event(...) and element.dispatchEvent(...).
  • For change events, the eventProperties might need to include a target property that mimics the actual input element's state (like value).
  • For keydown events, passing key or keyCode within eventProperties is essential. You'll need to ensure these properties are correctly assigned to the dispatched event.
  • Remember that Jest tests typically run in a JSDOM environment, which provides a simulated DOM.
Loading editor...
typescript