or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-assertions.mdconfiguration.mdcontainment-assertions.mderror-assertions.mdindex.mdnumber-assertions.mdpattern-matching.mdpromise-assertions.mdproperty-assertions.mdstring-assertions.mdtype-assertions.md

containment-assertions.mddocs/

0

# Collection and Containment Assertions

1

2

Methods for testing array and object containment, deep equality, and collection membership.

3

4

## Deep Equality Testing

5

6

### eql()

7

8

Test for deep equality, recursively comparing object and array contents.

9

10

```javascript { .api }

11

/**

12

* Assert deep equality, comparing object contents recursively

13

* @param expected - The expected value or object

14

* @param description - Optional error message

15

* @returns This assertion for chaining

16

*/

17

eql(expected: any, description?: string): Assertion;

18

```

19

20

**Usage:**

21

```javascript

22

import should from 'should';

23

24

// Object deep equality

25

const user1 = { name: 'john', age: 30 };

26

const user2 = { name: 'john', age: 30 };

27

user1.should.eql(user2); // Different objects, same content

28

29

// Array deep equality

30

[1, 2, 3].should.eql([1, 2, 3]);

31

['a', 'b'].should.eql(['a', 'b']);

32

33

// Nested objects

34

const config1 = {

35

database: { host: 'localhost', port: 5432 },

36

cache: { enabled: true }

37

};

38

const config2 = {

39

database: { host: 'localhost', port: 5432 },

40

cache: { enabled: true }

41

};

42

config1.should.eql(config2);

43

44

// With description

45

const actual = { status: 'success', data: [] };

46

const expected = { status: 'success', data: [] };

47

actual.should.eql(expected, 'Response should match expected format');

48

```

49

50

### deepEqual()

51

52

Alias for `eql()` - deep equality comparison.

53

54

```javascript { .api }

55

/**

56

* Assert deep equality - alias for eql()

57

* @param expected - The expected value or object

58

* @param description - Optional error message

59

* @returns This assertion for chaining

60

*/

61

deepEqual(expected: any, description?: string): Assertion;

62

```

63

64

**Usage:**

65

```javascript

66

// Same functionality as eql()

67

({ a: 1, b: 2 }).should.deepEqual({ a: 1, b: 2 });

68

[{ id: 1 }, { id: 2 }].should.deepEqual([{ id: 1 }, { id: 2 }]);

69

70

// Complex nested structures

71

const tree1 = {

72

root: {

73

left: { value: 1, children: [] },

74

right: { value: 2, children: [{ value: 3 }] }

75

}

76

};

77

const tree2 = {

78

root: {

79

left: { value: 1, children: [] },

80

right: { value: 2, children: [{ value: 3 }] }

81

}

82

};

83

tree1.should.deepEqual(tree2);

84

```

85

86

## Containment Testing

87

88

### containEql()

89

90

Test that an array or object contains an element that deeply equals the expected value.

91

92

```javascript { .api }

93

/**

94

* Assert that array/object contains an element deeply equal to expected

95

* @param expected - The value to find in the collection

96

* @returns This assertion for chaining

97

*/

98

containEql(expected: any): Assertion;

99

```

100

101

**Usage:**

102

```javascript

103

// Array containment

104

[1, 2, 3].should.containEql(2);

105

['a', 'b', 'c'].should.containEql('b');

106

107

// Object containment in arrays

108

const users = [

109

{ name: 'john', age: 30 },

110

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

111

{ name: 'bob', age: 35 }

112

];

113

users.should.containEql({ name: 'jane', age: 25 });

114

115

// Nested object matching

116

const products = [

117

{

118

id: 1,

119

details: { name: 'laptop', price: 1000 },

120

tags: ['electronics', 'computer']

121

},

122

{

123

id: 2,

124

details: { name: 'phone', price: 500 },

125

tags: ['electronics', 'mobile']

126

}

127

];

128

products.should.containEql({

129

id: 1,

130

details: { name: 'laptop', price: 1000 },

131

tags: ['electronics', 'computer']

132

});

133

134

// String containment in arrays

135

const permissions = ['read', 'write', 'delete'];

136

permissions.should.containEql('write');

137

```

138

139

### containDeep()

140

141

Test that an object contains the expected properties and values (partial matching).

142

143

