vuejs3vuetify.jsvitestvuetifyjs3vue-testing-library

Vuetify cannot find useGroup injection when mounting a custom component in a test


Background:
Vue3 app, using Vuetify, vitest, and vue-testing-library.

Problem:
I have a custom component whose template looks something like this:

<template>
  <v-expansion-panel>
    ... other code
  </v-expansion-panel>
</template

Each of the places this component is used is inside of a parent <v-expansion-panels> component, as is required.

I am currently trying to write a simple test for this component, and am currently getting the following error:

Error: [Vuetify] Could not find useGroup injection with symbol vuetify:v-expansion-panel
 ❯ Module.groupItem node_modules/vuetify/src/composables/group.ts:122:7
 ❯ Object.setup [as _setup] node_modules/vuetify/src/components/VExpansionPanel/VExpansionPanel.tsx:52:44
 ❯ setup node_modules/vuetify/src/util/defineComponent.tsx:125:85
 ❯ callWithErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:195:19
 ❯ setupStatefulComponent node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7572:25
 ❯ setupComponent node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7533:36
 ❯ mountComponent node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5861:7
 ❯ processComponent node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5827:9
 ❯ patch node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5306:11
 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5971:11

I've tried wrapping my custom component in a <v-expansion-panel> via a wrapper component (which I expected to remedy the error above):

import MyComponent from '@/components/MyComponent.vue';
import { describe, it } from 'vitest';
import { createVuetify } from 'vuetify';
import { render as testingLibraryRender } from '@testing-library/vue';

const WrapperComponent = {
  components: { MyComponent },
  props: { content: { type: String, default: '' } },
  template: `
    <v-expansion-panels>
      <MyComponent :content="content" />
    </v-expansion-panels>
  `,
};

describe('<MyComponent />', () => {
  it('renders the component', async () => {
    const vuetify = createVuetify();
    const wrapper = testingLibraryRender(WrapperComponent, {
      global: {
        plugins: [vuetify],
      },
      props: { content: 'some text' },
    });

    expect(await screen.findByText('some text')).toBeInTheDocument();
  });
});

I have been able to get the WrapperComponent to render without error by changing the template to the following, but this doesn't really solve my problem, since it completely removes my custom component:

const WrapperComponent = {
  props: { content: { type: String, default: '' } },
  template: `
    <v-expansion-panels>
      <v-expansion-panel>
        <v-expansion-panel-title>Foo Bar Baz</v-expansion-panel-title>
      </v-expansion-panel>
    </v-expansion-panels>
  `,
};

This seems to be due to some kind of nuance with the wrapper, and I'm hoping someone can shed some light on it!

Thanks in advance!


Solution

  • Simple answer: ended up being that I needed to register the VExpansionPanels component to the WrapperComponent like so:

    const WrapperComponent = {
      components: { MyComponent, VExpansionPanels },
      props: { content: { type: String, default: 'text' },
      template: `
        <v-expansion-panels>
          <MyComponent :content='content' />
        </v-expansion-panels>
      `,
    };