or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdbenchmarking.mdbrowser-testing.mdconfiguration.mdindex.mdmocking.mdnode-apis.mdreporters.mdtest-definition.mdtimers.mdtype-testing.md

browser-testing.mddocs/

0

# Browser Testing

1

2

Vitest provides native browser testing capabilities for running tests in real browser environments. Import from `vitest/browser`.

3

4

## Capabilities

5

6

### Browser Commands

7

8

File system commands available in browser context.

9

10

```typescript { .api }

11

interface BrowserCommands {

12

/**

13

* Read file from file system

14

* @param path - File path

15

* @param options - Read options

16

* @returns Promise resolving to file contents

17

*/

18

readFile(

19

path: string,

20

options?: { encoding?: BufferEncoding }

21

): Promise<string>;

22

23

/**

24

* Write file to file system

25

* @param path - File path

26

* @param content - File content

27

* @param options - Write options

28

* @returns Promise resolving when write completes

29

*/

30

writeFile(

31

path: string,

32

content: string,

33

options?: { encoding?: BufferEncoding }

34

): Promise<void>;

35

36

/**

37

* Remove file from file system

38

* @param path - File path

39

* @returns Promise resolving when file is removed

40

*/

41

removeFile(path: string): Promise<void>;

42

}

43

```

44

45

**Usage:**

46

47

```typescript

48

import { test, expect } from 'vitest';

49

import { readFile, writeFile, removeFile } from 'vitest/browser';

50

51

test('file operations', async () => {

52

await writeFile('./test.txt', 'Hello World');

53

54

const content = await readFile('./test.txt');

55

expect(content).toBe('Hello World');

56

57

await removeFile('./test.txt');

58

});

59

```

60

61

### Browser Coverage

62

63

Coverage collection APIs for browser tests.

64

65

```typescript { .api }

66

/**

67

* Start coverage collection in browser worker

68

* @returns Promise resolving when coverage starts

69

*/

70

function startCoverageInsideWorker(): Promise<void>;

71

72

/**

73

* Stop coverage collection in browser worker

74

* @returns Promise resolving when coverage stops

75

*/

76

function stopCoverageInsideWorker(): Promise<void>;

77

78

/**

79

* Take coverage snapshot in browser worker

80

* @returns Promise resolving to coverage data

81

*/

82

function takeCoverageInsideWorker(): Promise<Coverage>;

83

```

84

85

**Usage:**

86

87

```typescript

88

import { test, expect } from 'vitest';

89

import {

90

startCoverageInsideWorker,

91

takeCoverageInsideWorker,

92

stopCoverageInsideWorker

93

} from 'vitest/browser';

94

95

test('with coverage', async () => {

96

await startCoverageInsideWorker();

97

98

// Test code

99

100

const coverage = await takeCoverageInsideWorker();

101

expect(coverage).toBeDefined();

102

103

await stopCoverageInsideWorker();

104

});

105

```

106

107

### Browser Utilities

108

109

Utility functions for browser testing.

110

111

```typescript { .api }

112

/**

113

* Format values for display

114

*/

115

function format(...args: any[]): string;

116

117

/**

118

* Inspect objects

119

*/

120

function inspect(value: any, options?: InspectOptions): string;

121

122

/**

123

* Stringify values

124

*/

125

function stringify(value: any, options?: StringifyOptions): string;

126

127

/**

128

* Process error objects

129

*/

130

function processError(error: unknown): Error;

131

132

/**

133

* Get JavaScript type of value

134

*/

135

function getType(value: any): string;

136

137

/**

138

* Get safe timer functions

139

*/

140

function getSafeTimers(): SafeTimers;

141

142

/**

143

* Set safe timer functions

144

*/

145

function setSafeTimers(timers: SafeTimers): void;

146

147

/**

148

* Get original position from source map

149

*/

150

function getOriginalPosition(map: DecodedMap, pos: Position): Position | null;

151

152

/**

153

* Decoded source map class

154

*/

155

class DecodedMap {

156

// Source map utilities

157

}

158

159

/**

160

* Collect tests in browser

161

*/

162

function collectTests(): Promise<void>;

163

164

/**

165

* Start tests in browser

166

*/

167

function startTests(): Promise<void>;

168

```

169

170

## Browser Configuration

171

172

Configure browser testing in vitest.config.ts:

173

174

```typescript

175

import { defineConfig } from 'vitest/config';

176

177

export default defineConfig({

178

test: {

179

browser: {

180

enabled: true,

181

name: 'chrome', // or 'firefox', 'safari', 'edge'

182

provider: 'playwright', // or 'webdriverio', 'preview'

183

headless: true,

184

screenshotFailures: true,

185

viewport: {

186

width: 1280,

187

height: 720

188

}

189

}

190

}

191

});

192

```

193

194

### Browser Providers

195

196

Three browser providers available:

197

198

1. **playwright** - Uses Playwright for browser automation

199

2. **webdriverio** - Uses WebdriverIO for browser automation

200

3. **preview** - Lightweight preview mode

201

202

```typescript

203

// Install provider

204

npm install -D @vitest/browser-playwright

205

// or

206

npm install -D @vitest/browser-webdriverio

207

```

208

209

### Browser Configuration Options

210

211