```javascript { .api }

144

/**

145

* Assert that object contains all properties from expected (partial matching)

146

* @param expected - Object with properties that must be present

147

* @returns This assertion for chaining

148

*/

149

containDeep(expected: any): Assertion;

150

```

151

152

**Usage:**

153

```javascript

154

// Partial object matching

155

const user = {

156

id: 123,

157

name: 'john',

158

email: 'john@test.com',

159

preferences: { theme: 'dark', lang: 'en' }

160

};

161

162

// Contains these properties (others may exist)

163

user.should.containDeep({ name: 'john', id: 123 });

164

user.should.containDeep({

165

preferences: { theme: 'dark' }

166

}); // Nested partial matching

167

168

// Array with partial object matching

169

const items = [

170

{ id: 1, name: 'item1', category: 'A', active: true },

171

{ id: 2, name: 'item2', category: 'B', active: false },

172

{ id: 3, name: 'item3', category: 'A', active: true }

173

];

174

175

items.should.containDeep([

176

{ id: 1, name: 'item1' }, // Partial match - category and active ignored

177

{ id: 2, active: false } // Partial match - name and category ignored

178

]);

179

180

// API response validation

181

const apiResponse = {

182

status: 200,

183

data: {

184

users: [

185

{ id: 1, name: 'john', role: 'admin', lastLogin: '2023-01-01' },

186

{ id: 2, name: 'jane', role: 'user', lastLogin: '2023-01-02' }

187

],

188

pagination: { page: 1, total: 2 }

189

},

190

meta: { timestamp: 1234567890 }

191

};

192

193

apiResponse.should.containDeep({

194

status: 200,

195

data: {

196

users: [

197

{ id: 1, name: 'john' }, // Don't care about role, lastLogin

198

{ id: 2, name: 'jane' } // Don't care about role, lastLogin

199

]

200

}

201

});

202

```

203

204

### containDeepOrdered()

205

206

Test that an array contains elements in the specified order with deep equality.

207

208

```javascript { .api }

209

/**

210

* Assert that array contains elements in specified order (deep equality)

211

* @param expected - Array of elements that should be present in order

212

* @returns This assertion for chaining

213

*/

214

containDeepOrdered(expected: any): Assertion;

215

```

216

217

**Usage:**

218

```javascript

219

// Ordered containment

220

const sequence = [

221

{ step: 1, action: 'start' },

222

{ step: 2, action: 'process' },

223

{ step: 3, action: 'validate' },

224

{ step: 4, action: 'finish' }

225

];

226

227

// Must contain these in order (other elements can exist between)

228

sequence.should.containDeepOrdered([

229

{ step: 1, action: 'start' },

230

{ step: 3, action: 'validate' },

231

{ step: 4, action: 'finish' }

232

]);

233

234

// Event log validation

235

const eventLog = [

236

{ type: 'user_login', user: 'john', timestamp: 1001 },

237

{ type: 'page_view', page: '/dashboard', timestamp: 1002 },

238

{ type: 'button_click', element: 'save', timestamp: 1003 },

239

{ type: 'api_call', endpoint: '/save', timestamp: 1004 },

240

{ type: 'user_logout', user: 'john', timestamp: 1005 }

241

];

242

243

// Verify sequence of critical events

244

eventLog.should.containDeepOrdered([

245

{ type: 'user_login', user: 'john' },

246

{ type: 'api_call', endpoint: '/save' },

247

{ type: 'user_logout', user: 'john' }

248

]);

249

250

// Simple array ordering

251

[1, 5, 2, 8, 3, 9].should.containDeepOrdered([1, 2, 3]); // In order

252

[1, 5, 2, 8, 3, 9].should.not.containDeepOrdered([3, 2, 1]); // Wrong order

253

```

254

255

## Complex Collection Testing

256

257

### Nested Array and Object Validation

258

```javascript

259

// Complex data structure

260

const applicationState = {

261

user: {

262

id: 123,

263

profile: { name: 'john', email: 'john@test.com' },

264

permissions: ['read', 'write']

265

},

266

ui: {

267

theme: 'dark',

268

notifications: [

269

{ id: 1, type: 'info', message: 'Welcome' },

270

{ id: 2, type: 'warn', message: 'Update required' }

271

]

272

}

273

};

274

275

// Test nested structure contains expected data

276

applicationState.should.containDeep({

277

user: {

278

id: 123,

279

permissions: ['read', 'write']

280

},

281

ui: {

282

theme: 'dark'

283

}

284

});

285

286

// Test array within nested object

287

applicationState.ui.notifications.should.containEql({

288

id: 1,

289

type: 'info',

290

message: 'Welcome'

291

});

292

```

