or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

custom-extensions.mdenvironment-config.mdexpectations-matchers.mdindex.mdspy-system.mdtest-organization.mdtest-utilities.md
tile.json

test-utilities.mddocs/

0

# Test Utilities

1

2

Additional testing utilities including asymmetric equality testers, clock mocking, and helper functions for complex testing scenarios. These tools help handle edge cases and create more flexible test assertions.

3

4

## Capabilities

5

6

### Asymmetric Equality Testers

7

8

Special matcher objects that provide flexible matching for complex assertions.

9

10

```javascript { .api }

11

/**

12

* Match any instance of the given constructor

13

* @param constructor - Constructor function to match against

14

* @returns AsymmetricEqualityTester

15

*/

16

jasmine.any(constructor: Function): AsymmetricEqualityTester;

17

18

/**

19

* Match any non-null, non-undefined value

20

* @returns AsymmetricEqualityTester

21

*/

22

jasmine.anything(): AsymmetricEqualityTester;

23

24

/**

25

* Match objects that contain at least the provided properties

26

* @param sample - Object with properties to match

27

* @returns AsymmetricEqualityTester

28

*/

29

jasmine.objectContaining(sample: object): AsymmetricEqualityTester;

30

31

/**

32

* Match arrays that contain at least the provided elements

33

* @param sample - Array with elements to match

34

* @returns AsymmetricEqualityTester

35

*/

36

jasmine.arrayContaining(sample: any[]): AsymmetricEqualityTester;

37

38

/**

39

* Match arrays with exactly the provided contents (order independent)

40

* @param sample - Array with exact contents to match

41

* @returns AsymmetricEqualityTester

42

*/

43

jasmine.arrayWithExactContents(sample: any[]): AsymmetricEqualityTester;

44

45

/**

46

* Match Set objects that contain at least the provided values

47

* @param sample - Set with values to match

48

* @returns AsymmetricEqualityTester

49

*/

50

jasmine.setContaining(sample: Set<any>): AsymmetricEqualityTester;

51

52

/**

53

* Match Map objects that contain at least the provided key-value pairs

54

* @param sample - Map with entries to match

55

* @returns AsymmetricEqualityTester

56

*/

57

jasmine.mapContaining(sample: Map<any, any>): AsymmetricEqualityTester;

58

```

59

60

**Usage Examples:**

61

62

```javascript

63

// Match any string

64

expect('hello world').toEqual(jasmine.any(String));

65

expect(42).not.toEqual(jasmine.any(String));

66

67

// Match any number

68

expect(123).toEqual(jasmine.any(Number));

69

expect(new Date()).toEqual(jasmine.any(Date));

70

71

// Match anything non-null/undefined

72

expect('anything').toEqual(jasmine.anything());

73

expect(0).toEqual(jasmine.anything());

74

expect(false).toEqual(jasmine.anything());

75

expect(null).not.toEqual(jasmine.anything());

76

77

// Partial object matching

78

expect({

79

id: 123,

80

name: 'Alice',

81

email: 'alice@example.com',

82

metadata: { created: '2023-01-01' }

83

}).toEqual(jasmine.objectContaining({

84

name: 'Alice',

85

metadata: jasmine.objectContaining({ created: jasmine.any(String) })

86

}));

87

88

// Partial array matching

89

expect(['apple', 'banana', 'cherry', 'date']).toEqual(

90

jasmine.arrayContaining(['banana', 'cherry'])

91

);

92

93

// Exact array contents (order doesn't matter)

94

expect([3, 1, 2]).toEqual(jasmine.arrayWithExactContents([1, 2, 3]));

95

96

// Set matching

97

const userRoles = new Set(['admin', 'user', 'moderator']);

98

expect(userRoles).toEqual(jasmine.setContaining(new Set(['admin', 'user'])));

99

100

// Map matching

101

const userPrefs = new Map([

102

['theme', 'dark'],

103

['language', 'en'],

104

['notifications', true]

105

]);

106

expect(userPrefs).toEqual(jasmine.mapContaining(new Map([

107

['theme', 'dark'],

108

['notifications', jasmine.any(Boolean)]

109

])));

110

```

111

112

### String Matching Utilities

113

114

Asymmetric equality testers for string pattern matching.

115

116

```javascript { .api }

117

/**

118

* Match strings that match the given pattern

119

* @param pattern - RegExp or string pattern to match

120

* @returns AsymmetricEqualityTester

121

*/

122

jasmine.stringMatching(pattern: string | RegExp): AsymmetricEqualityTester;

123

124

/**

125

* Match strings that contain the given substring

126

* @param substring - Substring to search for

127

* @returns AsymmetricEqualityTester

128

*/

129

jasmine.stringContaining(substring: string): AsymmetricEqualityTester;

130

```

