swc icon indicating copy to clipboard operation
swc copied to clipboard

Incorrect Jest coverage

Open stephane-arista opened this issue 3 years ago • 76 comments

When using @swc/jest to transpile ts to commonjs and running jest --coverage certain branches are shown as not covered (console logging in these branches show that tests do run the code path). Using babel to transpile and run the tests shows the correct coverage.

stephane-arista avatar Sep 21 '21 21:09 stephane-arista

I added this to my Jest configuration in package.json which seemed to help.

"jest": {
    "collectCoverage": true,
    "transform": {
      "^.+\\.(t|j)sx?$": [
        "@swc/jest",
        {
          "sourceMaps": true
        }
      ]
    }
  }

pspeter3 avatar Oct 31 '21 17:10 pspeter3

@pspeter3 Thank you for your code snippet, it helps, but now there is another problem:

It looks like not covered code highlights are not displayed correctly.

There is an example of coverage report from project with:

image

the yellow highlight here says that the comma is supposedly not covered

krutoo avatar Dec 06 '21 08:12 krutoo

@krutoo ran into the same issues and guessed it is caused by the conversion to older JS syntax. We could fix these false-positives by targeting a newer ES version.

  transform: {
    '^.+\\.(t|j)sx?$': [
      '@swc/jest',
      {
        jsc: {
          target: 'es2021',
        },
        sourceMaps: true,
      },
    ],
  },

sebald avatar Dec 17 '21 12:12 sebald

@sebald Thank you, looks like it realy works with target: "es2021"

krutoo avatar Dec 28 '21 10:12 krutoo

Another reproduction here: https://github.com/typescript-eslint/tslint-to-eslint-config/pull/1367

I ended up only needing target: "es2021". Thanks!

JoshuaKGoldberg avatar Feb 20 '22 18:02 JoshuaKGoldberg

I think swc reusing span for various places may cause this.

Can you try https://sokra.github.io/source-map-visualization/#custom by manually invoking swc?

kdy1 avatar Feb 24 '22 07:02 kdy1

@kdy1 does this help? Maybe the Object.keys(_node).forEach produces the mismatch? Jest complains that this line is not covered: export * as node from './BodyNodesBuilder';

Bildschirmfoto 2022-02-25 um 15 19 50

Edit: tested with

  • @swc/jest 0.2.20
  • jest 27.5.1

bobaaaaa avatar Feb 25 '22 14:02 bobaaaaa

@bobaaaaa Can you share some code? I think the test file would be enough, as it does not have good sourcemap.

kdy1 avatar Mar 04 '22 08:03 kdy1

Oh... Maybe assumption about monotonic increment of source map position can be the cause. I'll add it to my tasklist

kdy1 avatar Mar 04 '22 08:03 kdy1

@kdy1 You can find it here: https://gist.github.com/bobaaaaa/3649b3a7e6312793a257bf67c500128a Let me know if something is missing.

(thx for investigating ❤️)

bobaaaaa avatar Mar 04 '22 09:03 bobaaaaa

You need sourceMaps: true or sourceMaps: "inline". I verified that it's working

kdy1 avatar Mar 05 '22 06:03 kdy1

@kdy1 Hm, I tested both sourceMaps in .swcrc and as an option in the jest.config.json. Both did not work for me. Even with target: "es2021".

bobaaaaa avatar Mar 05 '22 09:03 bobaaaaa

Hmm... Source maps are valid, maybe emitted tokens without sourcemap entry can be the cause I guess? Some sourcemap libraries have bugs related to it.

kdy1 avatar Mar 05 '22 09:03 kdy1

@kdy1 I updated the gist with the generated .js + .js.map files: https://gist.github.com/bobaaaaa/3649b3a7e6312793a257bf67c500128a

bobaaaaa avatar Mar 05 '22 09:03 bobaaaaa

I'm not sure why does jest can't understand the sourcemap. I need to dig into jest to know the source map library it uses...

kdy1 avatar Mar 11 '22 06:03 kdy1

Can you try the latest version of @swc/core? (v1.2.155)

Patches in https://github.com/swc-project/swc/pull/4007 are very likely to fix this issue.

kdy1 avatar Mar 14 '22 11:03 kdy1

