kulshekhar / ts-jest

A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
https://kulshekhar.github.io/ts-jest
MIT License
6.93k stars 453 forks source link

Line numbers are shown incorrectly when importing library that has default export #436

Closed thiagoh closed 6 years ago

thiagoh commented 6 years ago

following up what has been discussed on #405

@kulshekhar, I managed to create a minimal repo to reproduce the bug.

I guess the issue is somehow related to the use of mock-fs that mocks the filesystem. You can debug your lib and see that inside the function defaultRetrieveFileHandler an exception is thrown because fs cannot find the file.

The actual error is at line 18 so it should acuse that, not line 15.

https://github.com/thiagoh/minimal-repo-ts-jest-line-number-bug

screen shot 2018-02-10 at 1 39 11 pm
kulshekhar commented 6 years ago

@thiagoh I just tried this and it seems to be working fine :confused:

Note: I just added no-cache to the test script

I executed the following commands:

git clone https://github.com/thiagoh/minimal-repo-ts-jest-line-number-bug
yarn
yarn test

and got the following output:

mockfs-error

The complete output:

yarn run v1.3.2
$ jest --config=config.js --debug --verbose --no-cache
{
  "configs": [
    {
      "automock": false,
      "browser": false,
      "cache": false,
      "cacheDirectory": "/tmp/jest_rs",
      "clearMocks": false,
      "coveragePathIgnorePatterns": [
        "/node_modules/"
      ],
      "detectLeaks": false,
      "forceCoverageMatch": [],
      "globals": {
        "ts-jest": {
          "enableTsDiagnostics": true
        }
      },
      "haste": {
        "providesModuleNodeModules": []
      },
      "moduleDirectories": [
        "node_modules",
        "src"
      ],
      "moduleFileExtensions": [
        "ts",
        "tsx",
        "js",
        "jsx",
        "json",
        "node"
      ],
      "moduleNameMapper": {},
      "modulePathIgnorePatterns": [],
      "name": "bab15ff6c6c75a65f1df1b37c1dd0c66",
      "resetMocks": false,
      "resetModules": false,
      "restoreMocks": false,
      "rootDir": "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug",
      "roots": [
        "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug"
      ],
      "runner": "jest-runner",
      "setupFiles": [],
      "snapshotSerializers": [],
      "testEnvironment": "jest-environment-jsdom",
      "testEnvironmentOptions": {},
      "testLocationInResults": false,
      "testMatch": [
        "**/*.spec.ts"
      ],
      "testPathIgnorePatterns": [
        "/node_modules/"
      ],
      "testRegex": "",
      "testRunner": "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug/node_modules/jest-jasmine2/build/index.js",
      "testURL": "about:blank",
      "timers": "real",
      "transform": [
        [
          "^.+\\.tsx?$",
          "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug/node_modules/ts-jest/index.js"
        ]
      ],
      "transformIgnorePatterns": [
        "/node_modules/"
      ],
      "watchPathIgnorePatterns": []
    }
  ],
  "globalConfig": {
    "bail": false,
    "changedFilesWithAncestor": false,
    "coverageDirectory": "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug/coverage",
    "coverageReporters": [
      "json",
      "text",
      "lcov",
      "clover"
    ],
    "detectLeaks": false,
    "expand": false,
    "globalSetup": "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug/global-setup.js",
    "globalTeardown": "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug/global-teardown.js",
    "listTests": false,
    "mapCoverage": false,
    "maxWorkers": 3,
    "noStackTrace": false,
    "nonFlagArgs": [],
    "notify": false,
    "notifyMode": "always",
    "passWithNoTests": false,
    "rootDir": "/home/user/tmp/afdsfsa/minimal-repo-ts-jest-line-number-bug",
    "runTestsByPath": false,
    "testFailureExitCode": 1,
    "testPathPattern": "",
    "testResultsProcessor": null,
    "updateSnapshot": "new",
    "useStderr": false,
    "verbose": true,
    "watch": false,
    "watchman": true
  },
  "version": "22.2.2"
}
 FAIL  src/Dog.spec.ts (6.889s)
  Dog
    ✕ should woof (15ms)

  ● Dog › should woof

    expect(received).toBe(expected) // Object.is equality

    Expected value to be:
      "Woof!____ SHOULD FAIL AND DISPLAY LINE NUMBER 19"
    Received:
      "Woof!"

      16 |   test("should woof", () => {
      17 |     const dog = new Dog();
    > 18 |     expect(dog.woof()).toBe("Woof!____ SHOULD FAIL AND DISPLAY LINE NUMBER 19");
      19 |   });
      20 | });
      21 | 

      at Object.test (src/Dog.spec.ts:18:24)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        7.697s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
