diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 29debfb6c316..7291e22d1afd 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -594,24 +594,6 @@ export default ({ mode }: { mode: string }) => { }, ], }, - // { - // text: 'Render Function', - // collapsed: true, - // items: [ - // { - // text: 'react', - // link: '/config/browser/react', - // }, - // { - // text: 'vue', - // link: '/config/browser/vue', - // }, - // { - // text: 'svelte', - // link: '/config/browser/svelte', - // }, - // ], - // }, { text: 'browser.enabled', link: '/config/browser/enabled', @@ -1007,6 +989,28 @@ export default ({ mode }: { mode: string }) => { { text: 'Browser Mode', items: [ + { + text: 'Render Function', + collapsed: false, + items: [ + { + text: 'react', + link: '/api/browser/react', + }, + { + text: 'vue', + link: '/api/browser/vue', + }, + { + text: 'svelte', + link: '/api/browser/svelte', + }, + // { + // text: 'angular', + // link: '/api/browser/angular', + // }, + ], + }, { text: 'Context', link: '/api/browser/context', diff --git a/docs/api/browser/locators.md b/docs/api/browser/locators.md index b7eb6211f9fc..f81e040f8bcc 100644 --- a/docs/api/browser/locators.md +++ b/docs/api/browser/locators.md @@ -830,6 +830,10 @@ This method returns a single element matching the locator's selector or `null` i If multiple elements match the selector, this method will throw an error. Use [`.elements()`](#elements) when you need all matching DOM Elements or [`.all()`](#all) if you need an array of locators matching the selector. +::: danger +This is an escape hatch for external APIs that do not support locators. Prefer using locator methods instead. +::: + Consider the following DOM structure: ```html @@ -866,8 +870,10 @@ If _no element_ matches the selector, an error is thrown. Consider using [`.quer If _multiple elements_ match the selector, an error is thrown. Use [`.elements()`](#elements) when you need all matching DOM Elements or [`.all()`](#all) if you need an array of locators matching the selector. -::: tip -This method can be useful if you need to pass it down to an external library. It is called automatically when locator is used with `expect.element` every time the assertion is [retried](/api/browser/assertions): +::: danger +This is an escape hatch for external APIs that do not support locators. Prefer using locator methods instead. + +It is called automatically when locator is used with `expect.element` every time the assertion is [retried](/api/browser/assertions): ```ts await expect.element(page.getByRole('button')).toBeDisabled() diff --git a/docs/api/browser/react.md b/docs/api/browser/react.md new file mode 100644 index 000000000000..78e3fd8bd31d --- /dev/null +++ b/docs/api/browser/react.md @@ -0,0 +1,344 @@ +--- +outline: deep +--- + +# vitest-browser-react + +The community [`vitest-browser-react`](https://www.npmjs.com/package/vitest-browser-react) package renders [React](https://react.dev/) components in [Browser Mode](/guide/browser/). + +```jsx +import { render } from 'vitest-browser-react' +import { expect, test } from 'vitest' +import Component from './Component.jsx' + +test('counter button increments the count', async () => { + const screen = await render() + + await screen.getByRole('button', { name: 'Increment' }).click() + + await expect.element(screen.getByText('Count is 2')).toBeVisible() +}) +``` + +::: warning +This library takes inspiration from [`@testing-library/react`](https://github.com/testing-library/react-testing-library). + +If you have used `@testing-library/react` in your tests before, you can keep using it, however the `vitest-browser-react` package provides certain benefits unique to the Browser Mode that `@testing-library/react` lacks: + +`vitest-browser-react` returns APIs that interact well with built-in [locators](/api/browser/locators), [user events](/api/browser/interactivity) and [assertions](/api/browser/assertions): for example, Vitest will automatically retry the element until the assertion is successful, even if it was rerendered between the assertions. +::: + +The package exposes two entry points: `vitest-browser-react` and `vitest-browser-react/pure`. They expose almost identical API (`pure` also exposes `configure`), but the `pure` entry point doesn't add a handler to remove the component before the next test has started. + +## render + +```ts +export function render( + ui: React.ReactNode, + options?: ComponentRenderOptions, +): Promise +``` + +:::warning +Note that `render` is asynchronous, unlike in other packages. This is to support [`Suspense`](https://react.dev/reference/react/Suspense) correctly. + +```tsx +import { render } from 'vitest-browser-react' +const screen = render() // [!code --] +const screen = await render() // [!code ++] +``` +::: + +### Options + +#### container + +By default, Vitest will create a `div`, append it to `document.body`, and render your component there. If you provide your own `HTMLElement` container, it will not be appended automatically — you'll need to call `document.body.appendChild(container)` before `render`. + +For example, if you are unit testing a `tbody` element, it cannot be a child of a `div`. In this case, you can specify a `table` as the render container. + +```jsx +const table = document.createElement('table') + +const { container } = await render(, { + // ⚠️ appending the element to `body` manually before rendering + container: document.body.appendChild(table), +}) +``` + +#### baseElement + +If the `container` is specified, then this defaults to that, otherwise this defaults to `document.body`. This is used as the base element for the queries as well as what is printed when you use `debug()`. + +#### wrapper + +Pass a React Component as the `wrapper` option to have it rendered around the inner element. This is most useful for creating reusable custom render functions for common data providers. For example: + +```jsx +import React from 'react' +import { render } from 'vitest-browser-react' +import { ThemeProvider } from 'my-ui-lib' +import { TranslationProvider } from 'my-i18n-lib' + +function AllTheProviders({ children }) { + return ( + + + {children} + + + ) +} + +export function customRender(ui, options) { + return render(ui, { wrapper: AllTheProviders, ...options }) +} +``` + +### Render Result + +In addition to documented return value, the `render` function also returns all available [locators](/api/browser/locators) relative to the [`baseElement`](#baseelement), including [custom ones](/api/browser/locators#custom-locators). + +```tsx +const screen = await render() + +await screen.getByRole('link', { name: 'Expand' }).click() +``` + +#### container + +The containing `div` DOM node of your rendered React Element (rendered using `ReactDOM.render`). This is a regular DOM node, so you technically could call `container.querySelector` etc. to inspect the children. + +:::danger +If you find yourself using `container` to query for rendered elements then you should reconsider! The [locators](/api/browser/locators) are designed to be more resilient to changes that will be made to the component you're testing. Avoid using `container` to query for elements! +::: + +#### baseElement + +The containing DOM node where your React Element is rendered in the `container`. If you don't specify the `baseElement` in the options of render, it will default to `document.body`. + +This is useful when the component you want to test renders something outside the container `div`, e.g. when you want to snapshot test your portal component which renders its HTML directly in the body. + +:::tip +The queries returned by the `render` looks into `baseElement`, so you can use queries to test your portal component without the `baseElement`. +::: + +#### locator + +The [locator](/api/browser/locators) of your `container`. It is useful to use queries scoped only to your component, or pass it down to other assertions: + +```jsx +import { render } from 'vitest-browser-react' + +const { locator } = await render() + +await locator.getByRole('button').click() +await expect.element(locator).toHaveTextContent('Hello World') +``` + +#### debug + +```ts +function debug( + el?: HTMLElement | HTMLElement[] | Locator | Locator[], + maxLength?: number, + options?: PrettyDOMOptions, +): void +``` + +This method is a shortcut for `console.log(prettyDOM(baseElement))`. It will print the DOM content of the container or specified elements to the console. + +#### rerender + +```ts +function rerender(ui: React.ReactNode): Promise +``` + +It is better if you test the component that's doing the prop updating to ensure that the props are being updated correctly to avoid relying on implementation details in your tests. That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component. + +```jsx +import { render } from 'vitest-browser-react' + +const { rerender } = await render() + +// re-render the same component with different props +await rerender() +``` + +#### unmount + +```ts +function unmount(): Promise +``` + +This will cause the rendered component to be unmounted. This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks). + +```jsx +import { render } from 'vitest-browser-react' + +const { container, unmount } = await render() +await unmount() +// your component has been unmounted and now: container.innerHTML === '' +``` + +#### asFragment + +```ts +function asFragment(): DocumentFragment +``` + +Returns a `DocumentFragment` of your rendered component. This can be useful if you need to avoid live bindings and see how your component reacts to events. + +## cleanup + +```ts +export function cleanup(): Promise +``` + +Remove all components rendered with [`render`](#render). + +## renderHook + +```ts +export function renderHook( + renderCallback: (initialProps?: Props) => Result, + options: RenderHookOptions, +): Promise> +``` + +This is a convenience wrapper around `render` with a custom test component. The API emerged from a popular testing pattern and is mostly interesting for libraries publishing hooks. You should prefer `render` since a custom test component results in more readable and robust tests since the thing you want to test is not hidden behind an abstraction. + +```jsx +import { renderHook } from 'vitest-browser-react' + +test('returns logged in user', async () => { + const { result } = await renderHook(() => useLoggedInUser()) + expect(result.current).toEqual({ name: 'Alice' }) +}) +``` + +### Options + +`renderHook` accepts the same options as [`render`](#render) with an addition to `initialProps`: + +It declares the props that are passed to the render-callback when first invoked. These will not be passed if you call `rerender` without props. + +```jsx +import { renderHook } from 'vitest-browser-react' + +test('returns logged in user', async () => { + const { result, rerender } = await renderHook((props = {}) => props, { + initialProps: { name: 'Alice' }, + }) + expect(result.current).toEqual({ name: 'Alice' }) + await rerender() + expect(result.current).toEqual({ name: undefined }) +}) +``` + +:::warning +When using `renderHook` in conjunction with the `wrapper` and `initialProps` options, the `initialProps` are not passed to the `wrapper` component. To provide props to the `wrapper` component, consider a solution like this: + +```jsx +function createWrapper(Wrapper, props) { + return function CreatedWrapper({ children }) { + return {children} + } +} + +// ... + +await renderHook(() => {}, { + wrapper: createWrapper(Wrapper, { value: 'foo' }), +}) +``` +::: + +`renderHook` returns a few useful methods and properties: + +### Render Hook Result + +#### result + +Holds the value of the most recently committed return value of the render-callback: + +```jsx +import { useState } from 'react' +import { renderHook } from 'vitest-browser-react' +import { expect } from 'vitest' + +const { result } = await renderHook(() => { + const [name, setName] = useState('') + React.useEffect(() => { + setName('Alice') + }, []) + + return name +}) + +expect(result.current).toBe('Alice') +``` + +Note that the value is held in `result.current`. Think of result as a [ref](https://react.dev/learn/referencing-values-with-refs) for the most recently committed value. + +#### rerender {#renderhooks-rerender} + +Renders the previously rendered render-callback with the new props: + +```jsx +import { renderHook } from 'vitest-browser-react' + +const { rerender } = await renderHook(({ name = 'Alice' } = {}) => name) + +// re-render the same hook with different props +await rerender({ name: 'Bob' }) +``` + +#### unmount {#renderhooks-unmount} + +Unmounts the test hook. + +```jsx +import { renderHook } from 'vitest-browser-react' + +const { unmount } = await renderHook(({ name = 'Alice' } = {}) => name) + +await unmount() +``` + +## Extend Queries + +To extend locator queries, see [`"Custom Locators"`](/api/browser/locators#custom-locators). For example, to make `render` return a new custom locator, define it using the `locators.extend` API: + +```jsx {5-7,12} +import { locators } from 'vitest/browser' +import { render } from 'vitest-browser-react' + +locators.extend({ + getByArticleTitle(title) { + return `[data-title="${title}"]` + }, +}) + +const screen = await render() +await expect.element( + screen.getByArticleTitle('Hello World') +).toBeVisible() +``` + +## Configuration + +You can configure if the component should be rendered in Strict Mode with configure method from `vitest-browser-react/pure`: + +```js +import { configure } from 'vitest-browser-react/pure' + +configure({ + // disabled by default + reactStrictMode: true, +}) +``` + +## See also + +- [React Testing Library documentation](https://testing-library.com/docs/react-testing-library/intro) diff --git a/docs/api/browser/svelte.md b/docs/api/browser/svelte.md new file mode 100644 index 000000000000..1b100e9d0640 --- /dev/null +++ b/docs/api/browser/svelte.md @@ -0,0 +1,281 @@ +--- +outline: deep +--- + +# vitest-browser-svelte + +The community [`vitest-browser-svelte`](https://www.npmjs.com/package/vitest-browser-svelte) package renders [Svelte](https://svelte.dev/) components in [Browser Mode](/guide/browser/). + +```ts +import { render } from 'vitest-browser-svelte' +import { expect, test } from 'vitest' +import Component from './Component.svelte' + +test('counter button increments the count', async () => { + const screen = render(Component, { + initialCount: 1, + }) + + await screen.getByRole('button', { name: 'Increment' }).click() + + await expect.element(screen.getByText('Count is 2')).toBeVisible() +}) +``` + +::: warning +This library takes inspiration from [`@testing-library/svelte`](https://github.com/testing-library/svelte-testing-library). + +If you have used `@testing-library/svelte` in your tests before, you can keep using it, however the `vitest-browser-svelte` package provides certain benefits unique to the Browser Mode that `@testing-library/svelte` lacks: + +`vitest-browser-svelte` returns APIs that interact well with built-in [locators](/api/browser/locators), [user events](/api/browser/interactivity) and [assertions](/api/browser/assertions): for example, Vitest will automatically retry the element until the assertion is successful, even if it was rerendered between the assertions. +::: + +The package exposes two entry points: `vitest-browser-svelte` and `vitest-browser-svelte/pure`. They expose identical API, but the `pure` entry point doesn't add a handler to remove the component before the next test has started. + +## render + +```ts +export function render( + Component: ComponentImport, + options?: ComponentOptions, + renderOptions?: SetupOptions +): RenderResult +``` + +### Options + +The `render` function supports either options that you can pass down to [`mount`](https://svelte.dev/docs/svelte/imperative-component-api#mount) or props directly: + +```ts +const screen = render(Component, { + props: { // [!code --] + initialCount: 1, // [!code --] + }, // [!code --] + initialCount: 1, // [!code ++] +}) +``` + +#### props + +Component props. + +#### target + +By default, Vitest will create a `div`, append it to `document.body`, and render your component there. If you provide your own `HTMLElement` container, it will not be appended automatically — you'll need to call `document.body.appendChild(container)` before `render`. + +For example, if you are unit testing a `tbody` element, it cannot be a child of a `div`. In this case, you can specify a `table` as the render container. + +```ts +const table = document.createElement('table') + +const screen = render(TableBody, { + props, + // ⚠️ appending the element to `body` manually before rendering + target: document.body.appendChild(table), +}) +``` + +#### baseElement + +This can be passed down in a third argument. You should rarely, if ever, need to use this option. + +If the `target` is specified, then this defaults to that, otherwise this defaults to `document.body`. This is used as the base element for the queries as well as what is printed when you use `debug()`. + +### Render Result + +In addition to documented return value, the `render` function also returns all available [locators](/api/browser/locators) relative to the [`baseElement`](#baseelement), including [custom ones](/api/browser/locators#custom-locators). + +```ts +const screen = render(TableBody, props) + +await screen.getByRole('link', { name: 'Expand' }).click() +``` + +#### container + +The containing DOM node where your Svelte component is rendered. This is a regular DOM node, so you technically could call `container.querySelector` etc. to inspect the children. + +:::danger +If you find yourself using `container` to query for rendered elements then you should reconsider! The [locators](/api/browser/locators) are designed to be more resilient to changes that will be made to the component you're testing. Avoid using `container` to query for elements! +::: + +#### component + +The mounted Svelte component instance. You can use this to access component methods and properties if needed. + +```ts +const { component } = render(Counter, { + initialCount: 0, +}) + +// Access component exports if needed +``` + +#### locator + +The [locator](/api/browser/locators) of your `container`. It is useful to use queries scoped only to your component, or pass it down to other assertions: + +```ts +import { render } from 'vitest-browser-svelte' + +const { locator } = render(NumberDisplay, { + number: 2, +}) + +await locator.getByRole('button').click() +await expect.element(locator).toHaveTextContent('Hello World') +``` + +#### debug + +```ts +function debug( + el?: HTMLElement | HTMLElement[] | Locator | Locator[], +): void +``` + +This method is a shortcut for `console.log(prettyDOM(baseElement))`. It will print the DOM content of the container or specified elements to the console. + +#### rerender + +```ts +function rerender(props: Partial>): void +``` + +Updates the component's props and waits for Svelte to apply the changes. Use this to test how your component responds to prop changes. + +```ts +import { render } from 'vitest-browser-svelte' + +const { rerender } = render(NumberDisplay, { + number: 1, +}) + +// re-render the same component with different props +await rerender({ number: 2 }) +``` + +#### unmount + +```ts +function unmount(): void +``` + +Unmount and destroy the Svelte component. This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks). + +```ts +import { render } from 'vitest-browser-svelte' + +const { container, unmount } = render(Component) +unmount() +// your component has been unmounted and now: container.innerHTML === '' +``` + +## cleanup + +```ts +export function cleanup(): void +``` + +Remove all components rendered with [`render`](#render). + +## Extend Queries + +To extend locator queries, see [`"Custom Locators"`](/api/browser/locators#custom-locators). For example, to make `render` return a new custom locator, define it using the `locators.extend` API: + +```ts {5-7,12} +import { locators } from 'vitest/browser' +import { render } from 'vitest-browser-svelte' + +locators.extend({ + getByArticleTitle(title) { + return `[data-title="${title}"]` + }, +}) + +const screen = render(Component) +await expect.element( + screen.getByArticleTitle('Hello World') +).toBeVisible() +``` + +## Snippets + +For simple snippets, you can use a wrapper component and "dummy" children to test them. Setting `data-testid` attributes can be helpful when testing slots in this manner. + +::: code-group +```ts [basic.test.js] +import { render } from 'vitest-browser-svelte' +import { expect, test } from 'vitest' + +import SubjectTest from './basic-snippet.test.svelte' + +test('basic snippet', async () => { + const screen = render(SubjectTest) + + const heading = screen.getByRole('heading') + const child = heading.getByTestId('child') + + await expect.element(child).toBeInTheDocument() +}) +``` +```svelte [basic-snippet.svelte] + + +

