Skip to content

Using v-text on functional component with shallowMount #1693

Closed
@jeremy-cassou

Description

@jeremy-cassou

Subject of the issue

It seems that v-text directives are ignored on child functional components when the parent component is mounted with shallowMount. I am using Vuetify but in this case, there should be no impact.

Steps to reproduce

<!-- Foo.vue -->
<template>
  <v-card>
    <v-card-title v-text="title" />
  </v-card>
</template>

<script>
export default {
  name: 'Foo',
  props: {
    title: {
      type: String,
      required: true,
    },
  },
}
</script>
/* foo.spec.js */
import Vue from 'vue'
import Vuetify from 'vuetify'
import { createLocalVue, shallowMount } from '@vue/test-utils'
import Foo from '@/components/cards/Foo'

Vue.use(Vuetify)
const localVue = createLocalVue()

describe('Foo.vue', () => {
  it('should have a title', () => {
    const title = 'My Title'
    const wrapper = shallowMount(Foo, {
      localVue,
      vuetify: new Vuetify({}),
      propsData: { title },
    })
    expect(wrapper.find('v-card-title-stub').text()).toBe(title)
  })
})

Expected behaviour

Test should pass.

Actual behaviour

The test fail because the text inside stubed component v-card-title-stub is empty.

 FAIL  tests/unit/components/cards/foo.spec.js
  ● Foo.vue › should have a title

    expect(received).toBe(expected) // Object.is equality

    Expected: "My Title"
    Received: ""

      16 |       propsData: { title },
      17 |     })
    > 18 |     expect(wrapper.find('v-card-title-stub').text()).toBe(title)
         |                                                      ^
      19 |   })
      20 | })
      21 | 

      at Object.<anonymous> (tests/unit/components/cards/foo.spec.js:18:54)

Possible Solution

If I use mustache interpolation instead, the test works fine.

<template>
  <v-card>
    <v-card-title>{{ title }}</v-card-title>
  </v-card>
</template>

I don't know vue-test-utils library but, I think the bug is in createStubFromComponent function (create-component-stubs.js). The domProps in the context.data is never passed.

To try, I added a line to keep domProps as a ref and everything seems to work. I don't know if this is the good solution.

return h(
  tagName,
  {
    ref: componentOptions.functional ? context.data.ref : undefined,
    domProps: componentOptions.functional ? context.data.domProps : undefined, // <---- HERE
    attrs: componentOptions.functional
      ? {
          ...context.props,
          ...context.data.attrs,
          class: createClassString(
            context.data.staticClass,
            context.data.class
          )
        }
      : {
          ...this.$props
        }
  },
  context
    ? context.children
    : this.$options._renderChildren ||
        getScopedSlotRenderFunctions(this).map(x =>
          this.$options.parent._vnode.data.scopedSlots[x]({})
        )
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions