无法使用 v-dialog 测试 vue 组件

And*_*rey 5 unit-testing vue.js vue-component vuetify.js vitest

我一直在努力弄清楚如何使用 v-dialog 测试 Vue 组件,这在 Vue2 中运行得非常好。目前我正在使用Vue3、Vitest、Vuetify3。

这是一个非常简单的组件,它演示了一个问题

<template>
  <div>
    <v-btn @click.stop="dialog=true" class="open-dialog-btn">click me please</v-btn>
    <v-dialog v-model="dialog" max-width="290" >
      <div class="dialog-content">
        <v-card>welcome to dialog</v-card>
      </div>
    </v-dialog>
  </div>
</template>

<script setup>
import {ref} from "vue";

const dialog = ref(false);
</script>
Run Code Online (Sandbox Code Playgroud)

这是它的单元测试:

import '../setup';
import { mount } from '@vue/test-utils';
import { createVuetify } from "vuetify";
import HelloDialog from "@/components/HelloDialog.vue";

describe('HelloDialog', () => {
  let wrapper;
  let vuetify;

  beforeEach(() => {
    vuetify = createVuetify();
  });

  describe('dialog tests', () => {
    beforeEach(() => {
      wrapper = mount(HelloDialog, {
        global: {
          plugins: [vuetify],
        },
      });
    });

    test('test dialog', async () => {
      expect(wrapper.find('.dialog-content').exists()).toBeFalsy();
      await wrapper.find('.open-dialog-btn').trigger('click');
      console.log(wrapper.html());
      expect(wrapper.find('.dialog-content').exists()).toBeTruthy();
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

单元测试中的最后一行不起作用 - 不显示对话框内容。以下是单击按钮后wrapper.html() 的输出:

<div><button type="button" class="v-btn v-btn--elevated v-theme--light v-btn--density-default v-btn--size-default v-btn--variant-elevated open-dialog-btn"><span class="v-btn__overlay"></span><span class="v-btn__underlay"></span>
    <!----><span class="v-btn__content" data-no-activator="">click me please</span>
    <!---->
    <!---->
  </button>
  <!---->
  <!--teleport start-->
  <!--teleport end-->
</div>

AssertionError: expected false to be truthy
    at ....../HelloDialog.spec.js:27:56
Run Code Online (Sandbox Code Playgroud)

这是vite.config.js的测试部分:

  test: {
    // https://vitest.dev/config/
    globals:true,
    environment: 'happy-dom',
    setupFiles: "vuetify.config.js",
    deps: {
      inline: ["vuetify"],
    },
  },
Run Code Online (Sandbox Code Playgroud)

这是vuetify.config.js

global.CSS = { supports: () => false };
Run Code Online (Sandbox Code Playgroud)

这里是package.json的一些版本:

  "dependencies": {
    "@mdi/font": "7.1.96",
    "@pinia/testing": "^0.0.14",
    "axios": "^1.2.0",
    "dotenv": "^16.0.3",
    "happy-dom": "^8.1.1",
    "jsdom": "^20.0.3",
    "lodash": "^4.17.21",
    "pinia": "^2.0.27",
    "roboto-fontface": "*",
    "vue": "^3.2.45",
    "vuetify": "3.0.6",
    "webfontloader": "^1.0.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.0.0",
    "@vue/test-utils": "^2.2.6",
    "vite": "^4.0.3",
    "vite-plugin-vuetify": "^1.0.0-alpha.12",
    "vitest": "^0.26.2"
  }
Run Code Online (Sandbox Code Playgroud)

此时我已经尝试了所有方法,我认为问题与使用 teleport 组件的 v-dialog 有关。经过几天的努力试图找出答案后,我决定在测试时使用存根而不使用真正的对话框,但我真的不喜欢这种方法。

任何想法将不胜感激

小智 3

我有同样的问题,发现当我调用 时,内容v-dialog已呈现。您可以像下面这样测试对话框内容。document.bodymount()

// expect(wrapper.find('.dialog-content').exists()).toBeTruthy();
expect(document.querySelector('.dialog-content')).not.toBeNull();
Run Code Online (Sandbox Code Playgroud)

我建议每次测试后打电话unmount()

afterEach(() => {
  wrapper.unmount()
});
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助,尽管我怀疑这是一个好方法,因为我不想关心该组件是否使用传送。