Skip to content

shallowMount() behaves like mount() when components are lazy loaded #1279

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

Closed
xavism opened this issue Jul 22, 2019 · 24 comments
Closed

shallowMount() behaves like mount() when components are lazy loaded #1279

xavism opened this issue Jul 22, 2019 · 24 comments

Comments

@xavism
Copy link

xavism commented Jul 22, 2019

Version

1.0.0-beta.29

Reproduction link

https://github.com/xavism/lazyloading-vue-test-utils

Steps to reproduce

$ npm i
$ npm t

Then check the snapshots

What is expected?

Both snapshots (Parent and ParentLazy) are expected to be the same. shallowMount should stub the child components

What is actually happening?

ParentLazy's snapshot is rendering the Child component when using shallowMount, the child component in the snapshot is not stubbed


Related to a closed issue:

shallowMount will not stubs lazily registered components #959
#959

It should be fixed but it's not working in my case.

@xavism
Copy link
Author

xavism commented Jul 22, 2019

Duplicate of #959
Reopened

@anipendakur
Copy link

Hi there, I was wondering if there's any update on this.. We have the exact same issue.

@krausweb
Copy link

krausweb commented Nov 6, 2019

As I see in your Github you are using the Jest, lazy load (() => import) and of course NodeJS.

"Jest runs in Node, and thus requires ES modules to be transpiled to CommonJS modules.
If you use dynamic imports (import('some-file.js').then(module => ...)), you need to enable the dynamic-import-node plugin"
See Jest docs https://jestjs.io/docs/en/webpack.html#using-with-webpack-2

