Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

relative paths (projectRoot) for json reporter #701

Open
sebaplaza opened this issue Oct 28, 2022 · 5 comments · May be fixed by #702
Open

relative paths (projectRoot) for json reporter #701

sebaplaza opened this issue Oct 28, 2022 · 5 comments · May be fixed by #702

Comments

@sebaplaza
Copy link

Hello,

I have a monorepo with a bunch of projects.

Every project is generating a json coverage report.

I'm using nyc merge and then nyc report all these partial json coverage files into an unique one.

I made a lib to accomplish this.

All this is working great, but i have still an issue...

To optimize CI speeds, i'm caching the coverage task results (json coverage files) via turborepo cache

The generated paths in json coverage are absolutes, and of course, they are different between dev machines and CI. nyc report fails because the physical paths doesn't exists.

I would like to specify a custom path for json coverage files, just like the lcov reporter

sebaplaza pushed a commit to sebaplaza/istanbuljs that referenced this issue Oct 28, 2022
to support relative paths

Closes istanbuljs#701
sebaplaza pushed a commit to sebaplaza/istanbuljs that referenced this issue Oct 28, 2022
to support relative paths

Closes istanbuljs#701
@sebaplaza sebaplaza linked a pull request Oct 28, 2022 that will close this issue
@sebaplaza
Copy link
Author

any updates ?

This PR is ok for you ?

#702

@raspo
Copy link

raspo commented Mar 24, 2023

@sebaplaza I have the exact same setup (!) with a monorepo (using turborepo) and I am also combining all the coverage reports together into one big one.
In my case the combined report works fine, but shows a mix of different absolute paths, if say the coverage for one package was generated (and cached) locally and the others ran in CI...


My research also lead me to the missing projectRoot option in the json reporter... and your PR solves the issue 👍

@sebaplaza
Copy link
Author

sebaplaza commented Mar 24, 2023

@raspo i would love to merge this mr, but this project seems dead, there is no one to merge this.

I've been dealing with this issue using 2 different cache hashes (one for CI and the other one for local runs). To make a different turborepo hash i'm using an env variable that is only present in ci environments (in my case gitlab).

turbo.json example:

{
	"$schema": "https://turborepo.org/schema.json",
	"globalEnv": ["GITLAB_CI"],
	"pipeline": {
          ...
}

@raspo
Copy link

raspo commented Mar 24, 2023

@sebaplaza I opted for another workaround... by (ab)using a custom test reporter.
Here is my hacky reporter that takes the coverage-final.json and rewrite its content by replacing absolute paths with relative ones.

// tools/relative-coverage-reporter.js

const fs = require('fs');
const path = require('path');

function loadCoverageFile(coverageFilePath) {
  try {
    return require(coverageFilePath);
  } catch (e) {
    console.error(`There was an error trying to load the coverage file: ${e}`);
  }

  return false;
}

// NOTE: not technically a reporter, this is a custom script that runs after the tests
// it's a bit of a hack, but it's the only way to get the coverage report to show relative paths
class RelativeCoverageReporter {
  constructor(globalConfig, reporterOptions, _reporterContext) {
    this._globalConfig = globalConfig;
    this._options = reporterOptions;
  }

  onRunComplete() {
    // sanity check
    if (!this._globalConfig.collectCoverage) return;
    if (this._globalConfig.watch) return;

    const coverageFilePath = path.join(this._globalConfig.coverageDirectory, 'coverage-final.json');

    // the root path of the monorepo
    const projectRoot = this._options.projectRoot || path.resolve(__dirname, '../');

    // load coverage file generated by istanbul
    const coverageJSON = loadCoverageFile(coverageFilePath);

    const newCoverageJSON = Object.keys(coverageJSON).reduce((acc, key) => {
      const fileCoverage = coverageJSON[key];

      // convert to relative paths
      const relativePath = path.relative(projectRoot, fileCoverage.path);

      acc[relativePath] = { ...fileCoverage, path: relativePath };

      return acc;
    }, {});

    // overwrite the coverage results file
    fs.writeFileSync(coverageFilePath, JSON.stringify(newCoverageJSON));
  }
}

module.exports = RelativeCoverageReporter;

You can reference it from any jest.config.js like so:

module.exports = {
  coverageReporters: ['json'],
  reporters: ['default', require.resolve('../../tools/relative-coverage-reporter.js')] // or whatever path
  // ...
};

At first I thought about writing a custom coverage reporter that would wrap the json one, but unfortunately it's not currently possible because of how reporters are resolved (source); also see jestjs/jest#9112.

@work933k
Copy link

An alternative to the custom reporter might be to using "patch-package" to modify the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants