Skip to content

Component stubs stop working for grand children when registered globally #830

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
andre-tebart opened this issue Jul 17, 2018 · 9 comments
Closed
Labels

Comments

@andre-tebart
Copy link

Version

1.0.0-beta.20

Reproduction link

https://codesandbox.io/s/7krlyqn310

Steps to reproduce

  1. Have a look at the TestComponent.spec.js
  2. See how the stub for the child component works correctly and the test passes
  3. See how the stub for the grand child component does not work and the test fails

What is expected?

The test for the grand child should pass as it was stubbed.

What is actually happening?

The test fails because the stub does not apply.


This only seems to be an issue with components that are registered globally. The error did not occur when the sub-componentes were registered locally.

We experienced this bug when we upgraded from beta.16 to beta.20. The transition component which is stubbed per default suddenly stopped working in nested components.

@lmiller1990
Copy link
Member

lmiller1990 commented Jul 18, 2018

I think the reason this is happening is because at the moment stubs only works on the direct children, not the children's children. I didn't know this was even working in previous versions.

Edit: rolling back to "@vue/test-utils": "1.0.0-beta.15" does not yield a passing test in the reproduction link. Perhaps an earlier version?

One work around is to use find and pass the component:

expect(wrapper.find(GrandChildComponent).exists()).toBe(true)

Or you simply pass an object with a name property:

expect(wrapper.find({ name: "grand-child-component" }).exists()).toBe(true);

Maybe related to #649 - a 'dive' or depth API might let you stub on varying levels or depths.

My personal experience is using find({ name: ... }) is the most reliable and works for the most situations. But I think we should also support some kind of multi level rendering API, like Enzyme does with dive.

@eddyerburgh
Copy link
Member

This is a bug, stubs should be applied to all child components

@eddyerburgh
Copy link
Member

This actually is a problem with how you're stubbing.

First you were using Vue Test Utils beta.16 which would stop circular references, because the class had the name of the component it would throw an error (this has been fixed to only throw if the component name is the same).

Second, you were trying to find the element using a -stub suffix on the class, which is not added when it's stubbed.

Third, the TestComponent wasn't rendering the ChildComponent.

I've added these fixes to your code sample: https://codesandbox.io/s/jpo3lo2569.

There's a passing test for stubbing nested components in the Vue Test Utils—https://github.com/vuejs/vue-test-utils/blob/dev/test/specs/mounting-options/stubs.spec.js#L135

@andre-tebart
Copy link
Author

andre-tebart commented Jul 24, 2018

@eddyerburgh
Thanks for having a look at the issue and providing a solution. But I think I am missing something from your fixed code sample: There are two console logs in the test runs which show the html generated for the components.

In the first test you can see that the child component stub is applied (div.child-component-class exists).

In the second test you can see that the grand child component stub is not applied. The generated html still shows a div with the text "I am the grand child". If the stub would be applied then it should be replaced by a div.grand-child-component with no content. Thats what I was originally testing for.

Clarification on that would be appreciated :)

@eddyerburgh eddyerburgh reopened this Jul 24, 2018
@eddyerburgh
Copy link
Member

Sorry, yes this is in fact a bug.

eddyerburgh added a commit to eddyerburgh/vue-test-utils that referenced this issue Jul 28, 2018
@eddyerburgh
Copy link
Member

This is fixed in master, and will be included in the next release.

For now, a quick solution is to use localVue:

import { createLocalVue } from '@vue/test-utls'

const localVue = createLocalVue()
localVue.component('child-component', Child)
mount(TestComponent, {
  localVue
})

@Igor-Dataka
Copy link

Hello,
is this solved?
When I try to use a grandchild component,
which is defined in his father, I get the error saying if the component has been registered correctly.
Thank you,
Regards,

@jaythomas
Copy link

@Igor-Dataka and anyone else that ran into this problem and got taken to this GitHub issue via search engines: It doesn't seem that vue-test-utils supports a situation where the child component contains a dynamic <component> that can render into a <router-link> but the above solution is sufficient to resolve the issue.

import { describe, expect, jest, it } from '@jest/globals';
import { createLocalVue, mount, RouterLinkStub } from '@vue/test-utils';

import MyComponent from './MyComponent';

describe('MyComponent component', () => {
  it('renders with default props', () => {
    const localVue = createLocalVue();
    localVue.component('router-link', RouterLinkStub);

    const wrapper = mount(MyComponent, {
      localVue
    });

    expect(true);
  });

@lmiller1990
Copy link
Member

Yeah, I don't think this is supported. Stubs are applied before the runtime, so I suspect that's the reason - the stubs are applied before the dynamic behavior.

I have found that writing unit tests around routing logic is generally brittle and generates more work/maintenance then value, I generally recommend against unit testing that sort of thing.

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

No branches or pull requests

5 participants