unplugin-vue-components icon indicating copy to clipboard operation
unplugin-vue-components copied to clipboard

`<anonymous-stub>` when running in Vitest + Vue 3 + Vue test utils `{ shallow: true }`

Open Neophen opened this issue 2 years ago • 5 comments

Issue

When using single/multiple stubs option with vue test utils it renders the whole inner html of the component, like so:

import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';

import SomeComponent from './SomeComponent.vue';

test('stubs component', () => {
  const wrapper = mount(SomeComponent, {
    global: {
      stubs: {
        SomeComponent: true
      }
    }
  })

  console.log(wrapper.html())
  **Expected**
  /*
    <some-component-header-stub></some-component-header-stub>
    <h1>Welcome to Vue.js 3</h1>
  */

  **Actual**
  /*
    <div class="text-2xl font-bold">This header should be stubbed</div>
    <h1>Welcome to Vue.js 3</h1>
  */

  expect(wrapper.html()).toContain('Welcome to Vue.js 3')
})

When using with shallow mount the children component names become anonymous-stub:

test('shallow stubs out all child components', () => {
  const wrapper = mount(ComplexComponent, {
    shallow: true
  })

  console.log(wrapper.html())
  **Expected**
  /*
    <h1>Welcome to Vue.js 3</h1>
    <complex-a-stub></complex-a-stub>
    <complex-b-stub></complex-b-stub>
    <complex-c-stub></complex-c-stub>
  */

  **Actual**
  /*
    <h1>Welcome to Vue.js 3</h1>
    <anonymous-stub></anonymous-stub>
    <anonymous-stub></anonymous-stub>
    <anonymous-stub></anonymous-stub>
  */
})

both cases are wrong, is there a way to make this work?

Use Case

When using tailwind you can catch style changes with snapshot tests. which I assume are much faster, than cypress component tests.

And you only want to see the styles of the current component under test, so as not to make tests fail when the child element styles update. to avoid flaky tests.

as a workaround you can import components directly, without using unplugin-vue-components and it works, but that obviously defeats the purpose of this plugin.

Thank you

This plugin saves a ton of time and boilerplate would be awesome to get this little bit to work :)

I'd give it a show with a PR if you could just point me in the direction

Neophen avatar Jun 21 '22 03:06 Neophen

I'm facing the same issue here

TadasMil avatar Jul 17 '22 13:07 TadasMil

Can we see the ComplexComponent please ?

ady642 avatar Jul 21 '22 08:07 ady642

<script setup>
</script>
<template>
   <h1>Welcome to Vue.js 3</h1>
   <ComplexA />
   <ComplexB />
   <ComplexC />
</template>

Neophen avatar Aug 02 '22 00:08 Neophen

Where the Complex[x] components are auto imported by unplugin vue components

Neophen avatar Aug 02 '22 00:08 Neophen

When unplugin-vue-components is used, it is impossible to us the stubs feature of Vue Test Utils. This makes unplugin-vue-components practically unusable with Vitest.

Here is an example repo created with npm create vite@latest (vue-ts) + @testing-library/vue + vitest + unplugin-vue-components.

(It also fails with Vue Test Utils instead of Testing library)

I'm not certain this is related to the first comment but at least there seems to be anything wrong with stubbing.

fvanwijk avatar Aug 09 '22 19:08 fvanwijk

I've opened a pr to solve this.

hershelh avatar Sep 24 '22 01:09 hershelh

Is this a similar issue in Vue 2 components? I'm seeing vuecomponent-stub entries for all Vuetify related components when shallow mounting.

The PR above only applies to Vue3 - and not test utils for Vue2.

cadriel avatar Oct 14 '22 15:10 cadriel

I've resolved my issue, but it may be relevant here.

For a Vue 2.7 project - running Vitest and shallow mounting caused all Vuetify components to be returned as <vuecomponent-stub>. None of the slots rendered either.

To fix this, I had to disable unplugin-vue-components in the test environment, and instead import the entire Vuetify lib.

This was pretty easy;

In your vitest.config.ts

export default defineConfig((configEnv) => ({
  ...,
  plugins: [
    vue2(),
    Components({
      resolvers: (configEnv.mode !== 'test') ? [VuetifyResolver()] : [],
      ...
  ]

Then in your vitest.setup.ts make sure you import Vuetify from 'vuetify' and Vue.use(Vuetify).

cadriel avatar Oct 15 '22 20:10 cadriel

Is this a similar issue in Vue 2 components? I'm seeing vuecomponent-stub entries for all Vuetify related components when shallow mounting.

The thing is when stubbing a component that uses both <script setup> syntax and unplugin-vue-components, test utils won't do it correctly, which has been solved by the PR.

I'm not sure if Vuetify uses <script setup> syntax or not, and the PR only applies to the test utils for Vue3.

hershelh avatar Oct 16 '22 02:10 hershelh