or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md
tile.json

index.mddocs/

0

# jest-each

1

2

jest-each is a parameterized testing library that enables running the same test multiple times with different data sets. It provides two main approaches: array-based parameterization and tagged template literal syntax with readable table formatting. The library integrates seamlessly with all Jest test functions and modifiers.

3

4

## Package Information

5

6

- **Package Name**: jest-each

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install jest-each`

10

11

## Core Imports

12

13

```typescript

14

import each from "jest-each";

15

```

16

17

For CommonJS:

18

19

```javascript

20

const each = require("jest-each").default;

21

```

22

23

Named imports:

24

25

```typescript

26

import each, { bind } from "jest-each";

27

```

28

29

## Basic Usage

30

31

### Array Format

32

33

```typescript

34

import each from "jest-each";

35

36

// Array of arrays

37

each([

38

[1, 2, 3],

39

[4, 5, 9],

40

[7, 8, 15]

41

]).test('adds %i + %i to equal %i', (a, b, expected) => {

42

expect(a + b).toBe(expected);

43

});

44

45

// Array of objects

46

each([

47

{ name: 'John', age: 25 },

48

{ name: 'Jane', age: 30 }

49

]).test('user $name is $age years old', ({ name, age }) => {

50

expect(typeof name).toBe('string');

51

expect(typeof age).toBe('number');

52

});

53

```

54

55

### Template Literal Format

56

57

```typescript

58

each`

59

a | b | expected

60

${1} | ${2} | ${3}

61

${4} | ${5} | ${9}

62

${7} | ${8} | ${15}

63

`.test('adds $a + $b to equal $expected', ({ a, b, expected }) => {

64

expect(a + b).toBe(expected);

65

});

66

```

67

68

## Capabilities

69

70

### Main Each Function

71

72

Creates parameterized test functions that work with all Jest test methods and modifiers.

73

74

```typescript { .api }

75

/**

76

* Main function to create parameterized tests using arrays or template literals

77

* @param table - Test data as array of arrays, array of objects, or template literal

78

* @param data - Additional template data when using template literals

79

* @returns Object with Jest test methods (test, it, describe, etc.)

80

*/

81

function each(table: EachTable, ...data: TemplateData): {

82

test: EachTestFunction;

83

it: EachTestFunction;

84

describe: EachDescribeFunction;

85

xit: EachTestFunction;

86

fit: EachTestFunction;

87

xtest: EachTestFunction;

88

fdescribe: EachDescribeFunction;

89

xdescribe: EachDescribeFunction;

90

};

91

92

type EachTable = ArrayTable | TemplateTable;

93

type ArrayTable = Table | Row;

94

type Table = ReadonlyArray<Row>;

95

type Row = ReadonlyArray<unknown>;

96

type TemplateTable = TemplateStringsArray;

97

type TemplateData = ReadonlyArray<unknown>;

98

```

99

100

### With Global Context

101

102

Creates each function bound to a specific global context for custom Jest environments.

103

104

```typescript { .api }

105

/**

106

* Creates each function bound to specific global context

107

* @param g - Global Jest context object

108

* @returns Function that accepts table and returns test methods

109

*/

110

each.withGlobal: (g: Global) => (table: EachTable, ...data: TemplateData) => ReturnType<typeof each>;

111

112

interface Global {

113

test: TestFunction;

114

it: TestFunction;

115

describe: DescribeFunction;

116

xit: TestFunction;

117

fit: TestFunction;

118

xtest: TestFunction;

119

fdescribe: DescribeFunction;

120

xdescribe: DescribeFunction;

121

}

122

```

123

124

### Test Function Interface

125

126

All returned test functions support Jest's standard interface with modifiers.

127

128

```typescript { .api }

129

interface EachTestFunction {

130

/**

131

* Creates a parameterized test

132

* @param title - Test title with optional placeholders

133

* @param testFn - Test function receiving parameters from data table

134

* @param timeout - Optional timeout in milliseconds

135

*/

136

(title: string, testFn: EachTestFn<TestFn>, timeout?: number): void;

137

138

/** Run only this test */

139

only: EachTestFunction;

140

141

/** Skip this test */

142

skip: EachTestFunction;

143

144

/** Concurrent test execution */

145

concurrent: EachConcurrentTestFunction;

146

}

147

148

interface EachConcurrentTestFunction {

149

(title: string, testFn: EachTestFn<ConcurrentTestFn>, timeout?: number): void;

150

only: EachConcurrentTestFunction;

151

skip: EachConcurrentTestFunction;

152

}

153

154

