Przejdź do głównej treści

Vue.js

Vue.js to przyjazny, wydajny i wszechstronny framework do tworzenia interfejsów użytkownika dla stron internetowych. Możesz testować komponenty Vue.js bezpośrednio w prawdziwej przeglądarce za pomocą WebdriverIO i jego przeglądarkoego runnera.

Konfiguracja

Aby skonfigurować WebdriverIO w projekcie Vue.js, postępuj zgodnie z instrukcjami w naszej dokumentacji testowania komponentów. Upewnij się, że wybrałeś vue jako preset w opcjach runnera, np.:

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

Jeśli już używasz Vite jako serwera deweloperskiego, możesz również po prostu wykorzystać swoją konfigurację z vite.config.ts w konfiguracji WebdriverIO. Aby uzyskać więcej informacji, zobacz viteConfig w opcjach runnera.

Preset Vue wymaga zainstalowania @vitejs/plugin-vue. Zalecamy również używanie Testing Library do renderowania komponentu na stronie testowej. W związku z tym będziesz musiał zainstalować następujące dodatkowe zależności:

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

Następnie możesz uruchomić testy, wykonując:

npx wdio run ./wdio.conf.js

Pisanie testów

Załóżmy, że masz następujący komponent 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>

W swoim teście renderuj komponent do DOM i wykonuj na nim asercje. Zalecamy użycie @vue/test-utils lub @testing-library/vue do dołączenia komponentu do strony testowej. Do interakcji z komponentem używaj komend WebdriverIO, ponieważ zachowują się one bardziej podobnie do rzeczywistych interakcji użytkownika, np.:

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
})
})

Pełny przykład zestawu testów komponentów WebdriverIO dla Vue.js znajdziesz w naszym repozytorium przykładów.

Testowanie komponentów asynchronicznych w Vue3

Jeśli używasz Vue v3 i testujesz komponenty asynchroniczne takie jak poniższy:

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

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

Zalecamy użycie @vue/test-utils i małego wrappera suspense, aby wyrenderować komponent. Niestety @testing-library/vue nie ma jeszcze wsparcia dla tego. Utwórz plik helper.ts o następującej zawartości:

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 })
}

Następnie zaimportuj i przetestuj komponent w następujący sposób:

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()
})
})

Testowanie komponentów Vue w Nuxt

Jeśli używasz frameworka internetowego Nuxt, WebdriverIO automatycznie włączy funkcję auto-import i ułatwi testowanie komponentów Vue oraz stron Nuxt. Jednak wszelkie moduły Nuxt, które możesz zdefiniować w swojej konfiguracji i które wymagają kontekstu aplikacji Nuxt, nie mogą być obsługiwane.

Powody tego są następujące:

  • WebdriverIO nie może zainicjować aplikacji Nuxt wyłącznie w środowisku przeglądarki
  • Zbyt duża zależność testów komponentów od środowiska Nuxt tworzy złożoność i zalecamy uruchamianie tych testów jako testów e2e
informacja

WebdriverIO dostarcza również usługę do uruchamiania testów e2e na aplikacjach Nuxt. Zobacz webdriverio-community/wdio-nuxt-service dla informacji.

Mockowanie wbudowanych composables

W przypadku, gdy Twój komponent używa natywnego composable Nuxt, np. useNuxtData, WebdriverIO automatycznie zamockuje te funkcje i pozwoli Ci modyfikować ich zachowanie lub wykonywać na nich asercje, np.:

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: [...]
})

Obsługa composables innych firm

Wszystkie moduły innych firm, które mogą usprawnić Twój projekt Nuxt, nie mogą być automatycznie mockowane. W takich przypadkach musisz je ręcznie mockować, np. załóżmy, że Twoja aplikacja używa pluginu modułu Supabase:

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

i tworzysz instancję Supabase gdzieś w swoich composables, np.:

const superbase = useSupabaseClient()

test nie powiedzie się z powodu:

ReferenceError: useSupabaseClient is not defined

W tym przypadku zalecamy albo mockowanie całego modułu, który używa funkcji useSupabaseClient, albo utworzenie zmiennej globalnej, która mockuje tę funkcję, np.:

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

Welcome! How can I help?

WebdriverIO AI Copilot