Hone logo
Hone
Problems

Testing DOM Manipulations with Jest

This challenge focuses on writing robust unit tests for JavaScript code that manipulates the Document Object Model (DOM). We'll simulate DOM interactions within a Jest environment, ensuring that our components behave as expected when elements are added, removed, or updated. This is crucial for building interactive and reliable web applications.

Problem Description

Your task is to write Jest unit tests for a simple JavaScript module responsible for updating a list of items displayed in an HTML structure. The module will provide functions to add new items and remove existing ones from a dynamically managed list.

You will need to:

  • Simulate a DOM environment: Jest's jsdom environment will be used to mimic a browser's DOM.
  • Test adding items: Write a test to verify that a new list item is correctly appended to the DOM when the addItem function is called.
  • Test removing items: Write a test to verify that a specific list item is removed from the DOM when the removeItem function is called.
  • Handle edge cases: Consider scenarios like trying to remove an item that doesn't exist or adding an empty item.

The expected behavior is that the addItem function will create a new <li> element with the provided text content and append it to a designated parent element (e.g., a <ul> or <ol>). The removeItem function will find a specific <li> element (identified by its text content or a data attribute) and remove it from its parent.

Examples

Example 1: Adding an item

Assume the following initial HTML structure in the jsdom environment:

<ul id="item-list"></ul>

And the following JavaScript functions:

// addItem.ts
export function addItem(text: string): void {
  const ul = document.getElementById('item-list');
  if (!ul) return;

  const li = document.createElement('li');
  li.textContent = text;
  ul.appendChild(li);
}

Input to the test: Call addItem('Learn Jest').

Expected DOM after the test:

<ul id="item-list">
  <li>Learn Jest</li>
</ul>

Explanation: The addItem function is called with the text "Learn Jest". It finds the <ul> element, creates a new <li>, sets its textContent, and appends it.

Example 2: Removing an item

Assume the following initial HTML structure in the jsdom environment:

<ul id="item-list">
  <li data-id="1">Buy milk</li>
  <li data-id="2">Walk the dog</li>
</ul>

And the following JavaScript functions:

// removeItem.ts
export function removeItem(id: string): void {
  const liToRemove = document.querySelector(`li[data-id="${id}"]`);
  if (liToRemove && liToRemove.parentNode) {
    liToRemove.parentNode.removeChild(liToRemove);
  }
}

Input to the test: Call removeItem('1').

Expected DOM after the test:

<ul id="item-list">
  <li data-id="2">Walk the dog</li>
</ul>

Explanation: The removeItem function is called with the ID "1". It finds the <li> with data-id="1" and removes it from its parent <ul>.

Example 3: Removing a non-existent item

Using the same removeItem.ts as Example 2, with the same initial HTML.

Input to the test: Call removeItem('3').

Expected DOM after the test:

<ul id="item-list">
  <li data-id="1">Buy milk</li>
  <li data-id="2">Walk the dog</li>
</ul>

Explanation: The removeItem function is called with an ID that doesn't exist in the DOM. The function gracefully handles this by doing nothing, and the DOM remains unchanged.

Constraints

  • Your tests should be written in TypeScript.
  • You will be using Jest and its built-in jsdom environment.
  • Your tests should focus on verifying the DOM state after function calls.
  • You are not required to implement the actual HTML file; Jest's jsdom will handle the setup.
  • Focus on clear and descriptive test names that explain what is being tested.

Notes

  • Before writing your tests, ensure you have Jest and jsdom set up in your project. You might need to install them: npm install --save-dev jest @types/jest ts-jest.
  • Configure jest.config.js to use ts-jest and set the testEnvironment to jsdom.
  • You can simulate the initial DOM structure within your test files using document.body.innerHTML = '...' before calling your functions.
  • After your functions have executed, you can query the DOM using standard DOM APIs (document.querySelector, document.getElementById, querySelectorAll, etc.) to assert the expected state.
  • Consider using beforeEach or beforeAll in your Jest tests to set up a consistent initial DOM state for each test or suite.
Loading editor...
typescript