interface EachDescribeFunction {

155

/**

156

* Creates a parameterized describe block

157

* @param title - Describe title with optional placeholders

158

* @param suiteFn - Suite function receiving parameters from data table

159

* @param timeout - Optional timeout in milliseconds

160

*/

161

(title: string, suiteFn: EachTestFn<BlockFn>, timeout?: number): void;

162

163

/** Run only this describe block */

164

only: EachDescribeFunction;

165

166

/** Skip this describe block */

167

skip: EachDescribeFunction;

168

}

169

170

type EachTestFn<T extends TestCallback> = (...args: ReadonlyArray<any>) => ReturnType<T>;

171

```

172

173

### Bind Function (Advanced)

174

175

Core binding function for creating custom parameterized test functions.

176

177

```typescript { .api }

178

/**

179

* Creates parameterized test functions by binding to Jest global methods

180

* @param cb - Global Jest callback function to bind to

181

* @param supportsDone - Whether the callback supports done callback (default: true)

182

* @param needsEachError - Whether to pass error context (default: false)

183

* @returns Function that accepts table data and returns bound test function

184

*/

185

function bind<EachCallback extends TestCallback>(

186

cb: GlobalCallback,

187

supportsDone?: boolean,

188

needsEachError?: boolean

189

): EachTestFn<any>;

190

191

type GlobalCallback = (

192

testName: string,

193

fn: ConcurrentTestFn,

194

timeout?: number,

195

eachError?: Error

196

) => void;

197

198

type TestCallback = BlockFn | TestFn | ConcurrentTestFn;

199

```

200

201

## Title Formatting and Interpolation

202

203

### Printf-Style Placeholders

204

205

jest-each supports printf-style placeholders for automatic value formatting in test titles:

206

207

- `%s` - String formatting

208

- `%d`, `%i` - Integer formatting

209

- `%f` - Float formatting

210

- `%j` - JSON formatting

211

- `%o`, `%O` - Object formatting

212

- `%p` - Pretty-print formatting (with depth control)

213

- `%#` - Zero-based index placeholder

214

- `%$` - One-based index placeholder

215

216

```typescript

217

each([

218

[1, 2, 3],

219

[4, 5, 9]

220

]).test('test %# adds %i + %i to equal %i', (a, b, expected) => {

221

expect(a + b).toBe(expected);

222

});

223

// Results in: "test 0 adds 1 + 2 to equal 3", "test 1 adds 4 + 5 to equal 9"

224

```

225

226

### Template Variable Interpolation

227

228

When using template literals or object arrays, variables can be interpolated using `$variable` syntax:

229

230

```typescript

231

each`

232

name | age | status

233

${'John'} | ${25} | ${'active'}

234

${'Jane'} | ${30} | ${'inactive'}

235

`.test('user $name (age $age) is $status', ({ name, age, status }) => {

236

expect(typeof name).toBe('string');

237

});

238

```

239

240

### Object Property Access

241

242

Template variables support deep property access using dot notation:

243

244

```typescript

245

each([

246

{ user: { profile: { name: 'John' }, age: 25 } },

247

{ user: { profile: { name: 'Jane' }, age: 30 } }

248

]).test('user $user.profile.name is $user.age years old', ({ user }) => {

249

expect(user).toBeDefined();

250

});

251

```

252

253

## Data Table Formats

254

255

### Array of Arrays

256

257

Most basic format for simple parameter lists:

258

259

```typescript

260

each([

261

[1, 2, 3], // First test case

262

[4, 5, 9], // Second test case

263

[7, 8, 15] // Third test case

264

]).test('adds %i + %i to equal %i', (a, b, expected) => {

265

expect(a + b).toBe(expected);

266

});

267

```

268

269

### Array of Objects

270

271

Provides named parameters for better readability:

272

273

```typescript

274

each([

275

{ input: 'hello', expected: 5 },

276

{ input: 'world', expected: 5 },

277

{ input: '', expected: 0 }

278

]).test('$input has length $expected', ({ input, expected }) => {

279

expect(input.length).toBe(expected);

280

});

281

```

282

283

### Single Column Arrays

284

285

For tests with single parameters:

286

287

```typescript

288

each([1, 2, 3, 4, 5]).test('number %i is defined', (num) => {

289

expect(num).toBeDefined();

290

expect(typeof num).toBe('number');

291

});

292

```

293

294

### Template Literals

295

296

Tabular format with column headers for maximum readability:

297

298

```typescript

299

each`

300

operation | a | b | expected

301

${'add'} | ${1} | ${2} | ${3}

302

${'sub'} | ${5} | ${3} | ${2}

303

${'mul'} | ${3} | ${4} | ${12}

304

`.test('$operation: $a and $b equals $expected', ({ operation, a, b, expected }) => {

305

switch (operation) {

306

case 'add':

307

expect(a + b).toBe(expected);

308

break;

309

case 'sub':

310

expect(a - b).toBe(expected);

311

break;

312

case 'mul':

313

expect(a * b).toBe(expected);

314

break;

315

}

316

});

317

```

