or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argument-matching.mdbasic-mocking.mddeep-mocking.mdindex.mdmatchers.mdutilities.md
tile.json

matchers.mddocs/

0

# Matchers

1

2

Extensive built-in matcher system with type-safe argument validation and support for custom matcher creation.

3

4

## Capabilities

5

6

### Matcher Base Class

7

8

Foundation class for creating custom matchers that integrate with Jest's asymmetric matcher system.

9

10

```typescript { .api }

11

/**

12

* Base class for creating custom matchers

13

*/

14

class Matcher<T> implements MatcherLike<T> {

15

$$typeof: symbol;

16

inverse?: boolean;

17

18

/**

19

* Creates a new matcher instance

20

* @param asymmetricMatch - Function that performs the actual matching logic

21

* @param description - Human-readable description of the matcher

22

*/

23

constructor(

24

readonly asymmetricMatch: MatcherFn<T>,

25

private readonly description: string

26

);

27

28

/** Returns string representation of the matcher */

29

toString(): string;

30

31

/** Returns asymmetric matcher representation */

32

toAsymmetricMatcher(): string;

33

34

/** Returns expected type for Jest error messages */

35

getExpectedType(): string;

36

}

37

38

/**

39

* Function type for matcher predicate functions

40

*/

41

type MatcherFn<T> = (actualValue: T) => boolean;

42

```

43

44

### Built-in Type Matchers

45

46

Matchers for validating basic JavaScript types with full type safety.

47

48

```typescript { .api }

49

/** Matches any value of any type */

50

const any: MatcherCreator<any>;

51

52

/** Matches any boolean value (true or false) */

53

const anyBoolean: MatcherCreator<boolean>;

54

55

/** Matches any string value including empty strings */

56

const anyString: MatcherCreator<string>;

57

58

/** Matches any number that is not NaN */

59

const anyNumber: MatcherCreator<number>;

60

61

/** Matches any function */

62

const anyFunction: MatcherCreator<Function>;

63

64

/** Matches any symbol */

65

const anySymbol: MatcherCreator<Symbol>;

66

67

/** Matches any non-null object */

68

const anyObject: MatcherCreator<any>;

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import { mock, any, anyString, anyNumber, anyBoolean } from "jest-mock-extended";

75

76

interface Calculator {

77

add: (a: number, b: number) => number;

78

concat: (str1: string, str2: string) => string;

79

compare: (val1: any, val2: any) => boolean;

80

}

81

82

const calc = mock<Calculator>();

83

84

// Type-specific matching

85

calc.add.calledWith(anyNumber(), anyNumber()).mockReturnValue(42);

86

calc.concat.calledWith(anyString(), anyString()).mockReturnValue("result");

87

calc.compare.calledWith(any(), any()).mockReturnValue(anyBoolean());

88

89

// Test calls

90

expect(calc.add(5, 10)).toBe(42);

91

expect(calc.concat("hello", "world")).toBe("result");

92

expect(typeof calc.compare("a", 1)).toBe("boolean");

93

```

94

95

### Collection Matchers

96

97

Matchers for validating arrays, maps, sets, and other collection types.

98

99

```typescript { .api }

100

/** Matches any array */

101

const anyArray: MatcherCreator<any[]>;

102

103

/** Matches any Map instance */

104

const anyMap: MatcherCreator<Map<any, any>>;

105

106

/** Matches any Set instance */

107

const anySet: MatcherCreator<Set<any>>;

108

109

/**

110

* Matches instances of a specific class

111

* @param clazz - Constructor function to match against

112

*/

113

const isA: MatcherCreator<any>;

114

```

115

116

**Usage Examples:**

117

118

```typescript

119

import { mock, anyArray, anyMap, anySet, isA } from "jest-mock-extended";

120

121

class UserModel {

122

constructor(public id: string, public name: string) {}

123

}

124

125

interface DataService {

126

processArray: (items: any[]) => void;

127

processMap: (data: Map<string, any>) => void;

128

processSet: (unique: Set<string>) => void;

129

processUser: (user: UserModel) => void;

130

}

131

132

const service = mock<DataService>();

133

134

// Collection type matching

135

service.processArray.calledWith(anyArray()).mockReturnValue(undefined);

136

service.processMap.calledWith(anyMap()).mockReturnValue(undefined);

137

service.processSet.calledWith(anySet()).mockReturnValue(undefined);

138

139

// Class instance matching

140

service.processUser.calledWith(isA(UserModel)).mockReturnValue(undefined);

141

142

// Test with actual instances

143

service.processArray([1, 2, 3]);

144

service.processMap(new Map([["key", "value"]]));

145

service.processSet(new Set(["a", "b", "c"]));

146

service.processUser(new UserModel("123", "John"));

147

```

