istanbuljs / babel-plugin-istanbul

A babel plugin that adds istanbul instrumentation to ES6 code
BSD 3-Clause "New" or "Revised" License
624 stars 73 forks source link

Coverage reports 'Else path not taken' when there is no else path to take using ES6 imports #186

Open RonanQuigley opened 6 years ago

RonanQuigley commented 6 years ago

I'm not sure if this is a bug with babel-plugin-istanbul (if it's best to post there just let me know), nyc or just a misconfiguration issue I've missed, but when setting up a new project I've now encountered the following:

Expected Behavior

Coverage should report 100% when using ES6 imports for the test code below.

Observed Behavior

See the images, but the reporter seems to think that there are else branches when there isn't any. It also says the statement is not covered.

Bonus Points! Code (or Repository) that Reproduces Issue

This is using ES6 imports:

// index.js
export function test() {
    return 'test';
}
// index.test.js

import { expect } from 'chai';
import { test } from './test';
describe('foo', () => {
    it('should say test', () => {
        expect(test()).to.equal('test');
    });
});

Produces the following:

capture - imports

It also happens if you use default exports.

For module.exports, coverage is correct

// index.js - module.exports
module.exports function test() {
    return 'test';
}
//index.test.js
import { expect } from 'chai';
const test = require('./test');
describe('test', () => {
    it('should say test', () => {
        expect(test()).to.equal('test');
    });
});

capture - module

Forensic Information

Operating System: Windows 10 Environment Information: npm : 6.0.1 node : 10.1.0 nyc : 12.02 babel-plugin-istanbul : 4.1.6

This is the .babelrc.js

module.exports = {
    presets: [
        ['@babel/preset-env'],
        ['@babel/stage-0', { decoratorsLegacy: true }],
        '@babel/preset-react'
    ],
    plugins: ['react-hot-loader/babel'],
    retainLines: true,
    sourceMaps: true,
    env: {
        test: {
            presets: [['@babel/preset-env', { modules: false }]],
            plugins: [['istanbul']]
        }
    }
};

and this is the .nycrc:

{
    "check-coverage": true,
    "per-file": true,
    "include": [
    "./src/**/*.js"
    ],
    "reporter": [
      "lcov",
      "text"
    ],
    "cache": false,
    "all": false,
    "instruments" : false, 
    "sourceMap": false
}

I've also tried adding the instruments and sourceMap options to my package.json but that just causes the coverage to report back as empty. I'm using Mocha as my test runner.

anitin commented 6 years ago

any updates ?

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

temharay commented 4 years ago

was this issue solved?

coreyfarrell commented 3 years ago

I suspect this is caused by another transformation injecting a branch and producing source-maps pointing the branch to the original code. This sometimes happens when transpiling code and is outside our control.

aazcoita commented 2 years ago

IMO, this issue should be resolved. I checked the transpiled code from TS and no else was added... It looks like a bug.

toondaey commented 2 years ago

Was anyone able to resolve this?

th317erd commented 2 years ago

I have this same issue with vanilla node code... no exports, no transpiling. I confirmed without a doubt that the if path is taken (my tests wouldn't pass otherwise, but I also threw in a console.log to ensure I wasn't crazy).

if (this.roles) {
        roles = this.roles.map((role) => {
          if (typeof role === 'string')
            return role;
          else if (role instanceof Role) // <<----- claims that this else path is never taken... but it most certainly is!
            return role.name;
        });
      }
matart15 commented 2 years ago
Screen Shot 2022-06-15 at 21 08 42

same thing happening on my imported file. ( jest test )

content of lambda_shared_folder/error

import { createSlackLogger } from "lambda_shared_folder/sendMessageToSlack";
import lambda from "aws-lambda";

export const createThrowError = (functionName: string) => 
async ({ 
  errorName, 
  context, 
  sendSlackNotification = true, 
}: {
  errorName: string,
  sendSlackNotification?: boolean
  context: lambda.Context;
}) => {
  const fullErrorName = `${functionName}_${errorName}`
  if(sendSlackNotification){
    const { logGroupName , logStreamName } = context
    const slackLogger = createSlackLogger({
      logGroupName,
      logStreamName,
    })
    await slackLogger({ type: "ERROR", message: fullErrorName})
  }
  throw new Error(fullErrorName);
}

If I comment out if part in imported file, it passes.

import { createSlackLogger } from "lambda_shared_folder/sendMessageToSlack";
import lambda from "aws-lambda";

export const createThrowError = (functionName: string) => 
async ({ 
  errorName, 
  context, 
  sendSlackNotification = true, 
}: {
  errorName: string,
  sendSlackNotification?: boolean
  context: lambda.Context;
}) => {
  const fullErrorName = `${functionName}_${errorName}`
  // if(sendSlackNotification){
  //   const { logGroupName , logStreamName } = context
  //   const slackLogger = createSlackLogger({
  //     logGroupName,
  //     logStreamName,
  //   })
  //   await slackLogger({ type: "ERROR", message: fullErrorName})
  // }
  throw new Error(fullErrorName);
}

I don't think it should check content of imported file

matart15 commented 2 years ago

Not sure it helps.

For temporary solution adding this code to jest.config.js fixed problem.

jest.config.js

module.exports = {
  ...
  transform: {
    ".+\\.(t|j)sx?$": [
      "@swc/jest",
      {
        sourceMaps: true, // エラーを見やすくする( 有効じゃないと内容がズレて表示されます )
        module: {
          type: "commonjs", // 出力するファイルをcommonjsとする
        },
        jsc: {
          parser: {
            syntax: "typescript", // ソースコードをtypescriptとしてパースする
            tsx: true, // jsx記法を許可する
          },
          transform: {
            react: {
              // 必須。省略すると "ReferenceError: React is not defined" が発生します
              runtime: "automatic",
            },
          },
        },
      },
    ],
  },
  ...
}