318

319

## Jest Integration

320

321

### Test Methods

322

323

All Jest test methods are supported:

324

325

```typescript

326

each(testData).test('test title', testFn); // Standard test

327

each(testData).test.only('test title', testFn); // Run only this test

328

each(testData).test.skip('test title', testFn); // Skip this test

329

each(testData).test.concurrent('test title', testFn); // Concurrent execution

330

331

each(testData).it('test title', testFn); // Alias for test

332

each(testData).xit('test title', testFn); // Skip test (alias)

333

each(testData).fit('test title', testFn); // Focus test (alias)

334

each(testData).xtest('test title', testFn); // Skip test (alias)

335

```

336

337

### Describe Blocks

338

339

Parameterized describe blocks for grouping related tests:

340

341

```typescript

342

each([

343

{ type: 'user', endpoint: '/users' },

344

{ type: 'post', endpoint: '/posts' }

345

]).describe('$type API', ({ type, endpoint }) => {

346

test('should fetch all items', async () => {

347

const response = await api.get(endpoint);

348

expect(response.status).toBe(200);

349

});

350

351

test('should create new item', async () => {

352

const response = await api.post(endpoint, { name: 'Test' });

353

expect(response.status).toBe(201);

354

});

355

});

356

```

357

358

### Concurrent Test Execution

359

360

Support for concurrent test execution with proper typing:

361

362

```typescript

363

each([

364

{ url: '/api/users/1' },

365

{ url: '/api/users/2' },

366

{ url: '/api/users/3' }

367

]).test.concurrent('fetches data from $url', async ({ url }) => {

368

const response = await fetch(url);

369

expect(response.status).toBe(200);

370

});

371

```

372

373

### Done Callback Support

374

375

Automatic detection and support for Jest's done callback:

376

377

```typescript

378

each([

379

{ delay: 100 },

380

{ delay: 200 }

381

]).test('async test with $delay ms delay', ({ delay }, done) => {

382

setTimeout(() => {

383

expect(delay).toBeGreaterThan(0);

384

done();

385

}, delay);

386

});

387

```

388

389

## Error Handling and Validation

390

391

### Table Validation

392

393

Comprehensive validation with descriptive error messages:

394

395

```typescript

396

// Invalid: empty array

397

each([]).test('title', () => {}); // Throws: "Error: .each called with an empty Array of table data."

398

399

// Invalid: tagged template with no data

400

each``.test('title', () => {}); // Throws: "Error: .each called with an empty Tagged Template Literal of table data."

401

402

// Invalid: not an array or template literal

403

each("invalid").test('title', () => {}); // Throws: ".each must be called with an Array or Tagged Template Literal."

404

```

405

406

### Template Table Validation

407

408

Validation for template literal format and argument count:

409

410

```typescript

411

// Invalid: mismatched arguments

412

each`

413

a | b

414

${1} | ${2}

415

${3} // Missing second argument

416

`.test('title', () => {}); // Throws error with missing argument details

417

```

418

419

## Types

420

421

```typescript { .api }

422

// Core types for data tables

423

type Col = unknown;

424

type Row = ReadonlyArray<Col>;

425

type Table = ReadonlyArray<Row>;

426

type ArrayTable = Table | Row;

427

type TemplateTable = TemplateStringsArray;

428

type TemplateData = ReadonlyArray<unknown>;

429

type EachTable = ArrayTable | TemplateTable;

430

431

// Test function types

432

type ValidTestReturnValues = void | undefined;

433

type TestReturnValue = ValidTestReturnValues | Promise<unknown>;

434

type DoneFn = (reason?: string | Error) => void;

435

436

type TestFn = PromiseReturningTestFn | GeneratorReturningTestFn | DoneTakingTestFn;

437

type PromiseReturningTestFn = (this: TestContext) => TestReturnValue;

438

type DoneTakingTestFn = (this: TestContext, done: DoneFn) => ValidTestReturnValues;

439

type ConcurrentTestFn = () => Promise<unknown>;

440

type BlockFn = () => void;

441

442

// Generic test function type for parameterized tests

443

type EachTestFn<EachCallback extends TestCallback> = (

444

...args: ReadonlyArray<any>

445

) => ReturnType<EachCallback>;

446

447

// Template and interpolation types

448

type Template = Record<string, unknown>;

449

type Templates = Array<Template>;

450

type Headings = Array<string>;

451

452

// Internal test case representation

453

type EachTests = ReadonlyArray<{

454

title: string;

455

arguments: ReadonlyArray<unknown>;

456

}>;

457

```