Hone logo
Hone
Problems

Jest Coverage Merging

Jest is a popular JavaScript testing framework that provides powerful code coverage reporting. Often, you might run tests across multiple environments or configurations, resulting in separate coverage reports. This challenge focuses on implementing a mechanism to merge these individual coverage reports into a single, consolidated report, providing a holistic view of your codebase's test coverage.

Problem Description

Your task is to create a function that takes an array of Jest coverage report objects (typically JSON files generated by Jest's --coverage=true option) and merges them into a single, coherent coverage report object.

Key Requirements:

  • File-Level Merging: For each file present in any of the input reports, its coverage data (lines hit, branches covered, etc.) should be aggregated. If a file appears in multiple reports, its metrics should be summed up.
  • Global Metrics Aggregation: The global coverage metrics (total lines, hits, branches, etc.) for the merged report should be the sum of the global metrics from all input reports.
  • Handling Missing Files: If a file exists in one report but not another, it should still be included in the merged report with its original data.
  • Structure Preservation: The output merged report should maintain the same hierarchical structure as the input Jest coverage reports.

Expected Behavior:

The function should accept an array of coverage report objects and return a single coverage report object.

Edge Cases:

  • An empty input array of reports.
  • Input reports with no files.
  • Reports with identical file paths.

Examples

Example 1:

Input:

[
  {
    "total": {
      "lines": { "total": 10, "hit": 5 },
      "branches": { "total": 4, "hit": 2 }
    },
    "data": {
      "file1.js": {
        "lines": { "total": 10, "hit": 5 },
        "branches": { "total": 4, "hit": 2 }
      }
    }
  },
  {
    "total": {
      "lines": { "total": 5, "hit": 3 },
      "branches": { "total": 2, "hit": 1 }
    },
    "data": {
      "file1.js": {
        "lines": { "total": 5, "hit": 3 },
        "branches": { "total": 2, "hit": 1 }
      }
    }
  }
]

Output:

{
  "total": {
    "lines": { "total": 15, "hit": 8 },
    "branches": { "total": 6, "hit": 3 }
  },
  "data": {
    "file1.js": {
      "lines": { "total": 15, "hit": 8 },
      "branches": { "total": 6, "hit": 3 }
    }
  }
}

Explanation: The total metrics are summed (10+5=15 lines, 5+3=8 hits; 4+2=6 branches, 2+1=3 hits). The data for file1.js is also summed.

Example 2:

Input:

[
  {
    "total": {
      "lines": { "total": 10, "hit": 5 },
      "branches": { "total": 4, "hit": 2 }
    },
    "data": {
      "file1.js": {
        "lines": { "total": 10, "hit": 5 },
        "branches": { "total": 4, "hit": 2 }
      }
    }
  },
  {
    "total": {
      "lines": { "total": 8, "hit": 6 },
      "branches": { "total": 3, "hit": 2 }
    },
    "data": {
      "file2.js": {
        "lines": { "total": 8, "hit": 6 },
        "branches": { "total": 3, "hit": 2 }
      }
    }
  }
]

Output:

{
  "total": {
    "lines": { "total": 18, "hit": 11 },
    "branches": { "total": 7, "hit": 4 }
  },
  "data": {
    "file1.js": {
      "lines": { "total": 10, "hit": 5 },
      "branches": { "total": 4, "hit": 2 }
    },
    "file2.js": {
      "lines": { "total": 8, "hit": 6 },
      "branches": { "total": 3, "hit": 2 }
    }
  }
}

Explanation: file1.js is only in the first report. file2.js is only in the second. The total metrics are summed. The files are combined in the data object.

Example 3: Empty Input

Input:

[]

Output:

{
  "total": {
    "lines": { "total": 0, "hit": 0 },
    "branches": { "total": 0, "hit": 0 }
  },
  "data": {}
}

Explanation: An empty input array results in an empty, zeroed-out coverage report.

Constraints

  • The input reports will be an array of objects, each conforming to the Jest coverage report JSON structure.
  • Each coverage report object will have a total object and a data object.
  • The total object contains lines and branches (and potentially others, but focus on these two) with total and hit properties.
  • The data object is a map where keys are file paths (strings) and values are similar coverage metric objects as in total.
  • The number of input reports will not exceed 100.
  • The total number of files across all reports will not exceed 10,000.

Notes

  • You'll need to define the TypeScript interfaces for the Jest coverage report structure to ensure type safety.
  • Consider how to handle different types of coverage metrics if they exist (e.g., functions, statements) – for this challenge, focus on lines and branches.
  • The total metrics for a report are essentially the aggregated metrics of all files within its data object. Your merging logic should reflect this.
  • Think about how to efficiently aggregate data, especially when dealing with a large number of files and reports.
  • A helper function to merge individual metric objects (like lines or branches) might be useful.
Loading editor...
typescript