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

Dynamic import support? #258

Closed
screendriver opened this issue Jul 4, 2017 · 49 comments
Closed

Dynamic import support? #258

screendriver opened this issue Jul 4, 2017 · 49 comments

Comments

@screendriver
Copy link
Contributor

  • Issue

Because ts-jest overrides module to commonjs in thetsconfig.json no tests can be written with the new dynamic import('./myModule') syntax. You get either 'import' and 'export' may only appear at the top level or a Syntax error.

  • Expected behavior

Dynamic imports should work.

  • Link to a minimal repo that reproduces this issue

Just type import('./myModule') in your test or implementation. That's enough.

@kulshekhar
Copy link
Owner

This is a new feature in TypeScript, right?

I haven't tested this yet but I'm marking it as a bug.

@screendriver
Copy link
Contributor Author

Yes, it is a new feature 😉

@kulshekhar
Copy link
Owner

@screendriver I've added a test that seems to be passing

Can you see if the test covers this issue?

If it does, then I'm not sure why it isn't working for you. Did you test with the latest typescript version?

@screendriver
Copy link
Contributor Author

Oh. You are right. In my little test repository it is working as well 😳

But: if you enable "allowSyntheticDefaultImports": true the error occurs that I get currenlty in my real project.

@kulshekhar
Copy link
Owner

can you try setting skipBabel to false (docs)

(this will prevent hoisting of mocks, though)

@kulshekhar
Copy link
Owner

kulshekhar commented Jul 4, 2017

I've added a test for dynamic imports with allowSyntheticDefaultImports set to true. If you don't need babel, the solution is to skip it (see my previous comment).

