Nanna
Nanna

Reputation: 575

Jest encountered an unexpected token when testing a Vue single file component

I have a vue application with single file components and i want to add unit tests to test the components. I'm trying to use jest like described here but i keep getting the error "Jest encountered an unexpected token" with the following details:

/some_path/MyRecipe.vue:1
<template>
^

SyntaxError: Unexpected token <

  1 | import { shallowMount } from "@vue/test-utils"
> 2 | import MyRecipe from "../src/components/MyRecipe.vue"
    | ^
  3 | 
  4 | describe('MyRecipe', () => {
  5 |   test('is a Vue instance', () => {

  at Runtime._execModule (node_modules/jest-runtime/build/index.js:1166:56)
  at Object.<anonymous> (__tests__/MyRecipe.test.js:2:1)

After some research (e.g. from here) I gather that this is probably due to jest expecting a .js file, but the .vue single file components have html, javascript and css in them, usually dealt with by webpack and vue-loader. I've tried to follow jest configurations from various tutorials to make jest use vue-jest to transform .vue files, but the error persists. This is my package.json file (unnecessary parts removed):

{
  "name": "all-recipes ",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    // ...
    "test": "jest"
  },
  "dependencies": {
    // ...
    "core-js": "^3.4.3",
    "vue": "^2.6.10"
    // ...
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.1.0",
    "@vue/cli-plugin-eslint": "^4.1.0",
    "@vue/cli-service": "^4.1.0",
    "@vue/test-utils": "^1.0.3",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.0.3",
    "babel-jest": "^26.0.1",
    // ...
    "jest": "^26.0.1",
    "jest-serializer-vue": "^2.0.2",
    "vue-jest": "^3.0.5",
    "vue-template-compiler": "^2.6.10",
    "vue-test-utils": "^1.0.0-beta.11"
  },
  // ...
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "vue"
    ],
    "transform": {
      ".*\\.,(vue)$": "vue-jest",
      "^.+\\.js$": "babel-jest"
    },
    "snapshotSerializers": [
      "jest-serializer-vue"
    ]
  }
}

Any idea what might be wrong, or some tips on how to debug this?

EDIT: I have looked into this question and I don't believe the answer there would solve my problem since what I am trying to import is a .vue file and not an .html file.

EDIT 2: I have a feeling that jest is somehow just not picking up the transforms, because removing them from package.json doesn't change anything.

EDIT 3: No, jest is correctly using vue-jest for transforming. If I uninstall vue-jest and try running the test again, jest complains that vue-jest is missing.

Upvotes: 7

Views: 15255

Answers (5)

Herobrine
Herobrine

Reputation: 3143

You need to install vue-jest (https://github.com/vuejs/vue-jest) with

npm install -D @vue/vue3-jest

Here are the available versions and their corresponding vue and jest versions

Vue version Jest Version Package
Vue 2 Jest <= 26 vue-jest@4
Vue 3 Jest <= 26 vue-jest@5
Vue 2 Jest 27 @vue/vue2-jest
Vue 3 Jest 27 @vue/vue3-jest

Then, you'll just have to update your jest configuration (in jest.config.ts for example) and add a transform section

"transform": {
    "^.+\\.vue$": "@vue/vue3-jest"
}

Warning: be sure to update the npm install and the jest.config.ts with the vue-jest package that match your need!

Upvotes: 0

shalini
shalini

Reputation: 1290

I faced same issues tried many solution but none of them work ..below is following workaround in my case

  1. Check package json has following dev dependency entries and jest configurations

     "devDependencies": {
         "babel-jest": "^23.6.0",
         "@vue/cli-plugin-babel": "~4.5.0",
         "@vue/cli-plugin-eslint": "~4.5.0",
         "@vue/cli-plugin-unit-jest": "~4.5.0",
         "@vue/cli-service": "~4.5.0",
         "@vue/eslint-config-airbnb": "^5.0.2",
         "@vue/test-utils": "^1.0.3",
         "babel-eslint": "^10.1.0",
         "eslint": "^6.7.2",
         "eslint-plugin-import": "^2.20.2",
         "eslint-plugin-vue": "^6.2.2",
           },
    
      "jest": {
         "moduleFileExtensions": [
         "js",
         "jsx",
         "json",
         "vue"
        ],
      "transform": {
        "^.+\\.vue$": "vue-jest"
        },
     "moduleNameMapper": {
       "^@/(.*)$": "<rootDir>/src/$1"
      },
    "snapshotSerializers": [
       "jest-serializer-vue"
     ],
    "testMatch": [
       "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*. 
    (js|jsx|ts|tsx)"
     ],
     "testURL": "http://localhost/"
     }
    
  1. Check babel.config.js

      module.exports = {
        presets: [
        '@vue/cli-plugin-babel/preset',
      ],
     };
    
  2. check jest.config.js

      module.exports = {
       preset: '@vue/cli-plugin-unit-jest',
      };
    

Upvotes: 0

MrKudu
MrKudu

Reputation: 41

What worked for me was changing the transform of the vue-jest to what is shown in the documentation. https://github.com/vuejs/vue-jest

so try using "^.+\\.vue$": "vue-jest" instead of "^[^.]+.vue$": "vue-jest" full config might look like this

{
  "jest": {
    "moduleFileExtensions": ["js", "json", "vue"],
    "transform": {
      "^.+\\.js$": "babel-jest",
      "^.+\\.vue$": "vue-jest"
     }
   }
}

Upvotes: 2

Eugene
Eugene

Reputation: 85

Met same issuesome time ago. What i found.

The problem was in the short note of template v-slot

template(v-slot:body)

It works to compile, but Jest throws an error

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.

There was two ways i fount to solve this:

  1. Edit my jest.config.js, like this
globals: {
  'vue-jest': {
    pug: {
      doctype: 'html',
    },
  },
},
  1. Write a full note like this template(v-slot:body="")

Upvotes: 3

Nanna
Nanna

Reputation: 575

The solution to my problem turns out to be a bit anti-climatic.

The problem was that my regexp string to recognize .vue files was wrong and didn't pick up my MyRecipe.vue file. Therefore, vue-jest wasn't used to transform it for jest to interpret, hence the trouble understanding that the file in question started with a very non-js line; <template>. The regexp that works is ^[^.]+.vue$, so the transform section of my package.json file becomes

{
  // ...
  "jest": {
    // ...
    "transform": {
      "^[^.]+.vue$": "vue-jest",
      "^.+\\.js$": "babel-jest"
    },
    // ...
  }
}

Upvotes: 5

Related Questions