+ {@render children?.()} +

+``` +```svelte [basic-snippet.test.svelte] + + + + + +``` +::: + +For more complex snippets, e.g. where you want to check arguments, you can use Svelte's [`createRawSnippet`](https://svelte.dev/docs/svelte/svelte#createRawSnippet) API. + +::: code-group +```js [complex-snippet.test.js] +import { render } from 'vitest-browser-svelte' +import { createRawSnippet } from 'svelte' +import { expect, test } from 'vitest' + +import Subject from './complex-snippet.svelte' + +test('renders greeting in message snippet', async () => { + const screen = render(Subject, { + name: 'Alice', + message: createRawSnippet(greeting => ({ + render: () => `${greeting()}`, + })), + }) + + const message = screen.getByTestId('message') + + await expect.element(message).toHaveTextContent('Hello, Alice!') +}) +``` +```svelte [complex-snippet.svelte] + + +

+ {@render message?.(greeting)} +

+``` +::: + +## See also + +- [Svelte Testing Library documentation](https://testing-library.com/docs/svelte-testing-library/intro) +- [Svelte Testing Library examples](https://github.com/testing-library/svelte-testing-library/tree/main/examples) diff --git a/docs/api/browser/vue.md b/docs/api/browser/vue.md new file mode 100644 index 000000000000..965f9efcba2b --- /dev/null +++ b/docs/api/browser/vue.md @@ -0,0 +1,205 @@ +--- +outline: deep +--- + +# vitest-browser-vue + +The community [`vitest-browser-vue`](https://www.npmjs.com/package/vitest-browser-vue) package renders [Vue](https://vuejs.org/) components in [Browser Mode](/guide/browser/). + +```ts +import { render } from 'vitest-browser-vue' +import { expect, test } from 'vitest' +import Component from './Component.vue' + +test('counter button increments the count', async () => { + const screen = render(Component, { + props: { + initialCount: 1, + } + }) + + await screen.getByRole('button', { name: 'Increment' }).click() + + await expect.element(screen.getByText('Count is 2')).toBeVisible() +}) +``` + +::: warning +This library takes inspiration from [`@testing-library/vue`](https://github.com/testing-library/vue-testing-library). + +If you have used `@testing-library/vue` in your tests before, you can keep using it, however the `vitest-browser-vue` package provides certain benefits unique to the Browser Mode that `@testing-library/vue` lacks: + +`vitest-browser-vue` returns APIs that interact well with built-in [locators](/api/browser/locators), [user events](/api/browser/interactivity) and [assertions](/api/browser/assertions): for example, Vitest will automatically retry the element until the assertion is successful, even if it was rerendered between the assertions. +::: + +The package exposes two entry points: `vitest-browser-vue` and `vitest-browser-vue/pure`. They expose identical API, but the `pure` entry point doesn't add a handler to remove the component before the next test has started. + +## render + +```ts +export function render( + component: Component, + options?: ComponentRenderOptions, +): RenderResult +``` + +### Options + +The `render` function supports all [`mount` options](https://test-utils.vuejs.org/api/#mount) from `@vue/test-utils` (except `attachTo` - use `container` instead). In addition to them, there are also `container` and `baseElement`. + +#### container + +By default, Vitest will create a `div`, append it to `document.body`, and render your component there. If you provide your own `HTMLElement` container, it will not be appended automatically — you'll need to call `document.body.appendChild(container)` before `render`. + +For example, if you are unit testing a `tbody` element, it cannot be a child of a `div`. In this case, you can specify a `table` as the render container. + +```js +const table = document.createElement('table') + +const { container } = render(TableBody, { + props, + // ⚠️ appending the element to `body` manually before rendering + container: document.body.appendChild(table), +}) +``` + +#### baseElement + +If the `container` is specified, then this defaults to that, otherwise this defaults to `document.body`. This is used as the base element for the queries as well as what is printed when you use `debug()`. + +### Render Result + +In addition to documented return value, the `render` function also returns all available [locators](/api/browser/locators) relative to the [`baseElement`](#baseelement), including [custom ones](/api/browser/locators#custom-locators). + +```ts +const screen = render(TableBody, { props }) + +await screen.getByRole('link', { name: 'Expand' }).click() +``` + +#### container + +The containing DOM node where your Vue component is rendered. This is a regular DOM node, so you technically could call `container.querySelector` etc. to inspect the children. + +:::danger +If you find yourself using `container` to query for rendered elements then you should reconsider! The [locators](/api/browser/locators) are designed to be more resilient to changes that will be made to the component you're testing. Avoid using `container` to query for elements! +::: + +#### baseElement + +The containing DOM node where your Vue component is rendered in the `container`. If you don't specify the `baseElement` in the options of render, it will default to `document.body`. + +This is useful when the component you want to test renders something outside the container `div`, e.g. when you want to snapshot test your portal component which renders its HTML directly in the body. + +:::tip +The queries returned by the `render` looks into `baseElement`, so you can use queries to test your portal component without the `baseElement`. +::: + +#### locator + +The [locator](/api/browser/locators) of your `container`. It is useful to use queries scoped only to your component, or pass it down to other assertions: + +```js +import { render } from 'vitest-browser-vue' + +const { locator } = render(NumberDisplay, { + props: { number: 2 } +}) + +await locator.getByRole('button').click() +await expect.element(locator).toHaveTextContent('Hello World') +``` + +#### debug + +```ts +function debug( + el?: HTMLElement | HTMLElement[] | Locator | Locator[], + maxLength?: number, + options?: PrettyDOMOptions, +): void +``` + +This method is a shortcut for `console.log(prettyDOM(baseElement))`. It will print the DOM content of the container or specified elements to the console. + +#### rerender + +```ts +function rerender(props: Partial): void +``` + +It is better if you test the component that's doing the prop updating to ensure that the props are being updated correctly to avoid relying on implementation details in your tests. That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component. + +```js +import { render } from 'vitest-browser-vue' + +const { rerender } = render(NumberDisplay, { props: { number: 1 } }) + +// re-render the same component with different props +rerender({ number: 2 }) +``` + +#### unmount + +```ts +function unmount(): void +``` + +This will cause the rendered component to be unmounted. This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks). + +#### emitted + +```ts +function emitted(): Record +function emitted(eventName: string): undefined | T[] +``` + +Returns the emitted events from the Component. + +::: warning +Emitted values are an implementation detail not exposed directly to the user, so it is better to test how your emitted values are changing the displayed content by using [locators](/api/browser/locators) instead. +::: + +## cleanup + +```ts +export function cleanup(): void +``` + +Remove all components rendered with [`render`](#render). + +## Extend Queries + +To extend locator queries, see [`"Custom Locators"`](/api/browser/locators#custom-locators). For example, to make `render` return a new custom locator, define it using the `locators.extend` API: + +```js {5-7,12} +import { locators } from 'vitest/browser' +import { render } from 'vitest-browser-vue' + +locators.extend({ + getByArticleTitle(title) { + return `[data-title="${title}"]` + }, +}) + +const screen = render(Component) +await expect.element( + screen.getByArticleTitle('Hello World') +).toBeVisible() +``` + +## Configuration + +You can configure [Vue Test Utils](https://test-utils.vuejs.org/api/#config) options by assigning properties to the `config` export (available in both `vitest-browser-vue` and `vitest-browser-vue/pure`): + +```js +import { config } from 'vitest-browser-vue/pure' + +config.global.stubs.CustomComponent = { + template: '
', +} +``` + +## See also + +- [Vue Testing Library documentation](https://testing-library.com/docs/vue-testing-library/intro)