293

294

### API Response Validation

295

```javascript

296

function validateUserListResponse(response) {

297

// Overall structure

298

response.should.be.an.Object();

299

response.should.have.properties('data', 'meta', 'status');

300

response.status.should.equal(200);

301

302

// Data array validation

303

response.data.should.be.an.Array();

304

response.data.should.not.be.empty();

305

306

// Each user has required fields

307

response.data.forEach(user => {

308

user.should.have.properties('id', 'name', 'email');

309

user.id.should.be.a.Number();

310

user.name.should.be.a.String();

311

user.email.should.match(/\S+@\S+\.\S+/);

312

});

313

314

// Contains specific user

315

response.data.should.containEql({

316

id: 123,

317

name: 'john',

318

email: 'john@test.com'

319

});

320

}

321

322

const apiResponse = {

323

status: 200,

324

data: [

325

{ id: 123, name: 'john', email: 'john@test.com', role: 'admin' },

326

{ id: 124, name: 'jane', email: 'jane@test.com', role: 'user' }

327

],

328

meta: { total: 2, page: 1 }

329

};

330

331

validateUserListResponse(apiResponse);

332

```

333

334

### Configuration Validation

335

```javascript

336

function validateConfig(config) {

337

// Must contain required configuration sections

338

config.should.containDeep({

339

database: {

340

host: 'localhost'

341

},

342

server: {

343

port: 3000

344

}

345

});

346

347

// Database config contains connection settings

348

config.database.should.have.properties('host', 'port', 'database');

349

350

// Environment-specific settings

351

if (config.environment === 'production') {

352

config.should.containDeep({

353

ssl: { enabled: true },

354

logging: { level: 'warn' }

355

});

356

}

357

}

358

359

const devConfig = {

360

environment: 'development',

361

database: {

362

host: 'localhost',

363

port: 5432,

364

database: 'myapp_dev',

365

ssl: false

366

},

367

server: {

368

port: 3000,

369

cors: true

370

},

371

logging: {

372

level: 'debug',

373

format: 'json'

374

}

375

};

376

377

validateConfig(devConfig);

378

```

379

380

## Performance and Memory Testing

381

```javascript

382

// Large dataset containment

383

const bigArray = Array.from({ length: 10000 }, (_, i) => ({

384

id: i,

385

data: `item_${i}`,

386

active: i % 2 === 0

387

}));

388

389

// Efficient containment testing

390

bigArray.should.containEql({ id: 5000, data: 'item_5000', active: true });

391

392

// Partial matching in large datasets

393

bigArray.should.containDeep([

394

{ id: 0, active: true },

395

{ id: 1, active: false },

396

{ id: 2, active: true }

397

]);

398

```

399

400

## Negation and Edge Cases

401

402

```javascript

403

// Negation examples

404

[1, 2, 3].should.not.containEql(4);

405

[1, 2, 3].should.not.eql([3, 2, 1]); // Order matters for eql

406

407

const obj = { name: 'john', age: 30 };

408

obj.should.not.containDeep({ name: 'jane' });

409

obj.should.not.eql({ name: 'john' }); // Missing age property

410

411

// Edge cases

412

[].should.not.containEql(1); // Empty array

413

{}.should.not.containDeep({ key: 'value' }); // Empty object

414

415

// null and undefined handling

416

[null, undefined, 0, false].should.containEql(null);

417

[null, undefined, 0, false].should.containEql(undefined);

418

```

419

420

## Chaining with Other Assertions

421

422

```javascript

423

const data = [

424

{ id: 1, name: 'john', scores: [85, 90, 88] },

425

{ id: 2, name: 'jane', scores: [92, 89, 94] }

426

];

427

428

// Chain containment with other assertions

429

data.should.be.an.Array()

430

.and.have.length(2)

431

.and.containEql({ id: 1, name: 'john', scores: [85, 90, 88] });

432

433

// Test nested array properties

434

const user = data.find(u => u.id === 1);

435

user.should.have.property('scores')

436

.which.is.an.Array()

437

.and.containEql(90)

438

.and.have.length(3);

439

```