Hone logo
Hone
Problems

Testing Asynchronous Functions with Async/Await in Jest (TypeScript)

Testing asynchronous code can be tricky, but Jest provides excellent tools for it. This challenge focuses on writing Jest tests using async/await to verify the behavior of asynchronous functions, ensuring your code handles promises correctly and behaves as expected under various conditions. Successfully completing this challenge demonstrates proficiency in testing asynchronous TypeScript code.

Problem Description

You are given a module containing an asynchronous function called fetchData. This function simulates fetching data from an API and returns a promise that resolves with a string. Your task is to write a Jest test suite using async/await to thoroughly test fetchData. The test suite should cover the following scenarios:

  • Successful Fetch: Verify that fetchData resolves with the expected string when the API call is successful.
  • Error Handling: Verify that fetchData rejects with an error when the API call fails (simulated by throwing an error within the function).
  • Timeout Handling: Verify that fetchData rejects with a timeout error if the API call takes longer than a specified timeout duration.

Examples

Example 1: Successful Fetch

Input: fetchData() - successful API call
Output: "Data fetched successfully!"
Explanation: The function should resolve with the expected success message.

Example 2: Error Handling

Input: fetchData() - API call fails
Output: Error: "Failed to fetch data."
Explanation: The function should reject with an appropriate error message when the API call fails.

Example 3: Timeout Handling

Input: fetchData(500) - API call takes longer than 500ms
Output: Error: "Request timed out after 500ms."
Explanation: The function should reject with a timeout error if the API call exceeds the specified timeout.

Constraints

  • The fetchData function accepts an optional timeout parameter (in milliseconds). If no timeout is provided, a default timeout of 200ms should be used.
  • The timeout should be enforced using setTimeout and Promise.race.
  • The error messages should be clear and descriptive.
  • Your test suite should be well-structured and easy to understand.
  • Use Jest's expect assertions to verify the expected behavior.

Notes

  • Consider using try...catch blocks within your async test functions to handle promise rejections gracefully.
  • Think about how to simulate both successful and failed API calls within the fetchData function for testing purposes.
  • The fetchData function is provided below. Do not modify the fetchData function itself. Focus solely on writing the Jest tests.
  • You can use jest.setTimeout to adjust the default timeout for your tests if needed.
// fetchData.ts (Do not modify this file)
export async function fetchData(timeout?: number): Promise<string> {
  const defaultTimeout = 200;
  const actualTimeout = timeout || defaultTimeout;

  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const shouldFail = Math.random() < 0.3; // Simulate a 30% chance of failure

      if (shouldFail) {
        reject(new Error("Failed to fetch data."));
      } else {
        resolve("Data fetched successfully!");
      }
    }, actualTimeout);
  });
}
Loading editor...
typescript