diff --git a/docs/guide/browser/config.md b/docs/guide/browser/config.md
index aa3095c37..18af8295f 100644
--- a/docs/guide/browser/config.md
+++ b/docs/guide/browser/config.md
@@ -4,12 +4,13 @@ You can change the browser configuration by updating the `test.browser` field in
```ts [vitest.config.ts]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{
browser: 'chromium',
@@ -53,15 +54,6 @@ Defines multiple browser setups. Every config has to have at least a `browser` f
- [Configuring Playwright](/guide/browser/playwright)
- [Configuring WebdriverIO](/guide/browser/webdriverio)
-::: tip
-To have a better type safety when using built-in providers, you should reference one of these types (for provider that you are using) in your [config file](/config/):
-
-```ts
-///
-///
-```
-:::
-
In addition to that, you can also specify most of the [project options](/config/) (not marked with a icon) and some of the `browser` options like `browser.testerHtmlPath`.
::: warning
@@ -100,26 +92,12 @@ List of available `browser` options:
- [`browser.testerHtmlPath`](#browser-testerhtmlpath)
- [`browser.screenshotDirectory`](#browser-screenshotdirectory)
- [`browser.screenshotFailures`](#browser-screenshotfailures)
+- [`browser.provider`](#browser-provider)
By default, Vitest creates an array with a single element which uses the [`browser.name`](#browser-name) field as a `browser`. Note that this behaviour will be removed with Vitest 4.
Under the hood, Vitest transforms these instances into separate [test projects](/advanced/api/test-project) sharing a single Vite server for better caching performance.
-## browser.name deprecated {#browser-name}
-
-- **Type:** `string`
-- **CLI:** `--browser=safari`
-
-::: danger DEPRECATED
-This API is deprecated an will be removed in Vitest 4. Please, use [`browser.instances`](#browser-instances) option instead.
-:::
-
-Run all tests in a specific browser. Possible options in different providers:
-
-- `webdriverio`: `firefox`, `chrome`, `edge`, `safari`
-- `playwright`: `firefox`, `webkit`, `chromium`
-- custom: any string that will be passed to the provider
-
## browser.headless
- **Type:** `boolean`
@@ -150,70 +128,86 @@ A path to the HTML entry point. Can be relative to the root of the project. This
Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](#api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel.
-## browser.provider {#browser-provider}
+## browser.provider advanced {#browser-provider}
-- **Type:** `'webdriverio' | 'playwright' | 'preview' | string`
+- **Type:** `BrowserProviderOption`
- **Default:** `'preview'`
- **CLI:** `--browser.provider=playwright`
-Path to a provider that will be used when running browser tests. Vitest provides three providers which are `preview` (default), `webdriverio` and `playwright`. Custom providers should be exported using `default` export and have this shape:
+The return value of the provider factory. You can import the factory from `@vitest/browser/providers/` or make your own provider:
-```ts
-export interface BrowserProvider {
- name: string
- supportsParallelism: boolean
- getSupportedBrowsers: () => readonly string[]
- beforeCommand?: (command: string, args: unknown[]) => Awaitable
- afterCommand?: (command: string, args: unknown[]) => Awaitable
- getCommandsContext: (sessionId: string) => Record
- openPage: (sessionId: string, url: string, beforeNavigate?: () => Promise) => Promise
- getCDPSession?: (sessionId: string) => Promise
- close: () => Awaitable
- initialize(
- ctx: TestProject,
- options: BrowserProviderInitializationOptions
- ): Awaitable
-}
-```
+```ts{8-10}
+import { playwright } from '@vitest/browser/providers/playwright'
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
+import { preview } from '@vitest/browser/providers/preview'
-::: danger ADVANCED API
-The custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](#browser-instances) option instead.
-:::
-
-## browser.providerOptions deprecated {#browser-provideroptions}
-
-- **Type:** `BrowserProviderOptions`
-
-::: danger DEPRECATED
-This API is deprecated an will be removed in Vitest 4. Please, use [`browser.instances`](#browser-instances) option instead.
-:::
+export default defineConfig({
+ test: {
+ browser: {
+ provider: playwright(),
+ provider: webdriverio(),
+ provider: preview(), // default
+ },
+ },
+})
+```
-Options that will be passed down to provider when calling `provider.initialize`.
+To configure how provider initializes the browser, you can pass down options to the factory function:
-```ts
-import { defineConfig } from 'vitest/config'
+```ts{7-15,22-27}
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
test: {
browser: {
- providerOptions: {
- launch: {
- devtools: true,
+ // shared provider options between all instances
+ provider: playwright({
+ launchOptions: {
+ slowMo: 50,
+ channel: 'chrome-beta',
},
- },
+ actionTimeout: 5_000,
+ }),
+ instances: [
+ { browser: 'chromium' },
+ {
+ browser: 'firefox',
+ // overriding options only for a single instance
+ // this will NOT merge options with the parent one
+ provider: playwright({
+ launchOptions: {
+ firefoxUserPrefs: {
+ 'browser.startup.homepage': 'https://example.com',
+ },
+ },
+ })
+ }
+ ],
},
},
})
```
-::: tip
-To have a better type safety when using built-in providers, you should reference one of these types (for provider that you are using) in your [config file](/config/):
+### Custom Provider
+
+::: danger ADVANCED API
+The custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](#browser-instances) option instead.
+:::
```ts
-///
-///
+export interface BrowserProvider {
+ name: string
+ mocker?: BrowserModuleMocker
+ /**
+ * @experimental opt-in into file parallelisation
+ */
+ supportsParallelism: boolean
+ getCommandsContext: (sessionId: string) => Record
+ openPage: (sessionId: string, url: string) => Promise
+ getCDPSession?: (sessionId: string) => Promise
+ close: () => Awaitable
+}
```
-:::
## browser.ui
diff --git a/docs/guide/browser/index.md b/docs/guide/browser/index.md
index dd2f57bb7..5ae2281a4 100644
--- a/docs/guide/browser/index.md
+++ b/docs/guide/browser/index.md
@@ -99,10 +99,12 @@ To activate browser mode in your Vitest configuration, set the `browser.enabled`
```ts [vitest.config.ts]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
+
export default defineConfig({
test: {
browser: {
- provider: 'playwright', // or 'webdriverio'
+ provider: playwright(),
enabled: true,
// at least one instance is required
instances: [
@@ -125,13 +127,14 @@ If you have not used Vite before, make sure you have your framework's plugin ins
```ts [react]
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
plugins: [react()],
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
],
@@ -141,6 +144,7 @@ export default defineConfig({
```
```ts [vue]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
@@ -148,7 +152,7 @@ export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
],
@@ -159,13 +163,14 @@ export default defineConfig({
```ts [svelte]
import { defineConfig } from 'vitest/config'
import { svelte } from '@sveltejs/vite-plugin-svelte'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
plugins: [svelte()],
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
],
@@ -176,13 +181,14 @@ export default defineConfig({
```ts [solid]
import { defineConfig } from 'vitest/config'
import solidPlugin from 'vite-plugin-solid'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
plugins: [solidPlugin()],
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
],
@@ -193,13 +199,14 @@ export default defineConfig({
```ts [marko]
import { defineConfig } from 'vitest/config'
import marko from '@marko/vite'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
plugins: [marko()],
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
],
@@ -210,6 +217,7 @@ export default defineConfig({
```ts [qwik]
import { defineConfig } from 'vitest/config'
import { qwikVite } from '@builder.io/qwik/optimizer'
+import { playwright } from '@vitest/browser/providers/playwright'
// optional, run the tests in SSR mode
import { testSSR } from 'vitest-browser-qwik/ssr-plugin'
@@ -219,7 +227,7 @@ export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [{ browser: 'chromium' }]
},
},
@@ -370,10 +378,12 @@ Here's an example configuration enabling headless mode:
```ts [vitest.config.ts]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
+
export default defineConfig({
test: {
browser: {
- provider: 'playwright',
+ provider: playwright(),
enabled: true,
headless: true,
},
diff --git a/docs/guide/browser/multiple-setups.md b/docs/guide/browser/multiple-setups.md
index 811227f30..6113e71b7 100644
--- a/docs/guide/browser/multiple-setups.md
+++ b/docs/guide/browser/multiple-setups.md
@@ -10,11 +10,13 @@ You can use the `browser.instances` field to specify options for different brows
```ts [vitest.config.ts]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
+
export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium' },
@@ -33,11 +35,13 @@ You can also specify different config options independently from the browser (al
::: code-group
```ts [vitest.config.ts]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
+
export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{
diff --git a/docs/guide/browser/playwright.md b/docs/guide/browser/playwright.md
index 2601fcc66..c261f5fad 100644
--- a/docs/guide/browser/playwright.md
+++ b/docs/guide/browser/playwright.md
@@ -1,62 +1,59 @@
# Configuring Playwright
-By default, TypeScript doesn't recognize providers options and extra `expect` properties. Make sure to reference `@vitest/browser/providers/playwright` so TypeScript can pick up definitions for custom options:
+To run tests using playwright, you need to specify it in the `test.browser.provider` property in your config:
-```ts [vitest.shims.d.ts]
-///
-```
-
-Alternatively, you can also add it to `compilerOptions.types` field in your `tsconfig.json` file. Note that specifying anything in this field will disable [auto loading](https://www.typescriptlang.org/tsconfig/#types) of `@types/*` packages.
-
-```json [tsconfig.json]
-{
- "compilerOptions": {
- "types": ["@vitest/browser/providers/playwright"]
- }
-}
-```
-
-Vitest opens a single page to run all tests in the same file. You can configure the `launch`, `connect` and `context` properties in `instances`:
-
-```ts{9-11} [vitest.config.ts]
+```ts [vitest.config.js]
+import { playwright } from '@vitest/browser/providers/playwright'
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
browser: {
- instances: [
- {
- browser: 'firefox',
- launch: {},
- connect: {},
- context: {},
- },
- ],
+ provider: playwright(),
+ instances: [{ browser: 'chromium' }]
},
},
})
```
-::: warning
-Before Vitest 3, these options were located on `test.browser.providerOptions` property:
+Vitest opens a single page to run all tests in the same file. You can configure the `launch`, `connect` and `context` when calling `playwright` at the top level or inside instances:
+
+```ts{7-15,22-27} [vitest.config.js]
+import { playwright } from '@vitest/browser/providers/playwright'
+import { defineConfig } from 'vitest/config'
-```ts [vitest.config.ts]
export default defineConfig({
test: {
browser: {
- providerOptions: {
- launch: {},
- context: {},
- },
+ // shared provider options between all instances
+ provider: playwright({
+ launchOptions: {
+ slowMo: 50,
+ channel: 'chrome-beta',
+ },
+ actionTimeout: 5_000,
+ }),
+ instances: [
+ { browser: 'chromium' },
+ {
+ browser: 'firefox',
+ // overriding options only for a single instance
+ // this will NOT merge options with the parent one
+ provider: playwright({
+ launchOptions: {
+ firefoxUserPrefs: {
+ 'browser.startup.homepage': 'https://example.com',
+ },
+ },
+ })
+ }
+ ],
},
},
})
```
-`providerOptions` is deprecated in favour of `instances`.
-:::
-
-## launch
+## launchOptions
These options are directly passed down to `playwright[browser].launch` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-launch).
@@ -66,7 +63,7 @@ Vitest will ignore `launch.headless` option. Instead, use [`test.browser.headles
Note that Vitest will push debugging flags to `launch.args` if [`--inspect`](/guide/cli#inspect) is enabled.
:::
-## connect 3.2.0 {#connect}
+## connectOptions
These options are directly passed down to `playwright[browser].connect` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
@@ -74,9 +71,9 @@ These options are directly passed down to `playwright[browser].connect` command.
Since this command connects to an existing Playwright server, any `launch` options will be ignored.
:::
-## context
+## contextOptions
-Vitest creates a new context for every test file by calling [`browser.newContext()`](https://playwright.dev/docs/api/class-browsercontext). You can configure this behaviour by specifying [custom arguments](https://playwright.dev/docs/api/class-apirequest#api-request-new-context).
+Vitest creates a new context for every test file by calling [`browser.newContext()`](https://playwright.dev/docs/api/class-browsercontext). You can configure this behaviour by specifying [custom arguments](https://playwright.dev/docs/api/class-browser#browser-new-context).
::: tip
Note that the context is created for every _test file_, not every _test_ like in playwright test runner.
@@ -88,9 +85,9 @@ Vitest always sets `ignoreHTTPSErrors` to `true` in case your server is served v
It is also recommended to use [`test.browser.viewport`](/guide/browser/config#browser-headless) instead of specifying it here as it will be lost when tests are running in headless mode.
:::
-## `actionTimeout` 3.0.0
+## `actionTimeout`
-- **Default:** no timeout, 1 second before 3.0.0
+- **Default:** no timeout
This value configures the default timeout it takes for Playwright to wait until all accessibility checks pass and [the action](/guide/browser/interactivity-api) is actually done.
diff --git a/docs/guide/browser/visual-regression-testing.md b/docs/guide/browser/visual-regression-testing.md
index 544ea1de9..b6e3b7827 100644
--- a/docs/guide/browser/visual-regression-testing.md
+++ b/docs/guide/browser/visual-regression-testing.md
@@ -239,11 +239,14 @@ await page.viewport(1280, 720)
```
```ts [vitest.config.ts]
+import { playwright } from '@vitest/browser/providers/playwright'
+import { defineConfig } from 'vitest/config'
+
export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{
browser: 'chromium',
@@ -588,6 +591,7 @@ The cleanest approach is using [Test Projects](/guide/projects):
```ts [vitest.config.ts]
import { env } from 'node:process'
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
// ...global Vite config
@@ -610,7 +614,7 @@ export default defineConfig({
include: ['visual-regression-tests/**/*.test.ts?(x)'],
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{
diff --git a/docs/guide/browser/webdriverio.md b/docs/guide/browser/webdriverio.md
index b0afdf789..409beb3a9 100644
--- a/docs/guide/browser/webdriverio.md
+++ b/docs/guide/browser/webdriverio.md
@@ -4,66 +4,59 @@
If you do not already use WebdriverIO in your project, we recommend starting with [Playwright](/guide/browser/playwright) as it is easier to configure and has more flexible API.
:::
-By default, TypeScript doesn't recognize providers options and extra `expect` properties. Make sure to reference `@vitest/browser/providers/webdriverio` so TypeScript can pick up definitions for custom options:
+To run tests using WebdriverIO, you need to specify it in the `test.browser.provider` property in your config:
-```ts [vitest.shims.d.ts]
-///
-```
-
-Alternatively, you can also add it to `compilerOptions.types` field in your `tsconfig.json` file. Note that specifying anything in this field will disable [auto loading](https://www.typescriptlang.org/tsconfig/#types) of `@types/*` packages.
-
-```json [tsconfig.json]
-{
- "compilerOptions": {
- "types": ["@vitest/browser/providers/webdriverio"]
- }
-}
-```
-
-Vitest opens a single page to run all tests in the same file. You can configure any property specified in `RemoteOptions` in `instances`:
-
-```ts{9-12} [vitest.config.ts]
+```ts [vitest.config.js]
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
browser: {
- instances: [
- {
- browser: 'chrome',
- capabilities: {
- browserVersion: 86,
- platformName: 'Windows 10',
- },
- },
- ],
+ provider: webdriverio(),
+ instances: [{ browser: 'chrome' }]
},
},
})
```
-::: warning
-Before Vitest 3, these options were located on `test.browser.providerOptions` property:
+Vitest opens a single page to run all tests in the same file. You can configure all the parameters that [`remote`](https://webdriver.io/docs/api/modules/#remoteoptions-modifier) function accepts:
+
+```ts{8-12,19-23} [vitest.config.js]
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
+import { defineConfig } from 'vitest/config'
-```ts [vitest.config.ts]
export default defineConfig({
test: {
browser: {
- providerOptions: {
- capabilities: {},
- },
+ // shared provider options between all instances
+ provider: webdriverio({
+ capabilities: {
+ browserVersion: '82',
+ },
+ }),
+ instances: [
+ { browser: 'chrome' },
+ {
+ browser: 'firefox',
+ // overriding options only for a single instance
+ // this will NOT merge options with the parent one
+ provider: webdriverio({
+ 'moz:firefoxOptions': {
+ args: ['--disable-gpu'],
+ },
+ })
+ }
+ ],
},
},
})
```
-`providerOptions` is deprecated in favour of `instances`.
-:::
-
You can find most available options in the [WebdriverIO documentation](https://webdriver.io/docs/configuration/). Note that Vitest will ignore all test runner options because we only use `webdriverio`'s browser capabilities.
::: tip
Most useful options are located on `capabilities` object. WebdriverIO allows nested capabilities, but Vitest will ignore those options because we rely on a different mechanism to spawn several browsers.
-Note that Vitest will ignore `capabilities.browserName`. Use [`test.browser.instances.name`](/guide/browser/config#browser-capabilities-name) instead.
+Note that Vitest will ignore `capabilities.browserName`. Use [`test.browser.instances.browser`](/guide/browser/config#browser-capabilities-name) instead.
:::
diff --git a/docs/guide/debugging.md b/docs/guide/debugging.md
index 0e0fd934d..144aa89f7 100644
--- a/docs/guide/debugging.md
+++ b/docs/guide/debugging.md
@@ -52,13 +52,14 @@ vitest --inspect-brk --browser --no-file-parallelism
```
```ts [vitest.config.js]
import { defineConfig } from 'vitest/config'
+import { playwright } from '@vitest/browser/providers/playwright'
export default defineConfig({
test: {
inspectBrk: true,
fileParallelism: false,
browser: {
- provider: 'playwright',
+ provider: playwright(),
instances: [{ browser: 'chromium' }]
},
},
diff --git a/docs/guide/migration.md b/docs/guide/migration.md
index 5b97782ed..eaf92cfa9 100644
--- a/docs/guide/migration.md
+++ b/docs/guide/migration.md
@@ -229,6 +229,37 @@ export default defineWorkspace([ // [!code --]
```
:::
+### Browser Provider Accepts an Object
+
+In Vitest 4.0, the browser provider now accepts an object instead of a string (`'playwright'`, `'webdriverio'`). This makes it simpler to work with custom options and doesn't require adding `///
+import { playwright } from '@vitest/browser/providers/playwright'
import { defineConfig } from 'vite'
// https://vitejs.dev/config/
@@ -9,7 +10,7 @@ export default defineConfig({
// https://lit.dev/docs/tools/testing/#testing-in-the-browser
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
],
diff --git a/packages/browser/README.md b/packages/browser/README.md
index 1e5eac4cf..d6810bf7d 100644
--- a/packages/browser/README.md
+++ b/packages/browser/README.md
@@ -1,19 +1,7 @@
# @vitest/browser
-[Browser runner](https://vitest.dev/guide/browser/) for Vitest.
+[](https://www.npmjs.com/package/@vitest/browser)
-> ⚠️ This package is **experimental**. While this package will be released along with other packages, it will not follow SemVer for breaking changes until we mark it as ready.
+Running Vitest tests in the real browser.
-## Development Setup
-
-At project root:
-
-```bash
-cd test/browser
-# runs relevant tests for the browser mode
-# useful to confirm everything works fine
-pnpm test
-# runs tests as the browser mode
-# useful during development
-pnpm test-fixtures
-```
+[GitHub](https://github.com/vitest-dev/vitest) | [Documentation](https://vitest.dev/guide/browser/)
diff --git a/packages/browser/package.json b/packages/browser/package.json
index 0240d11a2..355de79e8 100644
--- a/packages/browser/package.json
+++ b/packages/browser/package.json
@@ -20,9 +20,9 @@
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
- "./providers": {
- "types": "./providers.d.ts",
- "default": "./dist/providers.js"
+ "./providers/*": {
+ "types": "./dist/providers/*.d.ts",
+ "default": "./dist/providers/*.js"
},
"./context": {
"types": "./context.d.ts",
@@ -35,14 +35,6 @@
"types": "./matchers.d.ts",
"default": "./dummy.js"
},
- "./providers/webdriverio": {
- "types": "./providers/webdriverio.d.ts",
- "default": "./dummy.js"
- },
- "./providers/playwright": {
- "types": "./providers/playwright.d.ts",
- "default": "./dummy.js"
- },
"./locator": {
"types": "./dist/locators/index.d.ts",
"default": "./dist/locators/index.js"
@@ -105,19 +97,14 @@
"@types/pngjs": "^6.0.5",
"@types/ws": "catalog:",
"@vitest/runner": "workspace:*",
- "@vitest/ui": "workspace:*",
- "@vitest/ws-client": "workspace:*",
- "@wdio/protocols": "^9.16.2",
"@wdio/types": "^9.16.2",
"birpc": "catalog:",
"flatted": "catalog:",
"ivya": "^1.7.0",
"mime": "^4.0.7",
"pathe": "catalog:",
- "periscopic": "^4.0.2",
"playwright": "^1.54.1",
"playwright-core": "^1.54.1",
- "safaridriver": "^1.0.0",
"vitest": "workspace:*",
"webdriverio": "^9.18.4"
}
diff --git a/packages/browser/providers/playwright.d.ts b/packages/browser/providers/playwright.d.ts
deleted file mode 100644
index 904d233b0..000000000
--- a/packages/browser/providers/playwright.d.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import type {
- BrowserContext,
- BrowserContextOptions,
- Frame,
- FrameLocator,
- LaunchOptions,
- Page,
- CDPSession,
- ConnectOptions
-} from 'playwright'
-import { Protocol } from 'playwright-core/types/protocol'
-import '../matchers.js'
-import type {} from "vitest/node"
-import type {
- Locator,
- ScreenshotComparatorRegistry,
- ScreenshotMatcherOptions,
-} from "@vitest/browser/context"
-
-declare module 'vitest/node' {
- export interface BrowserProviderOptions {
- launch?: LaunchOptions
- connect?: {
- wsEndpoint: string
- options?: ConnectOptions
- }
- context?: Omit<
- BrowserContextOptions,
- 'ignoreHTTPSErrors' | 'serviceWorkers'
- > & {
- /**
- * The maximum time in milliseconds to wait for `userEvent` action to complete.
- * @default 0 (no timeout)
- */
- actionTimeout?: number
- }
- }
-
- export interface BrowserCommandContext {
- page: Page
- frame(): Promise
- iframe: FrameLocator
- context: BrowserContext
- }
-
- export interface ToMatchScreenshotOptions
- extends Omit<
- ScreenshotMatcherOptions,
- "comparatorName" | "comparatorOptions"
- > {}
-
- export interface ToMatchScreenshotComparators
- extends ScreenshotComparatorRegistry {}
-}
-
-type PWHoverOptions = NonNullable[1]>
-type PWClickOptions = NonNullable[1]>
-type PWDoubleClickOptions = NonNullable[1]>
-type PWFillOptions = NonNullable[2]>
-type PWScreenshotOptions = NonNullable[0]>
-type PWSelectOptions = NonNullable[2]>
-type PWDragAndDropOptions = NonNullable[2]>
-type PWSetInputFiles = NonNullable[2]>
-
-declare module '@vitest/browser/context' {
- export interface UserEventHoverOptions extends PWHoverOptions {}
- export interface UserEventClickOptions extends PWClickOptions {}
- export interface UserEventDoubleClickOptions extends PWDoubleClickOptions {}
- export interface UserEventTripleClickOptions extends PWClickOptions {}
- export interface UserEventFillOptions extends PWFillOptions {}
- export interface UserEventSelectOptions extends PWSelectOptions {}
- export interface UserEventDragAndDropOptions extends PWDragAndDropOptions {}
- export interface UserEventUploadOptions extends PWSetInputFiles {}
-
- export interface ScreenshotOptions extends Omit {
- mask?: ReadonlyArray | undefined
- }
-
- export interface CDPSession {
- send(
- method: T,
- params?: Protocol.CommandParameters[T]
- ): Promise
- on(
- event: T,
- listener: (payload: Protocol.Events[T]) => void
- ): this;
- once(
- event: T,
- listener: (payload: Protocol.Events[T]) => void
- ): this;
- off(
- event: T,
- listener: (payload: Protocol.Events[T]) => void
- ): this;
- }
-}
diff --git a/packages/browser/providers/webdriverio.d.ts b/packages/browser/providers/webdriverio.d.ts
deleted file mode 100644
index 66fdd93d2..000000000
--- a/packages/browser/providers/webdriverio.d.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import type { remote, ClickOptions, DragAndDropOptions } from 'webdriverio'
-import '../matchers.js'
-import type {} from "vitest/node"
-import type {
- ScreenshotComparatorRegistry,
- ScreenshotMatcherOptions,
-} from "@vitest/browser/context";
-
-declare module 'vitest/node' {
- export interface BrowserProviderOptions extends Partial<
- Parameters[0]
- > {}
-
- export interface UserEventClickOptions extends ClickOptions {}
-
- export interface UserEventDragOptions extends DragAndDropOptions {
- sourceX?: number
- sourceY?: number
- targetX?: number
- targetY?: number
- }
-
- export interface BrowserCommandContext {
- browser: WebdriverIO.Browser
- }
-
- export interface ToMatchScreenshotOptions
- extends Omit<
- ScreenshotMatcherOptions,
- "comparatorName" | "comparatorOptions"
- > {}
-
- export interface ToMatchScreenshotComparators
- extends ScreenshotComparatorRegistry {}
-}
diff --git a/packages/browser/rollup.config.js b/packages/browser/rollup.config.js
index a87a86cad..6b56b7034 100644
--- a/packages/browser/rollup.config.js
+++ b/packages/browser/rollup.config.js
@@ -17,6 +17,7 @@ const external = [
'worker_threads',
'node:worker_threads',
'vite',
+ 'playwright-core/types/protocol',
]
const dtsUtils = createDtsUtils()
@@ -38,8 +39,10 @@ const plugins = [
]
const input = {
- index: './src/node/index.ts',
- providers: './src/node/providers/index.ts',
+ 'index': './src/node/index.ts',
+ 'providers/playwright': './src/node/providers/playwright.ts',
+ 'providers/webdriverio': './src/node/providers/webdriverio.ts',
+ 'providers/preview': './src/node/providers/preview.ts',
}
export default () =>
@@ -135,7 +138,7 @@ export default () =>
],
},
{
- input: dtsUtils.dtsInput(input.index),
+ input: dtsUtils.dtsInput(input),
output: {
dir: 'dist',
entryFileNames: '[name].d.ts',
diff --git a/packages/browser/src/client/tester/tester.ts b/packages/browser/src/client/tester/tester.ts
index 2c7c6a148..e542e8033 100644
--- a/packages/browser/src/client/tester/tester.ts
+++ b/packages/browser/src/client/tester/tester.ts
@@ -84,7 +84,6 @@ channel.addEventListener('message', async (e) => {
})
const url = new URL(location.href)
-const reloadStart = url.searchParams.get('__reloadStart')
const iframeId = url.searchParams.get('iframeId')!
const commands = new CommandsManager()
@@ -94,7 +93,7 @@ getBrowserState().iframeId = iframeId
let contextSwitched = false
async function prepareTestEnvironment(options: PrepareOptions) {
- debug?.('trying to resolve runner', `${reloadStart}`)
+ debug?.('trying to resolve the runner')
const config = getConfig()
const rpc = createSafeRpc(client)
diff --git a/packages/browser/src/node/commands/clear.ts b/packages/browser/src/node/commands/clear.ts
index 9de4737ee..79f26644b 100644
--- a/packages/browser/src/node/commands/clear.ts
+++ b/packages/browser/src/node/commands/clear.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const clear: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/click.ts b/packages/browser/src/node/commands/click.ts
index d804b043d..31047a013 100644
--- a/packages/browser/src/node/commands/click.ts
+++ b/packages/browser/src/node/commands/click.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const click: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/dragAndDrop.ts b/packages/browser/src/node/commands/dragAndDrop.ts
index 6fc66bbb5..c665fd9ea 100644
--- a/packages/browser/src/node/commands/dragAndDrop.ts
+++ b/packages/browser/src/node/commands/dragAndDrop.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const dragAndDrop: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/fill.ts b/packages/browser/src/node/commands/fill.ts
index b7651ce74..c3256cccb 100644
--- a/packages/browser/src/node/commands/fill.ts
+++ b/packages/browser/src/node/commands/fill.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const fill: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/hover.ts b/packages/browser/src/node/commands/hover.ts
index 9d90d21df..7672eb839 100644
--- a/packages/browser/src/node/commands/hover.ts
+++ b/packages/browser/src/node/commands/hover.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const hover: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/keyboard.ts b/packages/browser/src/node/commands/keyboard.ts
index 80f3ca8cf..6024e55ab 100644
--- a/packages/browser/src/node/commands/keyboard.ts
+++ b/packages/browser/src/node/commands/keyboard.ts
@@ -3,7 +3,7 @@ import type { UserEventCommand } from './utils'
import { defaultKeyMap } from '@testing-library/user-event/dist/esm/keyboard/keyMap.js'
import { parseKeyDef } from '@testing-library/user-event/dist/esm/keyboard/parseKeyDef.js'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export interface KeyboardState {
unreleased: string[]
diff --git a/packages/browser/src/node/commands/screenshot.ts b/packages/browser/src/node/commands/screenshot.ts
index 11553473b..a87a09f41 100644
--- a/packages/browser/src/node/commands/screenshot.ts
+++ b/packages/browser/src/node/commands/screenshot.ts
@@ -4,7 +4,7 @@ import { mkdir, rm } from 'node:fs/promises'
import { normalize } from 'node:path'
import { basename, dirname, relative, resolve } from 'pathe'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
interface ScreenshotCommandOptions extends Omit {
element?: string
diff --git a/packages/browser/src/node/commands/select.ts b/packages/browser/src/node/commands/select.ts
index 22da023a1..b2910a317 100644
--- a/packages/browser/src/node/commands/select.ts
+++ b/packages/browser/src/node/commands/select.ts
@@ -2,7 +2,7 @@ import type { ElementHandle } from 'playwright'
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const selectOptions: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/tab.ts b/packages/browser/src/node/commands/tab.ts
index 6c1f57b0d..3739841b9 100644
--- a/packages/browser/src/node/commands/tab.ts
+++ b/packages/browser/src/node/commands/tab.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const tab: UserEventCommand = async (
context,
diff --git a/packages/browser/src/node/commands/type.ts b/packages/browser/src/node/commands/type.ts
index 78ddc7a3f..189e7343b 100644
--- a/packages/browser/src/node/commands/type.ts
+++ b/packages/browser/src/node/commands/type.ts
@@ -1,7 +1,7 @@
import type { UserEvent } from '../../../context'
import type { UserEventCommand } from './utils'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
import { keyboardImplementation } from './keyboard'
export const type: UserEventCommand = async (
diff --git a/packages/browser/src/node/commands/upload.ts b/packages/browser/src/node/commands/upload.ts
index 81b2580c5..0893fa37a 100644
--- a/packages/browser/src/node/commands/upload.ts
+++ b/packages/browser/src/node/commands/upload.ts
@@ -2,7 +2,7 @@ import type { UserEventUploadOptions } from '@vitest/browser/context'
import type { UserEventCommand } from './utils'
import { resolve } from 'pathe'
import { PlaywrightBrowserProvider } from '../providers/playwright'
-import { WebdriverBrowserProvider } from '../providers/webdriver'
+import { WebdriverBrowserProvider } from '../providers/webdriverio'
export const upload: UserEventCommand<(element: string, files: Array
+ /**
+ * The maximum time in milliseconds to wait for `userEvent` action to complete.
+ * @default 0 (no timeout)
+ */
+ actionTimeout?: number
+}
-export interface PlaywrightProviderOptions
- extends BrowserProviderInitializationOptions {
- browser: PlaywrightBrowser
+export function playwright(options: PlaywrightProviderOptions = {}): BrowserProviderOption {
+ return {
+ name: 'playwright',
+ supportedBrowser: playwrightBrowsers,
+ factory(project) {
+ return new PlaywrightBrowserProvider(project, options)
+ },
+ // --browser.provider=playwright
+ // @ts-expect-error hidden way to bypass importing playwright
+ _cli: true,
+ }
}
export class PlaywrightBrowserProvider implements BrowserProvider {
@@ -38,39 +83,19 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
public browser: Browser | null = null
- private browserName!: PlaywrightBrowser
- private project!: TestProject
-
- private options?: {
- launch?: LaunchOptions
- connect?: {
- wsEndpoint: string
- options?: ConnectOptions
- }
- context?: BrowserContextOptions & { actionTimeout?: number }
- }
-
public contexts: Map = new Map()
public pages: Map = new Map()
+ public mocker: BrowserModuleMocker
+ public browserName: PlaywrightBrowser
private browserPromise: Promise | null = null
-
- public mocker: BrowserModuleMocker | undefined
-
private closing = false
- getSupportedBrowsers(): readonly string[] {
- return playwrightBrowsers
- }
-
- initialize(
- project: TestProject,
- { browser, options }: PlaywrightProviderOptions,
- ): void {
- this.closing = false
- this.project = project
- this.browserName = browser
- this.options = options as any
+ constructor(
+ private project: TestProject,
+ private options: PlaywrightProviderOptions,
+ ) {
+ this.browserName = project.config.browser.name as PlaywrightBrowser
this.mocker = this.createMocker()
}
@@ -92,22 +117,22 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
const playwright = await import('playwright')
- if (this.options?.connect) {
- if (this.options.launch) {
+ if (this.options.connectOptions) {
+ if (this.options.launchOptions) {
this.project.vitest.logger.warn(
c.yellow(`Found both ${c.bold(c.italic(c.yellow('connect')))} and ${c.bold(c.italic(c.yellow('launch')))} options in browser instance configuration.
Ignoring ${c.bold(c.italic(c.yellow('launch')))} options and using ${c.bold(c.italic(c.yellow('connect')))} mode.
You probably want to remove one of the two options and keep only the one you want to use.`),
)
}
- const browser = await playwright[this.browserName].connect(this.options.connect.wsEndpoint, this.options.connect.options)
+ const browser = await playwright[this.browserName].connect(this.options.connectOptions.wsEndpoint, this.options.connectOptions)
this.browser = browser
this.browserPromise = null
return this.browser
}
const launchOptions = {
- ...this.options?.launch,
+ ...this.options.launchOptions,
headless: options.headless,
} satisfies LaunchOptions
@@ -288,7 +313,8 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
const browser = await this.openBrowser()
await this._throwIfClosing(browser)
- const { actionTimeout, ...contextOptions } = this.options?.context ?? {}
+ const actionTimeout = this.options.actionTimeout
+ const contextOptions = this.options.contextOptions ?? {}
const options = {
...contextOptions,
ignoreHTTPSErrors: true,
@@ -298,7 +324,7 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
}
const context = await browser.newContext(options)
await this._throwIfClosing(context)
- if (actionTimeout) {
+ if (actionTimeout != null) {
context.setDefaultTimeout(actionTimeout)
}
debug?.('[%s][%s] the context is ready', sessionId, this.browserName)
@@ -423,12 +449,12 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
async close(): Promise {
debug?.('[%s] closing provider', this.browserName)
this.closing = true
- const browser = this.browser
- this.browser = null
if (this.browserPromise) {
await this.browserPromise
this.browserPromise = null
}
+ const browser = this.browser
+ this.browser = null
await Promise.all([...this.pages.values()].map(p => p.close()))
this.pages.clear()
await Promise.all([...this.contexts.values()].map(c => c.close()))
@@ -476,3 +502,64 @@ const directRequestRE = /[?&]direct\b/
function isDirectCSSRequest(request: string): boolean {
return isCSSRequest(request) && directRequestRE.test(request)
}
+
+declare module 'vitest/node' {
+ export interface BrowserCommandContext {
+ page: Page
+ frame(): Promise
+ iframe: FrameLocator
+ context: BrowserContext
+ }
+
+ export interface ToMatchScreenshotOptions
+ extends Omit<
+ ScreenshotMatcherOptions,
+ 'comparatorName' | 'comparatorOptions'
+ > {}
+
+ export interface ToMatchScreenshotComparators
+ extends ScreenshotComparatorRegistry {}
+}
+
+type PWHoverOptions = NonNullable[1]>
+type PWClickOptions = NonNullable[1]>
+type PWDoubleClickOptions = NonNullable[1]>
+type PWFillOptions = NonNullable[2]>
+type PWScreenshotOptions = NonNullable[0]>
+type PWSelectOptions = NonNullable[2]>
+type PWDragAndDropOptions = NonNullable[2]>
+type PWSetInputFiles = NonNullable[2]>
+
+declare module '@vitest/browser/context' {
+ export interface UserEventHoverOptions extends PWHoverOptions {}
+ export interface UserEventClickOptions extends PWClickOptions {}
+ export interface UserEventDoubleClickOptions extends PWDoubleClickOptions {}
+ export interface UserEventTripleClickOptions extends PWClickOptions {}
+ export interface UserEventFillOptions extends PWFillOptions {}
+ export interface UserEventSelectOptions extends PWSelectOptions {}
+ export interface UserEventDragAndDropOptions extends PWDragAndDropOptions {}
+ export interface UserEventUploadOptions extends PWSetInputFiles {}
+
+ export interface ScreenshotOptions extends Omit {
+ mask?: ReadonlyArray | undefined
+ }
+
+ export interface CDPSession {
+ send(
+ method: T,
+ params?: Protocol.CommandParameters[T]
+ ): Promise
+ on(
+ event: T,
+ listener: (payload: Protocol.Events[T]) => void
+ ): this
+ once(
+ event: T,
+ listener: (payload: Protocol.Events[T]) => void
+ ): this
+ off(
+ event: T,
+ listener: (payload: Protocol.Events[T]) => void
+ ): this
+ }
+}
diff --git a/packages/browser/src/node/providers/preview.ts b/packages/browser/src/node/providers/preview.ts
index 31eb96ff1..60ef88aca 100644
--- a/packages/browser/src/node/providers/preview.ts
+++ b/packages/browser/src/node/providers/preview.ts
@@ -1,4 +1,16 @@
-import type { BrowserProvider, TestProject } from 'vitest/node'
+import type { BrowserProvider, BrowserProviderOption, TestProject } from 'vitest/node'
+
+export function preview(): BrowserProviderOption {
+ return {
+ name: 'preview',
+ factory(project) {
+ return new PreviewBrowserProvider(project)
+ },
+ // --browser.provider=preview
+ // @ts-expect-error hidden way to bypass importing preview
+ _cli: true,
+ }
+}
export class PreviewBrowserProvider implements BrowserProvider {
public name = 'preview' as const
@@ -6,20 +18,7 @@ export class PreviewBrowserProvider implements BrowserProvider {
private project!: TestProject
private open = false
- getSupportedBrowsers(): string[] {
- // `none` is not restricted to certain browsers.
- return []
- }
-
- isOpen(): boolean {
- return this.open
- }
-
- getCommandsContext() {
- return {}
- }
-
- async initialize(project: TestProject): Promise {
+ constructor(project: TestProject) {
this.project = project
this.open = false
if (project.config.browser.headless) {
@@ -30,6 +29,14 @@ export class PreviewBrowserProvider implements BrowserProvider {
project.vitest.logger.printBrowserBanner(project)
}
+ isOpen(): boolean {
+ return this.open
+ }
+
+ getCommandsContext() {
+ return {}
+ }
+
async openPage(_sessionId: string, url: string): Promise {
this.open = true
if (!this.project.browser) {
diff --git a/packages/browser/src/node/providers/webdriver.ts b/packages/browser/src/node/providers/webdriverio.ts
similarity index 80%
rename from packages/browser/src/node/providers/webdriver.ts
rename to packages/browser/src/node/providers/webdriverio.ts
index 5c75b6474..08d6fdc5e 100644
--- a/packages/browser/src/node/providers/webdriver.ts
+++ b/packages/browser/src/node/providers/webdriverio.ts
@@ -1,9 +1,15 @@
+import type {
+ ScreenshotComparatorRegistry,
+ ScreenshotMatcherOptions,
+} from '@vitest/browser/context'
import type { Capabilities } from '@wdio/types'
import type {
BrowserProvider,
- BrowserProviderInitializationOptions,
+ BrowserProviderOption,
TestProject,
} from 'vitest/node'
+import type { ClickOptions, DragAndDropOptions, remote } from 'webdriverio'
+
import { createDebugger } from 'vitest/node'
const debug = createDebugger('vitest:browser:wdio')
@@ -11,9 +17,21 @@ const debug = createDebugger('vitest:browser:wdio')
const webdriverBrowsers = ['firefox', 'chrome', 'edge', 'safari'] as const
type WebdriverBrowser = (typeof webdriverBrowsers)[number]
-interface WebdriverProviderOptions
- extends BrowserProviderInitializationOptions {
- browser: WebdriverBrowser
+interface WebdriverProviderOptions extends Partial<
+ Parameters[0]
+ > {}
+
+export function webdriverio(options: WebdriverProviderOptions = {}): BrowserProviderOption {
+ return {
+ name: 'webdriverio',
+ supportedBrowser: webdriverBrowsers,
+ factory(project) {
+ return new WebdriverBrowserProvider(project, options)
+ },
+ // --browser.provider=webdriverio
+ // @ts-expect-error hidden way to bypass importing webdriverio
+ _cli: true,
+ }
}
export class WebdriverBrowserProvider implements BrowserProvider {
@@ -25,7 +43,7 @@ export class WebdriverBrowserProvider implements BrowserProvider {
private browserName!: WebdriverBrowser
private project!: TestProject
- private options?: Capabilities.WebdriverIOConfig
+ private options?: WebdriverProviderOptions
private closing = false
private iframeSwitched = false
@@ -35,10 +53,10 @@ export class WebdriverBrowserProvider implements BrowserProvider {
return webdriverBrowsers
}
- async initialize(
+ constructor(
project: TestProject,
- { browser, options }: WebdriverProviderOptions,
- ): Promise {
+ options: WebdriverProviderOptions,
+ ) {
// increase shutdown timeout because WDIO takes some extra time to kill the driver
if (!project.vitest.state._data.timeoutIncreased) {
project.vitest.state._data.timeoutIncreased = true
@@ -47,8 +65,8 @@ export class WebdriverBrowserProvider implements BrowserProvider {
this.closing = false
this.project = project
- this.browserName = browser
- this.options = options as Capabilities.WebdriverIOConfig
+ this.browserName = project.config.browser.name as WebdriverBrowser
+ this.options = options
}
isIframeSwitched(): boolean {
@@ -125,8 +143,8 @@ export class WebdriverBrowserProvider implements BrowserProvider {
const { remote } = await import('webdriverio')
const remoteOptions: Capabilities.WebdriverIOConfig = {
+ logLevel: 'silent',
...this.options,
- logLevel: 'error',
capabilities: this.buildCapabilities(),
}
@@ -208,3 +226,27 @@ export class WebdriverBrowserProvider implements BrowserProvider {
this.browser = null
}
}
+
+declare module 'vitest/node' {
+ export interface UserEventClickOptions extends ClickOptions {}
+
+ export interface UserEventDragOptions extends DragAndDropOptions {
+ sourceX?: number
+ sourceY?: number
+ targetX?: number
+ targetY?: number
+ }
+
+ export interface BrowserCommandContext {
+ browser: WebdriverIO.Browser
+ }
+
+ export interface ToMatchScreenshotOptions
+ extends Omit<
+ ScreenshotMatcherOptions,
+ 'comparatorName' | 'comparatorOptions'
+ > {}
+
+ export interface ToMatchScreenshotComparators
+ extends ScreenshotComparatorRegistry {}
+}
diff --git a/packages/browser/src/node/rpc.ts b/packages/browser/src/node/rpc.ts
index ed2777715..16b84aea2 100644
--- a/packages/browser/src/node/rpc.ts
+++ b/packages/browser/src/node/rpc.ts
@@ -5,7 +5,7 @@ import type { BrowserCommandContext, ResolveSnapshotPathHandlerContext, TestProj
import type { WebSocket } from 'ws'
import type { WebSocketBrowserEvents, WebSocketBrowserHandlers } from '../types'
import type { ParentBrowserProject } from './projectParent'
-import type { WebdriverBrowserProvider } from './providers/webdriver'
+import type { WebdriverBrowserProvider } from './providers/webdriverio'
import type { BrowserServerState } from './state'
import { existsSync, promises as fs } from 'node:fs'
import { AutomockedModule, AutospiedModule, ManualMockedModule, RedirectedModule } from '@vitest/mocker'
diff --git a/packages/browser/src/node/serverOrchestrator.ts b/packages/browser/src/node/serverOrchestrator.ts
index da2668ec5..9880d9713 100644
--- a/packages/browser/src/node/serverOrchestrator.ts
+++ b/packages/browser/src/node/serverOrchestrator.ts
@@ -36,7 +36,7 @@ export async function resolveOrchestrator(
: await globalServer.injectorJs
const injector = replacer(injectorJs, {
- __VITEST_PROVIDER__: JSON.stringify(browserProject.config.browser.provider || 'preview'),
+ __VITEST_PROVIDER__: JSON.stringify(browserProject.config.browser.provider?.name || 'preview'),
__VITEST_CONFIG__: JSON.stringify(browserProject.wrapSerializedConfig()),
__VITEST_VITE_CONFIG__: JSON.stringify({
root: browserProject.vite.config.root,
diff --git a/packages/browser/src/node/utils.ts b/packages/browser/src/node/utils.ts
index f3e0f20da..40308aeb6 100644
--- a/packages/browser/src/node/utils.ts
+++ b/packages/browser/src/node/utils.ts
@@ -1,45 +1,46 @@
-import type { BrowserProviderModule, ResolvedBrowserOptions, TestProject } from 'vitest/node'
+import type { BrowserProvider, ResolvedBrowserOptions, TestProject } from 'vitest/node'
export function replacer(code: string, values: Record): string {
return code.replace(/\{\s*(\w+)\s*\}/g, (_, key) => values[key] ?? _)
}
-const builtinProviders = ['webdriverio', 'playwright', 'preview']
-
export async function getBrowserProvider(
options: ResolvedBrowserOptions,
project: TestProject,
-): Promise {
- if (options.provider == null || builtinProviders.includes(options.provider)) {
- const providers = await import('./providers')
- const provider = (options.provider || 'preview') as
- | 'webdriverio'
- | 'playwright'
- | 'preview'
- return providers[provider]
- }
-
- let customProviderModule
-
- try {
- customProviderModule = (await project.import<{ default: BrowserProviderModule }>(
- options.provider,
- ))
- }
- catch (error) {
+): Promise {
+ const browser = project.config.browser.name
+ const name = project.name ? `[${project.name}] ` : ''
+ if (!browser) {
throw new Error(
- `Failed to load custom BrowserProvider from ${options.provider}`,
- { cause: error },
+ `${name}Browser name is required. Please, set \`test.browser.instances[].browser\` option manually.`,
)
}
-
- if (customProviderModule.default == null) {
+ if (
+ // nothing is provided by default
+ options.provider == null
+ // the provider is provided via `--browser.provider=playwright`
+ // or the config was serialized, but we can infer the factory by the name
+ || ('_cli' in options.provider && typeof options.provider.factory !== 'function')
+ ) {
+ const providers = await import('./providers/index')
+ const name = (options.provider?.name || 'preview') as 'preview' | 'webdriverio' | 'playwright'
+ if (!(name in providers)) {
+ throw new Error(`Unknown browser provider "${name}". Available providers: ${Object.keys(providers).join(', ')}.`)
+ }
+ return providers[name]().factory(project)
+ }
+ const supportedBrowsers = options.provider.supportedBrowser || []
+ if (supportedBrowsers.length && !supportedBrowsers.includes(browser)) {
throw new Error(
- `Custom BrowserProvider loaded from ${options.provider} was not the default export`,
+ `${name}Browser "${browser}" is not supported by the browser provider "${
+ options.provider.name
+ }". Supported browsers: ${supportedBrowsers.join(', ')}.`,
)
}
-
- return customProviderModule.default
+ if (typeof options.provider.factory !== 'function') {
+ throw new TypeError(`The "${name}" browser provider does not provide a "factory" function. Received ${typeof options.provider.factory}.`)
+ }
+ return options.provider.factory(project)
}
export function slash(path: string): string {
diff --git a/packages/ui/vite.config.ts b/packages/ui/vite.config.ts
index ad9ee9016..f8fd979c1 100644
--- a/packages/ui/vite.config.ts
+++ b/packages/ui/vite.config.ts
@@ -106,10 +106,4 @@ export default defineConfig({
build: {
outDir: './dist/client',
},
- test: {
- browser: {
- name: 'chromium',
- provider: 'playwright',
- },
- },
})
diff --git a/packages/ui/vitest.config.ts b/packages/ui/vitest.config.ts
new file mode 100644
index 000000000..1c3e3e320
--- /dev/null
+++ b/packages/ui/vitest.config.ts
@@ -0,0 +1,16 @@
+import { playwright } from '@vitest/browser/providers/playwright'
+import { mergeConfig } from 'vite'
+import { defineConfig } from 'vitest/config'
+import viteConfig from './vite.config'
+
+export default mergeConfig(
+ viteConfig,
+ defineConfig({
+ test: {
+ browser: {
+ provider: playwright(),
+ instances: [{ browser: 'chromium' }],
+ },
+ },
+ }),
+)
diff --git a/packages/vitest/src/create/browser/creator.ts b/packages/vitest/src/create/browser/creator.ts
index 51eee017d..2a55884ca 100644
--- a/packages/vitest/src/create/browser/creator.ts
+++ b/packages/vitest/src/create/browser/creator.ts
@@ -295,6 +295,7 @@ async function generateFrameworkConfigFile(options: {
const configContent = [
`import { defineConfig } from 'vitest/config'`,
+ `import { ${options.provider} } from '@vitest/browser/providers/${options.provider}'`,
options.frameworkPlugin ? frameworkImport : null,
``,
'export default defineConfig({',
@@ -302,7 +303,7 @@ async function generateFrameworkConfigFile(options: {
` test: {`,
` browser: {`,
` enabled: true,`,
- ` provider: '${options.provider}',`,
+ ` provider: ${options.provider}(),`,
options.provider !== 'preview' && ` // ${getProviderDocsLink(options.provider)}`,
` instances: [`,
...options.browsers.map(browser => ` { browser: '${browser}' },`),
diff --git a/packages/vitest/src/node/cli/cli-config.ts b/packages/vitest/src/node/cli/cli-config.ts
index d2ca85369..50385c9bc 100644
--- a/packages/vitest/src/node/cli/cli-config.ts
+++ b/packages/vitest/src/node/cli/cli-config.ts
@@ -380,12 +380,13 @@ export const cliOptionsConfig: VitestCLIOptions = {
'Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", "preview", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/guide/browser/config.html#browser-provider) for more information (default: `"preview"`)',
argument: '',
subcommands: null, // don't support custom objects
- },
- providerOptions: {
- description:
- 'Options that are passed down to a browser provider. Visit [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions) for more information',
- argument: '',
- subcommands: null, // don't support custom objects
+ transform(value) {
+ const supported = ['playwright', 'webdriverio', 'preview']
+ if (typeof value !== 'string' || !supported.includes(value)) {
+ throw new Error(`Unsupported browser provider: ${value}. Supported providers are: ${supported.join(', ')}`)
+ }
+ return { name: value, _cli: true }
+ },
},
isolate: {
description:
diff --git a/packages/vitest/src/node/config/resolveConfig.ts b/packages/vitest/src/node/config/resolveConfig.ts
index a915183f8..fdfd66ce3 100644
--- a/packages/vitest/src/node/config/resolveConfig.ts
+++ b/packages/vitest/src/node/config/resolveConfig.ts
@@ -275,19 +275,41 @@ export function resolveConfig(
// Browser-mode "Playwright + Chromium" only features:
if (browser.enabled && !playwrightChromiumOnly) {
- const browserConfig = {
- browser: {
- provider: browser.provider,
- name: browser.name,
- instances: browser.instances?.map(i => ({ browser: i.browser })),
- },
- }
+ const browserConfig = `
+{
+ browser: {
+ provider: ${browser.provider?.name || 'preview'}(),
+ instances: [
+ ${(browser.instances || []).map(i => `{ browser: '${i.browser}' }`).join(',\n ')}
+ ],
+ },
+}
+ `.trim()
+
+ const correctExample = `
+{
+ browser: {
+ provider: playwright(),
+ instances: [
+ { browser: 'chromium' }
+ ],
+ },
+}
+ `.trim()
if (resolved.coverage.enabled && resolved.coverage.provider === 'v8') {
+ const coverageExample = `
+{
+ coverage: {
+ provider: 'istanbul',
+ },
+}
+ `.trim()
+
throw new Error(
- `@vitest/coverage-v8 does not work with\n${JSON.stringify(browserConfig, null, 2)}\n`
- + `\nUse either:\n${JSON.stringify({ browser: { provider: 'playwright', instances: [{ browser: 'chromium' }] } }, null, 2)}`
- + `\n\n...or change your coverage provider to:\n${JSON.stringify({ coverage: { provider: 'istanbul' } }, null, 2)}\n`,
+ `@vitest/coverage-v8 does not work with\n${browserConfig}\n`
+ + `\nUse either:\n${correctExample}`
+ + `\n\n...or change your coverage provider to:\n${coverageExample}\n`,
)
}
@@ -295,8 +317,8 @@ export function resolveConfig(
const inspectOption = `--inspect${resolved.inspectBrk ? '-brk' : ''}`
throw new Error(
- `${inspectOption} does not work with\n${JSON.stringify(browserConfig, null, 2)}\n`
- + `\nUse either:\n${JSON.stringify({ browser: { provider: 'playwright', instances: [{ browser: 'chromium' }] } }, null, 2)}`
+ `${inspectOption} does not work with\n${browserConfig}\n`
+ + `\nUse either:\n${correctExample}`
+ `\n\n...or disable ${inspectOption}\n`,
)
}
@@ -712,7 +734,27 @@ export function resolveConfig(
resolved.browser.screenshotDirectory,
)
}
- const isPreview = resolved.browser.provider === 'preview'
+
+ resolved.browser.viewport ??= {} as any
+ resolved.browser.viewport.width ??= 414
+ resolved.browser.viewport.height ??= 896
+
+ resolved.browser.locators ??= {} as any
+ resolved.browser.locators.testIdAttribute ??= 'data-testid'
+
+ if (resolved.browser.enabled && stdProvider === 'stackblitz') {
+ resolved.browser.provider = undefined // reset to "preview"
+ }
+
+ if (typeof resolved.browser.provider === 'string') {
+ const source = `@vitest/browser/providers/${resolved.browser.provider}`
+ throw new TypeError(
+ 'The `browser.provider` configuration was changed to accept a factory instead of a string. '
+ + `Add an import of "${resolved.browser.provider}" from "${source}" instead. See: https://vitest.dev/guide/browser/config#provider`,
+ )
+ }
+
+ const isPreview = resolved.browser.provider?.name === 'preview'
if (isPreview && resolved.browser.screenshotFailures === true) {
console.warn(c.yellow(
[
@@ -727,17 +769,6 @@ export function resolveConfig(
resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui
}
- resolved.browser.viewport ??= {} as any
- resolved.browser.viewport.width ??= 414
- resolved.browser.viewport.height ??= 896
-
- resolved.browser.locators ??= {} as any
- resolved.browser.locators.testIdAttribute ??= 'data-testid'
-
- if (resolved.browser.enabled && stdProvider === 'stackblitz') {
- resolved.browser.provider = 'preview'
- }
-
resolved.browser.api = resolveApiServerConfig(
resolved.browser,
defaultBrowserPort,
@@ -804,7 +835,7 @@ export function resolveCoverageReporters(configReporters: NonNullable {
+ const provider = project.browser?.provider
return {
name: browser.name,
headless: browser.headless,
@@ -149,9 +150,9 @@ export function serializeConfig(project: TestProject): SerializedConfig {
locators: {
testIdAttribute: browser.locators.testIdAttribute,
},
- providerOptions: browser.provider === 'playwright'
+ providerOptions: provider?.name === 'playwright'
? {
- actionTimeout: (browser.providerOptions as any)?.context?.actionTimeout,
+ actionTimeout: (provider as any)?.options?.actionTimeout,
}
: {},
trackUnhandledErrors: browser.trackUnhandledErrors ?? true,
diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts
index 658ff0916..e3210e914 100644
--- a/packages/vitest/src/node/plugins/workspace.ts
+++ b/packages/vitest/src/node/plugins/workspace.ts
@@ -1,6 +1,6 @@
import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite'
import type { TestProject } from '../project'
-import type { ResolvedConfig, TestProjectInlineConfiguration } from '../types/config'
+import type { BrowserConfigOptions, ResolvedConfig, TestProjectInlineConfiguration } from '../types/config'
import { existsSync, readFileSync } from 'node:fs'
import { deepMerge } from '@vitest/utils'
import { basename, dirname, relative, resolve } from 'pathe'
@@ -66,7 +66,7 @@ export function WorkspaceVitestPlugin(
const isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled)
// keep project names to potentially filter it out
const workspaceNames = [name]
- const browser = viteConfig.test!.browser || {}
+ const browser = (viteConfig.test!.browser || {}) as BrowserConfigOptions
if (isBrowserEnabled && browser.name && !browser.instances?.length) {
// vitest injects `instances` in this case later on
workspaceNames.push(name ? `${name} (${browser.name})` : browser.name)
diff --git a/packages/vitest/src/node/projects/resolveProjects.ts b/packages/vitest/src/node/projects/resolveProjects.ts
index d21626452..5f596fed8 100644
--- a/packages/vitest/src/node/projects/resolveProjects.ts
+++ b/packages/vitest/src/node/projects/resolveProjects.ts
@@ -219,12 +219,6 @@ export async function resolveBrowserProjects(
return
}
- if (project.config.browser.providerOptions) {
- vitest.logger.warn(
- withLabel('yellow', 'Vitest', `"providerOptions"${originalName ? ` in "${originalName}" project` : ''} is ignored because it's overridden by the configs. To hide this warning, remove the "providerOptions" property from the browser configuration.`),
- )
- }
-
filteredInstances.forEach((config, index) => {
const browser = config.browser
if (!browser) {
@@ -300,6 +294,7 @@ function cloneConfig(project: TestProject, { browser, ...config }: BrowserInstan
// @ts-expect-error remove just in case
browser: _browser,
name,
+ provider,
...overrideConfig
} = config
const currentConfig = project.config.browser
@@ -318,9 +313,9 @@ function cloneConfig(project: TestProject, { browser, ...config }: BrowserInstan
screenshotDirectory: screenshotDirectory ?? currentConfig.screenshotDirectory,
screenshotFailures: screenshotFailures ?? currentConfig.screenshotFailures,
headless: headless ?? currentConfig.headless,
+ provider: provider ?? currentConfig.provider,
name: browser,
- providerOptions: config,
- instances: undefined, // projects cannot spawn more configs
+ instances: [], // projects cannot spawn more configs
},
// If there is no include or exclude or includeSource pattern in browser.instances[], we should use the that's pattern from the parent project
include: (overrideConfig.include && overrideConfig.include.length > 0) ? [] : clonedConfig.include,
diff --git a/packages/vitest/src/node/types/browser.ts b/packages/vitest/src/node/types/browser.ts
index 74ee9c74f..65e881599 100644
--- a/packages/vitest/src/node/types/browser.ts
+++ b/packages/vitest/src/node/types/browser.ts
@@ -7,11 +7,6 @@ import type { BrowserTesterOptions } from '../../types/browser'
import type { TestProject } from '../project'
import type { ApiConfig, ProjectConfig } from './config'
-export interface BrowserProviderInitializationOptions {
- browser: string
- options?: BrowserProviderOptions
-}
-
export interface CDPSession {
send: (method: string, params?: Record) => Promise
on: (event: string, listener: (...args: unknown[]) => void) => void
@@ -25,6 +20,12 @@ export interface BrowserModuleMocker {
clear: (sessionId: string) => Promise
}
+export interface BrowserProviderOption {
+ name: string
+ supportedBrowser?: ReadonlyArray
+ factory: (project: TestProject) => BrowserProvider
+}
+
export interface BrowserProvider {
name: string
mocker?: BrowserModuleMocker
@@ -32,24 +33,12 @@ export interface BrowserProvider {
* @experimental opt-in into file parallelisation
*/
supportsParallelism: boolean
- getSupportedBrowsers: () => readonly string[]
getCommandsContext: (sessionId: string) => Record
- openPage: (sessionId: string, url: string, beforeNavigate?: () => Promise) => Promise
+ openPage: (sessionId: string, url: string) => Promise
getCDPSession?: (sessionId: string) => Promise
close: () => Awaitable
- // eslint-disable-next-line ts/method-signature-style -- we want to allow extended options
- initialize(
- ctx: TestProject,
- options: BrowserProviderInitializationOptions
- ): Awaitable
-}
-
-export interface BrowserProviderModule {
- new (): BrowserProvider
}
-export interface BrowserProviderOptions {}
-
export type BrowserBuiltinProvider = 'webdriverio' | 'playwright' | 'preview'
type UnsupportedProperties
@@ -71,7 +60,7 @@ type UnsupportedProperties
| 'benchmark'
| 'name'
-export interface BrowserInstanceOption extends BrowserProviderOptions,
+export interface BrowserInstanceOption extends
Omit,
Pick<
BrowserConfigOptions,
@@ -81,6 +70,7 @@ export interface BrowserInstanceOption extends BrowserProviderOptions,
| 'testerHtmlPath'
| 'screenshotDirectory'
| 'screenshotFailures'
+ | 'provider'
> {
/**
* Name of the browser
@@ -101,33 +91,19 @@ export interface BrowserConfigOptions {
/**
* Name of the browser
* @deprecated use `instances` instead. if both are defined, this will filter `instances` by name.
+ * @internal
*/
name?: string
/**
* Configurations for different browser setups
*/
- instances?: BrowserInstanceOption[]
+ instances: BrowserInstanceOption[]
/**
* Browser provider
- *
- * @default 'preview'
- */
- provider?: BrowserBuiltinProvider | (string & {})
-
- /**
- * Options that are passed down to a browser provider.
- * To support type hinting, add one of the types to your tsconfig.json "compilerOptions.types" field:
- *
- * - for webdriverio: `@vitest/browser/providers/webdriverio`
- * - for playwright: `@vitest/browser/providers/playwright`
- *
- * @example
- * { playwright: { launch: { devtools: true } }
- * @deprecated use `instances` instead
*/
- providerOptions?: BrowserProviderOptions
+ provider?: BrowserProviderOption
/**
* enable headless mode
@@ -328,7 +304,6 @@ export interface BrowserScript {
export interface ResolvedBrowserOptions extends BrowserConfigOptions {
name: string
- providerOptions?: BrowserProviderOptions
enabled: boolean
headless: boolean
isolate: boolean
diff --git a/packages/vitest/src/public/node.ts b/packages/vitest/src/public/node.ts
index e8d55e3a8..0f2cfc903 100644
--- a/packages/vitest/src/public/node.ts
+++ b/packages/vitest/src/public/node.ts
@@ -67,9 +67,7 @@ export type {
BrowserModuleMocker,
BrowserOrchestrator,
BrowserProvider,
- BrowserProviderInitializationOptions,
- BrowserProviderModule,
- BrowserProviderOptions,
+ BrowserProviderOption,
BrowserScript,
BrowserServerState,
BrowserServerStateSession,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 310b17823..5e9dd7b17 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -478,15 +478,6 @@ importers:
'@vitest/runner':
specifier: workspace:*
version: link:../runner
- '@vitest/ui':
- specifier: workspace:*
- version: link:../ui
- '@vitest/ws-client':
- specifier: workspace:*
- version: link:../ws-client
- '@wdio/protocols':
- specifier: ^9.16.2
- version: 9.16.2
'@wdio/types':
specifier: ^9.16.2
version: 9.16.2
@@ -505,18 +496,12 @@ importers:
pathe:
specifier: 'catalog:'
version: 2.0.3
- periscopic:
- specifier: ^4.0.2
- version: 4.0.2
playwright:
specifier: ^1.54.1
version: 1.54.1
playwright-core:
specifier: ^1.54.1
version: 1.54.1
- safaridriver:
- specifier: ^1.0.0
- version: 1.0.0
vitest:
specifier: workspace:*
version: link:../vitest
@@ -6343,9 +6328,6 @@ packages:
is-reference@1.2.1:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
- is-reference@3.0.2:
- resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
-
is-regex@1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'}
@@ -7364,9 +7346,6 @@ packages:
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
- periscopic@4.0.2:
- resolution: {integrity: sha512-sqpQDUy8vgB7ycLkendSKS6HnVz1Rneoc3Rc+ZBUCe2pbqlVuCC5vF52l0NJ1aiMg/r1qfYF9/myz8CZeI2rjA==}
-
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -9133,9 +9112,6 @@ packages:
resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
engines: {node: '>=18'}
- zimmerframe@1.1.0:
- resolution: {integrity: sha512-+AmV37r9NPUy7KcuG0Fde9AAFSD88kN5pnqvD7Pkp5WLLK0jct7hAtIDXXFDCRk3l5Mc1r2Sth3gfP2ZLE+/Qw==}
-
zip-stream@6.0.1:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
@@ -14314,10 +14290,6 @@ snapshots:
dependencies:
'@types/estree': 1.0.8
- is-reference@3.0.2:
- dependencies:
- '@types/estree': 1.0.7
-
is-regex@1.1.4:
dependencies:
call-bind: 1.0.7
@@ -15546,12 +15518,6 @@ snapshots:
perfect-debounce@1.0.0: {}
- periscopic@4.0.2:
- dependencies:
- '@types/estree': 1.0.7
- is-reference: 3.0.2
- zimmerframe: 1.1.0
-
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -17607,8 +17573,6 @@ snapshots:
yoctocolors@2.1.1: {}
- zimmerframe@1.1.0: {}
-
zip-stream@6.0.1:
dependencies:
archiver-utils: 5.0.2
diff --git a/test/browser/fixtures/browser-crash/vitest.config.ts b/test/browser/fixtures/browser-crash/vitest.config.ts
index 099e62941..4aaf57d98 100644
--- a/test/browser/fixtures/browser-crash/vitest.config.ts
+++ b/test/browser/fixtures/browser-crash/vitest.config.ts
@@ -17,8 +17,7 @@ const forceCrash: BrowserCommand<[]> = async (context) => {
throw new Error(`Browser crash not supported for ${browser}`)
}
if (context.provider.name === 'webdriverio') {
- // @ts-expect-error not typed
- const browser = context.browser as any
+ const browser = context.browser
const name = context.project.config.browser.name
if (name === 'chrome') {
await browser.url('chrome://crash')
diff --git a/test/browser/fixtures/inspect/vitest.config.ts b/test/browser/fixtures/inspect/vitest.config.ts
index 44f91bdd5..2034fe691 100644
--- a/test/browser/fixtures/inspect/vitest.config.ts
+++ b/test/browser/fixtures/inspect/vitest.config.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from 'vitest/config';
export default defineConfig({
@@ -6,7 +7,7 @@ export default defineConfig({
watch: false,
browser: {
enabled: true,
- provider: "playwright",
+ provider: playwright(),
instances: [{ browser: "chromium" }],
headless: true,
},
diff --git a/test/browser/fixtures/inspect/vitest.config.with-workspace.ts b/test/browser/fixtures/inspect/vitest.config.with-workspace.ts
index ec6d2c097..24ceb3a1d 100644
--- a/test/browser/fixtures/inspect/vitest.config.with-workspace.ts
+++ b/test/browser/fixtures/inspect/vitest.config.with-workspace.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from "vitest/config";
export default defineConfig({
@@ -10,7 +11,7 @@ export default defineConfig({
test: {
name: "Browser in workspace",
browser: {
- provider: "playwright",
+ provider: playwright(),
enabled: true,
headless: true,
instances: [{ browser: "chromium" }]
diff --git a/test/browser/fixtures/multiple-different-configs/vitest.config.js b/test/browser/fixtures/multiple-different-configs/vitest.config.js
index 8c0598179..0bfb3d846 100644
--- a/test/browser/fixtures/multiple-different-configs/vitest.config.js
+++ b/test/browser/fixtures/multiple-different-configs/vitest.config.js
@@ -1,20 +1,19 @@
import { defineConfig } from 'vitest/config';
import { fileURLToPath } from 'node:url'
-
-const provider = process.env.PROVIDER || 'playwright'
+import { provider } from '../../settings'
export default defineConfig({
clearScreen: false,
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
test: {
browser: {
- provider: provider,
+ provider,
enabled: true,
headless: true,
screenshotFailures: false,
instances: [
{
- browser: provider === 'playwright' ? 'chromium' : 'chrome',
+ browser: provider.name === 'playwright' ? 'chromium' : 'chrome',
testerHtmlPath: './customTester.html',
provide: {
providedVar: true,
diff --git a/test/browser/fixtures/playwright-connect/vitest.config.js b/test/browser/fixtures/playwright-connect/vitest.config.js
index e86783018..8093a358c 100644
--- a/test/browser/fixtures/playwright-connect/vitest.config.js
+++ b/test/browser/fixtures/playwright-connect/vitest.config.js
@@ -1,14 +1,11 @@
import { defineConfig } from 'vitest/config';
import { fileURLToPath } from 'node:url'
-const provider = process.env.PROVIDER || 'playwright'
-
export default defineConfig({
clearScreen: false,
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
test: {
browser: {
- provider: provider,
enabled: true,
headless: true,
screenshotFailures: false,
diff --git a/test/browser/fixtures/server-url/vitest.config.ts b/test/browser/fixtures/server-url/vitest.config.ts
index ad483f64e..78c525250 100644
--- a/test/browser/fixtures/server-url/vitest.config.ts
+++ b/test/browser/fixtures/server-url/vitest.config.ts
@@ -2,7 +2,7 @@ import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vitest/config'
import basicSsl from '@vitejs/plugin-basic-ssl'
-import { instances, provider } from '../../settings'
+import { instances, providers, provider } from '../../settings'
// test https by
// TEST_HTTPS=1 pnpm test-fixtures --root fixtures/server-url
@@ -10,12 +10,15 @@ import { instances, provider } from '../../settings'
// ignore https errors due to self-signed certificate from plugin-basic-ssl
// https://playwright.dev/docs/api/class-browser#browser-new-context-option-ignore-https-errors
// https://webdriver.io/docs/configuration/#strictssl and acceptInsecureCerts in https://webdriver.io/docs/api/browser/#properties
-const providerOptions = (function () {
- switch (provider) {
- case 'playwright': return { page: { ignoreHTTPSErrors: true } }
- case 'webdriverio': return { strictSSL: false, capabilities: { acceptInsecureCerts: true } }
+const configuredProvider = (function () {
+ switch (provider.name) {
+ case 'playwright': return providers.playwright()
+ case 'webdriverio': return providers.webdriverio({ strictSSL: false, capabilities: { acceptInsecureCerts: true } })
+ default: {
+ throw new Error(`Invalid provider: ${provider.name}`)
+ }
}
-})() as any
+})()
export default defineConfig({
plugins: [
@@ -25,11 +28,8 @@ export default defineConfig({
browser: {
api: process.env.TEST_HTTPS ? 51122 : 51133,
enabled: true,
- provider,
- instances: instances.map(instance => ({
- ...instance,
- ...providerOptions,
- })),
+ provider: configuredProvider,
+ instances,
},
},
// separate cacheDir from test/browser/vite.config.ts
diff --git a/test/browser/fixtures/timeout/vitest.config.ts b/test/browser/fixtures/timeout/vitest.config.ts
index b482d8bb4..215dd0052 100644
--- a/test/browser/fixtures/timeout/vitest.config.ts
+++ b/test/browser/fixtures/timeout/vitest.config.ts
@@ -1,19 +1,16 @@
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vitest/config'
-import { instances, provider } from '../../settings'
+import { instances, provider, providers } from '../../settings'
export default defineConfig({
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
test: {
browser: {
enabled: true,
- provider,
- instances: instances.map(instance => ({
- ...instance,
- context: {
- actionTimeout: 500,
- },
- })),
+ provider: provider.name === 'playwright'
+ ? providers.playwright({ actionTimeout: 500 })
+ : provider,
+ instances,
},
expect: {
poll: {
diff --git a/test/browser/fixtures/worker/vitest.config.ts b/test/browser/fixtures/worker/vitest.config.ts
index 563c59b40..52962b06a 100644
--- a/test/browser/fixtures/worker/vitest.config.ts
+++ b/test/browser/fixtures/worker/vitest.config.ts
@@ -1,9 +1,6 @@
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vitest/config'
-
-const provider = process.env.PROVIDER || 'playwright'
-const browser =
- process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome')
+import { provider, instances } from '../../settings'
export default defineConfig({
cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),
@@ -11,7 +8,7 @@ export default defineConfig({
browser: {
enabled: true,
provider,
- instances: [{ browser }],
+ instances,
},
},
})
diff --git a/test/browser/settings.ts b/test/browser/settings.ts
index 19022e7ba..3da09eed6 100644
--- a/test/browser/settings.ts
+++ b/test/browser/settings.ts
@@ -1,7 +1,17 @@
import type { BrowserInstanceOption } from 'vitest/node'
+import { playwright } from '@vitest/browser/providers/playwright'
+import { preview } from '@vitest/browser/providers/preview'
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
-export const provider = process.env.PROVIDER || 'playwright'
-export const browser = process.env.BROWSER || (provider !== 'playwright' ? 'chromium' : 'chrome')
+const providerName = (process.env.PROVIDER || 'playwright') as 'playwright' | 'webdriverio' | 'preview'
+export const providers = {
+ playwright,
+ preview,
+ webdriverio,
+}
+
+export const provider = providers[providerName]()
+export const browser = process.env.BROWSER || (provider.name !== 'playwright' ? 'chromium' : 'chrome')
const devInstances: BrowserInstanceOption[] = [
{ browser },
@@ -20,6 +30,6 @@ const webdriverioInstances: BrowserInstanceOption[] = [
export const instances = process.env.BROWSER
? devInstances
- : provider === 'playwright'
+ : provider.name === 'playwright'
? playwrightInstances
: webdriverioInstances
diff --git a/test/browser/specs/multiple-different-configs.test.ts b/test/browser/specs/multiple-different-configs.test.ts
index 48cd36e4a..eb25d39c3 100644
--- a/test/browser/specs/multiple-different-configs.test.ts
+++ b/test/browser/specs/multiple-different-configs.test.ts
@@ -2,7 +2,7 @@ import { expect, test } from 'vitest'
import { provider } from '../settings'
import { runBrowserTests } from './utils'
-test.runIf(provider === 'playwright')('[playwright] runs multiple different configurations correctly', async () => {
+test.runIf(provider.name === 'playwright')('[playwright] runs multiple different configurations correctly', async () => {
const { stdout, exitCode, stderr } = await runBrowserTests({
root: './fixtures/multiple-different-configs',
})
@@ -13,7 +13,7 @@ test.runIf(provider === 'playwright')('[playwright] runs multiple different conf
expect(stdout).toContain('[firefox] HTML_INJECTED_VAR is undefined')
})
-test.runIf(provider === 'webdriverio')('[webdriverio] runs multiple different configurations correctly', async () => {
+test.runIf(provider.name === 'webdriverio')('[webdriverio] runs multiple different configurations correctly', async () => {
const { stdout, exitCode, stderr } = await runBrowserTests({
root: './fixtures/multiple-different-configs',
})
diff --git a/test/browser/specs/playwright-connect.test.ts b/test/browser/specs/playwright-connect.test.ts
index ec5130c2e..1d3cf6555 100644
--- a/test/browser/specs/playwright-connect.test.ts
+++ b/test/browser/specs/playwright-connect.test.ts
@@ -1,9 +1,10 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { chromium } from 'playwright'
import { expect, test } from 'vitest'
import { provider } from '../settings'
import { runBrowserTests } from './utils'
-test.runIf(provider === 'playwright')('[playwright] runs in connect mode', async () => {
+test.runIf(provider.name === 'playwright')('[playwright] runs in connect mode', async () => {
const browserServer = await chromium.launchServer()
const wsEndpoint = browserServer.wsEndpoint()
@@ -14,9 +15,11 @@ test.runIf(provider === 'playwright')('[playwright] runs in connect mode', async
{
browser: 'chromium',
name: 'chromium',
- connect: {
- wsEndpoint,
- },
+ provider: playwright({
+ connectOptions: {
+ wsEndpoint,
+ },
+ }),
},
],
},
@@ -29,7 +32,7 @@ test.runIf(provider === 'playwright')('[playwright] runs in connect mode', async
expect(stderr).toBe('')
})
-test.runIf(provider === 'playwright')('[playwright] warns if both connect and launch mode are configured', async () => {
+test.runIf(provider.name === 'playwright')('[playwright] warns if both connect and launch mode are configured', async () => {
const browserServer = await chromium.launchServer()
const wsEndpoint = browserServer.wsEndpoint()
@@ -40,10 +43,12 @@ test.runIf(provider === 'playwright')('[playwright] warns if both connect and la
{
browser: 'chromium',
name: 'chromium',
- connect: {
- wsEndpoint,
- },
- launch: {},
+ provider: playwright({
+ connectOptions: {
+ wsEndpoint,
+ },
+ launchOptions: {},
+ }),
},
],
},
diff --git a/test/browser/specs/runner.test.ts b/test/browser/specs/runner.test.ts
index 5a0d17b01..b3531742e 100644
--- a/test/browser/specs/runner.test.ts
+++ b/test/browser/specs/runner.test.ts
@@ -226,7 +226,7 @@ test('user-event', async () => {
const { stdout, stderr } = await runBrowserTests({
root: './fixtures/user-event',
})
- if (provider !== 'webdriverio') {
+ if (provider.name !== 'webdriverio') {
expect(stderr).toBe('')
}
onTestFailed(() => console.error(stderr))
@@ -244,11 +244,11 @@ test('timeout settings', async () => {
root: './fixtures/timeout',
})
expect(stderr).toContain('Matcher did not succeed in time.')
- if (provider === 'playwright') {
+ if (provider.name === 'playwright') {
expect(stderr).toContain('locator.click: Timeout 500ms exceeded.')
expect(stderr).toContain('locator.click: Timeout 345ms exceeded.')
}
- if (provider === 'webdriverio') {
+ if (provider.name === 'webdriverio') {
expect(stderr).toContain('Cannot find element with locator')
}
})
@@ -290,7 +290,7 @@ test('in-source tests run correctly when filtered', async () => {
expect(stdout).toContain(`Tests ${instances.length} passed`)
})
-test.runIf(provider === 'playwright')('timeout hooks', async () => {
+test.runIf(provider.name === 'playwright')('timeout hooks', async () => {
const { stderr } = await runBrowserTests({
root: './fixtures/timeout-hooks',
})
diff --git a/test/browser/specs/to-match-screenshot.test.ts b/test/browser/specs/to-match-screenshot.test.ts
index 250392c16..887357abc 100644
--- a/test/browser/specs/to-match-screenshot.test.ts
+++ b/test/browser/specs/to-match-screenshot.test.ts
@@ -2,6 +2,7 @@ import type { ViteUserConfig } from 'vitest/config.js'
import type { TestFsStructure } from '../../test-utils'
import { platform } from 'node:os'
import { resolve } from 'node:path'
+import { playwright } from '@vitest/browser/providers/playwright'
import { describe, expect, test } from 'vitest'
import { runVitestCli, useFS } from '../../test-utils'
import { extractToMatchScreenshotPaths } from '../fixtures/expect-dom/utils'
@@ -40,7 +41,7 @@ export async function runInlineTests(
browser: {
enabled: true,
screenshotFailures: false,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [{ browser }],
},
diff --git a/test/browser/specs/worker.test.ts b/test/browser/specs/worker.test.ts
index 060c4dc4e..4f7c54c64 100644
--- a/test/browser/specs/worker.test.ts
+++ b/test/browser/specs/worker.test.ts
@@ -2,9 +2,10 @@ import { expect, test } from 'vitest'
import { runBrowserTests } from './utils'
test('worker', async () => {
- const { ctx } = await runBrowserTests({
+ const { ctx, stderr } = await runBrowserTests({
root: './fixtures/worker',
})
+ expect(stderr).toBe('')
expect(Object.fromEntries(ctx.state.getFiles().map(f => [f.name, f.result.state]))).toMatchInlineSnapshot(`
{
"src/basic.test.ts": "pass",
diff --git a/test/browser/vitest.config.mts b/test/browser/vitest.config.mts
index 2f5d7a033..bb01b2175 100644
--- a/test/browser/vitest.config.mts
+++ b/test/browser/vitest.config.mts
@@ -2,12 +2,20 @@ import type { BrowserCommand, BrowserInstanceOption } from 'vitest/node'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import * as util from 'node:util'
+import { playwright } from '@vitest/browser/providers/playwright'
+import { preview } from '@vitest/browser/providers/preview'
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
import { defineConfig } from 'vitest/config'
const dir = dirname(fileURLToPath(import.meta.url))
-const provider = process.env.PROVIDER || 'playwright'
-const browser = process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome')
+const providerName = process.env.PROVIDER || 'playwright'
+const browser = process.env.BROWSER || (providerName === 'playwright' ? 'chromium' : 'chrome')
+const provider = {
+ playwright,
+ preview,
+ webdriverio,
+}[providerName]
const myCustomCommand: BrowserCommand<[arg1: string, arg2: string]> = ({ testPath }, arg1, arg2) => {
return { testPath, arg1, arg2 }
@@ -57,10 +65,10 @@ export default defineConfig({
headless: false,
instances: process.env.BROWSER
? devInstances
- : provider === 'playwright'
+ : providerName === 'playwright'
? playwrightInstances
: webdriverioInstances,
- provider,
+ provider: provider(),
// isolate: false,
testerHtmlPath: './custom-tester.html',
orchestratorScripts: [
diff --git a/test/cli/fixtures/browser-multiple/vitest.config.ts b/test/cli/fixtures/browser-multiple/vitest.config.ts
index 3703112fe..1df074e7b 100644
--- a/test/cli/fixtures/browser-multiple/vitest.config.ts
+++ b/test/cli/fixtures/browser-multiple/vitest.config.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { resolve } from 'pathe';
import { defineConfig } from 'vitest/config';
@@ -13,7 +14,7 @@ export default defineConfig({
browser: {
enabled: true,
instances: [{ browser: 'chromium' }],
- provider: 'playwright',
+ provider: playwright(),
headless: true,
}
}
@@ -27,7 +28,7 @@ export default defineConfig({
browser: {
enabled: true,
instances: [{ browser: 'chromium' }],
- provider: 'playwright',
+ provider: playwright(),
headless: true,
}
}
diff --git a/test/cli/fixtures/config-loader/browser/vitest.config.ts b/test/cli/fixtures/config-loader/browser/vitest.config.ts
index 7a387aaf2..4a0041e1b 100644
--- a/test/cli/fixtures/config-loader/browser/vitest.config.ts
+++ b/test/cli/fixtures/config-loader/browser/vitest.config.ts
@@ -1,11 +1,12 @@
import { defineConfig } from "vitest/config"
import "@test/test-dep-linked/ts";
+import { playwright } from '@vitest/browser/providers/playwright';
export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{
diff --git a/test/cli/fixtures/list/vitest.config.ts b/test/cli/fixtures/list/vitest.config.ts
index 3c5732b42..487485c4e 100644
--- a/test/cli/fixtures/list/vitest.config.ts
+++ b/test/cli/fixtures/list/vitest.config.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vitest/config'
@@ -7,7 +8,7 @@ export default defineConfig({
include: ['basic.test.ts', 'math.test.ts'],
browser: {
instances: [{ browser: 'chromium' }],
- provider: 'playwright',
+ provider: playwright(),
headless: true,
api: 7523,
}
diff --git a/test/cli/fixtures/public-api/vitest.config.ts b/test/cli/fixtures/public-api/vitest.config.ts
index 5dc5b97d2..3fe34057d 100644
--- a/test/cli/fixtures/public-api/vitest.config.ts
+++ b/test/cli/fixtures/public-api/vitest.config.ts
@@ -1,9 +1,10 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
browser: {
- provider: 'playwright',
+ provider: playwright(),
instances: [{ browser: 'chromium' }],
headless: true,
},
diff --git a/test/cli/test/annotations.test.ts b/test/cli/test/annotations.test.ts
index 8f9f4d6b3..414878805 100644
--- a/test/cli/test/annotations.test.ts
+++ b/test/cli/test/annotations.test.ts
@@ -1,4 +1,5 @@
import type { TestAnnotation } from 'vitest'
+import { playwright } from '@vitest/browser/providers/playwright'
import { describe, expect, test } from 'vitest'
import { runInlineTests } from '../../test-utils'
@@ -36,7 +37,7 @@ describe('API', () => {
name: 'browser',
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium' },
diff --git a/test/cli/test/fails.test.ts b/test/cli/test/fails.test.ts
index 4ddfd41ef..7efc4b4f9 100644
--- a/test/cli/test/fails.test.ts
+++ b/test/cli/test/fails.test.ts
@@ -1,6 +1,7 @@
import type { TestCase } from 'vitest/node'
-import { resolve } from 'pathe'
+import { playwright } from '@vitest/browser/providers/playwright'
+import { resolve } from 'pathe'
import { glob } from 'tinyglobby'
import { expect, it } from 'vitest'
import { runInlineTests, runVitest, ts } from '../../test-utils'
@@ -113,7 +114,7 @@ it('prints a warning if the assertion is not awaited in the browser mode', async
browser: {
enabled: true,
instances: [{ browser: 'chromium' }],
- provider: 'playwright',
+ provider: playwright(),
headless: true,
},
},
diff --git a/test/cli/test/init.test.ts b/test/cli/test/init.test.ts
index 7cd78339d..c2c9f89ef 100644
--- a/test/cli/test/init.test.ts
+++ b/test/cli/test/init.test.ts
@@ -54,12 +54,13 @@ test('initializes project', async () => {
expect(await getFileContent('/vitest.browser.config.ts')).toMatchInlineSnapshot(`
"import { defineConfig } from 'vitest/config'
+ import { preview } from '@vitest/browser/providers/preview'
export default defineConfig({
test: {
browser: {
enabled: true,
- provider: 'preview',
+ provider: preview(),
instances: [
],
},
diff --git a/test/cli/test/scoped-fixtures.test.ts b/test/cli/test/scoped-fixtures.test.ts
index 6da4dd840..40ce7785f 100644
--- a/test/cli/test/scoped-fixtures.test.ts
+++ b/test/cli/test/scoped-fixtures.test.ts
@@ -4,6 +4,7 @@ import type { TestAPI } from 'vitest'
import type { ViteUserConfig } from 'vitest/config'
import type { TestSpecification, TestUserConfig } from 'vitest/node'
import type { TestFsStructure } from '../../test-utils'
+import { playwright } from '@vitest/browser/providers/playwright'
import { runInlineTests } from '../../test-utils'
interface TestContext {
@@ -551,7 +552,7 @@ describe.for([
name: 'core',
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium', name: '' },
@@ -669,7 +670,7 @@ describe('browser tests', () => {
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
isolate: false,
instances: [
diff --git a/test/config/fixtures/bail/vitest.config.ts b/test/config/fixtures/bail/vitest.config.ts
index cc4be76a8..fd4743a03 100644
--- a/test/config/fixtures/bail/vitest.config.ts
+++ b/test/config/fixtures/bail/vitest.config.ts
@@ -29,6 +29,7 @@ export default defineConfig({
},
browser: {
headless: true,
+ instances: [],
},
},
})
diff --git a/test/config/fixtures/browser-custom-html/vitest.config.correct.ts b/test/config/fixtures/browser-custom-html/vitest.config.correct.ts
index bef458c6a..cc6645a06 100644
--- a/test/config/fixtures/browser-custom-html/vitest.config.correct.ts
+++ b/test/config/fixtures/browser-custom-html/vitest.config.correct.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from 'vitest/config';
export default defineConfig({
@@ -7,7 +8,7 @@ export default defineConfig({
instances: [{ browser: 'chromium' }],
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
testerHtmlPath: './custom-html.html'
},
},
diff --git a/test/config/fixtures/browser-custom-html/vitest.config.custom-transformIndexHtml.ts b/test/config/fixtures/browser-custom-html/vitest.config.custom-transformIndexHtml.ts
index ccb683258..136f218a6 100644
--- a/test/config/fixtures/browser-custom-html/vitest.config.custom-transformIndexHtml.ts
+++ b/test/config/fixtures/browser-custom-html/vitest.config.custom-transformIndexHtml.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from 'vitest/config';
export default defineConfig({
@@ -33,7 +34,7 @@ export default defineConfig({
instances: [{ browser: 'chromium' }],
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
testerHtmlPath: './custom-html.html',
},
},
diff --git a/test/config/fixtures/browser-custom-html/vitest.config.default-transformIndexHtml.ts b/test/config/fixtures/browser-custom-html/vitest.config.default-transformIndexHtml.ts
index d47640dff..f8fe90543 100644
--- a/test/config/fixtures/browser-custom-html/vitest.config.default-transformIndexHtml.ts
+++ b/test/config/fixtures/browser-custom-html/vitest.config.default-transformIndexHtml.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from 'vitest/config';
export default defineConfig({
@@ -33,7 +34,7 @@ export default defineConfig({
instances: [{ browser: 'chromium' }],
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
},
},
})
\ No newline at end of file
diff --git a/test/config/fixtures/browser-custom-html/vitest.config.error-hook.ts b/test/config/fixtures/browser-custom-html/vitest.config.error-hook.ts
index 9fbd6a978..4ad8f42e4 100644
--- a/test/config/fixtures/browser-custom-html/vitest.config.error-hook.ts
+++ b/test/config/fixtures/browser-custom-html/vitest.config.error-hook.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from 'vitest/config';
export default defineConfig({
@@ -15,7 +16,7 @@ export default defineConfig({
instances: [{ browser: 'chromium' }],
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
testerHtmlPath: './custom-html.html'
},
},
diff --git a/test/config/fixtures/browser-custom-html/vitest.config.non-existing.ts b/test/config/fixtures/browser-custom-html/vitest.config.non-existing.ts
index cdedec59b..8a259fc9f 100644
--- a/test/config/fixtures/browser-custom-html/vitest.config.non-existing.ts
+++ b/test/config/fixtures/browser-custom-html/vitest.config.non-existing.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright';
import { defineConfig } from 'vitest/config';
export default defineConfig({
@@ -6,7 +7,7 @@ export default defineConfig({
instances: [{ browser: 'chromium' }],
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
testerHtmlPath: './some-non-existing-path'
},
},
diff --git a/test/config/fixtures/browser-no-config/vitest.config.ts b/test/config/fixtures/browser-no-config/vitest.config.ts
index 35b54686a..742cc1027 100644
--- a/test/config/fixtures/browser-no-config/vitest.config.ts
+++ b/test/config/fixtures/browser-no-config/vitest.config.ts
@@ -4,6 +4,6 @@ export default defineConfig({
test: {
browser: {
headless: true,
- },
+ } as any, // testing that instances is required
},
})
\ No newline at end of file
diff --git a/test/config/test/bail.test.ts b/test/config/test/bail.test.ts
index 349fcee11..62f509dca 100644
--- a/test/config/test/bail.test.ts
+++ b/test/config/test/bail.test.ts
@@ -1,5 +1,6 @@
import type { TestUserConfig } from 'vitest/node'
+import { playwright } from '@vitest/browser/providers/playwright'
import { expect, test } from 'vitest'
import { runVitest } from '../../test-utils'
@@ -15,7 +16,7 @@ if (process.platform !== 'win32') {
{
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
fileParallelism: false,
instances: [
@@ -26,7 +27,7 @@ if (process.platform !== 'win32') {
{
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
fileParallelism: true,
instances: [
diff --git a/test/config/test/browser-configs.test.ts b/test/config/test/browser-configs.test.ts
index bacbd3bb8..2056b36ca 100644
--- a/test/config/test/browser-configs.test.ts
+++ b/test/config/test/browser-configs.test.ts
@@ -2,6 +2,7 @@ import type { ViteUserConfig } from 'vitest/config'
import type { TestUserConfig, VitestOptions } from 'vitest/node'
import type { TestFsStructure } from '../../test-utils'
import crypto from 'node:crypto'
+import { playwright } from '@vitest/browser/providers/playwright'
import { resolve } from 'pathe'
import { describe, expect, onTestFinished, test } from 'vitest'
import { createVitest } from 'vitest/node'
@@ -192,7 +193,7 @@ test('coverage provider v8 works correctly in browser mode if instances are filt
},
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
{ browser: 'firefox' },
@@ -214,7 +215,7 @@ test('coverage provider v8 works correctly in workspaced browser mode if instanc
name: 'browser',
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
{ browser: 'firefox' },
@@ -317,7 +318,7 @@ test('filter for the global browser project includes all browser instances', asy
name: 'myproject',
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium' },
@@ -347,6 +348,7 @@ test('can enable browser-cli options for multi-project workspace', async () => {
browser: {
enabled: true,
headless: true,
+ instances: [],
},
},
{
@@ -360,7 +362,7 @@ test('can enable browser-cli options for multi-project workspace', async () => {
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium', name: 'browser' },
],
@@ -460,7 +462,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
browser: {
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{
browser: 'chromium',
@@ -513,7 +515,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
browser: {
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{
browser: 'chromium',
@@ -573,7 +575,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
browser: {
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{
browser: 'chromium',
@@ -613,7 +615,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
test('correctly resolves extended project', async () => {
const { stdout } = await getCliConfig({
browser: {
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium' },
@@ -632,6 +634,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
name: 'browser',
browser: {
enabled: true,
+ instances: [],
},
},
},
@@ -666,7 +669,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
test('correctly overrides extended project', async () => {
const { stdout } = await getCliConfig({
browser: {
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium' },
@@ -685,6 +688,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
name: 'browser',
browser: {
enabled: true,
+ instances: [],
},
},
},
@@ -720,7 +724,7 @@ describe('[e2e] workspace configs are affected by the CLI options', () => {
const { stdout } = await getCliConfig({
browser: {
enabled: false,
- provider: 'playwright',
+ provider: playwright(),
headless: true,
instances: [
{ browser: 'chromium' },
diff --git a/test/config/test/failures.test.ts b/test/config/test/failures.test.ts
index bac6c719a..8b8f01854 100644
--- a/test/config/test/failures.test.ts
+++ b/test/config/test/failures.test.ts
@@ -1,12 +1,19 @@
import type { UserConfig as ViteUserConfig } from 'vite'
import type { TestUserConfig } from 'vitest/node'
import type { VitestRunnerCLIOptions } from '../../test-utils'
+import { playwright } from '@vitest/browser/providers/playwright'
+import { preview } from '@vitest/browser/providers/preview'
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
import { normalize, resolve } from 'pathe'
import { beforeEach, expect, test } from 'vitest'
import { version } from 'vitest/package.json'
import * as testUtils from '../../test-utils'
-const providers = ['playwright', 'webdriverio', 'preview'] as const
+const providers = [
+ playwright(),
+ webdriverio(),
+ preview(),
+] as const
const names = ['edge', 'chromium', 'webkit', 'chrome', 'firefox', 'safari'] as const
const browsers = providers.map(provider => names.map(name => ({ name, provider }))).flat()
@@ -75,7 +82,7 @@ test('inspect cannot be used with multi-threading', async () => {
})
test('inspect in browser mode requires no-file-parallelism', async () => {
- const { stderr } = await runVitest({ inspect: true, browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: 'playwright' } })
+ const { stderr } = await runVitest({ inspect: true, browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: playwright() } })
expect(stderr).toMatch('Error: You cannot use --inspect without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"')
})
@@ -87,7 +94,7 @@ test('inspect-brk cannot be used with multi processing', async () => {
})
test('inspect-brk in browser mode requires no-file-parallelism', async () => {
- const { stderr } = await runVitest({ inspectBrk: true, browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: 'playwright' } })
+ const { stderr } = await runVitest({ inspectBrk: true, browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: playwright() } })
expect(stderr).toMatch('Error: You cannot use --inspect-brk without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"')
})
@@ -97,7 +104,7 @@ test('inspect and --inspect-brk cannot be used when not playwright + chromium',
const cli = `--inspect${option === 'inspectBrk' ? '-brk' : ''}`
for (const { provider, name } of browsers) {
- if (provider === 'playwright' && name === 'chromium') {
+ if (provider.name === 'playwright' && name === 'chromium') {
continue
}
@@ -108,7 +115,7 @@ test('inspect and --inspect-brk cannot be used when not playwright + chromium',
browser: {
enabled: true,
provider,
- name,
+ instances: [{ browser: name }],
},
},
})
@@ -116,22 +123,22 @@ test('inspect and --inspect-brk cannot be used when not playwright + chromium',
expect(stderr).toMatch(
`Error: ${cli} does not work with
{
- "browser": {
- "provider": "${provider}",
- "name": "${name}"
- }
+ browser: {
+ provider: ${provider.name}(),
+ instances: [
+ { browser: '${name}' }
+ ],
+ },
}
Use either:
{
- "browser": {
- "provider": "playwright",
- "instances": [
- {
- "browser": "chromium"
- }
- ]
- }
+ browser: {
+ provider: playwright(),
+ instances: [
+ { browser: 'chromium' }
+ ],
+ },
}
...or disable ${cli}
@@ -141,60 +148,9 @@ Use either:
}
})
-test('v8 coverage provider throws when not playwright + chromium (browser.name)', async () => {
+test('v8 coverage provider throws when not playwright + chromium', async () => {
for (const { provider, name } of browsers) {
- if (provider === 'playwright' && name === 'chromium') {
- continue
- }
-
- const { stderr } = await runVitest({}, {
- test: {
- coverage: {
- enabled: true,
- },
- browser: {
- enabled: true,
- provider,
- name,
- },
- },
- })
-
- expect(stderr).toMatch(
- `Error: @vitest/coverage-v8 does not work with
-{
- "browser": {
- "provider": "${provider}",
- "name": "${name}"
- }
-}
-
-Use either:
-{
- "browser": {
- "provider": "playwright",
- "instances": [
- {
- "browser": "chromium"
- }
- ]
- }
-}
-
-...or change your coverage provider to:
-{
- "coverage": {
- "provider": "istanbul"
- }
-}
-`,
- )
- }
-})
-
-test('v8 coverage provider throws when not playwright + chromium (browser.instances)', async () => {
- for (const { provider, name } of browsers) {
- if (provider === 'playwright' && name === 'chromium') {
+ if (provider.name === 'playwright' && name === 'chromium') {
continue
}
@@ -214,33 +170,29 @@ test('v8 coverage provider throws when not playwright + chromium (browser.instan
expect(stderr).toMatch(
`Error: @vitest/coverage-v8 does not work with
{
- "browser": {
- "provider": "${provider}",
- "instances": [
- {
- "browser": "${name}"
- }
- ]
- }
+ browser: {
+ provider: ${provider.name}(),
+ instances: [
+ { browser: '${name}' }
+ ],
+ },
}
Use either:
{
- "browser": {
- "provider": "playwright",
- "instances": [
- {
- "browser": "chromium"
- }
- ]
- }
+ browser: {
+ provider: playwright(),
+ instances: [
+ { browser: 'chromium' }
+ ],
+ },
}
...or change your coverage provider to:
{
- "coverage": {
- "provider": "istanbul"
- }
+ coverage: {
+ provider: 'istanbul',
+ },
}
`,
)
@@ -256,7 +208,7 @@ test('v8 coverage provider throws when using chromium and other non-chromium bro
browser: {
enabled: true,
headless: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'chromium' },
{ browser: 'firefox' },
@@ -269,39 +221,31 @@ test('v8 coverage provider throws when using chromium and other non-chromium bro
expect(stderr).toMatch(
`Error: @vitest/coverage-v8 does not work with
{
- "browser": {
- "provider": "playwright",
- "instances": [
- {
- "browser": "chromium"
- },
- {
- "browser": "firefox"
- },
- {
- "browser": "webkit"
- }
- ]
- }
+ browser: {
+ provider: playwright(),
+ instances: [
+ { browser: 'chromium' },
+ { browser: 'firefox' },
+ { browser: 'webkit' }
+ ],
+ },
}
Use either:
{
- "browser": {
- "provider": "playwright",
- "instances": [
- {
- "browser": "chromium"
- }
- ]
- }
+ browser: {
+ provider: playwright(),
+ instances: [
+ { browser: 'chromium' }
+ ],
+ },
}
...or change your coverage provider to:
{
- "coverage": {
- "provider": "istanbul"
- }
+ coverage: {
+ provider: 'istanbul',
+ },
}`,
)
})
@@ -315,7 +259,7 @@ test('v8 coverage provider cannot be used in workspace without playwright + chro
name: 'Browser project',
browser: {
enabled: true,
- provider: 'webdriverio',
+ provider: webdriverio(),
instances: [{ browser: 'chrome' }],
},
},
@@ -325,14 +269,12 @@ test('v8 coverage provider cannot be used in workspace without playwright + chro
expect(stderr).toMatch(
`Error: @vitest/coverage-v8 does not work with
{
- "browser": {
- "provider": "webdriverio",
- "instances": [
- {
- "browser": "chrome"
- }
- ]
- }
+ browser: {
+ provider: webdriverio(),
+ instances: [
+ { browser: 'chrome' }
+ ],
+ },
}`,
)
})
@@ -451,7 +393,7 @@ test('browser.instances is empty', async () => {
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [],
},
},
@@ -483,7 +425,7 @@ test('browser.name filters all browser.instances are required', async () => {
browser: {
enabled: true,
name: 'chromium',
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'firefox' },
],
@@ -498,7 +440,7 @@ test('browser.instances throws an error if no custom name is provided', async ()
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'firefox' },
{ browser: 'firefox' },
@@ -515,7 +457,7 @@ test('browser.instances throws an error if no custom name is provided, but the c
name: 'custom',
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'firefox' },
{ browser: 'firefox' },
@@ -535,7 +477,7 @@ test('throws an error if name conflicts with a workspace name', async () => {
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
instances: [
{ browser: 'firefox' },
],
@@ -553,7 +495,7 @@ test('throws an error if several browsers are headed in nonTTY mode', async () =
test: {
browser: {
enabled: true,
- provider: 'playwright',
+ provider: playwright(),
headless: false,
instances: [
{ browser: 'chromium' },
diff --git a/test/coverage-test/test/isolation.test.ts b/test/coverage-test/test/isolation.test.ts
index 9b53de697..beb625c58 100644
--- a/test/coverage-test/test/isolation.test.ts
+++ b/test/coverage-test/test/isolation.test.ts
@@ -27,6 +27,7 @@ for (const isolate of [true, false]) {
browser: {
isolate,
+ instances: [],
},
})
diff --git a/test/coverage-test/utils.ts b/test/coverage-test/utils.ts
index 57c467dc4..764f13e2e 100644
--- a/test/coverage-test/utils.ts
+++ b/test/coverage-test/utils.ts
@@ -7,6 +7,7 @@ import { unlink } from 'node:fs/promises'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { stripVTControlCharacters } from 'node:util'
+import { playwright } from '@vitest/browser/providers/playwright'
import libCoverage from 'istanbul-lib-coverage'
import { normalize } from 'pathe'
import { vi, describe as vitestDescribe, test as vitestTest } from 'vitest'
@@ -56,7 +57,7 @@ export async function runVitest(config: TestUserConfig, options = { throwOnError
enabled: process.env.COVERAGE_BROWSER === 'true',
headless: true,
instances: [{ browser: 'chromium' }],
- provider: 'playwright',
+ provider: playwright(),
},
},
})
diff --git a/test/dts-playwright/vite.config.ts b/test/dts-playwright/vite.config.ts
index 250f59b25..0c32e8096 100644
--- a/test/dts-playwright/vite.config.ts
+++ b/test/dts-playwright/vite.config.ts
@@ -1,24 +1,26 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
browser: {
- provider: 'playwright',
- providerOptions: {
- launch: {
+ provider: playwright({
+ launchOptions: {
timeout: 1234,
// @ts-expect-error test type error
slowMo: 'wrong',
},
- },
+ }),
instances: [
{
browser: 'chromium',
- launch: {
- timeout: 1234,
- // @ts-expect-error test type error
- slowMo: 'wrong',
- },
+ provider: playwright({
+ launchOptions: {
+ timeout: 1234,
+ // @ts-expect-error test type error
+ slowMo: 'wrong',
+ },
+ }),
},
],
},
diff --git a/test/watch/test/config-watching.test.ts b/test/watch/test/config-watching.test.ts
index bbec2996d..9edc214e3 100644
--- a/test/watch/test/config-watching.test.ts
+++ b/test/watch/test/config-watching.test.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { expect, test } from 'vitest'
import { runInlineTests } from '../../test-utils'
@@ -15,7 +16,7 @@ test('rerun stops the previous browser server and restarts multiple times withou
browser: {
enabled: true,
instances: [{ browser: 'chromium' }],
- provider: 'playwright',
+ provider: playwright(),
headless: true,
},
},
diff --git a/test/watch/test/file-watching.test.ts b/test/watch/test/file-watching.test.ts
index 74af818c6..451ec6aa3 100644
--- a/test/watch/test/file-watching.test.ts
+++ b/test/watch/test/file-watching.test.ts
@@ -1,6 +1,7 @@
import { existsSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'
-import { afterEach, describe, expect, test } from 'vitest'
+import { webdriverio } from '@vitest/browser/providers/webdriverio'
+import { afterEach, describe, expect, test } from 'vitest'
import * as testUtils from '../../test-utils'
const sourceFile = 'fixtures/math.ts'
@@ -193,7 +194,7 @@ describe('browser', () => {
...options,
browser: {
instances: [{ browser: 'chromium' }],
- provider: 'webdriverio',
+ provider: webdriverio(),
enabled: true,
headless: true,
},
diff --git a/test/workspaces-browser/space_browser/vitest.config.ts b/test/workspaces-browser/space_browser/vitest.config.ts
index 5b64428f2..246901f82 100644
--- a/test/workspaces-browser/space_browser/vitest.config.ts
+++ b/test/workspaces-browser/space_browser/vitest.config.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { defineProject } from 'vitest/config'
export default defineProject({
@@ -6,7 +7,7 @@ export default defineProject({
enabled: true,
instances: [{ browser: process.env.BROWSER || 'chromium' }],
headless: true,
- provider: process.env.PROVIDER || 'playwright',
+ provider: playwright(),
},
},
})
diff --git a/test/workspaces-browser/vitest.config.ts b/test/workspaces-browser/vitest.config.ts
index 0e75c4df0..b550364fc 100644
--- a/test/workspaces-browser/vitest.config.ts
+++ b/test/workspaces-browser/vitest.config.ts
@@ -1,3 +1,4 @@
+import { playwright } from '@vitest/browser/providers/playwright'
import { defineConfig } from 'vitest/config'
if (process.env.TEST_WATCH) {
@@ -22,7 +23,7 @@ export default defineConfig({
enabled: true,
instances: [{ browser: process.env.BROWSER || 'chromium' }],
headless: true,
- provider: process.env.PROVIDER || 'playwright',
+ provider: playwright(),
},
alias: {
'test-alias-from-vitest': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,