Jest Integration Test for a User Profile Card Component
This challenge focuses on writing an integration test for a React component using Jest. You will simulate user interactions and verify that the component behaves as expected when integrated with its child components and external data. This is a crucial skill for ensuring the reliability and correctness of your React applications.
Problem Description
You are tasked with creating an integration test for a UserProfileCard React component. This component displays a user's name, avatar, and a list of their favorite hobbies. The UserProfileCard component fetches user data (name and avatar URL) from an external API and also receives a list of hobbies as a prop.
Your integration test should verify the following:
- Initial Rendering: The
UserProfileCardcorrectly renders the user's name and avatar when provided with valid data. - Hobby Display: All hobbies passed as props are rendered correctly within the component.
- Avatar Loading State: While the avatar is being fetched (simulated), a loading indicator is displayed. Once the avatar is loaded, the loading indicator should disappear and the avatar should be visible.
- Error Handling: If there's an error fetching the avatar, an appropriate error message is displayed instead of the avatar.
- Prop Updates: When the user data (name/avatar) or hobbies props change, the component updates accordingly.
Examples
Example 1: Basic Rendering with Hobbies
Input:
- `UserProfileCard` component
- Props:
- `userId`: 'user123'
- `hobbies`: ['Reading', 'Hiking', 'Coding']
- Mocked API response for `userId: 'user123'`:
```json
{
"name": "Alice Wonderland",
"avatarUrl": "https://example.com/avatars/alice.png"
}
Output (after initial render):
The rendered UserProfileCard should contain:
- The text "Alice Wonderland".
- An
<img>tag withsrcset to "https://example.com/avatars/alice.png". - A list displaying:
- "Reading"
- "Hiking"
- "Coding"
**Example 2: Avatar Loading State**
Input:
UserProfileCardcomponent- Props:
userId: 'user456'hobbies: ['Gaming']
- Mocked API behavior:
- Initially returns a loading state.
- After a short delay (e.g., 50ms), returns:
{ "name": "Bob The Builder", "avatarUrl": "https://example.com/avatars/bob.png" }
Output (during loading):
The rendered UserProfileCard should contain a "Loading avatar..." text or a spinner component.
Output (after loading):
The rendered UserProfileCard should contain:
- The text "Bob The Builder".
- An
<img>tag withsrcset to "https://example.com/avatars/bob.png". - A list displaying:
- "Gaming"
**Example 3: Error Handling during Avatar Fetch**
Input:
UserProfileCardcomponent- Props:
userId: 'user789'hobbies: ['Cooking', 'Gardening']
- Mocked API behavior:
- Returns an error (e.g., throws an exception or returns a 404 status).
Output:
The rendered UserProfileCard should contain:
- The text "Charlie Brown". (Assume name is fetched successfully or hardcoded if API fails for name too)
- An error message like "Failed to load avatar."
- A list displaying:
- "Cooking"
- "Gardening"
## Constraints
* The tests must be written using Jest and React Testing Library.
* You are expected to mock network requests using libraries like `jest.mock` and `axios-mock-adapter` or `msw`.
* All component logic, including data fetching, should be considered part of the integration.
* The avatar fetch is assumed to be an asynchronous operation.
* Assume standard React component structure and best practices.
## Notes
* Focus on how the `UserProfileCard` component interacts with its dependencies (API, child components) and renders based on the combined state.
* Think about how to simulate asynchronous operations and their outcomes (success, loading, error).
* React Testing Library's queries (`getByText`, `getByRole`, `findByAltText`, etc.) will be your primary tools for asserting component behavior.
* Consider using `waitFor` or `findBy*` queries to handle asynchronous updates.
* The actual implementation of `UserProfileCard` and its data fetching utility are not provided, so you will need to assume a plausible structure for them and mock them accordingly. For the purpose of this challenge, assume a function `fetchUserData(userId: string)` exists and returns a `Promise` resolving with `{ name: string, avatarUrl: string }` or rejects on error.