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

Jest tests can't process import statement #1584

Open
ijdickinson opened this issue Jun 15, 2018 · 249 comments
Open

Jest tests can't process import statement #1584

ijdickinson opened this issue Jun 15, 2018 · 249 comments

Comments

@ijdickinson
Copy link

ijdickinson commented Jun 15, 2018

Version

3.0.0-rc.2

Reproduction link

https://github.com/ijdickinson/vue-cli-jest-problem

Steps to reproduce

This is a similar problem to 1475, but I can't find a way to resolve it. I created a new app with vue-cli, selecting Jest tests. I added a simple POJO (src/models/model.js) and a test for it (tests/model.spec.js).

To repro the problem, just npm run test:unit

What is expected?

Tests to pass, or at least run

What is actually happening?

$ npm run test:unit

> [email protected] test:unit /home/ian/workspace/project/test-application
> vue-cli-service test:unit

 FAIL  tests/unit/model.spec.js
  ● 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://facebook.github.io/jest/docs/en/configuration.html

    Details:

    /home/ian/workspace/project/test-application/tests/unit/model.spec.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import "core-js/modules/es6.promise";
                                                                                             ^^^^^^

    SyntaxError: Unexpected token import

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:402:17)

 PASS  tests/unit/HelloWorld.spec.js

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.427s
Ran all test suites.
 ERROR  jest exited with code 1.
@minorgod

This comment has been minimized.

@ijdickinson

This comment has been minimized.

@Akryum

This comment has been minimized.

@marlonbarcarol

This comment has been minimized.

@onigunn
Copy link

onigunn commented Jun 22, 2018

Adding '^.+\\.js$': 'babel-jest' was not enough for me. Tests run only on empty cache once and started throwing Unexpected token errors on change. As mentioned here I also had to add transformIgnorePatterns ['<rootDir>/node_modules/'] to my jest.config.js

Full jest.config.js

module.exports = {
  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub',
    '^.+\\.(js|jsx)?$': 'babel-jest'
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  snapshotSerializers: ['jest-serializer-vue'],
  testMatch: [
    '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
  ],
  transformIgnorePatterns: ['<rootDir>/node_modules/']
};

For now everything seems to be good.

@tinchox5

This comment has been minimized.

@Akryum Akryum added bug scope: unit-jest priority: now needs team repro We acknowledged your report and will soon try to reproduce it labels Jun 28, 2018
@hajarrashidi

This comment has been minimized.

@beey-keey

This comment has been minimized.

@rahulakurati

This comment has been minimized.

@marcusnunes
Copy link

Is everyone here using windows? I didn't reproduce the error on mac.

@Akryum
Copy link
Member

Akryum commented Jul 5, 2018

Note: I can't reproduce on the dev environment.

@ijdickinson
Copy link
Author

ijdickinson commented Jul 5, 2018

Is everyone here using windows?

I'm using Ubuntu 18.04

@joebartels
Copy link

