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

assertions.mddocs/

0

# Assertions and Expectations

1

2

Jest-compatible assertion APIs powered by Chai with extensive matchers and custom matcher support.

3

4

## Expect API

5

6

```typescript { .api }

7

function expect<T>(actual: T): Assertion<T>;

8

9

interface ExpectStatic {

10

<T>(actual: T): Assertion<T>;

11

extend(matchers: Record<string, CustomMatcher>): void;

12

addEqualityTesters(testers: Array<Tester>): void;

13

getState(): MatcherState;

14

setState(state: Partial<MatcherState>): void;

15

unreachable(message?: string): never;

16

hasAssertions(): void;

17

assertions(count: number): void;

18

soft<T>(actual: T, message?: string): Assertion<T>;

19

poll<T>(fn: () => T | Promise<T>, options?: ExpectPollOptions): Promise<Assertion<T>>;

20

}

21

22

interface ExpectPollOptions {

23

interval?: number; // default: 50ms

24

timeout?: number; // default: 1000ms

25

message?: string;

26

}

27

```

28

29

## Core Matchers

30

31

### Equality

32

33

| Matcher | Purpose | Example |

34

|---------|---------|---------|

35

| `.toBe(expected)` | Strict equality (===) | `expect(x).toBe(5)` |

36

| `.toEqual(expected)` | Deep equality | `expect({a:1}).toEqual({a:1})` |

37

| `.toStrictEqual(expected)` | Strict deep equality | `expect({a:1,b:undefined}).toStrictEqual({a:1,b:undefined})` |

38

39

### Truthiness

40

41

```typescript { .api }

42

.toBeTruthy() // Truthy value

43

.toBeFalsy() // Falsy value

44

.toBeDefined() // Not undefined

45

.toBeUndefined() // Is undefined

46

.toBeNull() // Is null

47

.toBeNaN() // Is NaN

48

```

49

50

### Numbers

51

52

```typescript { .api }

53

.toBeGreaterThan(n)

54

.toBeGreaterThanOrEqual(n)

55

.toBeLessThan(n)

56

.toBeLessThanOrEqual(n)

57

.toBeCloseTo(n, digits?) // Floating point comparison

58

```

59

60

**Example:**

61

```typescript

62

expect(10).toBeGreaterThan(5);

63

expect(0.1 + 0.2).toBeCloseTo(0.3); // Handles floating point

64

```

65

66

### Strings

67

68

```typescript { .api }

69

.toMatch(regexp | string) // Matches pattern

70

.toContain(substring) // Contains substring

71

```

72

73

### Arrays/Iterables

74

75

```typescript { .api }

76

.toContain(item) // Array/string contains item

77

.toContainEqual(item) // Deep equality check for item

78

.toHaveLength(n) // Length equals n

79

```

80

81

**Example:**

82

```typescript

83

expect([1, 2, 3]).toContain(2);

84

expect([{id: 1}, {id: 2}]).toContainEqual({id: 1});

85

expect([1, 2, 3]).toHaveLength(3);

86

```

87

88

### Objects

89

90

```typescript { .api }

91

.toHaveProperty(keyPath, value?) // Has property at path

92

.toMatchObject(subset) // Partial object match

93

```

94

95

**Example:**

96

```typescript

97

expect({a: 1, b: {c: 2}}).toHaveProperty('b.c', 2);

98

expect({a: 1, b: 2, c: 3}).toMatchObject({a: 1, b: 2});

99

```

100

101

### Functions/Errors

102

103

```typescript { .api }

104

.toThrow(expected?) // Throws error

105

.toThrowError(expected?) // Alias for toThrow

106

```

107

108

**Example:**

109

```typescript

110

expect(() => { throw new Error('fail') }).toThrow('fail');

111

expect(() => { throw new Error('fail') }).toThrow(/fail/);

112

```

113

114

### Promises

115

116

```typescript { .api }

117

.resolves // Access resolved promise value

118

.rejects // Access rejected promise error

119

```

120

121

**Example:**

122

```typescript

123

await expect(Promise.resolve('success')).resolves.toBe('success');

124

await expect(Promise.reject(new Error('fail'))).rejects.toThrow('fail');

125

```

126

127

### Modifiers

128

129

```typescript { .api }

130

.not // Negate assertion

131

```

132

133

**Example:**

134

```typescript

135

expect(1).not.toBe(2);

136

expect('hello').not.toMatch(/world/);

137

```

138

139

## Mock Function Matchers

140

141