thiagoh commented 6 years ago

sorry @kulshekhar, I've just did the "fix" that breaks the code. could you take a look?

kulshekhar commented 6 years ago

@thiagoh taking a look now

kulshekhar commented 6 years ago

This still seems to be working fine :confused:

mockfs

kulshekhar commented 6 years ago

@thiagoh can you add a travis config to the minimal repo? We'll then have a common point of reference for output errors being displayed. Should help prevent problems like ^ where we're seeing different results on our machines

thiagoh commented 6 years ago

sorry @kulshekhar I also can't reproduce the error right now.. some library might have been updated since yesterday.. I have a private repo at work where this error happens.. I will try to understand what's going on there and get back to you here.. thanks

thiagoh commented 6 years ago

Hi @kulshekhar, I think I got the reason why jest is reporting wrong line numbers in my tests.

Original source

it('toBoolean should return true for true/on/yes/1 values', () => {
    expect(toBoolean(true)).toBe(true);
    expect(toBoolean(1)).toBe(true);
    expect(toBoolean('true')).toBe(true);
    expect(toBoolean('truE')).toBe(true);
    expect(toBoolean('True')).toBe(true);

    expect(toBoolean(' true ')).toBe(true);
    expect(toBoolean(' truE ')).toBe(true);
    expect(toBoolean(' True ')).toBe(true);

    expect(toBoolean('yes')).toBe(true);
    expect(toBoolean('yes')).toBe(true);
    expect(toBoolean('Yes')).toBe(true);

    expect(toBoolean(' Yes ')).toBe(true);
    expect(toBoolean(' YES ')).toBe(true);
    expect(toBoolean(' YES ')).toBe(true);

    expect(toBoolean('1')).toBe(true);
    expect(toBoolean(' 1')).toBe(true);
    expect(toBoolean(' 1 ')).toBe(true);

    expect(toBoolean('on')).toBe(true);
    expect(toBoolean('On')).toBe(true);
    expect(toBoolean('oN')).toBe(true);
    expect(toBoolean(' on ')).toBe(true);
    expect(toBoolean(' On ')).toBe(true);
    expect(toBoolean(' oN ')).toBe(false); // error
  });

