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.95k stars 452 forks source link

Issues with exporting and importing enums #281

Open glazar opened 7 years ago

glazar commented 7 years ago

TypeScript Version: 2.4.1

Code

file1.ts
export enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

export enum Numbers {
  ONE = 1,
  TWO = 2
}

file2.ts
import { Colors, Numbers } from "./file1";

Expected behavior: Colors and Numbers should not be undefined in file2. Colors should be:

{
  Red: "RED",
  Green: "GREEN",
  Blue: "BLUE"
}

Numbers should be

{
  ONE: 1,
  TWO: 2
  1: "ONE"
  2: "TWO"
}

Actual behavior: Colors and Numbers are undefined. Any enum entry requested fail with "Cannot read property 'enum entry' of undefined". It seems that this only occurs in case of a circular dependency. If you remove the circular dependency everything seems to work fine.

kulshekhar commented 7 years ago

@glazar is this similar to #112 ?

If not, would it be possible for you to create a minimal repo that reproduces this?

glazar commented 7 years ago

@kulshekhar I do not know whether this is related to #112 or is another issue altogether.

I have created a small repo reproducing this issue. Please have a look and let me know what you think.

This issue only happens for us only when running the unit tests. We have worked around this issue by removing the circular dependency. The problem is not visible when the code is bundled using webpack with ts-loader.

kulshekhar commented 7 years ago

Thanks for the repo. I was able to replicate this issue and dig into it a bit.

I think that this comment in the Typescript repo explains the cause of this issue.

Given that this is more of a Typescript issue, I'm not sure there's much we can do here

bencompton commented 7 years ago

From that comment, it appears that the TypeScript team has no intention of fixing this, and I don't really see how they could given that transpileModule has no consistently reliable way to resolve imports and access the enum definitions.

As this issue comment suggests, it isn't always safe to use transpileModule. I certainly understand the performance reasons why transpileModule was chosen for the preprocessor, though. The only solution I can think of would be to do a full compile ahead of time and then serve the transpiled JavaScript files as Jest requests them. That is not a trivial change, of course, and would require having a watch process in place as well.

rikkit commented 7 years ago

Would it be workable to change the preprocessor to use a different compiler api - but just passing in the test file and a preconfigured list of files containing const enums? Or would that still kill performance?

I remember a comment in another issue which suggested they rewrote the const enums after compilation using a webpack plugin - maybe that would be more viable?

kulshekhar commented 7 years ago

@rikkit if there's a workable solution, we can find a way to get that in

goloveychuk commented 7 years ago