```typescript { .api }

142

// Call assertions

143

.toHaveBeenCalled() // Called at least once

144

.toBeCalled() // Alias

145

.toHaveBeenCalledTimes(n) // Called exactly n times

146

.toHaveBeenCalledWith(...args) // Called with specific args

147

.toHaveBeenLastCalledWith(...args) // Last call had specific args

148

.toHaveBeenNthCalledWith(n, ...args) // Nth call had specific args

149

150

// Return assertions

151

.toHaveReturned() // Returned successfully

152

.toHaveReturnedTimes(n) // Returned n times

153

.toHaveReturnedWith(value) // Returned specific value

154

.toHaveLastReturnedWith(value) // Last return was specific value

155

.toHaveNthReturnedWith(n, value) // Nth return was specific value

156

```

157

158

**Example:**

159

```typescript

160

const mockFn = vi.fn((x) => x * 2);

161

mockFn(1); mockFn(2); mockFn(3);

162

163

expect(mockFn).toHaveBeenCalledTimes(3);

164

expect(mockFn).toHaveBeenCalledWith(2);

165

expect(mockFn).toHaveBeenNthCalledWith(2, 2);

166

expect(mockFn).toHaveReturnedWith(4);

167

expect(mockFn).toHaveLastReturnedWith(6);

168

```

169

170

## Snapshot Testing

171

172

```typescript { .api }

173

.toMatchSnapshot(message?) // Compare to saved snapshot

174

.toMatchInlineSnapshot(snapshot?, message?) // Inline snapshot in code

175

.toMatchFileSnapshot(filepath, message?) // Compare to file

176

.toThrowErrorMatchingSnapshot(message?) // Error snapshot

177

.toThrowErrorMatchingInlineSnapshot(snapshot?) // Inline error snapshot

178

```

179

180

**Example:**

181

```typescript

182

expect({id: 1, name: 'John'}).toMatchSnapshot();

183

184

expect({success: true, count: 5}).toMatchInlineSnapshot(`

185

{

186

"success": true,

187

"count": 5

188

}

189

`);

190

191

await expect('<div>Hello</div>').toMatchFileSnapshot('./snapshots/output.html');

192

```

193

194

## Advanced Features

195

196

### Soft Assertions

197

198

Continue test execution even when assertions fail.

199

200

```typescript

201

expect.soft(1 + 1).toBe(2);

202

expect.soft(2 + 2).toBe(5); // Fails but continues

203

expect.soft(3 + 3).toBe(6);

204

// Test reports all failures at end

205

```

206

207

### Polling Assertions

208

209

Retry assertions until condition is met.

210

211

```typescript

212

let value = 0;

213

setTimeout(() => { value = 10 }, 100);

214

215

await expect.poll(() => value, {

216

interval: 20,

217

timeout: 200

218

}).toBe(10);

219

220

// Async functions

221

await expect.poll(

222

async () => {

223

const res = await fetch('/api/status');

224

return res.json();

225

},

226

{ timeout: 5000 }

227

).toMatchObject({ status: 'ready' });

228

```

229

230

### Custom Matchers

231

232

```typescript { .api }

233

expect.extend(matchers: Record<string, CustomMatcher>): void;

234

235

interface CustomMatcher {

236

(this: MatcherContext, actual: any, ...expected: any[]): MatcherResult;

237

}

238

239

interface MatcherResult {

240

pass: boolean;

241

message: () => string;

242

actual?: any;

243

expected?: any;

244

}

245

```

246

247

**Example:**

248

```typescript

249

expect.extend({

250

toBeWithinRange(received: number, floor: number, ceiling: number) {

251

const pass = received >= floor && received <= ceiling;

252

return {

253

pass,

254

message: () => pass

255

? `expected ${received} not to be within ${floor}-${ceiling}`

256

: `expected ${received} to be within ${floor}-${ceiling}`,

257

};

258

},

259

});

260

261

expect(15).toBeWithinRange(10, 20);

262

expect(25).not.toBeWithinRange(10, 20);

263

```

264

265

### Assertion Count

266

267

```typescript

268

// Require exact number of assertions

269

test('exact count', () => {

270

expect.assertions(2);

271

expect(1).toBe(1);

272

expect(2).toBe(2);

273

// Fails if != 2 assertions

274

});

275

276

// Require at least one assertion

277

test('at least one', async () => {

278

expect.hasAssertions();

279

const data = await fetchData();

280

if (data) expect(data).toBeDefined();

281

// Fails if no assertions run

282

});

283

```

284

285

### Create Custom Expect

286

287

```typescript { .api }

288

function createExpect(test?: TaskPopulated): ExpectStatic;

289

```

290

291

**Example:**

292

```typescript

293

const customExpect = createExpect();

294

customExpect.extend({

295

toBeDivisibleBy(received: number, divisor: number) {

296

return {

297

pass: received % divisor === 0,

298

message: () => `expected ${received} to be divisible by ${divisor}`,

299

};

300

},

301

});

302

303

customExpect(10).toBeDivisibleBy(5);

304

```