If you need babel, you might have to add the right plugin and update your .babelrc (this is conjecture - I haven't tested this)

@screendriver
Copy link
Contributor Author

If if set skipBabel to true I get a lot of like TypeError: Cannot read property 'Nothing' of undefined or jest.fn() value must be a mock function or spy. If I set skipBabel to false everything works but dynamic imports.

By the way: I don't use Babel in my project. There is only TypeScript (and webpack). Nothing more.

@kulshekhar
Copy link
Owner

I'm not sure what's going on. Can you do one of the following:

  • create a minimal repo that reproduces this
  • add a test in the new branch here that reproduces this. I've already added two tests. You can add more to replicate this issue

?

@screendriver
Copy link
Contributor Author

I created for you a minimal repository where you can reproduce the error.

tsc runs fine (and it works in the browser as well)
jest fails with errors.

I added

"ts-jest": {
  "skipBabel": true
}

and allowSyntheticDefaultImports to true. If you set skipBabel to false you get the import syntax error.

@kulshekhar
Copy link
Owner

So when you set skipBabel to true, does it work for you?

@screendriver
Copy link
Contributor Author

If if set skipBabel to true I get a lot of like TypeError: Cannot read property 'Nothing' of undefined

@kulshekhar
Copy link
Owner

This doesn't look like a ts-jest issue. I've sent a PR to the minimal repo of a version which works fine. It's got something to do with how Maybe is imported

@kulshekhar
Copy link
Owner

on second thoughts, hang on. This might be an issue with ts-jest

@kulshekhar
Copy link
Owner

kulshekhar commented Jul 4, 2017

yeah, I've just tested this without ts-jest and the way Maybe is imported needs to change for this to work. Here's a repo that demonstrates this without ts-jest. Run 'yarn' and 'yarn test' to see the working version.

If you replace the import in App.tsx with the kind you have, it'll show Maybe as undefined

@screendriver
Copy link
Contributor Author

Thank you 👍

I ended up in fixing the type definition (because it was wrong. There is no default export) and disabled allowSyntheticDefaultImports in general. Now everything works fine 😎

@screendriver
Copy link
Contributor Author

Just a little update @kulshekhar : could you try it with target: "es2015" in your tsconfig.json? I'm getting errors again when I change target to es5 to es2015. This time a Unexpected token

@kulshekhar
Copy link
Owner

Jest needs to be fed the es5 version, either directly from typescript or via babel. That's probably what's causing this issue. It's most likely not related to dynamic imports

@screendriver
Copy link
Contributor Author

Ah ok. So no matter if I have Node 8.* installed and can use almost every shiny new JavaScript language feature I still have to transpile everything down to ES5? If yes: this results in slower transpilation and runtime. If we could use ES2015 as target for example, TypeScript has to transpile almost nothing and Node could run the code almost as it was written (except the imports and type definitions) => faster transpilation, faster runtime.

@kulshekhar
Copy link
Owner

It's just the module resolution part I think. Natively, node doesn't understand 'import'

@screendriver
Copy link
Contributor Author

except the imports and type definitions

as I said 😁

@jimthedev
Copy link
Contributor

Hi @screendriver, @kulshekhar so if I am correct then at the moment you cannot have allowSyntheticDefaultImports: true and have dynamic import work?

@gabeweaver
Copy link

i can confirm that's correct at least as far as i've experienced things....every time i try with it enabled, jest fails...

 FAIL  src/lib/localizations/LocalizationManager.spec.tsx
  ● Test suite failed to run

    /Users/Gabe/Sites/roastlogger-web/src/lib/docs/index.tsx: Unexpected token (6:18)
        4 | const Loader = props => React.createElement('div', props);
        5 | const Docs = loadableVisiblity({
      > 6 |     loader: () => import('./container'),
          |                   ^
        7 |     loading: Loader
        8 | });
        9 | export { actions, actionTypes, KEY, reducer };

@jimthedev
Copy link
Contributor

jimthedev commented Oct 26, 2017

@gabeweaver I actually have it working however I had to bring in react-loadable using require() syntax instead of import.

@GeeWee
Copy link
Collaborator

GeeWee commented Oct 30, 2017

I'm not quite sure why this doesn't work - would love a PR with a fix.

@Sun1ive
Copy link

Sun1ive commented Apr 10, 2018

++++

test failing to run cause of imports

component: () => import(/* webpackChunkName: 'group-app' */ '@/views/Dashboard.vue')

@huy-nguyen
Copy link

huy-nguyen commented Apr 27, 2018

I think I ran into the same problem as you guys and I made a minimal repro repo here so that the maintainers can figure out what's wrong. Steps to reproduce:

  • Clone and run yarn.
  • git checkout ea5ea730.
  • Run npm test. Tests fail because of the dynamic import in src/addAndMultiply.ts.
  • git checkout df062207.
  • Run npm test. Tests pass because of this change.

@kulshekhar
Copy link
Owner

@screendriver does the change that worked for @huy-nguyen work for you?

@screendriver
Copy link
Contributor Author

screendriver commented Apr 30, 2018

Hi @kulshekhar,

unfortunately not because @huy-nguyen just disable allowSyntheticDefaultImports for it's tests and that's it. That means that your code with third party dependencies (for example import React from 'react') will not compile anymore when you run tsc -p <your-directory-with-the-test-tsconfig>.

I already have two tsconfig.json files:

  • one for my production application code
  • one for my tests (where I set "module": "commonjs")

In my CI build I run tsc and after that tsc -p tests. When I enable allowSyntheticDefaultImports in the first tsconfig.json and disable that in in the test specific second tsconfig.json the build will fail. If I would disable the second build step tsc -p tests and just rely on jest and only would run the jest tests without compilation I get a lot of failing tests because for example

Warning: React.createElement: type is invalid -- expected a string (for built-in
components) or a class/function (for composite components) but got:
undefined. You likely forgot to export your component from the file it's
defined in, or you might have mixed up default and named imports.

because TypeScript emits wrong / no files for third party dependencies like import glamorous from 'glamorous';

@screendriver
Copy link
Contributor Author

Finally I could create a repository that reproduces this issue 🎉

  • If you run yarn tsc everything works.
  • If you run yarn jest you can see the new error coming up when I set allowSyntheticDefaultImports to false in my test tsconfig.json
  • If you run yarn tsc -p test-setup you can see that the workaround above is not a real solution (additionally to the failing tests)

@GeeWee
Copy link
Collaborator

GeeWee commented May 5, 2018

This might be solved by #505

@screendriver
Copy link
Contributor Author

I upgraded to version 22.4.5 now and nothing changed 🤔

@GeeWee
Copy link
Collaborator

GeeWee commented May 7, 2018

Did you set the useExperimentalLanguageServer flag to true?

@screendriver
Copy link
Contributor Author

I enabled that now (I oversight that flag...) but the tests are now really slow (4 tests are running in 30 seconds 😳) and I'm getting different errors now:

    TypeError: Cannot read property 'text' of undefined

      at transpileViaLanguageServer (node_modules/ts-jest/dist/transpiler.js:61:21)
      at Object.transpileTypescript (node_modules/ts-jest/dist/transpiler.js:10:16)
      at process (node_modules/ts-jest/dist/preprocessor.js:27:41)
      at Object.process (node_modules/ts-jest/index.js:8:51)

@GeeWee
Copy link
Collaborator

GeeWee commented May 14, 2018

Yeah it's definitely slower. Thanks for trying it out.

@noblica
Copy link

noblica commented May 22, 2018

The issue still persists in the 22.4.6 version.

I've created a small repo with steps to reproduce the issue.

@screendriver
Copy link
Contributor Author

@noblica this is a different issue. You just have to define

{
  "extends": "./tsconfig",
  "compilerOptions": {
    "module": "commonjs"
  }
}

in your tsconfig.jest.json as mentioned in the docs 😉

@noblica
Copy link

noblica commented May 22, 2018

@screendriver I did, but the error persisted.

But then I removed the enableTsDiagnostics flag, and it works, for some reason?

Also leaving the enableTsDiagnostics flag, and setting the allowSyntheticDefaultImports to false also makes the tests work, so I'm not sure what's going on.

@screendriver
Copy link
Contributor Author

In your repo I see "module": "esnext" and no "module": "commonjs" as I wrote so it can't work in your demo repository

@screendriver
Copy link
Contributor Author

screendriver commented May 22, 2018

I did a pull request and it works now in your repository (it's a different issue as I said 😉)

noblica/ts-jest-dynamic-imports#1

@rssfrncs
Copy link

Hi i've tried out the above solution with a separate jest tsconfig however i'm still getting the same error.

The only difference to add is that I'm in a mixed TS project (js enabled). Could this be the cause?

@christophercurrie
Copy link

In case this helps anyone in the future, I got this working by configuring .babelrc to add dynamic import support as indicated in the Jest docs:

{
  "presets": [["env", {"modules": false}]],

  "plugins": ["syntax-dynamic-import"],

  "env": {
    "test": {
      "plugins": ["dynamic-import-node"]
    }
  }
}

Note you may need to run jest --clearCache to clear your Jest cache to get this to work.

If you don't use babel for your project normally, you will still need to add a .babelrc file and devDependencies on these two plugins just for this use case.

@tim-yao
Copy link

tim-yao commented Jul 17, 2018

Thanks @christophercurrie ! jest --clearCache is the tricky part!! After add dynamic-import-node please remember to clear cache first. It took me a hour to figure out!

@huafu
Copy link
Collaborator

huafu commented Jul 24, 2018

tested with repo, #626 will address the caching part as well as the dynamic import()

@huafu
Copy link
Collaborator

huafu commented Aug 3, 2018

fixed in 23.1.2

@miluoshi
Copy link

In case someone still struggles with this problem, what helped for me was changing Jest preset from
ts-jest/presets/js-with-babel to ts-jest/presets/js-with-ts. I guess it had something to do with the fact that in our codebase we use mix of js and ts files and our tests are written in TS while the tested file with dynamic import was still JS.

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

No branches or pull requests