Commands
Command is a function that invokes another function on the server and passes down the result back to the browser. Vitest exposes several built-in commands you can use in your browser tests.
Built-in Commands
Files Handling
You can use readFile
, writeFile
and removeFile
API to handle files inside your browser tests. All paths are resolved relative to the test file even if they are called in a helper function located in another file.
By default, Vitest uses utf-8
encoding but you can override it with options.
TIP
This API follows server.fs
limitations for security reasons.
import { server } from '@vitest/browser/context'
const { readFile, writeFile, removeFile } = server.commands
it('handles files', async () => {
const file = './test.txt'
await writeFile(file, 'hello world')
const content = await readFile(file)
expect(content).toBe('hello world')
await removeFile(file)
})
CDP Session
Vitest exposes access to raw Chrome Devtools Protocol via the cdp
method exported from @vitest/browser/context
. It is mostly useful to library authors to build tools on top of it.
import { cdp } from '@vitest/browser/context'
const input = document.createElement('input')
document.body.appendChild(input)
input.focus()
await cdp().send('Input.dispatchKeyEvent', {
type: 'keyDown',
text: 'a',
})
expect(input).toHaveValue('a')
WARNING
CDP session works only with playwright
provider and only when using chromium
browser. You can read more about it in playwright's CDPSession
documentation.
Custom Commands
You can also add your own commands via browser.commands
config option. If you develop a library, you can provide them via a config
hook inside a plugin:
import type { Plugin } from 'vitest/config'
import type { BrowserCommand } from 'vitest/node'
const myCustomCommand: BrowserCommand<[arg1: string, arg2: string]> = ({
testPath,
provider
}, arg1, arg2) => {
if (provider.name === 'playwright') {
console.log(testPath, arg1, arg2)
return { someValue: true }
}
throw new Error(`provider ${provider.name} is not supported`)
}
export default function BrowserCommands(): Plugin {
return {
name: 'vitest:custom-commands',
config() {
return {
test: {
browser: {
commands: {
myCustomCommand,
}
}
}
}
}
}
}
Then you can call it inside your test by importing it from @vitest/browser/context
:
import { commands } from '@vitest/browser/context'
import { expect, test } from 'vitest'
test('custom command works correctly', async () => {
const result = await commands.myCustomCommand('test1', 'test2')
expect(result).toEqual({ someValue: true })
})
// if you are using TypeScript, you can augment the module
declare module '@vitest/browser/context' {
interface BrowserCommands {
myCustomCommand: (arg1: string, arg2: string) => Promise<{
someValue: true
}>
}
}
WARNING
Custom functions will override built-in ones if they have the same name.
Custom playwright
commands
Vitest exposes several playwright
specific properties on the command context.
page
references the full page that contains the test iframe. This is the orchestrator HTML and you most likely shouldn't touch it to not break things.frame
is an async method that will resolve testerFrame
. It has a simillar API to thepage
, but it doesn't support certain methods. If you need to query an element, you should prefer usingcontext.iframe
instead because it is more stable and faster.iframe
is aFrameLocator
that should be used to query other elements on the page.context
refers to the unique BrowserContext.
import { BrowserCommand } from 'vitest/node'
export const myCommand: BrowserCommand<[string, number]> = async (
ctx,
arg1: string,
arg2: number
) => {
if (ctx.provider.name === 'playwright') {
const element = await ctx.iframe.findByRole('alert')
const screenshot = await element.screenshot()
// do something with the screenshot
return difference
}
}
TIP
If you are using TypeScript, don't forget to reference @vitest/browser/providers/playwright
in your setup file or a config file to get autocompletion in the config and in userEvent
and page
options:
/// <reference types="@vitest/browser/providers/playwright" />
Custom webdriverio
commands
Vitest exposes some webdriverio
specific properties on the context object.
browser
is theWebdriverIO.Browser
API.
Vitest automatically switches the webdriver
context to the test iframe by calling browser.switchToFrame
before the command is called, so $
and $$
methods refer to the elements inside the iframe, not in the orchestrator, but non-webdriver APIs will still refer to the parent frame context.
TIP
If you are using TypeScript, don't forget to reference @vitest/browser/providers/webdriverio
in your setup file or a config file to get autocompletion:
/// <reference types="@vitest/browser/providers/webdriverio" />