0
# Utility Functions
1
2
Helper functions for object comparison, type checking, serialization, and debugging that support QUnit's testing capabilities.
3
4
## Capabilities
5
6
### Deep Equality Comparison
7
8
Compare complex objects and data structures for equality.
9
10
```javascript { .api }
11
/**
12
* Deep equality comparison utility used by deepEqual assertions
13
* @param {any} a - First value to compare
14
* @param {any} b - Second value to compare
15
* @returns {boolean} True if values are deeply equal
16
*/
17
QUnit.equiv(a, b)
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
import QUnit from "qunit";
24
25
QUnit.test("manual deep comparison", function(assert) {
26
const obj1 = { name: "Alice", settings: { theme: "dark", lang: "en" } };
27
const obj2 = { name: "Alice", settings: { theme: "dark", lang: "en" } };
28
const obj3 = { name: "Bob", settings: { theme: "light", lang: "fr" } };
29
30
assert.ok(QUnit.equiv(obj1, obj2), "objects with same structure and values are equal");
31
assert.notOk(QUnit.equiv(obj1, obj3), "objects with different values are not equal");
32
33
// Arrays
34
assert.ok(QUnit.equiv([1, 2, 3], [1, 2, 3]), "arrays with same elements are equal");
35
assert.notOk(QUnit.equiv([1, 2, 3], [1, 2, 4]), "arrays with different elements are not equal");
36
37
// Nested structures
38
const complex1 = { users: [{ id: 1, name: "Alice" }], meta: { count: 1 } };
39
const complex2 = { users: [{ id: 1, name: "Alice" }], meta: { count: 1 } };
40
assert.ok(QUnit.equiv(complex1, complex2), "complex nested structures can be compared");
41
});
42
```
43
44
### Object Serialization
45
46
Serialize objects for display and debugging purposes.
47
48
```javascript { .api }
49
/**
50
* Serialize object to human-readable string representation
51
* @param {any} obj - Object to serialize
52
* @returns {string} String representation of the object
53
*/
54
QUnit.dump.parse(obj)
55
```
56
57
**Usage Examples:**
58
59
```javascript
60
QUnit.test("object serialization", function(assert) {
61
const user = { id: 1, name: "Alice", active: true, tags: ["admin", "user"] };
62
const serialized = QUnit.dump.parse(user);
63
64
console.log("User object:", serialized);
65
// Output: { "id": 1, "name": "Alice", "active": true, "tags": [ "admin", "user" ] }
66
67
// Useful for debugging complex objects
68
const complexObj = {
69
nested: { deep: { value: 42 } },
70
fn: function() { return "test"; },
71
date: new Date("2023-01-01"),
72
regex: /test/gi
73
};
74
75
console.log("Complex object:", QUnit.dump.parse(complexObj));
76
77
assert.ok(typeof serialized === "string", "returns string representation");
78
});
79
```
80
81
### Type Checking
82
83
Detailed type checking utilities for runtime type validation.
84
85
```javascript { .api }
86
/**
87
* Check if value matches specific type
88
* @param {string} type - Type name to check against
89
* @param {any} obj - Value to check
90
* @returns {boolean} True if value matches the specified type
91
*/
92
QUnit.is(type, obj)
93
94
/**
95
* Get detailed object type information
96
* @param {any} obj - Object to analyze
97
* @returns {string} String describing the object's type
98
*/
99
QUnit.objectType(obj)
100
```
101
102
**Usage Examples:**
103
104
```javascript
105
QUnit.test("type checking utilities", function(assert) {
106
// Type checking - QUnit.is checks against specific type names
107
// Common types: 'string', 'number', 'boolean', 'object', 'array', 'function'
108
// 'null', 'undefined', 'regexp', 'date', etc.
109
110
assert.ok(QUnit.is('string', 'hello'), 'identifies strings');
111
assert.ok(QUnit.is('number', 42), 'identifies numbers');
112
assert.ok(QUnit.is('boolean', true), 'identifies booleans');
113
assert.ok(QUnit.is('array', [1, 2, 3]), 'identifies arrays');
114
assert.ok(QUnit.is('object', { key: 'value' }), 'identifies objects');
115
assert.ok(QUnit.is('function', function() {}), 'identifies functions');
116
117
// Object type analysis - returns specific type strings
118
assert.strictEqual(QUnit.objectType('hello'), 'string');
119
assert.strictEqual(QUnit.objectType([1, 2, 3]), 'array');
120
assert.strictEqual(QUnit.objectType(new Date()), 'date');
121
assert.strictEqual(QUnit.objectType(/test/), 'regexp');
122
assert.strictEqual(QUnit.objectType(null), 'null');
123
assert.strictEqual(QUnit.objectType(undefined), 'undefined');
124
125
// Custom objects
126
function CustomClass() {}
127
const instance = new CustomClass();
128
assert.strictEqual(QUnit.objectType(instance), "object");
129
});
130
```
131
132
### Difference Calculation
133
134
Calculate and display differences between values for better error reporting.
135
136
```javascript { .api }
137
/**
138
* Calculate difference between two values for assertion error reporting
139
* @param {any} a - First value
140
* @param {any} b - Second value
141
* @returns {string|null} String describing the differences or null if no meaningful diff
142
*/
143
QUnit.diff(a, b)
144
```
145
146
**Usage Examples:**
147
148
```javascript
149
QUnit.test("difference calculation", function(assert) {
150
const original = "The quick brown fox";
151
const modified = "The quick blue fox";
152
153
const difference = QUnit.diff(original, modified);
154
console.log("String difference:", difference);
155
156
// Object differences
157
const obj1 = { name: "Alice", age: 30, city: "New York" };
158
const obj2 = { name: "Alice", age: 31, city: "Boston" };
159
160
const objDiff = QUnit.diff(obj1, obj2);
161
console.log("Object difference:", objDiff);
162
163
// Array differences
164
const arr1 = [1, 2, 3, 4, 5];
165
const arr2 = [1, 2, 4, 5, 6];
166
167
const arrDiff = QUnit.diff(arr1, arr2);
168
console.log("Array difference:", arrDiff);
169
170
// No difference
171
const noDiff = QUnit.diff("same", "same");
172
assert.strictEqual(noDiff, null, "returns null when values are equal");
173
});
174
175
// Custom assertion using diff
176
QUnit.test("custom assertion with diff", function(assert) {
177
function customDeepEqual(actual, expected, message) {
178
const isEqual = QUnit.equiv(actual, expected);
179
180
if (!isEqual) {
181
const difference = QUnit.diff(actual, expected);
182
const enhancedMessage = message + (difference ? `\nDifference: ${difference}` : "");
183
184
assert.pushResult({
185
result: false,
186
actual: actual,
187
expected: expected,
188
message: enhancedMessage
189
});
190
} else {
191
assert.pushResult({
192
result: true,
193
actual: actual,
194
expected: expected,
195
message: message
196
});
197
}
198
}
199
200
const user1 = { name: "Alice", age: 30, roles: ["admin"] };
201
const user2 = { name: "Alice", age: 31, roles: ["user"] };
202
203
customDeepEqual(user1, user2, "users should be equal");
204
});
205
```
206
207
### Stack Trace Utilities
208
209
Generate and analyze stack traces for debugging and error reporting.
210
211
```javascript { .api }
212
/**
213
* Get stack trace with optional offset
214
* @param {number} [offset=0] - Number of stack frames to skip
215
* @returns {string} Stack trace string
216
*/
217
QUnit.stack(offset)
218
```
219
220
**Usage Examples:**
221
222
```javascript
223
QUnit.test("stack trace utilities", function(assert) {
224
function helperFunction() {
225
// Get stack trace from current location
226
return QUnit.stack();
227
}
228
229
function wrapperFunction() {
230
return helperFunction();
231
}
232
233
const stackTrace = wrapperFunction();
234
console.log("Stack trace:", stackTrace);
235
236
// Skip frames to get cleaner stack traces
237
const cleanStack = QUnit.stack(2); // Skip 2 frames
238
console.log("Clean stack trace:", cleanStack);
239
240
assert.ok(typeof stackTrace === "string", "returns string");
241
assert.ok(stackTrace.length > 0, "stack trace is not empty");
242
});
243
```
244
245
### Utility Integration Examples
246
247
Combine utilities for advanced testing scenarios.
248
249
**Usage Examples:**
250
251
```javascript
252
QUnit.test("combined utility usage", function(assert) {
253
// Custom comparison with detailed reporting
254
function advancedCompare(actual, expected, message) {
255
const type1 = QUnit.objectType(actual);
256
const type2 = QUnit.objectType(expected);
257
258
if (type1 !== type2) {
259
assert.pushResult({
260
result: false,
261
actual: `${type1}: ${QUnit.dump.parse(actual)}`,
262
expected: `${type2}: ${QUnit.dump.parse(expected)}`,
263
message: `${message} - Type mismatch`
264
});
265
return;
266
}
267
268
const isEqual = QUnit.equiv(actual, expected);
269
270
if (!isEqual) {
271
const difference = QUnit.diff(actual, expected);
272
assert.pushResult({
273
result: false,
274
actual: QUnit.dump.parse(actual),
275
expected: QUnit.dump.parse(expected),
276
message: `${message}${difference ? `\nDiff: ${difference}` : ""}`
277
});
278
} else {
279
assert.pushResult({
280
result: true,
281
actual: actual,
282
expected: expected,
283
message: message
284
});
285
}
286
}
287
288
// Test the custom comparison
289
const obj1 = { users: [{ name: "Alice" }], count: 1 };
290
const obj2 = { users: [{ name: "Bob" }], count: 1 };
291
292
advancedCompare(obj1, obj2, "complex objects should be equal");
293
});
294
295
// Performance testing helper
296
QUnit.test("performance testing utilities", function(assert) {
297
function performanceTest(fn, iterations = 1000) {
298
const start = performance.now();
299
300
for (let i = 0; i < iterations; i++) {
301
fn();
302
}
303
304
const duration = performance.now() - start;
305
const avgTime = duration / iterations;
306
307
return {
308
totalTime: duration,
309
averageTime: avgTime,
310
iterations: iterations
311
};
312
}
313
314
// Test object comparison performance
315
const largeObj1 = { data: new Array(1000).fill(0).map((_, i) => ({ id: i, value: i * 2 })) };
316
const largeObj2 = { data: new Array(1000).fill(0).map((_, i) => ({ id: i, value: i * 2 })) };
317
318
const perfResult = performanceTest(() => {
319
QUnit.equiv(largeObj1, largeObj2);
320
}, 100);
321
322
console.log(`Comparison performance: ${perfResult.averageTime.toFixed(3)}ms average`);
323
324
assert.ok(perfResult.averageTime < 100, "comparison should be reasonably fast");
325
});
326
```
327
328
## Available Utility Functions
329
330
The following utility functions are available on the QUnit object:
331
332
```javascript { .api }
333
/**
334
* Core utility functions available in QUnit v2.24.1
335
*/
336
337
// Deep comparison
338
QUnit.equiv(a, b) // Deep equivalence check used by deepEqual
339
340
// Object serialization
341
QUnit.dump.parse(obj) // Convert object to string representation
342
343
// Type checking
344
QUnit.is(type, obj) // Check if object matches type
345
QUnit.objectType(obj) // Get detailed type information
346
347
// Debugging utilities
348
QUnit.diff(a, b) // Generate diff between values (used in error reporting)
349
QUnit.stack(offset) // Get stack trace with optional frame offset
350
351
// Configuration and state
352
QUnit.config // Configuration object
353
QUnit.version // QUnit version string
354
QUnit.isLocal // Whether running from file:// protocol
355
356
// Test execution control
357
QUnit.start() // Start test execution (when autostart is false)
358
QUnit.pushFailure(msg, source) // Push test failure
359
360
// Error handling
361
QUnit.onError(callback) // Register global error handler
362
QUnit.onUncaughtException(callback) // Register uncaught exception handler
363
```
364
365
## Type Information
366
367
The `QUnit.objectType()` and `QUnit.is()` functions recognize these type strings:
368
369
- `'string'` - String values
370
- `'number'` - Number values (including NaN)
371
- `'boolean'` - Boolean values
372
- `'object'` - Plain objects and custom objects
373
- `'array'` - Array objects
374
- `'function'` - Function objects
375
- `'regexp'` - Regular expression objects
376
- `'date'` - Date objects
377
- `'null'` - null value
378
- `'undefined'` - undefined value
379
380
## Implementation Notes
381
382
- `QUnit.equiv()` handles circular references and provides deep comparison
383
- `QUnit.dump.parse()` respects `QUnit.config.maxDepth` for object traversal
384
- `QUnit.diff()` may return null if no meaningful difference can be calculated
385
- `QUnit.stack()` provides clean stack traces for error reporting