Implementation:Webdriverio Webdriverio Browser Runner Render
Metadata
| Field | Value |
|---|---|
| Page ID | Browser_Runner_Render |
| Wiki | Webdriverio_Webdriverio |
| Type | Implementation (Wrapper Doc) |
| Domains | Testing, Component_Testing, Frontend |
| Knowledge Sources | Repo (https://github.com/webdriverio/webdriverio), Doc (https://webdriver.io/docs/component-testing) |
| Related Principles | Principle: Component_Test_Rendering |
Overview
Wrapper documentation for component rendering in WebdriverIO browser runner tests using framework testing libraries. When using the WDIO browser runner, components are rendered using framework-specific testing libraries (e.g., @testing-library/vue for Vue, @testing-library/react for React). The render() function mounts a component into the browser DOM. After rendering, $() and $$() query the component's DOM, and expect() validates output. The browser runner includes mock/spy support via @vitest/spy.
Description
The browser runner render flow involves three stages:
- Rendering -- The framework-specific
render()function mounts a component into the real browser DOM with specified props and slots. - Querying -- Testing Library query utilities (
getByText,getByRole, etc.) or WebdriverIO selectors ($(),$$()) locate elements in the rendered output. - Asserting -- WebdriverIO's
expect()function withexpect-webdriveriomatchers validates the component's output and behavior.
The browser runner's expect system is implemented in packages/wdio-browser-runner/src/browser/expect.ts, which creates matcher factories that serialize assertions and send them to the Node.js worker process for evaluation. The mocking system in packages/wdio-browser-runner/src/browser/spy.ts re-exports @vitest/spy and provides mock(), unmock(), and mocked() functions.
Source
| File | Lines | Description |
|---|---|---|
examples/wdio/vite-vue-example/src/components/HelloWorld.test.ts |
L1-27 | Full Vue component test example |
packages/wdio-browser-runner/src/browser/expect.ts |
L1-50+ | Browser-side expect matcher factory |
packages/wdio-browser-runner/src/browser/spy.ts |
L1-55 | Mock/spy module (re-exports @vitest/spy, provides mock/unmock) |
examples/wdio/vite-vue-example/src/components/HelloWorld.vue |
L1-38 | Vue component under test |
APIs
render(Component, options?)
Mounts a UI component into the browser DOM. Provided by the framework-specific testing library.
For Vue:
import { render } from '@testing-library/vue'
import Component from './MyComponent.vue'
const { getByText, getByRole, container } = render(Component, {
props: { msg: 'Hello' },
slots: { default: '<span>slot content</span>' }
})
I/O Contract:
| Parameter | Type | Description |
|---|---|---|
Component |
Framework component | The component to render |
options.props |
Object (optional) | Props to pass to the component |
options.slots |
Object (optional) | Slot content (Vue-specific) |
| Returns | RenderResult | Object with query utilities: getByText, getByRole, container, etc.
|
$('selector') / $$('selector')
WebdriverIO global selectors for querying the rendered DOM. Can also wrap DOM elements returned by Testing Library queries.
// Query by CSS selector
const button = await $('button.submit')
// Wrap a Testing Library query result
const { getByText } = render(Component)
const element = await $(getByText('Click me'))
I/O Contract:
| Parameter | Type | Description |
|---|---|---|
selector |
string or HTMLElement | CSS selector string or DOM element |
| Returns | ChainablePromiseElement |
WebdriverIO element wrapper with full command API |
expect(element).matcher()
Assertion function using expect-webdriverio matchers. The browser runner's expect implementation serializes matcher calls and evaluates them in the Node.js worker process.
await expect(button).toHaveText('count is 2')
await expect($('.message')).toBeDisplayed()
await expect($('input')).toHaveValue('test')
mock(path, factory?) / unmock(moduleName)
Module mocking functions provided by the browser runner's spy module.
import { fn, spyOn } from '@wdio/browser-runner'
// Mock a module with a factory
mock('./api.js', () => ({
fetchData: fn().mockResolvedValue({ items: [] })
}))
// Remove a mock
unmock('./api.js')
I/O Contract:
| Function | Parameters | Description |
|---|---|---|
mock(path, factory?) |
path: string, factory: function (optional) | Replaces module imports with factory return value |
unmock(moduleName) |
moduleName: string | Removes a previously registered mock |
mocked(item) |
item: T | Type utility for casting to MaybeMocked<T> |
fn() |
None | Creates a mock function (from @vitest/spy) |
spyOn(obj, method) |
obj: object, method: string | Creates a spy on an object method (from @vitest/spy) |
Full Example: Vue Component Test
Component under test (HelloWorld.vue):
<script setup lang="ts">
import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
</div>
</template>
Test file (HelloWorld.test.ts):
import { expect, $ } from '@wdio/globals'
import { render } from '@testing-library/vue'
import * as matchers from '@testing-library/jest-dom/matchers'
expect.extend(matchers as any)
import Component from './HelloWorld.vue'
describe('Vue Component Tests', () => {
it('should do something cool', async () => {
// The render method returns a collection of utilities to query your component.
const { getByText } = render(Component)
// getByText returns the first matching node for the provided text, and
// throws an error if no elements match or if more than one match is found.
getByText('count is 0')
const button = await $(getByText('count is 0'))
// Dispatch a native click event to our button element.
await button.click()
await button.click()
getByText('count is 2')
await expect(button).toHaveText('count is 2')
})
})
Test flow:
- Import
renderfrom@testing-library/vueand the component. - Call
render(Component)to mount the component in the real browser DOM. - Use
getByText('count is 0')to verify initial render text. - Wrap the DOM element with
$(getByText(...))to get a WebdriverIO element. - Call
.click()twice to simulate user interaction. - Assert the button text changed to
'count is 2'usingtoHaveText().
Import Summary
// WebdriverIO globals (available in browser runner context)
import { expect, $ } from '@wdio/globals'
// Framework-specific render function
import { render } from '@testing-library/vue' // Vue
import { render } from '@testing-library/react' // React
import { render } from '@testing-library/svelte' // Svelte
// Mocking (from browser runner)
import { fn, spyOn, mock, unmock } from '@wdio/browser-runner'
Related Pages
- implements Principle: Component_Test_Rendering