```typescript { .api }

212

interface BrowserConfigOptions {

213

/** Enable browser mode */

214

enabled?: boolean;

215

216

/** Browser name */

217

name?: 'chrome' | 'firefox' | 'safari' | 'edge';

218

219

/** Browser provider */

220

provider?: 'playwright' | 'webdriverio' | 'preview';

221

222

/** Run in headless mode */

223

headless?: boolean;

224

225

/** Take screenshots on failure */

226

screenshotFailures?: boolean;

227

228

/** Viewport size */

229

viewport?: {

230

width: number;

231

height: number;

232

};

233

234

/** Browser instance options */

235

providerOptions?: Record<string, any>;

236

237

/** API server configuration */

238

api?: {

239

port?: number;

240

host?: string;

241

};

242

243

/** Scripts to load in browser */

244

scripts?: BrowserScript[];

245

246

/** Isolate tests */

247

isolate?: boolean;

248

249

/** File parallelism */

250

fileParallelism?: boolean;

251

}

252

253

interface BrowserScript {

254

/** Script content or path */

255

content?: string;

256

src?: string;

257

258

/** Load timing */

259

async?: boolean;

260

type?: string;

261

}

262

```

263

264

## Browser-Specific Matchers

265

266

### Screenshot Matching

267

268

```typescript { .api }

269

interface Assertion<T> {

270

/**

271

* Match screenshot against baseline

272

* @param options - Screenshot comparison options

273

*/

274

toMatchScreenshot(options?: ToMatchScreenshotOptions): Promise<void>;

275

}

276

277

interface ToMatchScreenshotOptions {

278

/** Threshold for image comparison (0-1) */

279

threshold?: number;

280

281

/** Baseline screenshot path */

282

name?: string;

283

284

/** Include only specific element */

285

element?: HTMLElement;

286

287

/** Viewport size for screenshot */

288

viewport?: {

289

width: number;

290

height: number;

291

};

292

}

293

```

294

295

**Usage:**

296

297

```typescript

298

import { test, expect } from 'vitest';

299

300

test('visual regression', async () => {

301

const element = document.querySelector('.my-component');

302

303

await expect(element).toMatchScreenshot({

304

threshold: 0.1,

305

name: 'my-component'

306

});

307

});

308

```

309

310

## Common Patterns

311

312

### DOM Testing

313

314

```typescript

315

import { test, expect } from 'vitest';

316

317

test('DOM manipulation', () => {

318

const button = document.createElement('button');

319

button.textContent = 'Click me';

320

button.onclick = () => {

321

button.textContent = 'Clicked!';

322

};

323

324

document.body.appendChild(button);

325

326

button.click();

327

328

expect(button.textContent).toBe('Clicked!');

329

330

button.remove();

331

});

332

```

333

334

### Browser API Testing

335

336

```typescript

337

import { test, expect } from 'vitest';

338

339

test('localStorage', () => {

340

localStorage.setItem('key', 'value');

341

342

expect(localStorage.getItem('key')).toBe('value');

343

344

localStorage.removeItem('key');

345

expect(localStorage.getItem('key')).toBeNull();

346

});

347

348

test('fetch API', async () => {

349

const response = await fetch('/api/data');

350

const data = await response.json();

351

352

expect(data).toBeDefined();

353

});

354

```

355

356

### Component Testing

357

358

```typescript

359

import { test, expect } from 'vitest';

360

import { render } from '@testing-library/react';

361

import MyComponent from './MyComponent';

362

363

test('renders component', () => {

364

const { container } = render(<MyComponent />);

365

366

expect(container.querySelector('.my-component')).toBeTruthy();

367

});

368

```

369

370

### Multi-Browser Testing

371

372

Configure multiple browser projects using the `projects` option:

373

374

```typescript

375

// vitest.config.ts

376

import { defineConfig } from 'vitest/config';

377

378

export default defineConfig({

379

test: {

380

projects: [

381

{

382

test: {

383

name: 'chrome',

384

browser: {

385

enabled: true,

386

name: 'chrome'

387

}

388

}

389

},

390

{

391

test: {

392

name: 'firefox',

393

browser: {

394

enabled: true,

395

name: 'firefox'

396

}

397

}

398

},

399

{

400

test: {

401

name: 'safari',

402

browser: {

403

enabled: true,

404

name: 'safari'

405

}

406

}

407

}

408

]

409

}

410

});

411

```

412

413

## Running Browser Tests

414

415

```bash

416

# Run browser tests

417

vitest --browser

418

419

# Run in specific browser

420

vitest --browser.name=chrome

421

422

# Run with UI

423

vitest --browser --ui

424

```

425

426

## Type Definitions

427

428

```typescript { .api }

429

interface Coverage {

430

functions: FunctionCoverage[];

431

statements: StatementCoverage[];

432

branches: BranchCoverage[];

433

}

434

435

interface FunctionCoverage {

436

name: string;

437

count: number;

438

line: number;

439

column: number;

440

}

441

442

interface SafeTimers {

443

setTimeout: typeof setTimeout;

444

setInterval: typeof setInterval;

445

clearTimeout: typeof clearTimeout;

446

clearInterval: typeof clearInterval;

447

setImmediate: typeof setImmediate;

448

clearImmediate: typeof clearImmediate;

449

}

450

451

interface Position {

452

line: number;

453

column: number;

454

}

455

456

interface InspectOptions {

457

depth?: number;

458

colors?: boolean;

459

compact?: boolean;

460

}

461

462

interface StringifyOptions {

463

indent?: number;

464

maxLength?: number;

465

}

466

```

467

468

## Environment Setup

469

470

Browser tests can use different DOM implementations:

471

472

1. **Real Browser** (browser mode)

473

2. **JSDOM** (jsdom environment)

474

3. **Happy DOM** (happy-dom environment)

475

476

```typescript

477

// Real browser

478

export default defineConfig({

479

test: {

480

browser: {

481

enabled: true,

482

name: 'chrome'

483

}

484

}

485

});

486

487

// JSDOM (simulated)

488

export default defineConfig({

489

test: {

490

environment: 'jsdom'

491

}

492

});

493

494

// Happy DOM (simulated, faster)

495

export default defineConfig({

496

test: {

497

environment: 'happy-dom'

498

}

499

});

500

```

501