148

149

### Content Matchers

150

151

Matchers for validating the contents of collections and objects.

152

153

```typescript { .api }

154

/**

155

* Checks if array includes the specified value

156

* @param arrayVal - Value that should be present in the array

157

*/

158

const arrayIncludes: MatcherCreator<any[], any>;

159

160

/**

161

* Checks if Set contains the specified value

162

* @param setVal - Value that should be present in the Set

163

*/

164

const setHas: MatcherCreator<Set<any>, any>;

165

166

/**

167

* Checks if Map contains the specified key

168

* @param mapKey - Key that should be present in the Map

169

*/

170

const mapHas: MatcherCreator<Map<any, any>, any>;

171

172

/**

173

* Checks if object contains the specified key

174

* @param key - Property name that should exist on the object

175

*/

176

const objectContainsKey: MatcherCreator<any, string>;

177

178

/**

179

* Checks if object contains the specified value

180

* @param value - Value that should be present in object's values

181

*/

182

const objectContainsValue: MatcherCreator<any>;

183

```

184

185

**Usage Examples:**

186

187

```typescript

188

import {

189

mock,

190

arrayIncludes,

191

setHas,

192

mapHas,

193

objectContainsKey,

194

objectContainsValue

195

} from "jest-mock-extended";

196

197

interface SearchService {

198

searchInArray: (items: string[], query: string) => boolean;

199

searchInSet: (items: Set<string>, query: string) => boolean;

200

searchInMap: (data: Map<string, any>, key: string) => boolean;

201

searchInObject: (obj: any, criteria: any) => boolean;

202

}

203

204

const search = mock<SearchService>();

205

206

// Content validation

207

search.searchInArray

208

.calledWith(arrayIncludes("target"), "target")

209

.mockReturnValue(true);

210

211

search.searchInSet

212

.calledWith(setHas("item"), "item")

213

.mockReturnValue(true);

214

215

search.searchInMap

216

.calledWith(mapHas("key"), "key")

217

.mockReturnValue(true);

218

219

search.searchInObject

220

.calledWith(objectContainsKey("name"), "name")

221

.mockReturnValue(true);

222

223

search.searchInObject

224

.calledWith(objectContainsValue("John"), "John")

225

.mockReturnValue(true);

226

227

// Test with matching content

228

expect(search.searchInArray(["a", "target", "c"], "target")).toBe(true);

229

expect(search.searchInSet(new Set(["a", "item", "c"]), "item")).toBe(true);

230

expect(search.searchInMap(new Map([["key", "value"]]), "key")).toBe(true);

231

expect(search.searchInObject({ name: "John", age: 25 }, "name")).toBe(true);

232

expect(search.searchInObject({ name: "John", age: 25 }, "John")).toBe(true);

233

```

234

235

### Null/Undefined Matchers

236

237

Matchers for validating null, undefined, and empty values.

238

239

```typescript { .api }

240

/** Matches values that are not null */

241

const notNull: MatcherCreator<any>;

242

243

/** Matches values that are not undefined */

244

const notUndefined: MatcherCreator<any>;

245

246

/** Matches values that are not null, undefined, or empty string */

247

const notEmpty: MatcherCreator<any>;

248

```

249

250

**Usage Examples:**

251

252

```typescript

253

import { mock, notNull, notUndefined, notEmpty } from "jest-mock-extended";

254

255

interface ValidationService {

256

validateRequired: (value: any) => boolean;

257

validateOptional: (value: any) => boolean;

258

validateNonEmpty: (value: any) => boolean;

259

}

260

261

const validator = mock<ValidationService>();

262

263

// Null/undefined validation

264

validator.validateRequired.calledWith(notNull()).mockReturnValue(true);

265

validator.validateOptional.calledWith(notUndefined()).mockReturnValue(true);

266

validator.validateNonEmpty.calledWith(notEmpty()).mockReturnValue(true);

267

268

// Test validation

269

expect(validator.validateRequired("value")).toBe(true);

270

expect(validator.validateOptional(0)).toBe(true);

271

expect(validator.validateNonEmpty("text")).toBe(true);

272

273

// These would not match the expectations

274

// validator.validateRequired(null); // Would not match notNull()

275

// validator.validateOptional(undefined); // Would not match notUndefined()

276

// validator.validateNonEmpty(""); // Would not match notEmpty()

277

```

