Vue-jest: Will vue-jest ever support code-splitting?

Created on 30 Oct 2017  路  9Comments  路  Source: vuejs/vue-jest

I'm following the guide on Testing SFC with Jest and vue-test-utils. There is note saying:

Note: vue-jest currently does not support all the features of vue-loader, for example custom block support and style loading. In addition, some webpack-specific features such as code-splitting are not supported either.

I'm wondering if there are any plans to include support for the above features. Also, is it even possible to support code-splitting without webpack?

Most helpful comment

@eddyerburgh @vincemukiiri This should do it:

yarn add --dev babel-plugin-dynamic-import-node

Then in the .babelrc-file

  "presets" [
    // ...
  ],

  // add env specific configuration
  "env": {
    "test": {
      "plugins": [
        "transform-runtime",
        "dynamic-import-node" // <-- this is the important line
      ]
    }
  }

All 9 comments

I'd like to add support, but I don't have much experience with code splitting and am unsure what would be involved to support it.

Can you describe your use case?

Well, I've only just started learning testing vue components with jest and code-splitting so I don't have a specific use case in mind. But in general I have a vue app that uses vue-router and would like to load components asynchronously like so

let routes = [
    {
        path: '/',
        component: () => import('./views/Home.vue'),
    },
    {
        path: '/about',
        component: () => import('./views/About.vue'),
    },

let router = new VueRouter({
    routes
});

app = new Vue({
    el: '#app',
    router: router,
});

Webpack compiles this down and separates the components (Home.vue and About.vue) into separate chunks that would be loaded asynchronously when their respective urls are navigated to. I'm guessing this won't work while testing with vue-jest since webpack isn't there to do the code-splitting.

Yes, you couldn't test this file in vue-jest.

In my mind this is something that should be tested in end to end tests, rather than unit tests.

True. I guess there aren't many cases where you be testing something that uses code-splitting within a unit test.

@eddyerburgh @vincemukiiri This should do it:

yarn add --dev babel-plugin-dynamic-import-node

Then in the .babelrc-file

  "presets" [
    // ...
  ],

  // add env specific configuration
  "env": {
    "test": {
      "plugins": [
        "transform-runtime",
        "dynamic-import-node" // <-- this is the important line
      ]
    }
  }

In the event that someone is searching for answers, I will post this here hoping it helps someone. This was the answer I was looking for and could not find:

To test components that have asynchronously-loaded (code-split) children like so:

// @file component.js
export default {
  components: {
    foo: () => import('./foo')
  }
}

You should do two things:

1) use babel-plugin-dynamic-import-node for your test transforms, per the comment above

You may need to use babel-plugin-dynamic-import-node-babel-7 until airbnb/babel-plugin-dynamic-import-node#62 is resolved
2) In your tests, you need to delete the require cache between each individual test that mounts (or even shallow mounts). Else, the test behavior will change when run in isolation vs. in series after another test that also mounts.

The reason is, the import() statements are transpiled into deferred requires, which will cause the component not to be rendered for the first spec, but will behave synchronously for subsequent specs. Then, you will have to require your parent component each time before mounting:

``js beforeEach(() => { // the only way vue-jest supportsimport()` is through transforming async imports to deferred requires.
// however deferred requires will cause the import to happen asynchronously once, and synchronously on subsequent calls.
// therefore to get isolation in test behavior, require cache needs to be reset each time a mount happens.
// @see https://github.com/vuejs/vue-jest/issues/20
jest.resetModules();
component = require('./component').default;
});

airbnb/babel-plugin-dynamic-import-node#62 is resolved.
Use babel-plugin-dynamic-import-node with no concern.

I tried the steps suggested by @justinhelmer because he describes the scenario I am struggling with now. I am importing components like

// @file component.js
export default {
  components: {
    foo: () => import('./foo')
  }
}

but in Jest the location at which these components should be rendered, you just find <!-- -->. The components do not appear even after using the plugin dynamic-import-node. Moreover, we are in 2020 now and I am using Node 14, which has native support for the await import() syntax.

If I change the syntax (back) to

// @file component.js
import Foo from './foo'
export default {
  components: {
    Foo
  }
}

the component does get rendered correctly in Jest, so it does have something to do with jest not resolving the lazy loaded components correctly. Does anybody have any leads on how to get this to work?

@rudionrails - https://github.com/vuejs/vue-jest/issues/20#issuecomment-340490204.
Thanks for this approach. But I found that it does not work in nuxt project. Do you have any idea about this?

Was this page helpful?
0 / 5 - 0 ratings