跳至主要内容

Vue.js

Vue.js 是一款易于使用、性能出色且用途广泛的框架,用于构建 Web 用户界面。您可以使用 WebdriverIO 及其浏览器运行器直接在真实的浏览器中测试 Vue.js 组件。

设置

要在 Vue.js 项目中设置 WebdriverIO,请按照组件测试文档中的说明进行操作。确保在运行器选项中选择vue作为预设,例如:

// wdio.conf.js
export const config = {
// ...
runner: ['browser', {
preset: 'vue'
}],
// ...
}
信息

如果您已经在使用Vite作为开发服务器,您也可以在 WebdriverIO 配置中重用vite.config.ts中的配置。有关更多信息,请参阅运行器选项中的viteConfig

Vue 预设需要安装@vitejs/plugin-vue。我们还建议使用Testing Library将组件渲染到测试页面中。因此,您需要安装以下其他依赖项

npm install --save-dev @testing-library/vue @vitejs/plugin-vue

然后,您可以通过运行以下命令启动测试:

npx wdio run ./wdio.conf.js

编写测试

假设您有以下 Vue.js 组件

./components/Component.vue
<template>
<div>
<p>Times clicked: {{ count }}</p>
<button @click="increment">increment</button>
</div>
</template>

<script>
export default {
data: () => ({
count: 0,
}),

methods: {
increment() {
this.count++
},
},
}
</script>

在您的测试中,将组件渲染到 DOM 中并在其上运行断言。我们建议使用@vue/test-utils@testing-library/vue将组件附加到测试页面。要与组件交互,请使用 WebdriverIO 命令,因为它们的运行方式更接近实际的用户交互,例如:

vue.test.js
import { $, expect } from '@wdio/globals'
import { mount } from '@vue/test-utils'
import Component from './components/Component.vue'

describe('Vue Component Testing', () => {
it('increments value on click', async () => {
// The render method returns a collection of utilities to query your component.
const wrapper = mount(Component, { attachTo: document.body })
expect(wrapper.text()).toContain('Times clicked: 0')

const button = await $('aria/increment')

// Dispatch a native click event to our button element.
await button.click()
await button.click()

expect(wrapper.text()).toContain('Times clicked: 2')
await expect($('p=Times clicked: 2')).toExist() // same assertion with WebdriverIO
})
})

您可以在我们的示例存储库中找到 Vue.js 的 WebdriverIO 组件测试套件的完整示例。

测试 Vue3 中的异步组件

如果您使用的是 Vue v3 并正在测试异步组件,如下所示:

<script setup>
const res = await fetch(...)
const posts = await res.json()
</script>

<template>
{{ posts }}
</template>

我们建议使用@vue/test-utils和一个简单的 suspense 包装器来渲染组件。不幸的是,@testing-library/vue目前尚不支持此功能。创建一个包含以下内容的helper.ts文件:

import { mount, type VueWrapper as VueWrapperImport } from '@vue/test-utils'
import { Suspense } from 'vue'

export type VueWrapper = VueWrapperImport<any>
const scheduler = typeof setImmediate === 'function' ? setImmediate : setTimeout

export function flushPromises(): Promise<void> {
return new Promise((resolve) => {
scheduler(resolve, 0)
})
}

export function wrapInSuspense(
component: ReturnType<typeof defineComponent>,
{ props }: { props: object },
): ReturnType<typeof defineComponent> {
return defineComponent({
render() {
return h(
'div',
{ id: 'root' },
h(Suspense, null, {
default() {
return h(component, props)
},
fallback: h('div', 'fallback'),
}),
)
},
})
}

export function renderAsyncComponent(vueComponent: ReturnType<typeof defineComponent>, props: object): VueWrapper{
const component = wrapInSuspense(vueComponent, { props })
return mount(component, { attachTo: document.body })
}

然后导入并测试组件,如下所示:

import { $, expect } from '@wdio/globals'

import { renderAsyncComponent, flushPromises, type VueWrapper } from './helpers.js'
import AsyncComponent from '/components/SomeAsyncComponent.vue'

describe('Testing Async Components', () => {
let wrapper: VueWrapper

it('should display component correctly', async () => {
const props = {}
wrapper = renderAsyncComponent(AsyncComponent, { props })
await flushPromises()
await expect($('...')).toBePresent()
})

afterEach(() => {
wrapper.unmount()
})
})

在 Nuxt 中测试 Vue 组件

如果您使用的是 Web 框架Nuxt,WebdriverIO 将自动启用自动导入功能,并使测试您的 Vue 组件和 Nuxt 页面变得容易。但是,您可能在配置中定义的任何Nuxt 模块都需要 Nuxt 应用程序的上下文才能得到支持。

原因如下:

  • WebdriverIO 无法仅在浏览器环境中初始化 Nuxt 应用程序。
  • 使组件测试过度依赖于 Nuxt 环境会增加复杂性,我们建议将这些测试作为端到端测试运行。
信息

WebdriverIO 还提供了一个服务,用于在 Nuxt 应用程序上运行端到端测试,有关信息,请参阅webdriverio-community/wdio-nuxt-service

模拟内置的可组合函数

如果您的组件使用本机 Nuxt 可组合函数,例如useNuxtData,WebdriverIO 将自动模拟这些函数,并允许您修改其行为或对其进行断言,例如:

import { mocked } from '@wdio/browser-runner'

// e.g. your component uses calls `useNuxtData` the following way
// `const { data: posts } = useNuxtData('posts')`
// in your test you can assert against it
expect(useNuxtData).toBeCalledWith('posts')
// and change their behavior
mocked(useNuxtData).mockReturnValue({
data: [...]
})

处理第三方可组合函数

所有可以增强您的 Nuxt 项目的第三方模块都不能自动模拟。在这些情况下,您需要手动模拟它们,例如,假设您的应用程序使用了Supabase模块插件

export default defineNuxtConfig({
modules: [
"@nuxtjs/supabase",
// ...
],
// ...
});

并且您在某个可组合函数中创建了 Supabase 的实例,例如:

const superbase = useSupabaseClient()

测试将由于以下原因而失败:

ReferenceError: useSupabaseClient is not defined

在此,我们建议模拟使用useSupabaseClient函数的整个模块,或者创建一个全局变量来模拟此函数,例如:

import { fn } from '@wdio/browser-runner'
globalThis.useSupabaseClient = fn().mockReturnValue({})

欢迎!我如何帮助您?

WebdriverIO AI Copilot