131

132

**Usage Examples:**

133

134

```javascript

135

// Pattern matching

136

expect('hello@example.com').toEqual(jasmine.stringMatching(/\S+@\S+\.\S+/));

137

expect('user123').toEqual(jasmine.stringMatching(/user\d+/));

138

expect('Product ABC-123').toEqual(jasmine.stringMatching('ABC'));

139

140

// Substring matching

141

expect('The quick brown fox').toEqual(jasmine.stringContaining('quick'));

142

expect('Error: File not found').toEqual(jasmine.stringContaining('Error:'));

143

144

// In object matching

145

expect({

146

id: 'user-456',

147

email: 'bob@company.com',

148

message: 'Welcome to our service!'

149

}).toEqual({

150

id: jasmine.stringMatching(/user-\d+/),

151

email: jasmine.stringContaining('@company.com'),

152

message: jasmine.stringContaining('Welcome')

153

});

154

```

155

156

### Truthiness and Collection Utilities

157

158

Asymmetric equality testers for common value patterns.

159

160

```javascript { .api }

161

/**

162

* Match any truthy value

163

* @returns AsymmetricEqualityTester

164

*/

165

jasmine.truthy(): AsymmetricEqualityTester;

166

167

/**

168

* Match any falsy value

169

* @returns AsymmetricEqualityTester

170

*/

171

jasmine.falsy(): AsymmetricEqualityTester;

172

173

/**

174

* Match empty collections or strings

175

* @returns AsymmetricEqualityTester

176

*/

177

jasmine.empty(): AsymmetricEqualityTester;

178

179

/**

180

* Match non-empty collections or strings

181

* @returns AsymmetricEqualityTester

182

*/

183

jasmine.notEmpty(): AsymmetricEqualityTester;

184

185

/**

186

* Match using reference equality (===)

187

* @param expected - Value to compare by reference

188

* @returns AsymmetricEqualityTester

189

*/

190

jasmine.is(expected: any): AsymmetricEqualityTester;

191

```

192

193

**Usage Examples:**

194

195

```javascript

196

// Truthiness matching

197

expect(1).toEqual(jasmine.truthy());

198

expect('hello').toEqual(jasmine.truthy());

199

expect(true).toEqual(jasmine.truthy());

200

expect(0).not.toEqual(jasmine.truthy());

201

202

expect(false).toEqual(jasmine.falsy());

203

expect(0).toEqual(jasmine.falsy());

204

expect('').toEqual(jasmine.falsy());

205

expect(null).toEqual(jasmine.falsy());

206

207

// Collection matching

208

expect([]).toEqual(jasmine.empty());

209

expect('').toEqual(jasmine.empty());

210

expect(new Set()).toEqual(jasmine.empty());

211

212

expect([1, 2, 3]).toEqual(jasmine.notEmpty());

213

expect('hello').toEqual(jasmine.notEmpty());

214

expect(new Map([['key', 'value']])).toEqual(jasmine.notEmpty());

215

216

// Reference equality

217

const obj = { name: 'test' };

218

expect(obj).toEqual(jasmine.is(obj));

219

expect({ name: 'test' }).not.toEqual(jasmine.is(obj)); // Different objects

220

```

221

222

### Clock Mocking

223

224

Functions for mocking JavaScript's timer functions and Date constructor.

225

226

```javascript { .api }

227

/**

228

* Get the mock clock instance

229

* @returns Clock instance for time manipulation

230

*/

231

jasmine.clock(): Clock;

232

233

interface Clock {

234

/**

235

* Install the mock clock, replacing native timer functions

236

*/

237

install(): void;

238

239

/**

240

* Uninstall the mock clock, restoring native timer functions

241

*/

242

uninstall(): void;

243

244

/**

245

* Advance the mock clock by the specified number of milliseconds

246

* @param milliseconds - Time to advance

247

*/

248

tick(milliseconds: number): void;

249

250

/**

251

* Set the mock current date

252

* @param date - Date to set as current time

253

*/

254

mockDate(date?: Date): void;

255

256

/**

257

* Get the current mock time

258

* @returns Current mock time as Date

259

*/

260

mockDate(): Date;

261

}

262

```

263

264

**Usage Examples:**

265

266

