diff --git a/docs/advanced/api/reporters.md b/docs/advanced/api/reporters.md
index 7978a1d813f8..06ebd06ae83e 100644
--- a/docs/advanced/api/reporters.md
+++ b/docs/advanced/api/reporters.md
@@ -81,6 +81,14 @@ export default new MyReporter()
```
:::
+## onBrowserInit experimental {#onbrowserinit}
+
+```ts
+function onBrowserInit(project: TestProject): Awaitable
+```
+
+This method is called when the browser instance is initiated. It receives an instance of the project for which the browser is initiated. `project.browser` will always be defined when this method is called.
+
## onTestRunStart
```ts
diff --git a/packages/vitest/src/node/project.ts b/packages/vitest/src/node/project.ts
index ce7858fa9cc4..195dd3f736bc 100644
--- a/packages/vitest/src/node/project.ts
+++ b/packages/vitest/src/node/project.ts
@@ -531,6 +531,7 @@ export class TestProject {
if (!this.browser && this._parent?._parentBrowser) {
this.browser = this._parent._parentBrowser.spawn(this)
+ await this.vitest.report('onBrowserInit', this)
}
})
diff --git a/packages/vitest/src/node/types/reporter.ts b/packages/vitest/src/node/types/reporter.ts
index 54708e842acf..3c4e19088d95 100644
--- a/packages/vitest/src/node/types/reporter.ts
+++ b/packages/vitest/src/node/types/reporter.ts
@@ -3,6 +3,7 @@ import type { SerializedError } from '@vitest/utils'
import type { SerializedTestSpecification } from '../../runtime/types/utils'
import type { Awaitable, UserConsoleLog } from '../../types/general'
import type { Vitest } from '../core'
+import type { TestProject } from '../project'
import type { ReportedHookContext, TestCase, TestModule, TestSuite } from '../reporters/reported-tasks'
import type { TestSpecification } from '../spec'
@@ -10,6 +11,12 @@ export type TestRunEndReason = 'passed' | 'interrupted' | 'failed'
export interface Reporter {
onInit?: (vitest: Vitest) => void
+ /**
+ * Called when the project initiated the browser instance.
+ * project.browser will always be defined.
+ * @experimental
+ */
+ onBrowserInit?: (project: TestProject) => Awaitable
/**
* @deprecated use `onTestRunStart` instead
*/
diff --git a/test/browser/specs/runner.test.ts b/test/browser/specs/runner.test.ts
index d0f72ec1cd6d..95a6d1f442ab 100644
--- a/test/browser/specs/runner.test.ts
+++ b/test/browser/specs/runner.test.ts
@@ -4,6 +4,8 @@ import { readFile } from 'node:fs/promises'
import { beforeAll, describe, expect, onTestFailed, test } from 'vitest'
import { instances, provider, runBrowserTests } from './utils'
+function noop() {}
+
describe('running browser tests', async () => {
let stderr: string
let stdout: string
@@ -11,13 +13,36 @@ describe('running browser tests', async () => {
let passedTests: any[]
let failedTests: any[]
let vitest: Vitest
+ const events: string[] = []
beforeAll(async () => {
({
stderr,
stdout,
ctx: vitest,
- } = await runBrowserTests())
+ } = await runBrowserTests({
+ reporters: [
+ {
+ onBrowserInit(project) {
+ events.push(`onBrowserInit ${project.name}`)
+ },
+ },
+ 'json',
+ {
+ onInit: noop,
+ onPathsCollected: noop,
+ onCollected: noop,
+ onFinished: noop,
+ onTaskUpdate: noop,
+ onTestRemoved: noop,
+ onWatcherStart: noop,
+ onWatcherRerun: noop,
+ onServerRestart: noop,
+ onUserConsoleLog: noop,
+ },
+ 'default',
+ ],
+ }))
const browserResult = await readFile('./browser.json', 'utf-8')
browserResultJson = JSON.parse(browserResult)
@@ -34,6 +59,11 @@ describe('running browser tests', async () => {
const testFiles = browserResultJson.testResults.map(t => t.name)
+ vitest.projects.forEach((project) => {
+ // the order is non-deterministic
+ expect(events).toContain(`onBrowserInit ${project.name}`)
+ })
+
// test files are optimized automatically
expect(vitest.projects.map(p => p.browser?.vite.config.optimizeDeps.entries))
.toEqual(vitest.projects.map(() => expect.arrayContaining(testFiles)))
diff --git a/test/browser/vitest.config.mts b/test/browser/vitest.config.mts
index 82562c4625f7..89331be8c974 100644
--- a/test/browser/vitest.config.mts
+++ b/test/browser/vitest.config.mts
@@ -6,8 +6,6 @@ import { defineConfig } from 'vitest/config'
const dir = dirname(fileURLToPath(import.meta.url))
-function noop() {}
-
const provider = process.env.PROVIDER || 'playwright'
const browser = process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome')
@@ -106,18 +104,6 @@ export default defineConfig({
html: './html/index.html',
json: './browser.json',
},
- reporters: ['json', {
- onInit: noop,
- onPathsCollected: noop,
- onCollected: noop,
- onFinished: noop,
- onTaskUpdate: noop,
- onTestRemoved: noop,
- onWatcherStart: noop,
- onWatcherRerun: noop,
- onServerRestart: noop,
- onUserConsoleLog: noop,
- }, 'default'],
env: {
BROWSER: browser,
},