Generated source (from jest cache source directory)

 it('toBoolean should return true for true/on/yes/1 values', function () {
        expect(utils_1.toBoolean(true)).toBe(true);
        expect(utils_1.toBoolean(1)).toBe(true);
        expect(utils_1.toBoolean('true')).toBe(true);
        expect(utils_1.toBoolean('truE')).toBe(true);
        expect(utils_1.toBoolean('True')).toBe(true);
        expect(utils_1.toBoolean(' true ')).toBe(true);
        expect(utils_1.toBoolean(' truE ')).toBe(true);
        expect(utils_1.toBoolean(' True ')).toBe(true);
        expect(utils_1.toBoolean('yes')).toBe(true);
        expect(utils_1.toBoolean('yes')).toBe(true);
        expect(utils_1.toBoolean('Yes')).toBe(true);
        expect(utils_1.toBoolean(' Yes ')).toBe(true);
        expect(utils_1.toBoolean(' YES ')).toBe(true);
        expect(utils_1.toBoolean(' YES ')).toBe(true);
        expect(utils_1.toBoolean('1')).toBe(true);
        expect(utils_1.toBoolean(' 1')).toBe(true);
        expect(utils_1.toBoolean(' 1 ')).toBe(true);
        expect(utils_1.toBoolean('on')).toBe(true);
        expect(utils_1.toBoolean('On')).toBe(true);
        expect(utils_1.toBoolean('oN')).toBe(true);
        expect(utils_1.toBoolean(' on ')).toBe(true);
        expect(utils_1.toBoolean(' On ')).toBe(true);
        expect(utils_1.toBoolean(' oN ')).toBe(false); // error

the compilation is somehow removing blank lines. Does that sound familiar to you?

PS: If I remove all blank lines from my original code then jest reports the error line number correctly

kulshekhar commented 6 years ago

@thiagoh can you try skipping babel?

be sure to clear the cache before that

thiagoh commented 6 years ago

@kulshekhar, in skipping babel what do you mean by "If you don't use mocks,..." cuz I'm using mocks...

thiagoh commented 6 years ago

anyway, @kulshekhar the best I could get was removing all blank lines (from inside my it blocks) replacing them by empty comments such as

it('test if this works', () => {
    ... some code here
    // empty workaround line
    ... some other code...

this way I get my line numbers correct when there's an error on my assertions

kulshekhar commented 6 years ago

@thiagoh can I reproduce this using the linked repo? I was using --no-cache earlier. Would not using this switch reproduce this? If so, I'll take a look at it again (most likely on the weekend)

xogeny commented 6 years ago

@thiagoh I'm curious...are you doing coverage analysis. I ask because I was having issues with lines not matching up while debugging. I would add debugger statements. It would jump into the debugger, but it would mark the wrong line. The farther into the file the debugger statement was, the more off it was, generally speaking. I noticed that removing blank lines had an effect, but it wasn't just blank lines that were causing this. But then I thought to try it with --coverage false and everything worked perfectly.

@kulshekhar I can give you a reproducible test case for this, but it won't be minimalistic if you want to try and chase it down. I can also open a separate issue if you want, to avoid confusion. Just let me know.

thiagoh commented 6 years ago

@kulshekhar I couldn't reproduce this error on my public repo. What I will do from now on is not using blank lines at all in my tests. At least until someone can reproduce this issue so that it can be fixed.

@xogeny with or without coverage analysis I get the same line mismatch.

xogeny commented 6 years ago

@thiagoh You might try just substituting the configuration files I've included in this article. I suspect your use case is perhaps beyond such a simple configuration. But I will say that I was having all kinds of difficulty with testing+debugging+coverage+TypeScript until I started from scratch and tried to create a minimal case. I couldn't reproduce the issues in my minimal case and copying the configurations to my existing project pretty much solved everything for me. So it might be worth a shot.

kulshekhar commented 6 years ago

closing this issue because I've been unable to replicate/debug it.

@thiagoh if this issue persists and if there's a way to replicate it via a minimal repo, let me know and I'll reopen this issue.

kulshekhar commented 6 years ago

@xogeny

I can give you a reproducible test case for this, but it won't be minimalistic if you want to try and chase it down

It's better than nothing. I've set aside some time for ts-jest this weekend so if you can share the repo, I'll take a look

xogeny commented 6 years ago

@kulshekhar Sorry, I could have done that at the time, but I've now worked through whatever issues I had so I don't think I could reproduce this now. Sorry.

cheskayang commented 5 years ago

@thiagoh did you manage to fix this other than adding comments in the blank line? I'm seeing the same issue with blank lines and wrong line numbers.

-update- might be helpful to people having similar issue: We finally fixed this issue. It turns out not a ts-jest issue, but a library that we were using. In this case it's cson-parser. The way we figured it out is to

  1. first set up a minimal repo with the same set up as in our source repo, write a minimal test, turns out the issue was not reproducible.
  2. Removing things added before the ts-jest preprocessor run one by one (globalSetup, setupFilesAfterEnv etc.), was able to finally find out which library is causing the problem.
Elyx0 commented 4 years ago

Same problem here with blank lines "jest": "^24.9.0",

marcj commented 4 years ago

Same here with

    "jest": "^24.9.0",
    "ts-jest": "^24.1.0",

I fixed it by adjust the tsconfig.json. I had "mapRoot": "src/", in it, after removing the line numbers were correct. Also make sure to not load somewhere the module source-map-support manually.

Elyx0 commented 4 years ago

I was definitely loading it manually! Fixed!