Vitest Browser Mode #5828
Replies: 17 comments 28 replies
-
Interesting, reading this with excitement |
Beta Was this translation helpful? Give feedback.
-
Amazing, can't wait for all the next evolutions!! |
Beta Was this translation helpful? Give feedback.
-
Incredible! |
Beta Was this translation helpful? Give feedback.
-
shut up and take my money |
Beta Was this translation helpful? Give feedback.
-
Maybe mention https://testcafe.io in your list of E2E frameworks? |
Beta Was this translation helpful? Give feedback.
-
Pretty stoked to see this work. I really appreciate being consulted about the future Vitest Browser Testing arch (compared to Cypress Component Testing's arch). I'm confident that this architecture will meet my needs for Vite-specific apps and I'll undoubtedly phase out teaching Cypress Component Testing once this lands. |
Beta Was this translation helpful? Give feedback.
-
Greeting, I am trying to use the rendering a canvas element by "@testing-library/react" 's render. but the Is there anything I need to pay attention to here?
|
Beta Was this translation helpful? Give feedback.
-
Will it be possible to set a custom render function to mount component from another framework than React ? |
Beta Was this translation helpful? Give feedback.
-
The above question is not important, so I modified it |
Beta Was this translation helpful? Give feedback.
-
Thanks for the detailed update! Do you have any idea how easy it would be to support electron as an option for browser mode? I was hoping after seeing the electron config for webdriverio that it wouldn't be too difficult, but I'm not very familiar yet with how |
Beta Was this translation helpful? Give feedback.
-
Any way to let the browser runner serve static files (in my case MSW's serviceWorker.js)? |
Beta Was this translation helpful? Give feedback.
-
Hi, I found that Are there any restrictions ? |
Beta Was this translation helpful? Give feedback.
-
While using I tried using addSnapshotSerializer in the setup file to handle this path. but I can't access Is there a better way to handle paths? |
Beta Was this translation helpful? Give feedback.
-
In browser mode, it seems that the iframe is destroyed every time after executing the test. Can we keep the iframe so that I can inspect the component's UI |
Beta Was this translation helpful? Give feedback.
-
I am going to lock the thread now. If you have any issues, bugs, or suggestions, please open a new issue or start a discussion. I will keep updating this thread whenever we want to release a significant change, so you can keep it in your subscriptions. |
Beta Was this translation helpful? Give feedback.
-
Vitest 2.1 will have some major improvements to the Browser Mode. We decided to have a built-in querying mechanism based on Playwright's locators - this API is available in all providers ( await expect.element(
page.getByRole('heading', { name: 'Sign up' })
).toBeVisible()
await page.getByRole('textbox', { name: 'Login' }).fill('admin')
No news on the release date yet, but you can already use these APIs in the beta. Looking forward to your feedback! |
Beta Was this translation helpful? Give feedback.
-
Vitest 2.1.4 introduces a new option called // vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
browser: {
testerHtmlPath: './my-custom-document.html',
},
},
}) <!DOCTYPE html>
<html lang="en">
<head>
<!-- custom meta tags -->
</head>
</html>
<body>
<!-- prepared HTML structure -->
<!-- vitest will inject your test file here -->
</body> Vitest will use serve the HTML content of this file in the tester iframe. It means that all your tests have access to it. If you want to use several HTML files, you can define a custom workspace with different project configs: // vitest.workspace.ts
import { defineWorkspace } from 'vitest/config'
export default defineWorkspace([
{
test: {
browser: {
testerHtmlPath: './my-custom-document.html',
},
},
},
{
test: {
include: ['*.special.test.ts'],
browser: {
testerHtmlPath: './my-special-document.html',
},
},
},
]) The HTML content is processed with the plugins' // vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [
{
transformIndexHtml() {
return [
{
tag: 'script',
children: 'windows.test = true',
},
]
}
},
],
}) |
Beta Was this translation helpful? Give feedback.
-
It's been some time since we gave any update on the Browser Mode, and Vitest 2.0 seems like a good time to explain how we feel about it. And we have a lot of plans!
The initial purpose of Vitest was to allow running tests without a complex Jest setup but with the battle-tested Jest API everyone is already familiar with. This also meant faking the browser environment (with
jsdom
orhappy-dom
). With time, as the JavaScript ecosystem evolved, we started to hit roadblocks with this approach (like this issue, for example, #4043). Switching to Jest's VM approach allowed us to bypass some of them, but introduced many more along the way (#3203).Using fake browser environments means that developers introduce an environment that doesn't exist anywhere except tests which can lead to testing something that cannot happen when an actual person uses your Web Application. Fake environments also have their own limitations like not providing common Web APIs (
fetch
,canvas
,PerformanceObserver
,HTMLDialogElement
, Pointer Lock, and so on) - this means that to test a single component you have to resort to E2E testing which throws a lot of APIs at you and can require a complex setup. There are already several solutions to that by different testing frameworks:Browser Mode is our take on component testing.
Future Plans
Browser mode aims to replace
jsdom
andhappy-dom
environment with an easy migration path. Right now you are able to opt-in to using browser mode by creating a separate workspace project:When you switch to the browser mode, all your tests should work as before unless you use Node.js APIs directly. This means that tests will be isolated by file, not by the
test
function (similar to Web Test Runner or Cypress). Most of the Vitest APIs includingvi.mock
,vi.dynamicImportSettled
should just work. Some of them we are unable to implement due to ESM limitations likeresetModules
- these will throw an error when running in the browser.The Vitest team is not interested in exploring the E2E testing (Vitest already provides integration for
webdriverio
andplaywright
that you can use alongside Vitest Browser Mode). In E2E tests you are typically testing a site that is deployed and doesn't need any changes. In Vitest Browser Mode you provide what is mounted on the DOM and mock the modules you want. Changing different states of the DOM becomes easier. This also means that we will not provide higher-level APIs like network interception. (On that note, our current recommendation is to use MSW for both browser and Node.js tests - this will be reflected in the browser guide in our documentation).It's hard to start using the browser mode in CI at the moment because you need to know what provider to choose and how to configure Vitest. To address this, we will improve the documentation and also provide a command to install all necessary packages and update the configuration to use the browser mode.
Additional API
Vitest will provide the context object via
@vitest/browser/context
import that exposes utilities (like file reading/writing) and allows you to communicate with the Node.js server via the Commands API. The context will expose thepage
object with interactive APIs that should replace theuserEvent
from@testing-library/user-event
. The current idea is to replace the@testing-library/user-event
import with a module that exposes the way to interact with the browser through Chrome DevTools or Webdriver protocols instead of mocking events that might not follow the actual browser specification:Vitest will also provide a way to hook into CDP directly to make developing libraries easier.
By default, Vitest provides playwright and webdriverio APIs wrapped in a common API out of the box (depending on which one you use) unless you use
preview
provider (previously namednone
).The
preview
provider (callednone
in Vitest 1.6) allows running tests in any browser of your choice by simply opening a link. It exposes a subset of APIs available inplaywright
andwebdriverio
, and uses the actualuserEvent
library to simulate events without relying on DevTool or Webdriver protocols. This provider is useful for a quick inspection of your code and tests and it doesn't require installing additional libraries and browsers, it is also the only provider that works in Stackblitz. However, be aware that if you don't use it to run tests in Stackblitz, your browser extensions/cookies/localStorage will affect your tests and possibly the dev environment making it hard to debug potential issues with tests. We recommend installingplaywright
orwebdriverio
to run your tests locally.Retryability is important when testing in the browser. Vitest 2.0 provides new
expect.poll
API to retry your assertions manually:Currently, there are no plans to implement our own built-in retryability+query API, but this can change based on community feedback.
Viewport can be configured globally with the
browser.viewport
option, but you can also change it during your test by clicking on one of the presets in the UI or by usingpage.viewport
command:Providers
Vitest requires
playwright
orwebdriverio
provider to run tests without simulating any events. Providers are used to install browsers, connect to CDP, and expose the testing browser environment.Vitest doesn't use test runners from these providers and doesn't expose any of their APIs directly. Built-in
userEvent
usespage
and$
APIs under the hood depending on the provider. You can write Custom Commands to get access to providers APIs on the server. Beware that you might need to usepage.frameLocator
orbrowser.switchToFrame
APIs to get access to HTML elements. This is considered an advanced use case, and we do not encourage overusing it.Test Isolation
Vitest opens a single page during the test run. Tests are isolated using iframes inside of that page. During development, you can see the iframe inside the UI (configurable by
test.browser.ui
):Running tresjs example in Vitest Browser Mode
The
--no-isolate
flag also allows running all browser tests inside the same iframe in cases where you do not depend on the global state and do a proper cleanup. This can make your test run several times faster. Module mocking works even when isolation is disabled.Debugging
Debugging using the IDE is not supported at the moment, but it's on the roadmap. In the meantime, you can use the
debugger
statement in your tests to automatically stop execution and open devtools:Unfortunately, you might need to rerun the test several times to hit the debugger statement if they are too fast. Better debugging experience is one of the highest priorities for the next feature release.
Node.js Polyfills
Vitest doesn't polyfill any Node.js APIs because it would create a situation where your code will work in tests, but won't work in dev or production. If you rely on some Node.js APIs in your setup files, you can add
vite-plugin-node-polyfills
to your plugins list ifprocess.env.VITEST
is set and manually add them toinclude
option:Current State
Vitest 1.6 implements browser tests using iframes. During the test run, you will see the Vitest UI, changing the file will reload the browser page.
Vitest 2.0 will ship with Commands API and module mocking supported. You can already test changes using the beta branch.
This release also implements better watch mode support - you can change files directly inside the UI and the tests will be reloaded without a page refresh like it was in Vitest 1.6. Changing the file outside the UI will also not reload the page.
The interactivity API is planned to be released after Vitest 2.0.
Special thanks to wonderful @Aslemammad and @userquin who worked on the initial implementation 🎉
Beta Was this translation helpful? Give feedback.
All reactions