0
# Object and Property Assertions
1
2
Methods for testing object properties, structure, ownership, and collection characteristics.
3
4
## Property Existence and Values
5
6
### property()
7
8
Test that an object has a property, optionally with a specific value. **Changes assertion target to the property value.**
9
10
```javascript { .api }
11
/**
12
* Assert that object has the specified property, optionally with a value
13
* Changes the assertion target to the property value for chaining
14
* @param name - Property name to check
15
* @param value - Optional expected property value
16
* @returns This assertion for chaining (now targeting the property value)
17
*/
18
property(name: string, value?: any): Assertion;
19
```
20
21
**Usage:**
22
```javascript
23
import should from 'should';
24
25
const user = { name: 'john', age: 30, active: true };
26
27
// Test property existence
28
user.should.have.property('name');
29
user.should.have.property('age');
30
31
// Test property with specific value
32
user.should.have.property('name', 'john');
33
user.should.have.property('age', 30);
34
35
// Chain assertions on the property value
36
user.should.have.property('name').which.is.a.String();
37
user.should.have.property('age').which.is.above(18);
38
39
// Nested objects
40
const config = { database: { host: 'localhost', port: 5432 } };
41
config.should.have.property('database').which.is.an.Object();
42
config.database.should.have.property('host', 'localhost');
43
```
44
45
### properties()
46
47
Test that an object has multiple properties.
48
49
```javascript { .api }
50
/**
51
* Assert that object has all specified properties
52
* @param names - Property names as individual arguments or array
53
* @returns This assertion for chaining
54
*/
55
properties(...names: string[]): Assertion;
56
properties(names: string[]): Assertion;
57
properties(props: object): Assertion;
58
```
59
60
**Usage:**
61
```javascript
62
const user = { name: 'john', age: 30, email: 'john@test.com' };
63
64
// Multiple properties as arguments
65
user.should.have.properties('name', 'age', 'email');
66
67
// Properties as array
68
user.should.have.properties(['name', 'age']);
69
70
// Properties with values (as object)
71
user.should.have.properties({
72
name: 'john',
73
age: 30
74
});
75
76
// Partial property checking
77
const response = { status: 200, data: {}, headers: {} };
78
response.should.have.properties('status', 'data');
79
```
80
81
### ownProperty() / hasOwnProperty()
82
83
Test that an object has its own property (not inherited).
84
85
```javascript { .api }
86
/**
87
* Assert that object has the property as its own (not inherited)
88
* @param name - Property name to check
89
* @param description - Optional error message
90
* @returns This assertion for chaining
91
*/
92
ownProperty(name: string, description?: string): Assertion;
93
hasOwnProperty(name: string, description?: string): Assertion;
94
```
95
96
**Usage:**
97
```javascript
98
const obj = { name: 'test' };
99
100
obj.should.have.ownProperty('name');
101
obj.should.have.hasOwnProperty('name');
102
103
// Won't match inherited properties
104
obj.should.not.have.ownProperty('toString'); // toString is inherited
105
obj.should.not.have.ownProperty('constructor');
106
107
// With description
108
const config = { timeout: 5000 };
109
config.should.have.ownProperty('timeout', 'Config should have timeout setting');
110
```
111
112
### propertyWithDescriptor()
113
114
Test that an object has a property with specific descriptor attributes.
115
116
```javascript { .api }
117
/**
118
* Assert that object has property with matching descriptor attributes
119
* @param name - Property name to check
120
* @param descriptor - Expected descriptor properties (enumerable, configurable, etc.)
121
* @returns This assertion for chaining
122
*/
123
propertyWithDescriptor(name: string, descriptor: object): Assertion;
124
```
125
126
**Usage:**
127
```javascript
128
const obj = {};
129
Object.defineProperty(obj, 'hidden', {
130
value: 'secret',
131
enumerable: false,
132
configurable: true
133
});
134
135
obj.should.have.propertyWithDescriptor('hidden', {
136
enumerable: false,
137
configurable: true
138
});
139
140
// Partial descriptor matching
141
obj.should.have.propertyWithDescriptor('hidden', {
142
enumerable: false
143
});
144
```
145
146
## Collection Properties
147
148
### length() / lengthOf()
149
150
Test the length property of arrays, strings, or array-like objects.
151
152
```javascript { .api }
153
/**
154
* Assert that object has a length property with the specified value
155
* @param value - Expected length value
156
* @param description - Optional error message
157
* @returns This assertion for chaining
158
*/
159
length(value: number, description?: string): Assertion;
160
lengthOf(value: number, description?: string): Assertion;
161
```
162
163
**Usage:**
164
```javascript
165
[1, 2, 3].should.have.length(3);
166
'hello'.should.have.length(5);
167
''.should.have.length(0);
168
169
// Array-like objects
170
const arrayLike = { 0: 'a', 1: 'b', length: 2 };
171
arrayLike.should.have.length(2);
172
173
// With description
174
const items = ['a', 'b', 'c'];
175
items.should.have.lengthOf(3, 'Should have 3 items');
176
177
// Chaining with other assertions
178
const users = [{ name: 'john' }, { name: 'jane' }];
179
users.should.have.length(2).and.be.an.Array();
180
```
181
182
### empty()
183
184
Test that a collection or string is empty.
185
186
```javascript { .api }
187
/**
188
* Assert that the value is empty (array, string, object with no own properties)
189
* @returns This assertion for chaining
190
*/
191
empty(): Assertion;
192
```
193
194
**Usage:**
195
```javascript
196
[].should.be.empty();
197
''.should.be.empty();
198
{}.should.be.empty();
199
200
// Maps and Sets
201
new Map().should.be.empty();
202
new Set().should.be.empty();
203
204
// Non-empty examples
205
[1, 2, 3].should.not.be.empty();
206
'hello'.should.not.be.empty();
207
{ name: 'john' }.should.not.be.empty();
208
```
209
210
### size()
211
212
Test the size property of Maps, Sets, and other collections.
213
214
```javascript { .api }
215
/**
216
* Assert that object has a size property with the specified value
217
* @param value - Expected size value
218
* @returns This assertion for chaining
219
*/
220
size(value: number): Assertion;
221
```
222
223
**Usage:**
224
```javascript
225
const map = new Map([['a', 1], ['b', 2]]);
226
map.should.have.size(2);
227
228
const set = new Set([1, 2, 3, 3]); // Duplicates ignored
229
set.should.have.size(3);
230
231
// Custom objects with size property
232
const collection = {
233
items: ['a', 'b', 'c'],
234
get size() { return this.items.length; }
235
};
236
collection.should.have.size(3);
237
```
238
239
## Object Keys and Values
240
241
### keys() / key()
242
243
Test object keys.
244
245
```javascript { .api }
246
/**
247
* Assert that object has the specified keys
248
* @param keys - Expected keys as individual arguments or array
249
* @returns This assertion for chaining
250
*/
251
keys(...keys: any[]): Assertion;
252
key(key: any): Assertion;
253
```
254
255
**Usage:**
256
```javascript
257
const obj = { name: 'john', age: 30, active: true };
258
259
// All keys (order doesn't matter)
260
obj.should.have.keys('name', 'age', 'active');
261
obj.should.have.keys(['name', 'age', 'active']);
262
263
// Single key
264
obj.should.have.key('name');
265
266
// Subset of keys (using .any modifier)
267
obj.should.have.any.keys('name', 'email'); // Has 'name', missing 'email' is ok
268
269
// Exact key matching
270
obj.should.have.only.keys('name', 'age', 'active');
271
272
// Array key testing
273
const arr = ['a', 'b', 'c'];
274
arr.should.have.keys('0', '1', '2', 'length');
275
```
276
277
### value()
278
279
Test that an object has a key with a specific value.
280
281
```javascript { .api }
282
/**
283
* Assert that object has the specified key with the given value
284
* @param key - Property key to check
285
* @param value - Expected value for the key
286
* @returns This assertion for chaining
287
*/
288
value(key: any, value: any): Assertion;
289
```
290
291
**Usage:**
292
```javascript
293
const obj = { name: 'john', age: 30 };
294
295
obj.should.have.value('name', 'john');
296
obj.should.have.value('age', 30);
297
298
// Works with arrays
299
const arr = ['a', 'b', 'c'];
300
arr.should.have.value(0, 'a');
301
arr.should.have.value(2, 'c');
302
303
// Maps
304
const map = new Map([['key1', 'value1'], ['key2', 'value2']]);
305
map.should.have.value('key1', 'value1');
306
```
307
308
### propertyByPath()
309
310
Test nested property access using a path.
311
312
```javascript { .api }
313
/**
314
* Assert that object has a property accessible by the given path
315
* @param path - Property path as individual arguments or array
316
* @returns This assertion for chaining (targeting the nested value)
317
*/
318
propertyByPath(...path: string[]): Assertion;
319
propertyByPath(path: string[]): Assertion;
320
```
321
322
**Usage:**
323
```javascript
324
const obj = {
325
user: {
326
profile: {
327
name: 'john',
328
settings: {
329
theme: 'dark'
330
}
331
}
332
}
333
};
334
335
// Path as arguments
336
obj.should.have.propertyByPath('user', 'profile', 'name');
337
338
// Path as array
339
obj.should.have.propertyByPath(['user', 'profile', 'settings', 'theme']);
340
341
// Chain assertions on nested value
342
obj.should.have.propertyByPath('user', 'profile', 'name').which.equals('john');
343
344
// Array indices in path
345
const data = {
346
items: [
347
{ id: 1, name: 'first' },
348
{ id: 2, name: 'second' }
349
]
350
};
351
data.should.have.propertyByPath('items', 0, 'name').which.equals('first');
352
```
353
354
## Complex Object Testing
355
356
### Chaining Property Assertions
357
358
Property assertions can be chained for complex object validation:
359
360
```javascript
361
const user = {
362
id: 123,
363
profile: {
364
name: 'john',
365
email: 'john@test.com',
366
preferences: {
367
theme: 'dark',
368
notifications: true
369
}
370
},
371
roles: ['user', 'admin']
372
};
373
374
// Complex chaining
375
user.should.have.property('id').which.is.a.Number().and.be.above(0);
376
user.should.have.property('profile').which.is.an.Object()
377
.and.have.properties('name', 'email');
378
user.should.have.property('roles').which.is.an.Array()
379
.and.have.length(2)
380
.and.containEql('admin');
381
382
// Nested property testing
383
user.profile.should.have.property('preferences').which.is.an.Object();
384
user.profile.preferences.should.have.property('theme', 'dark');
385
```
386
387
### Negation
388
389
All property assertions support negation:
390
391
```javascript
392
const obj = { name: 'john' };
393
394
obj.should.not.have.property('age');
395
obj.should.not.have.properties('email', 'phone');
396
obj.should.not.have.ownProperty('toString'); // inherited property
397
obj.should.not.be.empty();
398
obj.should.not.have.keys('age', 'email');
399
```