```javascript

267

describe('Timer functions', () => {

268

beforeEach(() => {

269

jasmine.clock().install();

270

});

271

272

afterEach(() => {

273

jasmine.clock().uninstall();

274

});

275

276

it('should handle setTimeout', () => {

277

let callback = jasmine.createSpy('callback');

278

279

setTimeout(callback, 1000);

280

expect(callback).not.toHaveBeenCalled();

281

282

jasmine.clock().tick(1000);

283

expect(callback).toHaveBeenCalled();

284

});

285

286

it('should handle setInterval', () => {

287

let callback = jasmine.createSpy('callback');

288

289

setInterval(callback, 500);

290

291

jasmine.clock().tick(1500);

292

expect(callback).toHaveBeenCalledTimes(3);

293

});

294

295

it('should mock Date', () => {

296

const mockDate = new Date(2023, 0, 1); // January 1, 2023

297

jasmine.clock().mockDate(mockDate);

298

299

expect(new Date()).toEqual(mockDate);

300

expect(Date.now()).toBe(mockDate.getTime());

301

302

// Advance time

303

jasmine.clock().tick(60000); // 1 minute

304

expect(new Date().getTime()).toBe(mockDate.getTime() + 60000);

305

});

306

307

it('should handle async operations with timers', async () => {

308

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

309

310

const startTime = Date.now();

311

const promise = delay(2000).then(() => Date.now() - startTime);

312

313

jasmine.clock().tick(2000);

314

const elapsed = await promise;

315

316

expect(elapsed).toBe(2000);

317

});

318

});

319

```

320

321

### Pretty Printing Utilities

322

323

Functions for formatting objects in test output and error messages.

324

325

```javascript { .api }

326

/**

327

* Pretty print any value for display in test output

328

* @param object - Value to format

329

* @returns Formatted string representation

330

*/

331

jasmine.pp(object: any): string;

332

333

/**

334

* Check if a value is undefined

335

* @param obj - Value to check

336

* @returns Whether value is undefined

337

*/

338

jasmine.isUndefined(obj: any): boolean;

339

340

/**

341

* Create a shallow clone of an object or array

342

* @param obj - Object or array to clone

343

* @returns Shallow copy of the input

344

*/

345

jasmine.clone(obj: any): any;

346

347

/**

348

* Clone function arguments into a regular array

349

* @param args - Arguments object to clone

350

* @returns Array containing the arguments

351

*/

352

jasmine.cloneArgs(args: IArguments): any[];

353

```

354

355

**Usage Examples:**

356

357

```javascript

358

// Pretty printing for custom error messages

359

const complexObject = {

360

users: [{ name: 'Alice' }, { name: 'Bob' }],

361

settings: { theme: 'dark', notifications: true }

362

};

363

364

console.log(jasmine.pp(complexObject));

365

// Output: Object({ users: [ Object({ name: 'Alice' }), Object({ name: 'Bob' }) ], settings: Object({ theme: 'dark', notifications: true }) })

366

367

// Utility functions

368

expect(jasmine.isUndefined(undefined)).toBe(true);

369

expect(jasmine.isUndefined(null)).toBe(false);

370

371

const original = { a: 1, b: [2, 3] };

372

const cloned = jasmine.clone(original);

373

cloned.a = 99;

374

expect(original.a).toBe(1); // Original unchanged

375

376

function testFunction() {

377

const argsArray = jasmine.cloneArgs(arguments);

378

expect(Array.isArray(argsArray)).toBe(true);

379

expect(argsArray).toEqual(['arg1', 'arg2']);

380

}

381

testFunction('arg1', 'arg2');

382

```

383

384

### Utility Helper Functions

385

386

Additional utility functions for testing scenarios.

387

388

```javascript { .api }

389

/**

390

* Get property descriptor from object or its prototype chain

391

* @param obj - Object to inspect

392

* @param prop - Property name

393

* @returns Property descriptor or undefined

394

*/

395

jasmine.getPropertyDescriptor(obj: any, prop: string): PropertyDescriptor | undefined;

396

397

/**

398

* Create a matcher that always fails (useful for testing)

399

* @param message - Optional failure message

400

* @returns Failed matcher result

401

*/

402

jasmine.createSpy.isSpy(obj: any): boolean;

403

```

404

405

**Usage Examples:**

406

407

```javascript

408

// Property descriptor inspection

409

const obj = {

410

get name() { return this._name; },

411

set name(value) { this._name = value; }

412

};

413

414

const descriptor = jasmine.getPropertyDescriptor(obj, 'name');

415

expect(descriptor.get).toBeDefined();

416

expect(descriptor.set).toBeDefined();

417

418

// Spy detection

419

const regularFunction = () => {};

420

const spy = jasmine.createSpy('testSpy');

421

422

expect(jasmine.createSpy.isSpy(regularFunction)).toBe(false);

423

expect(jasmine.createSpy.isSpy(spy)).toBe(true);

424

425

// This is useful for conditional spy setup

426

function maybeSpyOn(obj, method) {

427

if (!jasmine.createSpy.isSpy(obj[method])) {

428

spyOn(obj, method);

429

}

430

}

431

```