faced with same problem. But not with enums but with using my library (https://github.com/goloveychuk/tsruntime) which uses custom transformers api. It emits types metadata and requires types from imported module. So it's any everywhere. So, as I see, two options to workaround 1) run program.emit with filelist of all files. But this will affect performance since it will compile same files many times. 2) use LanguageServiceHost compiler api, and compile all files before jest stage starts.

goloveychuk commented 7 years ago

https://github.com/goloveychuk/awesome-ts-jest Proof of concept, which solves problem with imported enums and custom transformers. With smart files updating (versioning) it should work pretty fast.

GeeWee commented 6 years ago

This might be solved by #505

huafu commented 6 years ago

You can test with beta version (see #697) which handles const enum and others thanks to the language service.

nikoremi97 commented 5 years ago

I faced the same problem with enum in unit tests. The problem was the services with the enum var were mocked, and the mock did not have the enum var. The solution was copy the enum also in the mocked service and export it so the classes that used the service can access to it.

on ServiceA.ts

export enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

and also on ServiceAMock.ts

export enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}
yoasia commented 5 years ago

I had the same problem. Here is what helped me:

  1. Make enum const. export const enum OneTwoThreeEnum { One = 'one', Two = 'two', Three = 'three' }
  2. Use it like this: const something = "One" as OneTwoThreeEnum.One
rikkit commented 5 years ago

@yoasia This issue is fixed with version 23.10 - try upgrading if you haven't already.

thefill commented 5 years ago

I can confirm this is still an issue for version "24.0.2".

germain-receeve commented 5 years ago

Any update on this once, we're still facing the issue in our Vue project?

rikkit commented 5 years ago

What's the issue @germain-receeve @thefill ? 23.10 works for me, referencing const enums in test files with no problem. What's the difference?

germain-receeve commented 5 years ago

To give a bit more context, we had an issue with one of our dependency ,for the example let's call itDEPENDENCY_NAME, that wouldn't compile properly when running tests.

We ended up solving the issue by updating our jest.config.js file: we added core-js to setup files and isolated modules from ts jest.

  setupFiles: ["core-js"],
  transformIgnorePatterns: ["/node_modules/(?!(DEPENDENCY_NAME)/)"],
  globals: {
    "ts-jest": {
      isolatedModules: true
    }
  }

Hope this can help other people!

dskopa-softdev commented 5 years ago

Why is it closed? I can't use exported enum in my tests

actions.ts:

export const enum DefinitionActionType {
    LOADING_DEFINITIONS = 'definitions/LOADING_DEFINITIONS',
    LOADED_DEFINITIONS = 'definitions/LOADED_DEFINITIONS',
}

When running normally it's fine, but when i run tests it fails:

 FAIL  src/reducers/definitions/reducer.test.ts
  ● Test suite failed to run

    TypeError: Cannot read property 'LOADING_DEFINITIONS' of undefined

      25 | export function reducer(state = initialState, action: DefinitionActions): State {
      26 |     switch (action.type) {
    > 27 |         case DefinitionActionType.LOADING_DEFINITIONS:
         |                                       ^
      28 |             return {
jemerald commented 4 years ago

I'm seeing the same problem with version 24.0.2.

Seems to only happen when isolatedModules: true is used, but we need this setting to improve performance issue (#1115).

cbaron commented 4 years ago

I found a workaround that sort of makes things okay:

It works if you have a module file that only exports enums

     jest": "^24.9.0",
    "ts-jest": "^24.2.0",
    "typescript": "^3.7.2"
ahnpnl commented 4 years ago

There is a note that if using enum inside .d.ts won’t work, but const enum will work.

droplet-js commented 4 years ago

There is a note that if using enum inside .d.ts won’t work, but const enum will work.

i have same issue!

lucasriondel commented 4 years ago

@ahnpnl @v7lin same here.

ahnpnl commented 4 years ago

I'm seeing the same problem with version 24.0.2.

Seems to only happen when isolatedModules: true is used, but we need this setting to improve performance issue (#1115).

Const enum doesn’t work with isolatedModules: true because typescript transpile API doesn’t support it, you can check in the documentation.

@lucasriondel are you using isolatedModules: true ?

safareli commented 3 years ago

I still have same issue. what's the solution and is it documented somewhere?

ahnpnl commented 3 years ago

@safareli are you using isolatedModules: true ?

safareli commented 3 years ago

@ahnpnl, no I don't have it in my tsconfig.json (or any other place)

ahnpnl commented 3 years ago

I meant ts-jest option isolatedModules in your jest config.

If you have it as true, enum won't work. If you have it as false (default) it should work.

If you have it as false and it still doesn't work, you can share a repo so I can help.

safareli commented 3 years ago

@ahnpnl 🤦 so the issue was that I had one file "foo.json" and "foo.ts" in same folder and when I was compiling using tsc foo.ts and checking output it was fine. But when jest was resolving import of "./foo" looks like it is first checking if .json exists which it was, so it was requiring the json file instead of the ts file, that's why I had the issue.

DoctypeRosenthal commented 3 years ago

@safareli you gave me the idea of checking this in my code because I had the same problem. Turns out we had too many index.ts which re-exported stuff from sub-modules. So I specified my inports in those modules where the error occured and voilá: fixed it! eg. import { crudEntityFactory, ReduxEntities, RootState } from '@core/data'; became import { crudEntityFactory, ReduxEntities, RootState } from '@core/data/redux';

zarnoevic commented 3 years ago

I can confirm the issue remains in version "26.2.0".

jdpaterson commented 3 years ago

Experiencing this issue in "27.0.5" when exporting default const enums. Seems to work properly when just exporting default enums (not const)

johny-nowotny commented 2 years ago

Thank you for all suggestions, they solved my problem! I'll leave what helped me for others to find. For me making the dependency tree a bit more granular helped, either:

njfix6 commented 2 years ago

I am also still seeing this issue. I just isolatedModules: true and isolatedModules: false and still running into Cannot read properties of undefined (reading 'All') for both.

My enum that I am exporting is not with const:

export enum Type {
  All = 'All',
  Both = 'BOTH',
}
gtwebsite commented 2 years ago

Im using ts-jest 27.1.4, it still shows the error. isolatedModules doesnt affect any. im using export enum inside a d.ts file. I cannot changed this file because it's from codegen

atheck commented 2 years ago

I have the same issue with an enum from a third-party package.

Mnigos commented 1 year ago

same here

  ● Test suite failed to run

    TypeError: Cannot read properties of undefined (reading 'AUTH')

      4 |
      5 | @Module({
    > 6 |   imports: [RmqModule.register({ name: Services.AUTH })],
        |                                                 ^
      7 |   exports: [RmqModule],
      8 | })
      9 | export class AuthModule {}
 export enum Services {
  AUTH = 'AUTH',
  STATISTICS = 'STATISTICS',
}
hichemBAALI commented 1 year ago

Hi people.

On my end the issue was only happening for .ts files and not for .tsx I duplicated the declaration on the .ts files then the test passed.

rubickecho commented 1 year ago

yes, i have this problem too, but I don't know how to solve it either.

MatejVukosav commented 1 year ago

Just put enum in separate file. It works for me.

Aure77 commented 1 year ago

Still happen in ts-jest v29. Why is this issue closed ?

christiangrothaus commented 8 months ago

The only workaround I have found is to mock the enum in the test file and declare it as a object. Trying to mock it in anyway in a mock file failed to work and declaring it as an enum in the test file also failed to work.

redplane commented 4 months ago

Still happens to:

"ts-jest": "^29.1.4"
"jest": "^29.7.0",
"jest-environment-node": "^29.7.0",

This is very annoyning and frustrating issue. I wonder whether the fix has been tested carefully before closing this issue ?

bayraak commented 2 months ago

Still happening :/ How the fundamental thing in TS can not work for years I can't understand

timvw commented 1 month ago

Only thing that works for me is putting the enum in a .ts file (and not in tsx)