305

306

## Asymmetric Matchers

307

308

Partial matching for complex objects.

309

310

```typescript { .api }

311

expect.any(constructor) // Match any instance of type

312

expect.anything() // Match anything except null/undefined

313

expect.arrayContaining(items) // Array contains items

314

expect.objectContaining(obj) // Object contains properties

315

expect.stringContaining(str) // String contains substring

316

expect.stringMatching(regexp) // String matches pattern

317

expect.closeTo(n, precision?) // Number close to value

318

```

319

320

**Example:**

321

```typescript

322

expect({id: 1, name: 'John', age: 30}).toEqual({

323

id: expect.any(Number),

324

name: expect.any(String),

325

age: expect.any(Number)

326

});

327

328

expect([1, 2, 3, 4]).toEqual(expect.arrayContaining([2, 3]));

329

expect({a: 1, b: 2, c: 3}).toEqual(expect.objectContaining({a: 1}));

330

expect('hello world').toEqual(expect.stringContaining('world'));

331

expect('test123').toEqual(expect.stringMatching(/test\d+/));

332

```

333

334

## Chai API

335

336

Vitest re-exports Chai for alternative assertion styles.

337

338

```typescript { .api }

339

const assert: Chai.AssertStatic;

340

const chai: Chai.ChaiStatic;

341

const should: Chai.Should;

342

```

343

344

**Example:**

345

```typescript

346

import { assert, should } from 'vitest';

347

348

// Node.js assert style

349

assert.equal(1 + 1, 2);

350

assert.isTrue(true);

351

assert.deepEqual({a: 1}, {a: 1});

352

353

// Chai should style

354

should();

355

(1 + 1).should.equal(2);

356

'hello'.should.be.a('string');

357

[1, 2, 3].should.have.lengthOf(3);

358

```

359

360

## Type Definitions

361

362

```typescript { .api }

363

interface Assertion<T> {

364

not: Assertion<T>;

365

resolves: Assertion<Awaited<T>>;

366

rejects: Assertion<any>;

367

368

toBe(expected: any): void;

369

toEqual(expected: any): void;

370

toStrictEqual(expected: any): void;

371

toBeTruthy(): void;

372

toBeFalsy(): void;

373

toBeDefined(): void;

374

toBeUndefined(): void;

375

toBeNull(): void;

376

toBeNaN(): void;

377

toBeTypeOf(expected: string): void;

378

toBeInstanceOf(expected: any): void;

379

toBeGreaterThan(expected: number | bigint): void;

380

toBeGreaterThanOrEqual(expected: number | bigint): void;

381

toBeLessThan(expected: number | bigint): void;

382

toBeLessThanOrEqual(expected: number | bigint): void;

383

toBeCloseTo(expected: number, numDigits?: number): void;

384

toMatch(expected: string | RegExp): void;

385

toContain(expected: any): void;

386

toContainEqual(expected: any): void;

387

toHaveLength(expected: number): void;

388

toHaveProperty(keyPath: string | string[], value?: any): void;

389

toMatchObject(expected: object): void;

390

toThrow(expected?: string | RegExp | Error): void;

391

toSatisfy(predicate: (value: any) => boolean): void;

392

toMatchSnapshot(message?: string): void;

393

toMatchInlineSnapshot(snapshot?: string, message?: string): void;

394

toMatchFileSnapshot(filepath: string, message?: string): Promise<void>;

395

}

396

397

interface MatcherState {

398

assertionCalls: number;

399

isExpectingAssertions: boolean;

400

expectedAssertionsNumber: number | null;

401

environment: Environment;

402

testPath?: string;

403

currentTestName?: string;

404

}

405

```

406

407

## Matcher Selection Guide

408

409

| Need | Use | Example |

410

|------|-----|---------|

411

| Primitive equality | `.toBe()` | `expect(5).toBe(5)` |

412

| Object equality | `.toEqual()` | `expect({a:1}).toEqual({a:1})` |

413

| Partial object | `.toMatchObject()` | `expect(obj).toMatchObject({a:1})` |

414

| Type check | `.any()` | `expect.any(String)` |

415

| Range check | Custom matcher | `toBe WithinRange()` |

416

| Async success | `.resolves` | `expect(p).resolves.toBe(x)` |

417

| Async failure | `.rejects` | `expect(p).rejects.toThrow()` |

418

| Function called | `.toHaveBeenCalled()` | Mock assertions |

419

| Contains item | `.toContain()` | Array/string search |

420

| Has property | `.toHaveProperty()` | Object property |

421

| Pattern match | `.toMatch()` | String/regex |

422