Hone logo
Hone
Problems

Implementing a Custom afterAll Hook in Jest (TypeScript)

Jest's afterAll hook allows you to run code after all tests in a describe block have completed. This is useful for tasks like cleaning up resources, closing database connections, or logging final results. This challenge asks you to implement a simplified version of afterAll functionality, focusing on the core logic of executing a callback function only once after all tests within a given block have finished.

Problem Description

You need to create a function called afterAll that takes a callback function as an argument. This afterAll function should ensure that the provided callback is executed only once after all tests within a specified block (simulated by an array of test functions) have completed. The afterAll function should not execute the callback immediately; it should wait until all tests have finished. The tests are represented as an array of functions, each function representing a single test.

Key Requirements:

  • Single Execution: The callback function must be executed only once, regardless of the number of tests in the block.
  • Deferred Execution: The callback should not be executed immediately when afterAll is called. It should wait for all tests to complete.
  • Error Handling: If any of the test functions throw an error, the afterAll callback should still be executed. The error should not prevent the afterAll callback from running.
  • TypeScript: The solution must be written in TypeScript.

Expected Behavior:

When afterAll is called with a callback and an array of test functions, the callback should be executed after all functions in the array have been executed (either successfully or with an error).

Edge Cases to Consider:

  • Empty array of tests: The callback should still be executed (though it will have nothing to do).
  • Tests that throw errors: The callback should still be executed, even if errors occur during the tests.
  • Asynchronous tests (though this challenge focuses on synchronous tests, consider how your solution might behave if tests were asynchronous).

Examples

Example 1:

Input:
tests: [() => console.log("Test 1"), () => console.log("Test 2")]
afterAllCallback: () => console.log("After All Tests")

Output:
Test 1
Test 2
After All Tests
Explanation: The tests are executed sequentially, and the afterAllCallback is executed after both tests have completed.

Example 2:

Input:
tests: [() => console.log("Test 1"), () => { throw new Error("Test 2 failed"); }],
afterAllCallback: () => console.log("After All Tests")

Output:
Test 1
Error: Test 2 failed
After All Tests
Explanation:  Test 2 throws an error, but the afterAllCallback is still executed.

Example 3:

Input:
tests: []
afterAllCallback: () => console.log("After All Tests")

Output:
After All Tests
Explanation: The test array is empty, but the afterAllCallback is still executed.

Constraints

  • The tests array will contain only functions.
  • The afterAllCallback will be a function that takes no arguments.
  • The tests are synchronous functions.
  • The solution should be reasonably efficient; avoid unnecessary overhead.

Notes

Consider using try...catch blocks to handle errors thrown by the test functions. Think about how to ensure the callback is only executed once, even if the tests are executed multiple times (e.g., in a testing framework). The core of the challenge is managing the execution timing of the callback function. You don't need to implement a full Jest environment; just focus on the afterAll logic itself.

Loading editor...
typescript