vuejs / vue-jest

Jest Vue transformer
MIT License
746 stars 157 forks source link

Vue3 "SyntaxError: Unexpected token 'export'" on import of js-vue file inside of ts-vue file #435

Open gsedlacz opened 2 years ago

gsedlacz commented 2 years ago

When importing a javascript based vue component inside of typescript vue component I receive the following error:

  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • 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/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    C:\dev\git\vite-jest-issue-example\src\components\TestWorld.vue:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export default {
                                                                                      ^^^^^^

    SyntaxError: Unexpected token 'export'

      1 | <script setup lang="ts">
    > 2 | import TestWorld from "@/components/TestWorld.vue";
        | ^
      3 |
      4 | defineProps<{ msg: string }>()
      5 | </script>

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
      at Object.<anonymous> (src/components/HelloWorld.vue:2:1)

By making TestWorld use ts (<script lang="ts"> ...) the test is able to work as expected.

Example Project: https://github.com/gsedlacz/vue3-jest-issue-example

Is there any known Workaround? I already found these isues which unfortunately did not work for me:

kinoli commented 2 years ago

Did you find a solution for this. I'm experiencing the same issue. Not using TS though.

<script>
export const someVar = 'something'; // this is where the error is coming from
</script>

<script setup>
...
</script>
vetruvet commented 2 years ago

I am experiencing this too (very similar reproduction to the repo linked in the initial report), but with @vue/vue2-jest@28.0.1 and vue@2.7.8 - adding lang="ts" to non-TS components seems to help but (a) not technically correct as those components aren't typed and/or will fail type checks; and (b) not an option for some third-party components

vetruvet commented 1 year ago

For me the issue turned out to be babel config not being used correctly. After digging through the code I found a way to make it work using a somwhat-undocumented config option to provide a custom babel transformer:

Jest config:

module.exports = {
  // ... whatever else ...
  globals: {
    'vue-jest': {
      transform: {
        js: './babel-jest-transformer.js',
      },
    },
  },
  transform: {
    '.*\\.js$': './babel-jest-transformer.js',
    '.*\\.vue$': '@vue/vue2-jest',
  },
};

babel-jest-transformer.js:

const babelConfig = {
  // ... whatever else ...
  plugins: [
      '@babel/plugin-transform-modules-commonjs',
  ],
};

module.exports = require('babel-jest').createTransformer(babelConfig);
letehaha commented 1 year ago

For me the issue turned out to be babel config not being used correctly. After digging through the code I found a way to make it work using a somwhat-undocumented config option to provide a custom babel transformer:

Jest config:

module.exports = {
  // ... whatever else ...
  globals: {
    'vue-jest': {
      transform: {
        js: './babel-jest-transformer.js',
      },
    },
  },
  transform: {
    '.*\\.js$': './babel-jest-transformer.js',
    '.*\\.vue$': '@vue/vue2-jest',
  },
};

babel-jest-transformer.js:

const babelConfig = {
  // ... whatever else ...
  plugins: [
      '@babel/plugin-transform-modules-commonjs',
  ],
};

module.exports = require('babel-jest').createTransformer(babelConfig);

For me it worked perfectly!

Btw I got this problem when moved my configs out of the root directory. In case it helps to fix.