Reproduced on mac here.
For me it occurred after manually incremented all the @vue/* packages to rc.3 from one of the betas (beta.16 I think).
I did a rm -rf node_modules && npm cache clean --force && npm install

^ began erroring.

What ended up working for me was globally installing the latest @vue/vue-cli (rc.3) and starting a new project. This also installed all rc.3 @vue/* packages but for some reason it no longer errored.

@zhangfaliang

This comment has been minimized.

@onekiloparsec
Copy link

onekiloparsec commented Jul 6, 2018

I did a full clean as proposed by @joebartels above, and I also updated (through the UI) to RC3, but to no avail. Same errors.

It seems to appear only in my tests involving vuex.

@rahulakurati
Copy link

I’m running on Mac. I configured this for vuejs. And it worked for me.

@Akryum
Copy link
Member

Akryum commented Jul 8, 2018

I can't reproduce the issue on Windows 10 & Node 10.4.1:

@Akryum Akryum closed this as completed Jul 8, 2018
@Akryum Akryum added cannot reproduce We cannot reproduce the problem with the given information. More env information needed. and removed needs team repro We acknowledged your report and will soon try to reproduce it bug labels Jul 8, 2018
@k-funk

This comment has been minimized.

@onekiloparsec
Copy link

That's it ? Closed ? Well, I am on a Mac, with RC3, and still have the exact same errors. I tried everything that is suggested in this thread. For the archive, here is my latest jest.config.js:

module.exports = {
  moduleFileExtensions: [
    'js',
    'jsx',
    'json',
    'vue'
  ],
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
    '^.+\\.js$': 'babel-jest'
  },
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  snapshotSerializers: [
    'jest-serializer-vue'
  ],
  testMatch: [
    '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
  ],
  transformIgnorePatterns: ['<rootDir>/node_modules/']
}

@onekiloparsec
Copy link

onekiloparsec commented Jul 12, 2018

Since it was failing on my newly created test file, I decided to remove it. But after 2 min, not happy with this situation, I wanted to retry, so I put it back. And all green ! Tested again, all green.

There must be something fishy with a cache somewhere, no?

@joebartels
Copy link

@onekiloparsec that loosely resembles what happened to me.
However, instead of removing the file and placing it back, I started a new project with latest vue-cli (@vue/vue-cli (rc.3)) and one-by-one copied files from the "broken" directory into the new one...

@VIGDXX
Copy link

VIGDXX commented Mar 27, 2020

[ '@babel/preset-env', { modules: 'commonjs', } ]
i meet this problem and solved id by setting 'modules' as 'commonjs' 😄

@jzebgul
Copy link

jzebgul commented Apr 4, 2020

its cannot find the import and getting this error
RUNS src/tests/add.test.js
RUNS src/tests/actions/expenses.test.js

FAIL src/tests/actions/expenses.test.js

RUNS src/tests/add.test.js
RUNS src/tests/actions/expenses.test.js

● 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:

C:\expensify\src\tests\actions\expenses.test.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { addExpense, editExpense, removeExpense } from '../../actions/expenses';
                                                                                         ^^^^^^

SyntaxError: Cannot use import statement outside a module

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1085:14)

RUNS src/tests/add.test.js
RUNS src/tests/actions/expenses.test.js

RUNS src/tests/add.test.js
RUNS src/tests/actions/expenses.test.js

RUNS src/tests/add.test.js

PASS src/tests/add.test.js (5.007s)

RUNS src/tests/add.test.js

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

@mohsenuss91
Copy link

mohsenuss91 commented Apr 15, 2020

@onigunn @onekiloparsec Can't find the jest.config.js file!

@WebKieth
Copy link

WebKieth commented Apr 15, 2020

Same error on Create React App with jest-puppeteer e2e test.
I replaced import statements to require and for CRA it works!

sign_in.test.js:

const signIn = require('./jest.sign_in')
describe('sign_in', () => {
  beforeEach(async () => {
    await page.goto('http://localhost:3000')
  })
 it('should log in auth form', async () => {
    try {
      await signIn(page)
    } catch (err) {
      console.warn(`Unexpected test error: ${err}`)
    }
  }, 4000)
})

jest.sign_in.js:

async function signIn (page) {
    await page.click('input[type=email]')
    await page.keyboard.type('[email protected]', {delay: 10});
    await page.click('input[type=password]')
    await page.keyboard.type('Password', {delay: 10});
    await page.keyboard.press('Enter');
    await page.waitFor(1000);
    await expect(page.url()).toMatch('/account')
}

module.exports = signIn

@WebKieth
Copy link

[ '@babel/preset-env', { modules: 'commonjs', } ]
i meet this problem and solved id by setting 'modules' as 'commonjs' 😄

Surely it's a ES6 module syntax transpiling issue. Your solution, as mine goin to work for any boilerplate, I think. But i wont eject webpack from CRA and hasnt got .babelrc, babel.config and jest.config, as you, @mohsenuss91. Try to my solution
Just replace es6 import to commonjs require

@mohsenuss91
Copy link

@WebKieth I'm using VueJs and I'm trying with:
import { shallowMount } from '@vue/test-utils'

But still getting this:
`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:

D:\Users\PC01\school\tests\features\Unit.spec.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { shallowMount } from '@vue/test-utils';
                                                                                         ^^^^^^

SyntaxError: Cannot use import statement outside a module

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1086:14)`

@WebKieth
Copy link

WebKieth commented Apr 15, 2020

shallowMount

@mohsenuss91 aw, as u see I dont use built-in test utilities (like vue's shallowMount or react's renderer), I use puppeteer instructions - It's just another way to test. My React Tools dont do anything inside test scripts - so I dont import it. I import only required repeated actions.
When I need to test, I just turn on my dev server and run tests inside puppeteer session.

@mohsenuss91
Copy link

Is everyone here using windows? I didn't reproduce the error on mac.

@marcusnunes I'm using windows10, and still got this :

`({"Object.":function(module,exports,require,__dirname,__filename,global,jest){import { shallowMount } from '@vue/test-utils';
^^^^^^

SyntaxError: Cannot use import statement outside a module

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1086:14)

Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.3s
Ran all test suites.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test: jest
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
`

Here is my jest.config.js file:
module.exports = { moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], transform: { "^.+\\.js$": "babel-jest", ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub" }, moduleNameMapper: { "^.+.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub" }, snapshotSerializers: [ "<rootDir>/node_modules/jest-serializer-vue" ], testMatch: [ '<rootDir>/tests/**/*.spec.(js|jsx|ts|tsx)|<rootDir>/**/__tests__/*.(js|jsx|ts|tsx)' ], transformIgnorePatterns: ['<rootDir>/node_modules/'] };

@kaypon
Copy link

kaypon commented May 1, 2020

I'm currently stuck on something I believe is related.

My components.spec.js contains the following basic test:

import { mount } from '@vue/test-utils'
import Quiz from '@/Quiz.vue'

describe('Quiz', () => {
    test('is a Vue instance', () => {
        const wrapper = mount(Quiz)
        expect(wrapper.isVueInstance()).toBeTruthy()
    })
})

The Quiz.vue has the following imports:

......
<script>
import { mapState } from 'vuex'
import Loading from '~/components/Quiz/Loading'
import QuizStep from '~/components/Quiz/Step'
import NameStep from '~/components/Quiz/StepType/Name'
import GradeStep from '~/components/Quiz/StepType/Grade'
......

When I run jest I receive the following output:

$ yarn test
yarn run v1.22.4
$ jest
 FAIL  components/__tests__/components.spec.js
  ● Test suite failed to run

    Cannot find module '~/components/Quiz/Loading' from 'Quiz.vue'

    Require stack:
      components/Quiz.vue
      components/__tests__/components.spec.js

      38 | <script>
      39 | import { mapState } from 'vuex'
    > 40 | import Loading from '~/components/Quiz/Loading'
         | ^
      41 | import QuizStep from '~/components/Quiz/Step'
      42 | import NameStep from '~/components/Quiz/StepType/Name'
      43 | import GradeStep from '~/components/Quiz/StepType/Grade'

      at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:299:11)
      at components/Quiz.vue:40:1
      at Object.<anonymous> (components/Quiz.vue:456:3)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        3.041s
Ran all test suites.

I have bashed my head the whole day trying to get it to work but nothing. I can provide further info/configs if required.

For tests on other components that do not have any imports from my components directory work fine. I'm confused (first time trying to implement unit tests)

@mika76
Copy link

mika76 commented May 1, 2020

@kaypon have you tried absolute paths and including the .vue extension?

@vincent-lee90
Copy link

@kaypon i have the same problem , did you solve it yet?

@mohamadsdg
Copy link

ES modules are not supported in Node. Because Jest is running in Node, when it hits this import statement, we're getting that syntax error.

.babelrc.js

presets: [
['@babel/preset-env', {modules: 'commonjs' }] , ....]

@nulmete
Copy link

nulmete commented Jul 23, 2020

I spent a considerable amount of time trying various combinations of configuration. I finally discovered that for vue-cli v3.11 you must include [email protected]. Do not skip this step and do not use any other version tag!

If you previously ran vue-cli-service test:unit without the above requirement, then you must run npx jest --clearCache. After that, Jest should start using babel-jest as expected.

I only figured this out after reading @vue/cli-plugin-unit-jest here: https://github.com/vuejs/vue-cli/blob/v3.11.0/packages/%40vue/cli-plugin-unit-jest/generator/index.js#L58

This worked for me, thank you! @sirlancelot

@RamParameswaran
Copy link

I use vue-cli-service test:unit to run my test suites. npx jest --clearCache worked for me. Something funny was going on in cache..
Thanks!

I spent a considerable amount of time trying various combinations of configuration. I finally discovered that for vue-cli v3.11 you must include [email protected]. Do not skip this step and do not use any other version tag!

If you previously ran vue-cli-service test:unit without the above requirement, then you must run npx jest --clearCache. After that, Jest should start using babel-jest as expected.

I only figured this out after reading @vue/cli-plugin-unit-jest here: https://github.com/vuejs/vue-cli/blob/v3.11.0/packages/%40vue/cli-plugin-unit-jest/generator/index.js#L58

@ikhidebright
Copy link

None of this worked for me, i am using vuejs

@sirlancelot
Copy link
Contributor

This issue is over two years old now. It is very likely not "fixable" by the team per se. Most folks have found this comment to be the most helpful:

I spent a considerable amount of time trying various combinations of configuration. I finally discovered that for vue-cli v3.11 you must include [email protected]. Do not skip this step and do not use any other version tag!

If you previously ran vue-cli-service test:unit without the above requirement, then you must run npx jest --clearCache. After that, Jest should start using babel-jest as expected.

I only figured this out after reading @vue/cli-plugin-unit-jest here: https://github.com/vuejs/vue-cli/blob/v3.11.0/packages/%40vue/cli-plugin-unit-jest/generator/index.js#L58

This is probably worth closing and locking with this as the last comment as it's far too broad. cc: @Akryum

@FirePontiac
Copy link

Test fail. SyntaxError: Cannot use import statement outside a module. at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14) Jest encountered an unexpected token. Babel config module.exports = { presets: [ [ '@babel/preset-env', { targets: { node: 'current', }, }, ], ], plugins: ['@babel/plugin-proposal-class-properties'], }; Babel V7

@theGeekyLad
Copy link

I spent a considerable amount of time trying various combinations of configuration. I finally discovered that for vue-cli v3.11 you must include [email protected]. Do not skip this step and do not use any other version tag!

If you previously ran vue-cli-service test:unit without the above requirement, then you must run npx jest --clearCache. After that, Jest should start using babel-jest as expected.

I only figured this out after reading @vue/cli-plugin-unit-jest here: https://github.com/vuejs/vue-cli/blob/v3.11.0/packages/%40vue/cli-plugin-unit-jest/generator/index.js#L58

No go for me. Still stuck at SyntaxError: Cannot use import statement outside a module. If it's something got to do with CommonJS, I've also tried those workaround listed on this issue page but then again, no luck.

And yeah vue -V says @vue/cli 4.5.10. For Vue without Typescript, is there any solution to this yet?

@el-pol
Copy link

el-pol commented Feb 15, 2021

A fix that worked for me: replace .babel.config.js by .babelrc :)

@dsaw
Copy link

dsaw commented Feb 23, 2021

I am getting this error with webpack config, when it detects import {mod1, mod2,..} from 'modpath' (named imports) in modules.
Here is the webpack config:

module.exports = {
    entry: {
        'myapp': ['@babel/polyfill', 'whatwg-fetch', paths.appIndex]
    },
    module: {
        rules: [
            {
                test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
                loader: require.resolve('url-loader'),
                options: {
                    limit: 10000,
                    name: 'static/media/[name].[hash:8].[ext]'
                }
            },
            {
                enforce: 'pre',
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                loader: 'eslint-loader',
                options: {
                    cache: true,
                    fix: true,
                    configFile: './.eslintrc',
                }
            },
            {
                test: /\.(js|jsx)$/,
                include: [paths.appSrc, paths.appMrc],
                loader: 'babel-loader',
                options: {
                    cacheDirectory: true,
                    presets: ['@babel/preset-env', '@babel/preset-react'],
                    plugins: ['@babel/plugin-proposal-class-properties']
                }
            },
            {
                test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                use: [
                    {
                        loader: require.resolve('file-loader'),
                        options: {
                            name: '[name].[hash:8].[ext]'
                        }
                    }
                ]
            }
        ]
    },
    resolve: {
        modules: [paths.appNodeModules],
        alias: aliasConfig,
        extensions: ['*', '.js', '.jsx']
    },
    plugins: [
        // Generates an `index.html` file with the <script> injected.
        new HtmlWebpackPlugin({
            inject: true,
            template: paths.appHtml,
            filename: 'index.html'
        }),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery'
        }),
        new webpack.DefinePlugin({
            VERSION: JSON.stringify(require('../package.json').version)
        })
    ],
    resolveLoader: {
        alias: {
            text: 'html-loader'
        }
    }
};

There is a preset option in there, where I added target but alas does not work.

jest.config.json:

moduleDirectories: [paths.appNodeModules, paths.appJs],
moduleFileExtensions: ['js', 'jsx'],
moduleNameMapper: {
        '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)$': '<rootDir>/tests/__mocks__/fileMock.js',
        '\\.(css|scss)$': '<rootDir>/tests/__mocks__/styleMock.js',
        '^xyz-react-components(.*)$': '<rootDir>/node_modules/xyz-react-components/dist/$1',
        'xyz-session': '<rootDir>/tests/__mocks__/session.js',
        'xyz-i18n': '<rootDir>/tests/__mocks__/i18n.js',
        '@babel-polyfill': '<rootDir>/node_modules/@babel/polyfill/dist/polyfill.js'
},
rootDir: '../',
roots: ['<rootDir>/tests'],
setupFiles: []

@rlam3
Copy link

rlam3 commented Mar 17, 2021

I'm getting this same error when I try to import json into my component.
Is there a way to just disable this feature?

@marr
Copy link

marr commented Jul 22, 2022

Not sure what the status of this one is, but I think there is a simple solution that I haven't seen mentioned:

the only two things I needed to do for happy jest testing is:

npm i -D @vue/babel-preset-app

My babelrc is simply:

{
  "presets": ["@vue/babel-preset-app"]
}

I am using nuxt 2, that is not configured to use babelrc (default behavior), so YMMV.. but this change above should make testing work fine. Some other things that might apply:

in jest.config.js this may be a nuxt thing? just allows for aliased imports (import foo from '@/components/foo'):

moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
},

And other jest v28 stuff:
You'd need jest-environment-jsdom, and @vue/vue2-jest and possible others listed below.

testEnvironment: 'jsdom',
transform: {
    '^.+\\.js$': 'babel-jest',
    '^.+\\.vue$': '@vue/vue2-jest',
    '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
  },

@FichteFoll
Copy link

FichteFoll commented Dec 30, 2022

For me, changing the transform to use '@vue/vue2-jest' instead of 'vue-jest' made it work eventually. Thanks for the hint.

Perhaps that should be updated in https://v1.test-utils.vuejs.org/guides/using-with-typescript.html#processing-single-file-components-in-jest ?

@SalahAdDin
Copy link

It happens with axios.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests