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
jsdomenvironment 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
addItemfunction is called. - Test removing items: Write a test to verify that a specific list item is removed from the DOM when the
removeItemfunction 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
jsdomenvironment. - Your tests should focus on verifying the DOM state after function calls.
- You are not required to implement the actual HTML file; Jest's
jsdomwill 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
jsdomset up in your project. You might need to install them:npm install --save-dev jest @types/jest ts-jest. - Configure
jest.config.jsto usets-jestand set thetestEnvironmenttojsdom. - 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
beforeEachorbeforeAllin your Jest tests to set up a consistent initial DOM state for each test or suite.