vuejs/vue-cli

Jest and TSX are not working

Maxim-Mazurok opened this issue · 5 comments

Version

4.5.12

Reproduction link

https://github.com/Maxim-Mazurok/vue-jest-tsx-error-repro

Environment info

Environment Info:

  System:
    OS: Linux 4.19 Ubuntu 20.04.2 LTS (Focal Fossa)
    CPU: (12) x64 AMD Ryzen 5 3600 6-Core Processor
  Binaries:
    Node: 14.16.0 - ~/.nvm/versions/node/v14.16.0/bin/node
    Yarn: 1.22.10 - ~/.nvm/versions/node/v14.16.0/bin/yarn
    npm: 6.14.11 - ~/.nvm/versions/node/v14.16.0/bin/npm
  Browsers:
    Chrome: 89.0.4389.90
    Firefox: Not Found
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.2.1 
    @vue/babel-helper-vue-transform-on:  1.0.2 
    @vue/babel-plugin-jsx:  1.0.4 
    @vue/babel-plugin-transform-vue-jsx:  1.2.1 
    @vue/babel-preset-app:  4.5.12 
    @vue/babel-preset-jsx:  1.2.4 
    @vue/babel-sugar-composition-api-inject-h:  1.2.1 
    @vue/babel-sugar-composition-api-render-instance:  1.2.4 
    @vue/babel-sugar-functional-vue:  1.2.2 
    @vue/babel-sugar-inject-h:  1.2.2 
    @vue/babel-sugar-v-model:  1.2.3 
    @vue/babel-sugar-v-on:  1.2.3 
    @vue/cli-overlay:  4.5.12 
    @vue/cli-plugin-babel: ~4.5.0 => 4.5.12 
    @vue/cli-plugin-router:  4.5.12 
    @vue/cli-plugin-typescript: ~4.5.0 => 4.5.12 
    @vue/cli-plugin-unit-jest: ~4.5.0 => 4.5.12 
    @vue/cli-plugin-vuex:  4.5.12 
    @vue/cli-service: ~4.5.0 => 4.5.12 
    @vue/cli-shared-utils:  4.5.12 
    @vue/component-compiler-utils:  3.2.0 
    @vue/preload-webpack-plugin:  1.1.2 
    @vue/test-utils: ^1.0.3 => 1.1.3 
    @vue/web-component-wrapper:  1.3.0 
    jest-serializer-vue:  2.0.2 
    typescript: ~4.1.5 => 4.1.5 
    vue: ^2.6.11 => 2.6.12 
    vue-cli-plugin-tsx-support: ~0.4.1 => 0.4.1 
    vue-hot-reload-api:  2.3.4 
    vue-jest:  3.0.7 
    vue-jsx-hot-loader: ^1.4.1 => 1.4.1 
    vue-loader:  15.9.6 (16.2.0)
    vue-style-loader:  4.1.3 
    vue-template-compiler: ^2.6.11 => 2.6.12 
    vue-template-es2015-compiler:  1.9.1 
    vue-tsx-support: ^3.1.0 => 3.1.0 
  npmGlobalPackages:
    @vue/cli: 4.5.12

Steps to reproduce

Clone the master branch of the repro repo, yarn, yarn test:unit, observe error: SyntaxError: Unexpected token 'export'

What is expected?

yarn test:unit
yarn run v1.22.10
$ vue-cli-service test:unit
ts-jest[versions] (WARN) Version 4.1.5 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions.
 PASS  tests/unit/example.spec.ts
  HelloWorld
    ✓ renders props.msg when passed (8ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.948s
Ran all test suites.
Done in 4.52s.

What is actually happening?

yarn test:unit
yarn run v1.22.10
$ vue-cli-service test:unit
ts-jest[versions] (WARN) Version 4.1.5 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions.
 FAIL  tests/unit/example.spec.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /home/maxim/vue-jest-tsx-error-repro/node_modules/vue-tsx-support/lib/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export * from "./api";
                                                                                             ^^^^^^

    SyntaxError: Unexpected token 'export'

    > 1 | import * as tsx from "vue-tsx-support";
        | ^
      2 | import { VNode } from "vue";
      3 |
      4 | export default tsx.component({

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at Object.<anonymous> (src/components/HelloWorld.tsx:1:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.701s
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.

See fixed branch for what has worked for me: https://github.com/Maxim-Mazurok/vue-jest-tsx-error-repro/tree/fixed (adding transformIgnorePatterns: [] to babel config).
Follow up to #3100

Thanks for reporting the issue.
This is kinda the expected behavior… And your fix is the correct way to work around this issue.

It's because Jest runs tests in the Node.js environment. It expects all the files to be in CommonJS format.
For user-written files, we've enabled the babel transformation that transpile ES modules into CommonJS modules.
But for dependencies, I think it's a reasonable assumption that Node.js packages should provide a CommonJS entry. So out of performance concerns, the node_modules directory is excluded.

A proper fix is to change the vue-tsx-support package to provide both CommonJS and ES module entries, following the guide from the Node.js documentation: https://nodejs.org/api/packages.html#packages_conditional_exports

Got it, I was having similar thoughts, thank you for confirming, I'll open an issue for vue-tsx-support. Feel free to close this one, if you think it should be closed.

@sodatea now that this issue was fixed in vue-tsx-support@3.2.0-beta.1, I'm getting the same issue with vuetify package:

SyntaxError: Unexpected token 'export'

      1 | import * as tsx from "vue-tsx-support";
      2 | import { VNode } from "vue";
    > 3 | import { VTabs, VTabsItems } from "vuetify/lib";
        | ^

Currently this workaround works:

transformIgnorePatterns: ["node_modules/(?!(vuetify)/)"],

Do you think I can get rid of transformIgnorePatterns completely? Should I open an issue for vuetify repo?

@sodatea can you take a look at this again, please?

Also, see vuetifyjs/vuetify#13841 and https://github.com/Maxim-Mazurok/vue-jest-tsx-error-repro/tree/vuetify (note vuetify branch) for repro.