Solution:
Need to install the babel-plugin-dynamic-import-node (https://www.npmjs.com/package/babel-plugin-dynamic-import-node).
Or the import works only with "--experimental-modules" in NodeJS(current LTS https://nodejs.org/dist/latest-v12.x/docs/api/esm.html#esm_enabling).

// my .babelrc

{
    "env": {
        "test": {
            "presets": [
                ["env", {
                    "targets": {
                        "node": "current"
                    }
                }]
            ],
            "plugins": ["dynamic-import-node"]
        }
    }
}

// my jest.config.js

module.exports = {
    moduleFileExtensions: [
        'js',
        'json',
        'vue'
    ],
    'transform': {
        '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
        '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
    },
};

// my env:

  1. Laravel v5.8.23;

  2. main "devDependencies":
    "jest": "^24.9.0",

"vue": "^2.5.17",
"vue-jest": "^3.0.5",
"@vue/test-utils": "^1.0.0-beta.29",

"babel-core": "^6.26.3",
"babel-jest": "^24.9.0",
"babel-plugin-dynamic-import-node": "^2.3.0",
"babel-preset-env": "^1.7.0",

"laravel-mix": 4.0.7,

  1. the Docker image with NodeJS v8

@miguelrincon
Copy link

I face a similar issue when using to dynamic components as the components that are set get fully rendered.

Would a fix for this issue cover this use case as well?

@xavism
Copy link
Author

xavism commented Nov 18, 2019

As I see in your Github you are using the Jest, lazy load (() => import) and of course NodeJS.

"Jest runs in Node, and thus requires ES modules to be transpiled to CommonJS modules.
If you use dynamic imports (import('some-file.js').then(module => ...)), you need to enable the dynamic-import-node plugin"
See Jest docs https://jestjs.io/docs/en/webpack.html#using-with-webpack-2

Solution:
Need to install the babel-plugin-dynamic-import-node (https://www.npmjs.com/package/babel-plugin-dynamic-import-node).
Or the import works only with "--experimental-modules" in NodeJS(current LTS https://nodejs.org/dist/latest-v12.x/docs/api/esm.html#esm_enabling).

// my .babelrc

{
    "env": {
        "test": {
            "presets": [
                ["env", {
                    "targets": {
                        "node": "current"
                    }
                }]
            ],
            "plugins": ["dynamic-import-node"]
        }
    }
}

// my jest.config.js

module.exports = {
    moduleFileExtensions: [
        'js',
        'json',
        'vue'
    ],
    'transform': {
        '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
        '.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
    },
};

// my env:

  1. Laravel v5.8.23;
  2. main "devDependencies":
    "jest": "^24.9.0",

"vue": "^2.5.17",
"vue-jest": "^3.0.5",
"@vue/test-utils": "^1.0.0-beta.29",

"babel-core": "^6.26.3",
"babel-jest": "^24.9.0",
"babel-plugin-dynamic-import-node": "^2.3.0",
"babel-preset-env": "^1.7.0",

"laravel-mix": 4.0.7,

  1. the Docker image with NodeJS v8

I've added your solution to the reproduction package ( https://github.com/xavism/lazyloading-vue-test-utils) and it is still not working.
Could you tell me what am I doing wrong?

@Zilvinaskli
Copy link

have you found a solution for that?

@xavism
Copy link
Author

xavism commented Jan 21, 2020

have you found a solution for that?

Unfortunately no :(

@seoplay
Copy link

seoplay commented Feb 19, 2020

still no update on this?

@lmiller1990
Copy link
Member

lmiller1990 commented Mar 14, 2020

So I think the reason this happens is because the way shallowMount works is by overriding this.$createElement to stub out components before they are mounted. Since the import is async (lazy), the component is loaded after all the stubbing has occurred.

If my guess is correct, this is not something we can fix without a major rework of the library. The only suggested I can come up with to make your snapshots match is to use mount. I don't think this is so bad; using mount will make your snapshot more closely resemble your production code.

If anyone wants to dig into this one, I can provide some guidance or even pair with you on it.

@rdunk
Copy link

rdunk commented Mar 16, 2020

As a less-than-ideal workaround, you can explicitly provide stubs for async components.

@Dinuz
Copy link

Dinuz commented Mar 25, 2020

I am having the same issue, I lazy load my components, and shallowMount behave like mount, but mount itself doesn't really work.
I need to explicitly setup the stubs for my child component in shallowMount, and then it works properly.
If instead I try to use mount, the stub is not be consider at all.

I created a factory function to switch easily between mount and shallow, but mount just doesn't work.

@lmiller1990
Copy link
Member

Call me crazy but if you are loading a component why would you want to use shallowMount? That will stub out your async component (now you can't test it, because it's stubbed out).

@xavism
Copy link
Author

xavism commented Mar 26, 2020

Hi @lmiller1990 , first of all thanks for your time.
In my case, I want to use shallowMount even when I'm lazy-loading my child components because I don´t want to add to my localVue the dependencies this child components needs.
Does it make sense?

@lmiller1990
Copy link
Member

I see, makes sense. Time for a deep dive into the dark depths of shallowMount!

@CodePlato3721
Copy link

Since shallowMount() behaves like mount(). I'm thinking about consider this problem in the opposite way: make mount() behaves like shallowMount.

For example, Parent component lazy load Child component

<template>
  <div>
    Parent
    <Child />
  </div>
</template>

<script>

export default {
  components: {
    Child: () => import('./Child')
  }
}
</script>

Step 1. Change shallowMount into mount in unit tests

const wrapper = mount(Parent)

Step 2. Add stubs option to mount

const wrapper = mount(Parent, {
      stubs: {
        Child: true
    }
  })

The child component will be mount as <child-stub></child-stub> like we are using shallowMount.

@lmiller1990
Copy link
Member

^ seems like a good work around!

@CodePlato3721
Copy link

CodePlato3721 commented May 13, 2020

@lmiller1990 I wonder that if mount can make child stub as <child-stub> exactly like the same thing shallowMount would do. Why shallowMount can't do it? Is there anything blocks this process? Would it be possible to let shallowMount be improved to compatible with dynamic import if we found the things block the process?

@lmiller1990
Copy link
Member

I have no idea why this happens, I took a look but didn't have much luck fixing it. I would probably need to spend more time on it.

If you would like to try figuring it out I can try to help out. I personally recommend against using shallowMount - what is your use-case that prevents you from using mount?

@dobromir-hristov
Copy link
Contributor

I have tried hacking this as well many times, alas got nowhere... I think this is finally fixed in VTU 2 though 😄

@Ariane-B
Copy link

Ariane-B commented Nov 3, 2020

@dobromir-hristov Do we have a confirmation that it's actually fixed in Vue Test Utils 2 / Vue 3?

@lmiller1990
Copy link
Member

lmiller1990 commented Nov 4, 2020

I just cloned and updated the repo linked in the first post. I used Vue 3, VTU v2 and ts-jest v25. The first two tests passed fine, I had to update the snapshots with -u and then everything was green.

So yep, seems fine. This is because the shallow mounting is (kind of) baked into Vue core now via a transformVNodeArgs function.

Of course that is in a different codebase using different dependencies - I do not expect this issue will be fixed in VTU v1 (for Vue 2) at this point.

@ebisbe
Copy link
Collaborator

ebisbe commented Jan 27, 2023

@lmiller1990 Should I mark this ticket as won't fix and close it or as a bug and leave it open?

@lmiller1990
Copy link
Member

Considering how much time has passed and how complex this likely is to fix, I'd say closed and wontfix is probably fine -- it's clear there isn't a lot of motivation to fix this particular issue.

@ebisbe ebisbe closed this as completed Jan 30, 2023
@pmrotule
Copy link

I just wanted to mention that we had this issue before and it simply went away after upgrading from Vue 2.5 to 2.7. We're on Jest v29.

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

No branches or pull requests