432

433

### Error Handling Utilities

434

435

Utilities for working with errors and exceptions in tests.

436

437

```javascript { .api }

438

/**

439

* Create an error with a specific message and stack trace

440

* Used internally by Jasmine for consistent error formatting

441

*/

442

jasmine.createError(message: string, stack?: string): Error;

443

444

/**

445

* Format error messages consistently

446

* Used by matchers for error reporting

447

*/

448

jasmine.formatErrorMsg(domain: string, usage: string): (msg: string) => string;

449

```

450

451

**Usage Examples:**

452

453

```javascript

454

// In custom matchers or test utilities

455

function validateInput(input) {

456

if (!input) {

457

throw jasmine.createError('Input is required');

458

}

459

return input.toUpperCase();

460

}

461

462

// Custom matcher using error formatting

463

jasmine.addMatchers({

464

toBeValidConfig: (util) => {

465

return {

466

compare: (actual) => {

467

const formatter = jasmine.formatErrorMsg('ConfigValidator', 'toBeValidConfig()');

468

469

if (typeof actual !== 'object') {

470

return {

471

pass: false,

472

message: formatter('Expected an object')

473

};

474

}

475

476

return { pass: true };

477

}

478

};

479

}

480

});

481

```

482

483

### Debug and Development Utilities

484

485

Utilities for debugging tests and working with Jasmine's internal functionality.

486

487

```javascript { .api }

488

/**

489

* Log a debug message that will be included in spec results if the spec fails

490

* @param message - Message to log for debugging

491

*/

492

jasmine.debugLog(message: string): void;

493

494

/**

495

* Check if a function is a Jasmine spy

496

* @param putativeSpy - Function to check

497

* @returns Whether the function is a spy

498

*/

499

jasmine.isSpy(putativeSpy: any): boolean;

500

501

/**

502

* Replace global error handling with a spy for testing uncaught exceptions

503

* @param fn - Async function to run with global error spy active

504

* @returns Promise that resolves when the function completes

505

*/

506

jasmine.spyOnGlobalErrorsAsync(fn: (globalErrorSpy: Spy) => Promise<void>): Promise<void>;

507

```

508

509

**Usage Examples:**

510

511

```javascript

512

describe('Debug utilities', () => {

513

it('should log debug messages on failure', () => {

514

jasmine.debugLog('Setting up test data');

515

const testData = { id: 1, name: 'test' };

516

517

jasmine.debugLog('Performing validation');

518

expect(testData.id).toBe(2); // This will fail

519

520

// Debug messages will appear in the failure output

521

});

522

523

it('should detect spies correctly', () => {

524

const regularFunction = () => 'result';

525

const spyFunction = jasmine.createSpy('testSpy');

526

527

expect(jasmine.isSpy(regularFunction)).toBe(false);

528

expect(jasmine.isSpy(spyFunction)).toBe(true);

529

530

// Useful for conditional logic

531

if (!jasmine.isSpy(regularFunction)) {

532

console.log('This is not a spy');

533

}

534

});

535

536

it('should spy on global errors', async () => {

537

await jasmine.spyOnGlobalErrorsAsync(async (globalErrorSpy) => {

538

// Trigger an uncaught exception

539

setTimeout(() => {

540

throw new Error('Test error');

541

}, 0);

542

543

// Wait for the error to be thrown

544

await new Promise(resolve => setTimeout(resolve, 10));

545

546

// Verify the error was caught by the spy

547

expect(globalErrorSpy).toHaveBeenCalledWith(jasmine.any(Error));

548

expect(globalErrorSpy.calls.argsFor(0)[0].message).toBe('Test error');

549

});

550

});

551

});

552

```

553

554

## Types

555

556

```javascript { .api }

557

interface AsymmetricEqualityTester {

558

asymmetricMatch(other: any, customTesters: EqualityTester[]): boolean;

559

jasmineToString(): string;

560

}

561

562

interface Clock {

563

install(): void;

564

uninstall(): void;

565

tick(milliseconds: number): void;

566

mockDate(date?: Date): void | Date;

567

}

568

569

interface EqualityTester {

570

(first: any, second: any): boolean | undefined;

571

}

572

```