@kdy1 I tested the new version. Unfortunately, its still not fixed :(

Tested with es2020 & es2021 + sourceMaps: true & sourceMaps: "inline". I updated all files in my gist build with v1.2.155: https://gist.github.com/bobaaaaa/3649b3a7e6312793a257bf67c500128a

(Keep in mind, this is not a huge blocker/issue for us. Still thx for looking into this)

bobaaaaa avatar Mar 14 '22 14:03 bobaaaaa

Can you try the latest version? (v1.2.156) There was a bug fix for a module that only contains export * from './foo' and such module is super common, so I think it can be the cause of this.

kdy1 avatar Mar 16 '22 10:03 kdy1

Can confirm same issue with vitest + swc with all recommended configs and latest version (v1.2.156)

wight554 avatar Mar 17 '22 09:03 wight554

@kdy1 problem is still there with v1.2.156

bobaaaaa avatar Mar 17 '22 09:03 bobaaaaa

@kdy1 I saw you created another fix (https://github.com/swc-project/swc/pull/4074) 👍 Because in 1.2.157 the issue is still present.

bobaaaaa avatar Mar 18 '22 11:03 bobaaaaa

I changed the milestone, thanks!

kdy1 avatar Mar 18 '22 11:03 kdy1

I triggered publishing of the new version

kdy1 avatar Mar 18 '22 12:03 kdy1

I see you fixed this in v1.2.158, but the problem persists after I update, is it my configuration problem?

transform: {
    '^.+\\.(t|j)sx?$': [
      '@swc/jest',
      {
        jsc: {
          target: 'es2021',
        },
        sourceMaps: true,
      },
    ],
  },

Edit: tested with

  • @nestjs 7.6.15
  • @swc/jest 0.2.20
  • @swc/core 1.2.158
  • jest 26.6.3

sscode02 avatar Mar 19 '22 10:03 sscode02

In my case all decorator occurrences in code are marked as uncovered branches Only way to get proper coverage report is to use tsc for test compilation

wight554 avatar Mar 19 '22 10:03 wight554

My reproduction repo for reference: https://github.com/wight554/blog-template/tree/swc-test Coverage report is included in coverage folder (see controllers)

---------------------------------------|---------|----------|---------|---------|-------------------
File                                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------------------------------|---------|----------|---------|---------|-------------------
All files                              |   99.61 |    67.21 |     100 |   99.61 |                   
 server/auth                           |     100 |      100 |     100 |     100 |                   
  AuthController.ts                    |     100 |      100 |     100 |     100 |                   
  AuthService.ts                       |     100 |      100 |     100 |     100 |                   
 server/auth/guards                    |      80 |      100 |     100 |      80 |                   
  JwtAuthGuard.ts                      |      80 |      100 |     100 |      80 | 1                 
  LocalAuthGuard.ts                    |      80 |      100 |     100 |      80 | 1                 
 server/comment                        |     100 |     37.5 |     100 |     100 |                   
  CommentController.ts                 |     100 |     37.5 |     100 |     100 | 19,25-26,33       
  CommentService.ts                    |     100 |      100 |     100 |     100 |                   
 server/comment/dto                    |     100 |      100 |     100 |     100 |                   
  CreateCommentDto.ts                  |     100 |      100 |     100 |     100 |                   
  UpdateCommentDto.ts                  |     100 |      100 |     100 |     100 |                   
 server/constants                      |     100 |      100 |     100 |     100 |                   
  controllers.ts                       |     100 |      100 |     100 |     100 |                   
 server/crypto                         |     100 |      100 |     100 |     100 |                   
  CryptoService.ts                     |     100 |      100 |     100 |     100 |                   
 server/decorators                     |     100 |      100 |     100 |     100 |                   
  UserDecorator.ts                     |     100 |      100 |     100 |     100 |                   
 server/enums                          |     100 |      100 |     100 |     100 |                   
  MongoError.ts                        |     100 |      100 |     100 |     100 |                   
 server/interceptors                   |   97.56 |      100 |     100 |   97.56 |                   
  ...ooseClassSerializerInterceptor.ts |   97.56 |      100 |     100 |   97.56 | 1                 
 server/post                           |     100 |    41.17 |     100 |     100 |                   
  PostController.ts                    |     100 |    41.17 |     100 |     100 | ...58-59,66,73-76 
  PostService.ts                       |     100 |      100 |     100 |     100 |                   
 server/post/dto                       |     100 |      100 |     100 |     100 |                   
  CreatePostDto.ts                     |     100 |      100 |     100 |     100 |                   
  UpdatePostDto.ts                     |     100 |      100 |     100 |     100 |                   
 server/user                           |     100 |       50 |     100 |     100 |                   
  UserController.ts                    |     100 |       50 |     100 |     100 | 28,31,37-40       
  UserService.ts                       |     100 |      100 |     100 |     100 |                   
 server/user/dto                       |     100 |      100 |     100 |     100 |                   
  CreateUserDto.ts                     |     100 |      100 |     100 |     100 |                   
  UpdateUserDto.ts                     |     100 |      100 |     100 |     100 |                   
 src                                   |     100 |      100 |     100 |     100 |                   
  app.tsx                              |     100 |      100 |     100 |     100 |                   
  logo.tsx                             |     100 |      100 |     100 |     100 |                   
---------------------------------------|---------|----------|---------|---------|-------------------

tsc reports 100% for all

wight554 avatar Mar 19 '22 10:03 wight554

yes, can confirm. This is still not fixed. But /* istanbul ignore next */ now works :)

bobaaaaa avatar Mar 19 '22 12:03 bobaaaaa

still not fixed in @swc/core 1.2.159 if it was meant to be fixed

wight554 avatar Mar 19 '22 16:03 wight554

yes, can confirm. This is still not fixed. But /* istanbul ignore next */ now works :)

@bobaaaaa

Do you find that while this works, it's not quite as well as babel-jest? For example I cannot ignore a whole file or large function blocks that have nested functions.

I'm able to ignore these files in collectCoverageFrom so not a blocker, but something I have observed.

chortis avatar Apr 01 '22 00:04 chortis

for no reason in one of the projects it is reproduced again

example: изображение

dependencies:

{
  "@swc/core": "^1.2.207",
  "@swc/jest": "^0.2.21",
  "jest": "^28.1.1"
}

krutoo avatar Jun 29 '22 10:06 krutoo