278

279

### Argument Captor

280

281

Special matcher for capturing argument values during mock function calls.

282

283

```typescript { .api }

284

/**

285

* Captor matcher for capturing argument values

286

*/

287

class CaptorMatcher<T> {

288

$$typeof: symbol;

289

readonly asymmetricMatch: MatcherFn<T>;

290

/** Last captured value */

291

readonly value: T;

292

/** All captured values in order */

293

readonly values: T[];

294

295

constructor();

296

getExpectedType(): string;

297

toString(): string;

298

toAsymmetricMatcher(): string;

299

}

300

301

/**

302

* Creates an argument captor for capturing call arguments

303

* @returns Captor matcher instance

304

*/

305

const captor: <T = any>() => CaptorMatcher<T>;

306

```

307

308

**Usage Examples:**

309

310

```typescript

311

import { mock, captor } from "jest-mock-extended";

312

313

interface EventLogger {

314

logEvent: (event: string, data: any, timestamp: number) => void;

315

logError: (error: Error, context: string) => void;

316

}

317

318

const logger = mock<EventLogger>();

319

320

// Create captors for different argument types

321

const eventCaptor = captor<string>();

322

const dataCaptor = captor<any>();

323

const timestampCaptor = captor<number>();

324

325

// Set up captor expectations

326

logger.logEvent

327

.calledWith(eventCaptor, dataCaptor, timestampCaptor)

328

.mockReturnValue(undefined);

329

330

// Make calls that will be captured

331

logger.logEvent("user:login", { userId: "123" }, Date.now());

332

logger.logEvent("user:logout", { userId: "123", reason: "timeout" }, Date.now());

333

334

// Access captured values

335

expect(eventCaptor.value).toBe("user:logout"); // Last captured value

336

expect(eventCaptor.values).toEqual(["user:login", "user:logout"]); // All values

337

338

expect(dataCaptor.values[0]).toEqual({ userId: "123" });

339

expect(dataCaptor.values[1]).toEqual({ userId: "123", reason: "timeout" });

340

341

expect(typeof timestampCaptor.value).toBe("number");

342

```

343

344

### Custom Matcher Creation

345

346

Create custom matchers with specific validation logic.

347

348

```typescript { .api }

349

/**

350

* Creates a custom matcher from a predicate function

351

* @param matcher - Function that returns true for matching values

352

* @returns Custom matcher instance

353

*/

354

const matches: <T = any>(matcher: MatcherFn<T>) => Matcher<T>;

355

356

/**

357

* Interface for creating reusable matcher functions

358

*/

359

interface MatcherCreator<T, E = T> {

360

(expectedValue?: E): Matcher<T>;

361

}

362

```

363

364

**Usage Examples:**

365

366

```typescript

367

import { mock, matches, MatcherCreator, Matcher } from "jest-mock-extended";

368

369

interface StringValidator {

370

validateEmail: (email: string) => boolean;

371

validatePhone: (phone: string) => boolean;

372

validateLength: (text: string, min: number, max: number) => boolean;

373

}

374

375

const validator = mock<StringValidator>();

376

377

// Simple custom matcher

378

const isValidEmail = matches<string>((email) =>

379

/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)

380

);

381

382

validator.validateEmail.calledWith(isValidEmail).mockReturnValue(true);

383

384

// Reusable custom matcher creator

385

const hasLength: MatcherCreator<string, number> = (expectedLength) =>

386

new Matcher(

387

(actualValue) => actualValue.length === expectedLength,

388

`hasLength(${expectedLength})`

389

);

390

391

const isLongerThan: MatcherCreator<string, number> = (minLength) =>

392

new Matcher(

393

(actualValue) => actualValue.length > minLength,

394

`isLongerThan(${minLength})`

395

);

396

397

// Use custom matchers

398

validator.validateLength

399

.calledWith(hasLength(10), 5, 15)

400

.mockReturnValue(true);

401

402

validator.validatePhone

403

.calledWith(isLongerThan(9))

404

.mockReturnValue(true);

405

406

// Test with custom matchers

407

expect(validator.validateEmail("user@example.com")).toBe(true);

408

expect(validator.validateLength("1234567890", 5, 15)).toBe(true);

409

expect(validator.validatePhone("1234567890")).toBe(true);

410

```