Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/testing/asserts.js
4500 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
goog.provide('goog.testing.asserts');
8
goog.setTestOnly();
9
10
goog.require('goog.dom.safe');
11
goog.require('goog.html.uncheckedconversions');
12
goog.require('goog.string');
13
goog.require('goog.string.Const');
14
goog.require('goog.testing.JsUnitException');
15
16
var DOUBLE_EQUALITY_PREDICATE = function(var1, var2) {
17
'use strict';
18
return var1 == var2;
19
};
20
var JSUNIT_UNDEFINED_VALUE = void 0;
21
var TO_STRING_EQUALITY_PREDICATE = function(var1, var2) {
22
'use strict';
23
return var1.toString() === var2.toString();
24
};
25
var OUTPUT_NEW_LINE_THRESHOLD = 40;
26
27
28
/** @typedef {function(?, ?):boolean} */
29
var PredicateFunctionType;
30
31
32
/**
33
* An associative array of constructors corresponding to primitive and
34
* well-known JS types.
35
* @const {!Array<string>}
36
*/
37
const PRIMITIVE_TRUE_TYPES =
38
['String', 'Boolean', 'Number', 'Array', 'RegExp', 'Date', 'Function'];
39
40
if (typeof ArrayBuffer === 'function') {
41
PRIMITIVE_TRUE_TYPES.push('ArrayBuffer');
42
}
43
44
45
/**
46
* @const {{
47
* String : !PredicateFunctionType,
48
* Number : !PredicateFunctionType,
49
* Boolean : !PredicateFunctionType,
50
* Date : !PredicateFunctionType,
51
* RegExp : !PredicateFunctionType,
52
* Function : !PredicateFunctionType,
53
* TrustedHTML : !PredicateFunctionType,
54
* TrustedScript : !PredicateFunctionType,
55
* TrustedScriptURL : !PredicateFunctionType
56
* }}
57
*/
58
const EQUALITY_PREDICATES = {
59
'String': DOUBLE_EQUALITY_PREDICATE,
60
'Number': DOUBLE_EQUALITY_PREDICATE,
61
'Bigint': DOUBLE_EQUALITY_PREDICATE,
62
'Boolean': DOUBLE_EQUALITY_PREDICATE,
63
'Date': function(date1, date2) {
64
'use strict';
65
return date1.getTime() == date2.getTime();
66
},
67
'RegExp': TO_STRING_EQUALITY_PREDICATE,
68
'Function': TO_STRING_EQUALITY_PREDICATE,
69
'TrustedHTML': TO_STRING_EQUALITY_PREDICATE,
70
'TrustedScript': TO_STRING_EQUALITY_PREDICATE,
71
'TrustedScriptURL': TO_STRING_EQUALITY_PREDICATE
72
};
73
74
75
/**
76
* Compares equality of two numbers, allowing them to differ up to a given
77
* tolerance.
78
* @param {number} var1 A number.
79
* @param {number} var2 A number.
80
* @param {number} tolerance the maximum allowed difference.
81
* @return {boolean} Whether the two variables are sufficiently close.
82
* @private
83
*/
84
goog.testing.asserts.numberRoughEqualityPredicate_ = function(
85
var1, var2, tolerance) {
86
'use strict';
87
return Math.abs(var1 - var2) <= tolerance;
88
};
89
90
91
/**
92
* @type {!Object<string, function(?, ?, number): boolean>}
93
* @private
94
*/
95
goog.testing.asserts.primitiveRoughEqualityPredicates_ = {
96
'Number': goog.testing.asserts.numberRoughEqualityPredicate_
97
};
98
99
100
var _trueTypeOf = function(something) {
101
'use strict';
102
let result = typeof something;
103
try {
104
switch (result) {
105
case 'string':
106
break;
107
case 'boolean':
108
break;
109
case 'number':
110
break;
111
case 'object':
112
if (something == null) {
113
result = 'null';
114
break;
115
}
116
case 'function':
117
let foundConstructor = false;
118
for (let i = 0; i < PRIMITIVE_TRUE_TYPES.length; i++) {
119
// NOTE: this cannot be a for-of loop because it's used from Rhino
120
// without the necessary Array.prototype[Symbol.iterator] polyfill.
121
const trueType = PRIMITIVE_TRUE_TYPES[i];
122
if (something.constructor === goog.global[trueType]) {
123
result = trueType;
124
foundConstructor = true;
125
break;
126
}
127
}
128
// Constructor doesn't match any of the known "primitive" constructors.
129
if (!foundConstructor) {
130
const m =
131
something.constructor.toString().match(/function\s*([^( ]+)\(/);
132
if (m) {
133
result = m[1];
134
}
135
}
136
break;
137
}
138
} catch (e) {
139
} finally {
140
result = result.slice(0, 1).toUpperCase() + result.slice(1);
141
}
142
return result;
143
};
144
145
var _displayStringForValue = function(aVar) {
146
'use strict';
147
var result;
148
try {
149
result = '<' + String(aVar) + '>';
150
} catch (ex) {
151
result = '<toString failed: ' + ex.message + '>';
152
// toString does not work on this object :-(
153
}
154
if (!(aVar === null || aVar === JSUNIT_UNDEFINED_VALUE)) {
155
result += ' (' + _trueTypeOf(aVar) + ')';
156
}
157
return result;
158
};
159
160
/** @param {?} failureMessage */
161
goog.testing.asserts.fail = function(failureMessage) {
162
'use strict';
163
_assert('Call to fail()', false, failureMessage);
164
};
165
/**
166
* @const
167
* @suppress {duplicate,checkTypes} Test frameworks like Jasmine may also
168
* define global fail functions.
169
*/
170
var fail = goog.testing.asserts.fail;
171
172
var argumentsIncludeComments = function(expectedNumberOfNonCommentArgs, args) {
173
'use strict';
174
return args.length == expectedNumberOfNonCommentArgs + 1;
175
};
176
177
var commentArg = function(expectedNumberOfNonCommentArgs, args) {
178
'use strict';
179
if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args)) {
180
return args[0];
181
}
182
183
return null;
184
};
185
186
var nonCommentArg = function(
187
desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) {
188
'use strict';
189
return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ?
190
args[desiredNonCommentArgIndex] :
191
args[desiredNonCommentArgIndex - 1];
192
};
193
194
var _validateArguments = function(expectedNumberOfNonCommentArgs, args) {
195
'use strict';
196
var valid = args.length == expectedNumberOfNonCommentArgs ||
197
args.length == expectedNumberOfNonCommentArgs + 1 &&
198
typeof args[0] === 'string';
199
if (!valid) {
200
goog.testing.asserts.raiseException(
201
'Incorrect arguments passed to assert function.\n' +
202
'Expected ' + expectedNumberOfNonCommentArgs + ' argument(s) plus ' +
203
'optional comment; got ' + args.length + '.');
204
}
205
};
206
207
/**
208
* @return {?} goog.testing.TestCase or null
209
* We suppress the lint error and we explicitly do not goog.require()
210
* goog.testing.TestCase to avoid a build time dependency cycle.
211
* @suppress {missingRequire|undefinedVars|missingProperties}
212
* @private
213
*/
214
var _getCurrentTestCase = function() {
215
'use strict';
216
// Some users of goog.testing.asserts do not use goog.testing.TestRunner and
217
// they do not include goog.testing.TestCase. Exceptions will not be
218
// completely correct for these users.
219
if (!goog.testing.TestCase) {
220
if (goog.global.console) {
221
goog.global.console.error(
222
'Missing goog.testing.TestCase, ' +
223
'add /* @suppress {extraRequire} */' +
224
'goog.require(\'goog.testing.TestCase\')');
225
}
226
return null;
227
}
228
return goog.testing.TestCase.getActiveTestCase();
229
};
230
231
var _assert = function(comment, booleanValue, failureMessage) {
232
'use strict';
233
// If another framework has installed an adapter, tell it about the assertion.
234
var adapter =
235
typeof window !== 'undefined' && window['Closure assert adapter'];
236
if (adapter) {
237
adapter['assertWithMessage'](
238
booleanValue,
239
goog.testing.JsUnitException.generateMessage(comment, failureMessage));
240
// Also throw an error, for callers that assume that asserts throw. We don't
241
// include error details to avoid duplicate failure messages.
242
if (!booleanValue) throw new Error('goog.testing assertion failed');
243
}
244
if (!booleanValue) {
245
goog.testing.asserts.raiseException(comment, failureMessage);
246
}
247
};
248
249
250
/**
251
* @param {*} expected The expected value.
252
* @param {*} actual The actual value.
253
* @return {string} A failure message of the values don't match.
254
* @private
255
*/
256
goog.testing.asserts.getDefaultErrorMsg_ = function(expected, actual) {
257
'use strict';
258
var expectedDisplayString = _displayStringForValue(expected);
259
var actualDisplayString = _displayStringForValue(actual);
260
var shouldUseNewLines =
261
expectedDisplayString.length > OUTPUT_NEW_LINE_THRESHOLD ||
262
actualDisplayString.length > OUTPUT_NEW_LINE_THRESHOLD;
263
var msg = [
264
'Expected', expectedDisplayString, 'but was', actualDisplayString
265
].join(shouldUseNewLines ? '\n' : ' ');
266
267
if ((typeof expected == 'string') && (typeof actual == 'string')) {
268
// Try to find a human-readable difference.
269
var limit = Math.min(expected.length, actual.length);
270
var commonPrefix = 0;
271
while (commonPrefix < limit &&
272
expected.charAt(commonPrefix) == actual.charAt(commonPrefix)) {
273
commonPrefix++;
274
}
275
276
var commonSuffix = 0;
277
while (commonSuffix < limit &&
278
expected.charAt(expected.length - commonSuffix - 1) ==
279
actual.charAt(actual.length - commonSuffix - 1)) {
280
commonSuffix++;
281
}
282
283
if (commonPrefix + commonSuffix > limit) {
284
commonSuffix = 0;
285
}
286
287
if (commonPrefix > 2 || commonSuffix > 2) {
288
var printString = function(str) {
289
'use strict';
290
var startIndex = Math.max(0, commonPrefix - 2);
291
var endIndex = Math.min(str.length, str.length - (commonSuffix - 2));
292
return (startIndex > 0 ? '...' : '') +
293
str.substring(startIndex, endIndex) +
294
(endIndex < str.length ? '...' : '');
295
};
296
297
var expectedPrinted = printString(expected);
298
var expectedActual = printString(actual);
299
var shouldUseNewLinesInDiff =
300
expectedPrinted.length > OUTPUT_NEW_LINE_THRESHOLD ||
301
expectedActual.length > OUTPUT_NEW_LINE_THRESHOLD;
302
msg += '\nDifference was at position ' + commonPrefix + '. ' + [
303
'Expected', '[' + expectedPrinted + ']', 'vs. actual',
304
'[' + expectedActual + ']'
305
].join(shouldUseNewLinesInDiff ? '\n' : ' ');
306
}
307
}
308
return msg;
309
};
310
311
312
/**
313
* @param {*} a The value to assert (1 arg) or debug message (2 args).
314
* @param {*=} opt_b The value to assert (2 args only).
315
*/
316
goog.testing.asserts.assert = function(a, opt_b) {
317
'use strict';
318
_validateArguments(1, arguments);
319
var comment = commentArg(1, arguments);
320
var booleanValue = nonCommentArg(1, 1, arguments);
321
322
_assert(
323
comment, typeof booleanValue === 'boolean',
324
'Bad argument to assert(boolean): ' +
325
_displayStringForValue(booleanValue));
326
_assert(comment, booleanValue, 'Call to assert(boolean) with false');
327
};
328
/** @const */
329
var assert = goog.testing.asserts.assert;
330
331
332
/**
333
* Asserts that the function throws an error.
334
*
335
* @param {!(string|Function)} a The assertion comment or the function to call.
336
* @param {!Function=} opt_b The function to call (if the first argument of
337
* `assertThrows` was the comment).
338
* @return {!Error} The error thrown by the function. Beware that code may throw
339
* other types in strange scenarios.
340
* @throws {goog.testing.JsUnitException} If the assertion failed.
341
*/
342
goog.testing.asserts.assertThrows = function(a, opt_b) {
343
'use strict';
344
_validateArguments(1, arguments);
345
var func = nonCommentArg(1, 1, arguments);
346
var comment = commentArg(1, arguments);
347
_assert(
348
comment, typeof func == 'function',
349
'Argument passed to assertThrows is not a function');
350
351
try {
352
func();
353
} catch (e) {
354
goog.testing.asserts.removeOperaStacktrace_(e);
355
356
var testCase = _getCurrentTestCase();
357
if (e && e['isJsUnitException'] && testCase) {
358
goog.testing.asserts.raiseException(
359
comment,
360
'Function passed to assertThrows caught a JsUnitException (usually ' +
361
'from an assert or call to fail()). If this is expected, use ' +
362
'assertThrowsJsUnitException instead.');
363
}
364
365
return e;
366
}
367
goog.testing.asserts.raiseException(
368
comment, 'No exception thrown from function passed to assertThrows');
369
throw new Error('Should have thrown an error.'); // Make the compiler happy.
370
};
371
/** @const */
372
var assertThrows = goog.testing.asserts.assertThrows;
373
374
375
/**
376
* Removes a stacktrace from an Error object for Opera 10.0.
377
* @param {*} e
378
* @private
379
*/
380
goog.testing.asserts.removeOperaStacktrace_ = function(e) {
381
'use strict';
382
if (!goog.isObject(e)) return;
383
const stack = e['stacktrace'];
384
const errorMsg = e['message'];
385
if (typeof stack !== 'string' || typeof errorMsg !== 'string') {
386
return;
387
}
388
const stackStartIndex = errorMsg.length - stack.length;
389
if (errorMsg.indexOf(stack, stackStartIndex) == stackStartIndex) {
390
e['message'] = errorMsg.slice(0, stackStartIndex - 14);
391
}
392
};
393
394
395
/**
396
* Asserts that the function does not throw an error.
397
*
398
* @param {!(string|Function)} a The assertion comment or the function to call.
399
* @param {!Function=} opt_b The function to call (if the first argument of
400
* `assertNotThrows` was the comment).
401
* @return {*} The return value of the function.
402
* @throws {goog.testing.JsUnitException} If the assertion failed.
403
*/
404
goog.testing.asserts.assertNotThrows = function(a, opt_b) {
405
'use strict';
406
_validateArguments(1, arguments);
407
var comment = commentArg(1, arguments);
408
var func = nonCommentArg(1, 1, arguments);
409
_assert(
410
comment, typeof func == 'function',
411
'Argument passed to assertNotThrows is not a function');
412
413
try {
414
return func();
415
} catch (e) {
416
comment = comment ? (comment + '\n') : '';
417
comment += 'A non expected exception was thrown from function passed to ' +
418
'assertNotThrows';
419
// Some browsers don't have a stack trace so at least have the error
420
// description.
421
var stackTrace = e['stack'] || e['stacktrace'] || e.toString();
422
goog.testing.asserts.raiseException(comment, stackTrace);
423
}
424
};
425
/** @const */
426
var assertNotThrows = goog.testing.asserts.assertNotThrows;
427
428
429
/**
430
* Asserts that the given callback function results in a JsUnitException when
431
* called, and that the resulting failure message matches the given expected
432
* message.
433
* @param {function() : void} callback Function to be run expected to result
434
* in a JsUnitException (usually contains a call to an assert).
435
* @param {string=} opt_expectedMessage Failure message expected to be given
436
* with the exception.
437
* @return {!goog.testing.JsUnitException} The error thrown by the function.
438
* @throws {goog.testing.JsUnitException} If the function did not throw a
439
* JsUnitException.
440
*/
441
goog.testing.asserts.assertThrowsJsUnitException = function(
442
callback, opt_expectedMessage) {
443
'use strict';
444
try {
445
callback();
446
} catch (e) {
447
var testCase = _getCurrentTestCase();
448
if (testCase) {
449
testCase.invalidateAssertionException(e);
450
} else {
451
goog.global.console.error(
452
'Failed to remove expected exception: no test case is installed.');
453
}
454
455
if (!e.isJsUnitException) {
456
goog.testing.asserts.fail(
457
'Expected a JsUnitException, got \'' + e + '\' instead');
458
}
459
460
if (typeof opt_expectedMessage != 'undefined' &&
461
e.message != opt_expectedMessage) {
462
goog.testing.asserts.fail(
463
'Expected message [' + opt_expectedMessage + '] but got [' +
464
e.message + ']');
465
}
466
467
return e;
468
}
469
470
var msg = 'Expected a failure';
471
if (typeof opt_expectedMessage != 'undefined') {
472
msg += ': ' + opt_expectedMessage;
473
}
474
throw new goog.testing.JsUnitException(msg);
475
};
476
/** @const */
477
var assertThrowsJsUnitException =
478
goog.testing.asserts.assertThrowsJsUnitException;
479
480
481
/**
482
* Asserts that the IThenable rejects.
483
*
484
* This is useful for asserting that async functions throw, like an asynchronous
485
* assertThrows. Example:
486
*
487
* ```
488
* async function shouldThrow() { throw new Error('error!'); }
489
* async function testShouldThrow() {
490
* const error = await assertRejects(shouldThrow());
491
* assertEquals('error!', error.message);
492
* }
493
* ```
494
*
495
* @param {!(string|IThenable)} a The assertion comment or the IThenable.
496
* @param {!IThenable=} opt_b The IThenable (if the first argument of
497
* `assertRejects` was the comment).
498
* @return {!IThenable<*>} A child IThenable which resolves with the error that
499
* the passed in IThenable rejects with. This IThenable will reject if the
500
* passed in IThenable does not reject.
501
*/
502
goog.testing.asserts.assertRejects = function(a, opt_b) {
503
'use strict';
504
_validateArguments(1, arguments);
505
var thenable = /** @type {!IThenable<*>} */ (nonCommentArg(1, 1, arguments));
506
var comment = commentArg(1, arguments);
507
_assert(
508
comment, goog.isObject(thenable) && typeof thenable.then === 'function',
509
'Argument passed to assertRejects is not an IThenable');
510
511
return thenable.then(
512
function() {
513
'use strict';
514
goog.testing.asserts.raiseException(
515
comment, 'IThenable passed into assertRejects did not reject');
516
},
517
function(e) {
518
'use strict';
519
goog.testing.asserts.removeOperaStacktrace_(e);
520
return e;
521
});
522
};
523
/** @const */
524
var assertRejects = goog.testing.asserts.assertRejects;
525
526
527
/**
528
* @param {*} a The value to assert (1 arg) or debug message (2 args).
529
* @param {*=} opt_b The value to assert (2 args only).
530
*/
531
goog.testing.asserts.assertTrue = function(a, opt_b) {
532
'use strict';
533
_validateArguments(1, arguments);
534
var comment = commentArg(1, arguments);
535
var booleanValue = nonCommentArg(1, 1, arguments);
536
537
_assert(
538
comment, typeof booleanValue === 'boolean',
539
'Bad argument to assertTrue(boolean): ' +
540
_displayStringForValue(booleanValue));
541
_assert(comment, booleanValue, 'Call to assertTrue(boolean) with false');
542
};
543
/** @const */
544
var assertTrue = goog.testing.asserts.assertTrue;
545
546
547
/**
548
* @param {*} a The value to assert (1 arg) or debug message (2 args).
549
* @param {*=} opt_b The value to assert (2 args only).
550
*/
551
goog.testing.asserts.assertFalse = function(a, opt_b) {
552
'use strict';
553
_validateArguments(1, arguments);
554
var comment = commentArg(1, arguments);
555
var booleanValue = nonCommentArg(1, 1, arguments);
556
557
_assert(
558
comment, typeof booleanValue === 'boolean',
559
'Bad argument to assertFalse(boolean): ' +
560
_displayStringForValue(booleanValue));
561
_assert(comment, !booleanValue, 'Call to assertFalse(boolean) with true');
562
};
563
/** @const */
564
var assertFalse = goog.testing.asserts.assertFalse;
565
566
567
/**
568
* @param {*} a The expected value (2 args) or the debug message (3 args).
569
* @param {*} b The actual value (2 args) or the expected value (3 args).
570
* @param {*=} opt_c The actual value (3 args only).
571
*/
572
goog.testing.asserts.assertEquals = function(a, b, opt_c) {
573
'use strict';
574
_validateArguments(2, arguments);
575
var var1 = nonCommentArg(1, 2, arguments);
576
var var2 = nonCommentArg(2, 2, arguments);
577
_assert(
578
commentArg(2, arguments), var1 === var2,
579
goog.testing.asserts.getDefaultErrorMsg_(var1, var2));
580
};
581
/** @const */
582
var assertEquals = goog.testing.asserts.assertEquals;
583
584
585
/**
586
* @param {*} a The expected value (2 args) or the debug message (3 args).
587
* @param {*} b The actual value (2 args) or the expected value (3 args).
588
* @param {*=} opt_c The actual value (3 args only).
589
*/
590
goog.testing.asserts.assertNotEquals = function(a, b, opt_c) {
591
'use strict';
592
_validateArguments(2, arguments);
593
var var1 = nonCommentArg(1, 2, arguments);
594
var var2 = nonCommentArg(2, 2, arguments);
595
_assert(
596
commentArg(2, arguments), var1 !== var2,
597
'Expected not to be ' + _displayStringForValue(var2));
598
};
599
/** @const */
600
var assertNotEquals = goog.testing.asserts.assertNotEquals;
601
602
/**
603
* @param {*} a The value to assert (1 arg) or debug message (2 args).
604
* @param {*=} opt_b The value to assert (2 args only).
605
*/
606
goog.testing.asserts.assertNull = function(a, opt_b) {
607
'use strict';
608
_validateArguments(1, arguments);
609
var aVar = nonCommentArg(1, 1, arguments);
610
_assert(
611
commentArg(1, arguments), aVar === null,
612
goog.testing.asserts.getDefaultErrorMsg_(null, aVar));
613
};
614
/** @const */
615
var assertNull = goog.testing.asserts.assertNull;
616
617
618
/**
619
* @param {*} a The value to assert (1 arg) or debug message (2 args).
620
* @param {*=} opt_b The value to assert (2 args only).
621
*/
622
goog.testing.asserts.assertNotNull = function(a, opt_b) {
623
'use strict';
624
_validateArguments(1, arguments);
625
var aVar = nonCommentArg(1, 1, arguments);
626
_assert(
627
commentArg(1, arguments), aVar !== null,
628
'Expected not to be ' + _displayStringForValue(null));
629
};
630
/** @const */
631
var assertNotNull = goog.testing.asserts.assertNotNull;
632
633
634
/**
635
* @param {*} a The value to assert (1 arg) or debug message (2 args).
636
* @param {*=} opt_b The value to assert (2 args only).
637
*/
638
goog.testing.asserts.assertUndefined = function(a, opt_b) {
639
'use strict';
640
_validateArguments(1, arguments);
641
var aVar = nonCommentArg(1, 1, arguments);
642
_assert(
643
commentArg(1, arguments), aVar === JSUNIT_UNDEFINED_VALUE,
644
goog.testing.asserts.getDefaultErrorMsg_(JSUNIT_UNDEFINED_VALUE, aVar));
645
};
646
/** @const */
647
var assertUndefined = goog.testing.asserts.assertUndefined;
648
649
650
/**
651
* @param {*} a The value to assert (1 arg) or debug message (2 args).
652
* @param {*=} opt_b The value to assert (2 args only).
653
*/
654
goog.testing.asserts.assertNotUndefined = function(a, opt_b) {
655
'use strict';
656
_validateArguments(1, arguments);
657
var aVar = nonCommentArg(1, 1, arguments);
658
_assert(
659
commentArg(1, arguments), aVar !== JSUNIT_UNDEFINED_VALUE,
660
'Expected not to be ' + _displayStringForValue(JSUNIT_UNDEFINED_VALUE));
661
};
662
/** @const */
663
var assertNotUndefined = goog.testing.asserts.assertNotUndefined;
664
665
/**
666
* @param {*} a The value to assert (1 arg) or debug message (2 args).
667
* @param {*=} opt_b The value to assert (2 args only).
668
*/
669
goog.testing.asserts.assertNullOrUndefined = function(a, opt_b) {
670
'use strict';
671
_validateArguments(1, arguments);
672
var aVar = nonCommentArg(1, 1, arguments);
673
_assert(
674
commentArg(1, arguments), aVar == null,
675
'Expected ' + _displayStringForValue(null) + ' or ' +
676
_displayStringForValue(JSUNIT_UNDEFINED_VALUE) + ' but was ' +
677
_displayStringForValue(aVar));
678
};
679
/** @const */
680
var assertNullOrUndefined = goog.testing.asserts.assertNullOrUndefined;
681
682
/**
683
* @param {*} a The value to assert (1 arg) or debug message (2 args).
684
* @param {*=} opt_b The value to assert (2 args only).
685
*/
686
goog.testing.asserts.assertNotNullNorUndefined = function(a, opt_b) {
687
'use strict';
688
_validateArguments(1, arguments);
689
goog.testing.asserts.assertNotNull.apply(null, arguments);
690
goog.testing.asserts.assertNotUndefined.apply(null, arguments);
691
};
692
/** @const */
693
var assertNotNullNorUndefined = goog.testing.asserts.assertNotNullNorUndefined;
694
695
696
/**
697
* @param {*} a The value to assert (1 arg) or debug message (2 args).
698
* @param {*=} opt_b The value to assert (2 args only).
699
*/
700
goog.testing.asserts.assertNonEmptyString = function(a, opt_b) {
701
'use strict';
702
_validateArguments(1, arguments);
703
var aVar = nonCommentArg(1, 1, arguments);
704
_assert(
705
commentArg(1, arguments), aVar !== JSUNIT_UNDEFINED_VALUE &&
706
aVar !== null && typeof aVar == 'string' && aVar !== '',
707
'Expected non-empty string but was ' + _displayStringForValue(aVar));
708
};
709
/** @const */
710
var assertNonEmptyString = goog.testing.asserts.assertNonEmptyString;
711
712
713
/**
714
* @param {*} a The value to assert (1 arg) or debug message (2 args).
715
* @param {*=} opt_b The value to assert (2 args only).
716
*/
717
goog.testing.asserts.assertNaN = function(a, opt_b) {
718
'use strict';
719
_validateArguments(1, arguments);
720
var aVar = nonCommentArg(1, 1, arguments);
721
_assert(
722
commentArg(1, arguments), aVar !== aVar,
723
'Expected NaN but was ' + _displayStringForValue(aVar));
724
};
725
/** @const */
726
var assertNaN = goog.testing.asserts.assertNaN;
727
728
729
/**
730
* @param {*} a The value to assert (1 arg) or debug message (2 args).
731
* @param {*=} opt_b The value to assert (2 args only).
732
*/
733
goog.testing.asserts.assertNotNaN = function(a, opt_b) {
734
'use strict';
735
_validateArguments(1, arguments);
736
var aVar = nonCommentArg(1, 1, arguments);
737
_assert(commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN');
738
};
739
/** @const */
740
var assertNotNaN = goog.testing.asserts.assertNotNaN;
741
742
743
/**
744
* The return value of the equality predicate passed to findDifferences below,
745
* in cases where the predicate can't test the input variables for equality.
746
* @type {?string}
747
*/
748
goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS = null;
749
750
751
/**
752
* The return value of the equality predicate passed to findDifferences below,
753
* in cases where the input vriables are equal.
754
* @type {?string}
755
*/
756
goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL = '';
757
758
759
/**
760
* @const {!Object<string, boolean>}
761
*/
762
goog.testing.asserts.ARRAY_TYPES = {
763
'Array': true,
764
'Float32Array': true,
765
'Float64Array': true,
766
'Int8Array': true,
767
'Int16Array': true,
768
'Int32Array': true,
769
'Uint8Array': true,
770
'Uint8ClampedArray': true,
771
'Uint16Array': true,
772
'Uint32Array': true,
773
'BigInt64Array': true,
774
'BigUint64Array': true
775
};
776
777
/**
778
* The result of a comparison performed by an EqualityFunction: if undefined,
779
* the inputs are equal; otherwise, a human-readable description of their
780
* inequality.
781
*
782
* @typedef {string|undefined}
783
*/
784
goog.testing.asserts.ComparisonResult;
785
786
/**
787
* A equality predicate.
788
*
789
* The first two arguments are the values to be compared. The third is an
790
* equality function which can be used to recursively apply findDifferences.
791
*
792
* An example comparison implementation for Array could be:
793
*
794
* function arrayEq(a, b, eq) {
795
* if (a.length !== b.length) {
796
* return "lengths unequal";
797
* }
798
*
799
* const differences = [];
800
* for (let i = 0; i < a.length; i++) {
801
* // Use the findDifferences implementation to perform recursive
802
* // comparisons.
803
* const diff = eq(a[i], b[i], eq);
804
* if (diff) {
805
* differences[i] = diff;
806
* }
807
* }
808
*
809
* if (differences) {
810
* return `found array differences: ${differences}`;
811
* }
812
*
813
* // Otherwise return undefined, indicating no differences.
814
* return undefined;
815
* }
816
*
817
* @typedef {function(?, ?, !goog.testing.asserts.EqualityFunction):
818
* ?goog.testing.asserts.ComparisonResult}
819
*/
820
goog.testing.asserts.EqualityFunction;
821
822
/**
823
* A map from prototype to custom equality matcher.
824
*
825
* @type {!Map<!Object, !goog.testing.asserts.EqualityFunction>}
826
* @private
827
*/
828
goog.testing.asserts.CUSTOM_EQUALITY_MATCHERS = new Map();
829
830
/**
831
* Returns the custom equality predicate for a given prototype, or else
832
* undefined.
833
*
834
* @param {?Object} prototype
835
* @return {!goog.testing.asserts.EqualityFunction|undefined}
836
* @private
837
*/
838
goog.testing.asserts.getCustomEquality = function(prototype) {
839
for (; (prototype != null) && (typeof prototype === 'object') &&
840
(prototype !== Object.prototype);
841
prototype = Object.getPrototypeOf(prototype)) {
842
const matcher = goog.testing.asserts.CUSTOM_EQUALITY_MATCHERS.get(
843
/** @type {!Object} */ (prototype));
844
if (matcher) {
845
return matcher;
846
}
847
}
848
return undefined;
849
};
850
851
/**
852
* Returns the most specific custom equality predicate which can be applied to
853
* both arguments, or else undefined.
854
*
855
* @param {!Object} obj1
856
* @param {!Object} obj2
857
* @return {!goog.testing.asserts.EqualityFunction|undefined}
858
* @private
859
*/
860
goog.testing.asserts.getMostSpecificCustomEquality = function(obj1, obj2) {
861
for (let prototype = Object.getPrototypeOf(obj1); (prototype != null) &&
862
(typeof prototype === 'object') && (prototype !== Object.prototype);
863
prototype = Object.getPrototypeOf(prototype)) {
864
if (prototype.isPrototypeOf(obj2)) {
865
return goog.testing.asserts.getCustomEquality(prototype);
866
}
867
}
868
869
// Otherwise, obj1 and obj2 did not share a common ancestor other than
870
// Object.prototype so we cannot have a comparator.
871
return undefined;
872
};
873
874
/**
875
* Executes a custom equality function
876
*
877
* @param {!goog.testing.asserts.EqualityFunction} comparator
878
* @param {!Object} obj1
879
* @param {!Object} obj2
880
* @param {string} path of the current field being checked.
881
* @return {?goog.testing.asserts.ComparisonResult}
882
* @private
883
*/
884
goog.testing.asserts.applyCustomEqualityFunction = function(
885
comparator, obj1, obj2, path) {
886
const /* !goog.testing.asserts.EqualityFunction */ callback =
887
(left, right, unusedEq) => {
888
const result = goog.testing.asserts.findDifferences(left, right);
889
return result ? (path ? path + ': ' : '') + result : undefined;
890
};
891
return comparator(obj1, obj2, callback);
892
};
893
894
/**
895
* Marks the given prototype as having equality semantics provided by the given
896
* custom equality function.
897
*
898
* This will cause findDifferences and assertObjectEquals to use the given
899
* function when comparing objects with this prototype. When comparing two
900
* objects with different prototypes, the equality (if any) attached to their
901
* lowest common ancestor in the prototype hierarchy will be used.
902
*
903
* @param {!Object} prototype
904
* @param {!goog.testing.asserts.EqualityFunction} fn
905
*/
906
goog.testing.asserts.registerComparator = function(prototype, fn) {
907
// First check that there is no comparator currently defined for this
908
// prototype.
909
if (goog.testing.asserts.CUSTOM_EQUALITY_MATCHERS.has(prototype)) {
910
throw new Error('duplicate comparator installation for ' + prototype);
911
}
912
913
// We cannot install custom equality matchers on Object.prototype, as it
914
// would replace all other comparisons.
915
if (prototype === Object.prototype) {
916
throw new Error('cannot customize root object comparator');
917
}
918
919
goog.testing.asserts.CUSTOM_EQUALITY_MATCHERS.set(prototype, fn);
920
};
921
922
/**
923
* Clears the custom equality function currently applied to the given prototype.
924
* Returns true if a function was removed.
925
*
926
* @param {!Object} prototype
927
* @return {boolean} whether a comparator was removed.
928
*/
929
goog.testing.asserts.clearCustomComparator = function(prototype) {
930
return goog.testing.asserts.CUSTOM_EQUALITY_MATCHERS.delete(prototype);
931
};
932
933
/**
934
* Determines if two items of any type match, and formulates an error message
935
* if not.
936
* @param {*} expected Expected argument to match.
937
* @param {*} actual Argument as a result of performing the test.
938
* @param {(function(string, *, *): ?string)=} opt_equalityPredicate An optional
939
* function that can be used to check equality of variables. It accepts 3
940
* arguments: type-of-variables, var1, var2 (in that order) and returns an
941
* error message if the variables are not equal,
942
* goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL if the variables
943
* are equal, or
944
* goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS if the predicate
945
* couldn't check the input variables. The function will be called only if
946
* the types of var1 and var2 are identical.
947
* @return {?string} Null on success, error message on failure.
948
*/
949
goog.testing.asserts.findDifferences = function(
950
expected, actual, opt_equalityPredicate) {
951
'use strict';
952
var failures = [];
953
// Non-null if there an error at the root (with no path). If so, we should
954
// fail, but not add to the failures array (because it will be included at the
955
// top anyway).
956
let /** ?string*/ rootFailure = null;
957
var seen1 = [];
958
var seen2 = [];
959
960
// To avoid infinite recursion when the two parameters are self-referential
961
// along the same path of properties, keep track of the object pairs already
962
// seen in this call subtree, and abort when a cycle is detected.
963
function innerAssertWithCycleCheck(var1, var2, path) {
964
// This is used for testing, so we can afford to be slow (but more
965
// accurate). So we just check whether var1 is in seen1. If we
966
// found var1 in index i, we simply need to check whether var2 is
967
// in seen2[i]. If it is, we do not recurse to check var1/var2. If
968
// it isn't, we know that the structures of the two objects must be
969
// different.
970
//
971
// This is based on the fact that values at index i in seen1 and
972
// seen2 will be checked for equality eventually (when
973
// innerAssertImplementation(seen1[i], seen2[i], path) finishes).
974
for (var i = 0; i < seen1.length; ++i) {
975
var match1 = seen1[i] === var1;
976
var match2 = seen2[i] === var2;
977
if (match1 || match2) {
978
if (!match1 || !match2) {
979
// Asymmetric cycles, so the objects have different structure.
980
failures.push('Asymmetric cycle detected at ' + path);
981
}
982
return;
983
}
984
}
985
986
seen1.push(var1);
987
seen2.push(var2);
988
innerAssertImplementation(var1, var2, path);
989
seen1.pop();
990
seen2.pop();
991
}
992
993
const equalityPredicate = function(type, var1, var2) {
994
'use strict';
995
// use the custom predicate if supplied.
996
const customPredicateResult = opt_equalityPredicate ?
997
opt_equalityPredicate(type, var1, var2) :
998
goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
999
if (customPredicateResult !==
1000
goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS) {
1001
return customPredicateResult;
1002
}
1003
// otherwise use the default behavior.
1004
const typedPredicate = EQUALITY_PREDICATES[type];
1005
if (!typedPredicate) {
1006
return goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
1007
}
1008
const equal = typedPredicate(var1, var2);
1009
return equal ? goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL :
1010
goog.testing.asserts.getDefaultErrorMsg_(var1, var2);
1011
};
1012
1013
/**
1014
* @param {*} var1 An item in the expected object.
1015
* @param {*} var2 The corresponding item in the actual object.
1016
* @param {string} path Their path in the objects.
1017
* @suppress {missingProperties} The map_ property is unknown to the compiler
1018
* unless goog.structs.Map is loaded.
1019
*/
1020
function innerAssertImplementation(var1, var2, path) {
1021
if (var1 === var2) {
1022
return;
1023
}
1024
1025
var typeOfVar1 = _trueTypeOf(var1);
1026
var typeOfVar2 = _trueTypeOf(var2);
1027
1028
if (typeOfVar1 === typeOfVar2) {
1029
// For two objects of the same type, if one is a prototype of another, use
1030
// the custom equality function for the more generic of the two
1031
// prototypes, if available.
1032
if (var1 && typeof var1 === 'object') {
1033
try {
1034
const o1 = /** @type {!Object} */ (var1);
1035
const o2 = /** @type {!Object} */ (var2);
1036
const comparator =
1037
goog.testing.asserts.getMostSpecificCustomEquality(o1, o2);
1038
if (comparator) {
1039
const result = goog.testing.asserts.applyCustomEqualityFunction(
1040
comparator, o1, o2, path);
1041
if (result != null) {
1042
if (path) {
1043
failures.push(path + ': ' + result);
1044
} else {
1045
rootFailure = result;
1046
}
1047
}
1048
return;
1049
}
1050
} catch (e) {
1051
// Catch and log errors from custom comparators but fall back onto
1052
// ordinary comparisons. Such errors can occur, e.g. with proxies or
1053
// when the prototypes of a polyfill are not traversable.
1054
//
1055
// If you see a failure due to this line, please do not use
1056
// findDifferences or assertObjectEquals on these argument types.
1057
goog.global.console.error('Error in custom comparator: ' + e);
1058
}
1059
}
1060
1061
const isArrayBuffer = typeOfVar1 === 'ArrayBuffer';
1062
if (isArrayBuffer) {
1063
// Since ArrayBuffer instances can't themselves be iterated through,
1064
// compare 1-byte-per-element views of them.
1065
var1 = new Uint8Array(/** @type {!ArrayBuffer} */ (var1));
1066
var2 = new Uint8Array(/** @type {!ArrayBuffer} */ (var2));
1067
}
1068
const isArray =
1069
isArrayBuffer || goog.testing.asserts.ARRAY_TYPES[typeOfVar1];
1070
var errorMessage = equalityPredicate(typeOfVar1, var1, var2);
1071
if (errorMessage !=
1072
goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS) {
1073
if (errorMessage !=
1074
goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL) {
1075
if (path) {
1076
failures.push(path + ': ' + errorMessage);
1077
} else {
1078
rootFailure = errorMessage;
1079
}
1080
}
1081
} else if (isArray && var1.length != var2.length) {
1082
failures.push(
1083
(path ? path + ': ' : '') + 'Expected ' + var1.length +
1084
'-element array ' +
1085
'but got a ' + var2.length + '-element array');
1086
} else if (typeOfVar1 == 'String') {
1087
// If the comparer cannot process strings (eg, roughlyEquals).
1088
if (var1 != var2) {
1089
const error = goog.testing.asserts.getDefaultErrorMsg_(var1, var2);
1090
if (path) {
1091
failures.push(path + ': ' + error);
1092
} else {
1093
rootFailure = error;
1094
}
1095
}
1096
} else {
1097
var childPath = path + (isArray ? '[%s]' : (path ? '.%s' : '%s'));
1098
// These type checks do not use _trueTypeOf because that does not work
1099
// for polyfilled Map/Set. Note that these checks may potentially fail
1100
// if var1 comes from a different window.
1101
if ((typeof Map != 'undefined' && var1 instanceof Map) ||
1102
(typeof Set != 'undefined' && var1 instanceof Set)) {
1103
var1.forEach(function(value, key) {
1104
'use strict';
1105
if (var2.has(key)) {
1106
// For a map, the values must be compared, but with Set, checking
1107
// that the second set contains the first set's "keys" is
1108
// sufficient.
1109
if (var2.get) {
1110
innerAssertWithCycleCheck(
1111
// NOTE: replace will call functions, so stringify eagerly.
1112
value, var2.get(key), childPath.replace('%s', String(key)));
1113
}
1114
} else {
1115
failures.push(
1116
key + ' not present in actual ' + (path || typeOfVar2));
1117
}
1118
});
1119
1120
var2.forEach(function(value, key) {
1121
'use strict';
1122
if (!var1.has(key)) {
1123
failures.push(
1124
key + ' not present in expected ' + (path || typeOfVar1));
1125
}
1126
});
1127
} else if (!var1['__iterator__']) {
1128
// if an object has an __iterator__ property, we have no way of
1129
// actually inspecting its raw properties, and JS 1.7 doesn't
1130
// overload [] to make it possible for someone to generically
1131
// use what the iterator returns to compare the object-managed
1132
// properties. This gets us into deep poo with things like
1133
// goog.structs.Map, at least on systems that support iteration.
1134
for (var prop in var1) {
1135
if (isArray && goog.testing.asserts.isArrayIndexProp_(prop)) {
1136
// Skip array indices for now. We'll handle them later.
1137
continue;
1138
}
1139
1140
if (prop in var2) {
1141
innerAssertWithCycleCheck(
1142
var1[prop], var2[prop], childPath.replace('%s', prop));
1143
} else {
1144
failures.push(
1145
'property ' + prop + ' not present in actual ' +
1146
(path || typeOfVar2));
1147
}
1148
}
1149
// make sure there aren't properties in var2 that are missing
1150
// from var1. if there are, then by definition they don't
1151
// match.
1152
for (var prop in var2) {
1153
if (isArray && goog.testing.asserts.isArrayIndexProp_(prop)) {
1154
// Skip array indices for now. We'll handle them later.
1155
continue;
1156
}
1157
1158
if (!(prop in var1)) {
1159
failures.push(
1160
'property ' + prop + ' not present in expected ' +
1161
(path || typeOfVar1));
1162
}
1163
}
1164
1165
// Handle array indices by iterating from 0 to arr.length.
1166
//
1167
// Although all browsers allow holes in arrays, browsers
1168
// are inconsistent in what they consider a hole. For example,
1169
// "[0,undefined,2]" has a hole on IE but not on Firefox.
1170
//
1171
// Because our style guide bans for...in iteration over arrays,
1172
// we assume that most users don't care about holes in arrays,
1173
// and that it is ok to say that a hole is equivalent to a slot
1174
// populated with 'undefined'.
1175
if (isArray) {
1176
for (prop = 0; prop < var1.length; prop++) {
1177
innerAssertWithCycleCheck(
1178
var1[prop], var2[prop],
1179
childPath.replace('%s', String(prop)));
1180
}
1181
}
1182
} else {
1183
// special-case for closure objects that have iterators
1184
if (typeof var1.equals === 'function') {
1185
// use the object's own equals function, assuming it accepts an
1186
// object and returns a boolean
1187
if (!var1.equals(var2)) {
1188
failures.push(
1189
'equals() returned false for ' + (path || typeOfVar1));
1190
}
1191
} else if (var1.map_) {
1192
// assume goog.structs.Map or goog.structs.Set, where comparing
1193
// their private map_ field is sufficient
1194
innerAssertWithCycleCheck(
1195
var1.map_, var2.map_, childPath.replace('%s', 'map_'));
1196
} else {
1197
// else die, so user knows we can't do anything
1198
failures.push(
1199
'unable to check ' + (path || typeOfVar1) +
1200
' for equality: it has an iterator we do not ' +
1201
'know how to handle. please add an equals method');
1202
}
1203
}
1204
}
1205
} else if (path) {
1206
failures.push(
1207
path + ': ' + goog.testing.asserts.getDefaultErrorMsg_(var1, var2));
1208
} else {
1209
rootFailure = goog.testing.asserts.getDefaultErrorMsg_(var1, var2);
1210
}
1211
}
1212
1213
innerAssertWithCycleCheck(expected, actual, '');
1214
1215
if (rootFailure) {
1216
return rootFailure;
1217
}
1218
return failures.length == 0 ? null : goog.testing.asserts.getDefaultErrorMsg_(
1219
expected, actual) +
1220
'\n ' + failures.join('\n ');
1221
};
1222
1223
1224
/**
1225
* Notes:
1226
* Object equality has some nasty browser quirks, and this implementation is
1227
* not 100% correct. For example,
1228
*
1229
* <code>
1230
* var a = [0, 1, 2];
1231
* var b = [0, 1, 2];
1232
* delete a[1];
1233
* b[1] = undefined;
1234
* assertObjectEquals(a, b); // should fail, but currently passes
1235
* </code>
1236
*
1237
* See asserts_test.html for more interesting edge cases.
1238
*
1239
* The first comparison object provided is the expected value, the second is
1240
* the actual.
1241
*
1242
* @param {*} a Assertion message or comparison object.
1243
* @param {*} b Comparison object.
1244
* @param {*=} opt_c Comparison object, if an assertion message was provided.
1245
*/
1246
goog.testing.asserts.assertObjectEquals = function(a, b, opt_c) {
1247
'use strict';
1248
_validateArguments(2, arguments);
1249
var v1 = nonCommentArg(1, 2, arguments);
1250
var v2 = nonCommentArg(2, 2, arguments);
1251
var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
1252
var differences = goog.testing.asserts.findDifferences(v1, v2);
1253
1254
_assert(failureMessage, !differences, differences);
1255
};
1256
/** @const */
1257
var assertObjectEquals = goog.testing.asserts.assertObjectEquals;
1258
1259
1260
/**
1261
* Similar to assertObjectEquals above, but accepts a tolerance margin.
1262
*
1263
* @param {*} a Assertion message or comparison object.
1264
* @param {*} b Comparison object.
1265
* @param {*} c Comparison object or tolerance.
1266
* @param {*=} opt_d Tolerance, if an assertion message was provided.
1267
*/
1268
goog.testing.asserts.assertObjectRoughlyEquals = function(a, b, c, opt_d) {
1269
'use strict';
1270
_validateArguments(3, arguments);
1271
var v1 = nonCommentArg(1, 3, arguments);
1272
var v2 = nonCommentArg(2, 3, arguments);
1273
var tolerance = nonCommentArg(3, 3, arguments);
1274
var failureMessage = commentArg(3, arguments) ? commentArg(3, arguments) : '';
1275
var equalityPredicate = function(type, var1, var2) {
1276
'use strict';
1277
var typedPredicate =
1278
goog.testing.asserts.primitiveRoughEqualityPredicates_[type];
1279
if (!typedPredicate) {
1280
return goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
1281
}
1282
var equal = typedPredicate(var1, var2, tolerance);
1283
return equal ? goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL :
1284
goog.testing.asserts.getDefaultErrorMsg_(var1, var2) +
1285
' which was more than ' + tolerance + ' away';
1286
};
1287
var differences =
1288
goog.testing.asserts.findDifferences(v1, v2, equalityPredicate);
1289
1290
_assert(failureMessage, !differences, differences);
1291
};
1292
/** @const */
1293
var assertObjectRoughlyEquals = goog.testing.asserts.assertObjectRoughlyEquals;
1294
1295
/**
1296
* Compares two arbitrary objects for non-equalness.
1297
*
1298
* All the same caveats as for assertObjectEquals apply here:
1299
* Undefined values may be confused for missing values, or vice versa.
1300
*
1301
* @param {*} a Assertion message or comparison object.
1302
* @param {*} b Comparison object.
1303
* @param {*=} opt_c Comparison object, if an assertion message was provided.
1304
*/
1305
goog.testing.asserts.assertObjectNotEquals = function(a, b, opt_c) {
1306
'use strict';
1307
_validateArguments(2, arguments);
1308
var v1 = nonCommentArg(1, 2, arguments);
1309
var v2 = nonCommentArg(2, 2, arguments);
1310
var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
1311
var differences = goog.testing.asserts.findDifferences(v1, v2);
1312
1313
_assert(failureMessage, differences, 'Objects should not be equal');
1314
};
1315
/** @const */
1316
var assertObjectNotEquals = goog.testing.asserts.assertObjectNotEquals;
1317
1318
1319
/**
1320
* Compares two arrays ignoring negative indexes and extra properties on the
1321
* array objects. Use case: Internet Explorer adds the index, lastIndex and
1322
* input enumerable fields to the result of string.match(/regexp/g), which makes
1323
* assertObjectEquals fail.
1324
* @param {*} a The expected array (2 args) or the debug message (3 args).
1325
* @param {*} b The actual array (2 args) or the expected array (3 args).
1326
* @param {*=} opt_c The actual array (3 args only).
1327
*/
1328
goog.testing.asserts.assertArrayEquals = function(a, b, opt_c) {
1329
'use strict';
1330
_validateArguments(2, arguments);
1331
var v1 = nonCommentArg(1, 2, arguments);
1332
var v2 = nonCommentArg(2, 2, arguments);
1333
var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
1334
1335
var typeOfVar1 = _trueTypeOf(v1);
1336
_assert(
1337
failureMessage, typeOfVar1 == 'Array',
1338
'Expected an array for assertArrayEquals but found a ' + typeOfVar1);
1339
1340
var typeOfVar2 = _trueTypeOf(v2);
1341
_assert(
1342
failureMessage, typeOfVar2 == 'Array',
1343
'Expected an array for assertArrayEquals but found a ' + typeOfVar2);
1344
1345
goog.testing.asserts.assertObjectEquals(
1346
failureMessage, Array.prototype.concat.call(v1),
1347
Array.prototype.concat.call(v2));
1348
};
1349
/** @const */
1350
var assertArrayEquals = goog.testing.asserts.assertArrayEquals;
1351
1352
1353
/**
1354
* Compares two objects that can be accessed like an array and assert that
1355
* each element is equal.
1356
* @param {string|Object} a Failure message (3 arguments)
1357
* or object #1 (2 arguments).
1358
* @param {Object} b Object #2 (2 arguments) or object #1 (3 arguments).
1359
* @param {Object=} opt_c Object #2 (3 arguments).
1360
*/
1361
goog.testing.asserts.assertElementsEquals = function(a, b, opt_c) {
1362
'use strict';
1363
_validateArguments(2, arguments);
1364
1365
var v1 = nonCommentArg(1, 2, arguments);
1366
var v2 = nonCommentArg(2, 2, arguments);
1367
var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
1368
1369
if (!v1) {
1370
goog.testing.asserts.assert(failureMessage, !v2);
1371
} else {
1372
goog.testing.asserts.assertEquals(
1373
'length mismatch: ' + failureMessage, v1.length, v2.length);
1374
for (var i = 0; i < v1.length; ++i) {
1375
goog.testing.asserts.assertEquals(
1376
'mismatch at index ' + i + ': ' + failureMessage, v1[i], v2[i]);
1377
}
1378
}
1379
};
1380
/** @const */
1381
var assertElementsEquals = goog.testing.asserts.assertElementsEquals;
1382
1383
1384
/**
1385
* Compares two objects that can be accessed like an array and assert that
1386
* each element is roughly equal.
1387
* @param {string|Object} a Failure message (4 arguments)
1388
* or object #1 (3 arguments).
1389
* @param {Object} b Object #1 (4 arguments) or object #2 (3 arguments).
1390
* @param {Object|number} c Object #2 (4 arguments) or tolerance (3 arguments).
1391
* @param {number=} opt_d tolerance (4 arguments).
1392
*/
1393
goog.testing.asserts.assertElementsRoughlyEqual = function(a, b, c, opt_d) {
1394
'use strict';
1395
_validateArguments(3, arguments);
1396
1397
var v1 = nonCommentArg(1, 3, arguments);
1398
var v2 = nonCommentArg(2, 3, arguments);
1399
var tolerance = nonCommentArg(3, 3, arguments);
1400
var failureMessage = commentArg(3, arguments) ? commentArg(3, arguments) : '';
1401
1402
if (!v1) {
1403
goog.testing.asserts.assert(failureMessage, !v2);
1404
} else {
1405
goog.testing.asserts.assertEquals(
1406
'length mismatch: ' + failureMessage, v1.length, v2.length);
1407
for (var i = 0; i < v1.length; ++i) {
1408
goog.testing.asserts.assertRoughlyEquals(
1409
failureMessage, v1[i], v2[i], tolerance);
1410
}
1411
}
1412
};
1413
/** @const */
1414
var assertElementsRoughlyEqual =
1415
goog.testing.asserts.assertElementsRoughlyEqual;
1416
1417
/**
1418
* Compares elements of two array-like or iterable objects using strict equality
1419
* without taking their order into account.
1420
* @param {string|!IArrayLike|!Iterable} a Assertion message or the
1421
* expected elements.
1422
* @param {!IArrayLike|!Iterable} b Expected elements or the actual
1423
* elements.
1424
* @param {!IArrayLike|!Iterable=} opt_c Actual elements.
1425
*/
1426
goog.testing.asserts.assertSameElements = function(a, b, opt_c) {
1427
'use strict';
1428
_validateArguments(2, arguments);
1429
var expected = nonCommentArg(1, 2, arguments);
1430
var actual = nonCommentArg(2, 2, arguments);
1431
var message = commentArg(2, arguments);
1432
1433
goog.testing.asserts.assertTrue(
1434
'Value of \'expected\' should be array-like or iterable',
1435
goog.testing.asserts.isArrayLikeOrIterable_(expected));
1436
1437
goog.testing.asserts.assertTrue(
1438
'Value of \'actual\' should be array-like or iterable',
1439
goog.testing.asserts.isArrayLikeOrIterable_(actual));
1440
1441
// Clones expected and actual and converts them to real arrays.
1442
expected = goog.testing.asserts.toArray_(expected);
1443
actual = goog.testing.asserts.toArray_(actual);
1444
// TODO(user): It would be great to show only the difference
1445
// between the expected and actual elements.
1446
_assert(
1447
message, expected.length == actual.length, 'Expected ' + expected.length +
1448
' elements: [' + expected + '], ' +
1449
'got ' + actual.length + ' elements: [' + actual + ']');
1450
1451
var toFind = goog.testing.asserts.toArray_(expected);
1452
for (var i = 0; i < actual.length; i++) {
1453
var index = goog.testing.asserts.indexOf_(toFind, actual[i]);
1454
_assert(
1455
message, index != -1,
1456
'Expected [' + expected + '], got [' + actual + ']');
1457
toFind.splice(index, 1);
1458
}
1459
};
1460
/** @const */
1461
var assertSameElements = goog.testing.asserts.assertSameElements;
1462
1463
/**
1464
* @param {*} obj Object to test.
1465
* @return {boolean} Whether given object is array-like or iterable.
1466
* @private
1467
*/
1468
goog.testing.asserts.isArrayLikeOrIterable_ = function(obj) {
1469
'use strict';
1470
return goog.isArrayLike(obj) || goog.testing.asserts.isIterable_(obj);
1471
};
1472
1473
/**
1474
* @param {*} a The value to assert (1 arg) or debug message (2 args).
1475
* @param {*=} opt_b The value to assert (2 args only).
1476
*/
1477
goog.testing.asserts.assertEvaluatesToTrue = function(a, opt_b) {
1478
'use strict';
1479
_validateArguments(1, arguments);
1480
var value = nonCommentArg(1, 1, arguments);
1481
if (!value) {
1482
_assert(commentArg(1, arguments), false, 'Expected to evaluate to true');
1483
}
1484
};
1485
/** @const */
1486
var assertEvaluatesToTrue = goog.testing.asserts.assertEvaluatesToTrue;
1487
1488
/**
1489
* @param {*} a The value to assert (1 arg) or debug message (2 args).
1490
* @param {*=} opt_b The value to assert (2 args only).
1491
*/
1492
goog.testing.asserts.assertEvaluatesToFalse = function(a, opt_b) {
1493
'use strict';
1494
_validateArguments(1, arguments);
1495
var value = nonCommentArg(1, 1, arguments);
1496
if (value) {
1497
_assert(commentArg(1, arguments), false, 'Expected to evaluate to false');
1498
}
1499
};
1500
/** @const */
1501
var assertEvaluatesToFalse = goog.testing.asserts.assertEvaluatesToFalse;
1502
1503
/**
1504
* Compares two HTML snippets.
1505
*
1506
* Take extra care if attributes are involved. `assertHTMLEquals`'s
1507
* implementation isn't prepared for complex cases. For example, the following
1508
* comparisons erroneously fail:
1509
* <pre>
1510
* assertHTMLEquals('<a href="x" target="y">', '<a target="y" href="x">');
1511
* assertHTMLEquals('<div class="a b">', '<div class="b a">');
1512
* assertHTMLEquals('<input disabled>', '<input disabled="disabled">');
1513
* </pre>
1514
*
1515
* When in doubt, use `goog.testing.dom.assertHtmlMatches`.
1516
*
1517
* @param {*} a The expected value (2 args) or the debug message (3 args).
1518
* @param {*} b The actual value (2 args) or the expected value (3 args).
1519
* @param {*=} opt_c The actual value (3 args only).
1520
*/
1521
goog.testing.asserts.assertHTMLEquals = function(a, b, opt_c) {
1522
'use strict';
1523
_validateArguments(2, arguments);
1524
var var1 = nonCommentArg(1, 2, arguments);
1525
var var2 = nonCommentArg(2, 2, arguments);
1526
var var1Standardized = standardizeHTML(var1);
1527
var var2Standardized = standardizeHTML(var2);
1528
1529
_assert(
1530
commentArg(2, arguments), var1Standardized === var2Standardized,
1531
goog.testing.asserts.getDefaultErrorMsg_(
1532
var1Standardized, var2Standardized));
1533
};
1534
/** @const */
1535
var assertHTMLEquals = goog.testing.asserts.assertHTMLEquals;
1536
1537
1538
/**
1539
* Compares two CSS property values to make sure that they represent the same
1540
* things. This will normalize values in the browser. For example, in Firefox,
1541
* this assertion will consider "rgb(0, 0, 255)" and "#0000ff" to be identical
1542
* values for the "color" property. This function won't normalize everything --
1543
* for example, in most browsers, "blue" will not match "#0000ff". It is
1544
* intended only to compensate for unexpected normalizations performed by
1545
* the browser that should also affect your expected value.
1546
* @param {string} a Assertion message, or the CSS property name.
1547
* @param {string} b CSS property name, or the expected value.
1548
* @param {string} c The expected value, or the actual value.
1549
* @param {string=} opt_d The actual value.
1550
*/
1551
goog.testing.asserts.assertCSSValueEquals = function(a, b, c, opt_d) {
1552
'use strict';
1553
_validateArguments(3, arguments);
1554
var propertyName = nonCommentArg(1, 3, arguments);
1555
var expectedValue = nonCommentArg(2, 3, arguments);
1556
var actualValue = nonCommentArg(3, 3, arguments);
1557
var expectedValueStandardized =
1558
standardizeCSSValue(propertyName, expectedValue);
1559
var actualValueStandardized = standardizeCSSValue(propertyName, actualValue);
1560
1561
_assert(
1562
commentArg(3, arguments),
1563
expectedValueStandardized == actualValueStandardized,
1564
goog.testing.asserts.getDefaultErrorMsg_(
1565
expectedValueStandardized, actualValueStandardized));
1566
};
1567
/** @const */
1568
var assertCSSValueEquals = goog.testing.asserts.assertCSSValueEquals;
1569
1570
1571
/**
1572
* @param {*} a The expected value (2 args) or the debug message (3 args).
1573
* @param {*} b The actual value (2 args) or the expected value (3 args).
1574
* @param {*=} opt_c The actual value (3 args only).
1575
*/
1576
goog.testing.asserts.assertHashEquals = function(a, b, opt_c) {
1577
'use strict';
1578
_validateArguments(2, arguments);
1579
var var1 = nonCommentArg(1, 2, arguments);
1580
var var2 = nonCommentArg(2, 2, arguments);
1581
var message = commentArg(2, arguments);
1582
for (var key in var1) {
1583
_assert(
1584
message, key in var2,
1585
'Expected hash had key ' + key + ' that was not found');
1586
_assert(
1587
message, var1[key] == var2[key], 'Value for key ' + key +
1588
' mismatch - expected = ' + var1[key] + ', actual = ' + var2[key]);
1589
}
1590
1591
for (var key in var2) {
1592
_assert(
1593
message, key in var1,
1594
'Actual hash had key ' + key + ' that was not expected');
1595
}
1596
};
1597
/** @const */
1598
var assertHashEquals = goog.testing.asserts.assertHashEquals;
1599
1600
1601
/**
1602
* @param {*} a The expected value (3 args) or the debug message (4 args).
1603
* @param {*} b The actual value (3 args) or the expected value (4 args).
1604
* @param {*} c The tolerance (3 args) or the actual value (4 args).
1605
* @param {*=} opt_d The tolerance (4 args only).
1606
*/
1607
goog.testing.asserts.assertRoughlyEquals = function(a, b, c, opt_d) {
1608
'use strict';
1609
_validateArguments(3, arguments);
1610
var expected = nonCommentArg(1, 3, arguments);
1611
var actual = nonCommentArg(2, 3, arguments);
1612
var tolerance = nonCommentArg(3, 3, arguments);
1613
_assert(
1614
commentArg(3, arguments),
1615
goog.testing.asserts.numberRoughEqualityPredicate_(
1616
expected, actual, tolerance),
1617
'Expected ' + expected + ', but got ' + actual + ' which was more than ' +
1618
tolerance + ' away');
1619
};
1620
/** @const */
1621
var assertRoughlyEquals = goog.testing.asserts.assertRoughlyEquals;
1622
1623
1624
/**
1625
* Checks if the test value is included in the given container. The container
1626
* can be a string (where "included" means a substring), an array or any
1627
* `IArrayLike` (where "included" means a member), or any type implementing
1628
* `indexOf` with similar semantics (returning -1 for not included).
1629
*
1630
* @param {*} a Failure message (3 arguments) or the test value
1631
* (2 arguments).
1632
* @param {*} b The test value (3 arguments) or the container
1633
* (2 arguments).
1634
* @param {*=} opt_c The container.
1635
*/
1636
goog.testing.asserts.assertContains = function(a, b, opt_c) {
1637
'use strict';
1638
_validateArguments(2, arguments);
1639
var contained = nonCommentArg(1, 2, arguments);
1640
var container = nonCommentArg(2, 2, arguments);
1641
_assert(
1642
commentArg(2, arguments),
1643
goog.testing.asserts.contains_(container, contained),
1644
'Expected \'' + container + '\' to contain \'' + contained + '\'');
1645
};
1646
/** @const */
1647
var assertContains = goog.testing.asserts.assertContains;
1648
1649
/**
1650
* Checks if the test value is not included in the given container. The
1651
* container can be a string (where "included" means a substring), an array or
1652
* any `IArrayLike` (where "included" means a member), or any type implementing
1653
* `indexOf` with similar semantics (returning -1 for not included).
1654
* @param {*} a Failure message (3 arguments) or the contained element
1655
* (2 arguments).
1656
* @param {*} b The contained element (3 arguments) or the container
1657
* (2 arguments).
1658
* @param {*=} opt_c The container.
1659
*/
1660
goog.testing.asserts.assertNotContains = function(a, b, opt_c) {
1661
'use strict';
1662
_validateArguments(2, arguments);
1663
var contained = nonCommentArg(1, 2, arguments);
1664
var container = nonCommentArg(2, 2, arguments);
1665
_assert(
1666
commentArg(2, arguments),
1667
!goog.testing.asserts.contains_(container, contained),
1668
'Expected \'' + container + '\' not to contain \'' + contained + '\'');
1669
};
1670
/** @const */
1671
var assertNotContains = goog.testing.asserts.assertNotContains;
1672
1673
1674
/**
1675
* Checks if the given string matches the given regular expression.
1676
* @param {*} a Failure message (3 arguments) or the expected regular
1677
* expression as a string or RegExp (2 arguments).
1678
* @param {*} b The regular expression (3 arguments) or the string to test
1679
* (2 arguments).
1680
* @param {*=} opt_c The string to test.
1681
*/
1682
goog.testing.asserts.assertRegExp = function(a, b, opt_c) {
1683
'use strict';
1684
_validateArguments(2, arguments);
1685
var regexp = nonCommentArg(1, 2, arguments);
1686
var string = nonCommentArg(2, 2, arguments);
1687
if (typeof(regexp) == 'string') {
1688
regexp = new RegExp(regexp);
1689
}
1690
_assert(
1691
commentArg(2, arguments), regexp.test(string),
1692
'Expected \'' + string + '\' to match RegExp ' + regexp.toString());
1693
};
1694
/** @const */
1695
var assertRegExp = goog.testing.asserts.assertRegExp;
1696
1697
1698
/**
1699
* Converts an array-like or iterable object to an array (clones it if it's
1700
* already an array).
1701
* @param {!Iterable|!IArrayLike} obj The collection object.
1702
* @return {!Array<?>} Copy of the collection as array.
1703
* @private
1704
*/
1705
goog.testing.asserts.toArray_ = function(obj) {
1706
'use strict';
1707
var ret = [];
1708
if (goog.testing.asserts.isIterable_(obj)) {
1709
var iterator =
1710
goog.testing.asserts.getIterator_(/** @type {!Iterable} */ (obj));
1711
1712
// Cannot use for..of syntax here as ES6 syntax is not available in Closure.
1713
// See b/117231092
1714
while (true) {
1715
var result = iterator.next();
1716
if (result.done) {
1717
return ret;
1718
}
1719
ret.push(result.value);
1720
}
1721
}
1722
1723
for (var i = 0; i < /** @type {!IArrayLike} */ (obj).length; i++) {
1724
ret[i] = obj[i];
1725
}
1726
return ret;
1727
};
1728
1729
// TODO(nnaze): Consider moving isIterable_ and getIterator_ functionality
1730
// into goog.iter.es6. See discussion in cl/217356297.
1731
1732
/**
1733
* @param {*} obj
1734
* @return {boolean} Whether the object is iterable (JS iterator protocol).
1735
* @private
1736
*/
1737
goog.testing.asserts.isIterable_ = function(obj) {
1738
'use strict';
1739
return !!(
1740
typeof Symbol !== 'undefined' && Symbol.iterator && obj[Symbol.iterator]);
1741
};
1742
1743
/**
1744
* @param {!Iterable} iterable
1745
* @return {!Iterator} An iterator for obj.
1746
* @throws {!goog.testing.JsUnitException} If the given object is not iterable.
1747
* @private
1748
*/
1749
goog.testing.asserts.getIterator_ = function(iterable) {
1750
'use strict';
1751
if (!goog.testing.asserts.isIterable_(iterable)) {
1752
goog.testing.asserts.raiseException('parameter iterable is not iterable');
1753
}
1754
1755
return iterable[Symbol.iterator]();
1756
};
1757
1758
1759
/**
1760
* Finds the position of the first occurrence of an element in a container.
1761
* @param {IArrayLike<?>|{indexOf: function(*): number}} container
1762
* The array to find the element in.
1763
* @param {*} contained Element to find.
1764
* @return {number} Index of the first occurrence or -1 if not found.
1765
* @private
1766
*/
1767
goog.testing.asserts.indexOf_ = function(container, contained) {
1768
'use strict';
1769
if (typeof container.indexOf == 'function') {
1770
return /** @type {{indexOf: function(*): number}} */ (container).indexOf(
1771
contained);
1772
} else {
1773
// IE6/7 do not have indexOf so do a search.
1774
for (var i = 0; i < /** @type {!IArrayLike<?>} */ (container).length; i++) {
1775
if (container[i] === contained) {
1776
return i;
1777
}
1778
}
1779
return -1;
1780
}
1781
};
1782
1783
1784
/**
1785
* Tells whether the array contains the given element.
1786
* @param {IArrayLike<?>|{indexOf: function(*): number}} container The array to
1787
* find the element in.
1788
* @param {*} contained Element to find.
1789
* @return {boolean} Whether the element is in the array.
1790
* @private
1791
*/
1792
goog.testing.asserts.contains_ = function(container, contained) {
1793
'use strict';
1794
// TODO(user): Can we check for container.contains as well?
1795
// That would give us support for most goog.structs (though weird results
1796
// with anything else with a contains method, like goog.math.Range). Falling
1797
// back with container.some would catch all iterables, too.
1798
return goog.testing.asserts.indexOf_(container, contained) != -1;
1799
};
1800
1801
var standardizeHTML = function(html) {
1802
'use strict';
1803
var translator = document.createElement('div');
1804
1805
goog.dom.safe.setInnerHtml(
1806
translator,
1807
goog.html.uncheckedconversions
1808
.safeHtmlFromStringKnownToSatisfyTypeContract(
1809
goog.string.Const.from('HTML is never attached to DOM'), html));
1810
1811
// Trim whitespace from result (without relying on goog.string)
1812
return translator.innerHTML.replace(/^\s+|\s+$/g, '');
1813
};
1814
1815
1816
/**
1817
* Standardizes a CSS value for a given property by applying it to an element
1818
* and then reading it back.
1819
* @param {string} propertyName CSS property name.
1820
* @param {string} value CSS value.
1821
* @return {string} Normalized CSS value.
1822
*/
1823
var standardizeCSSValue = function(propertyName, value) {
1824
'use strict';
1825
var styleDeclaration = document.createElement('div').style;
1826
styleDeclaration[propertyName] = value;
1827
return styleDeclaration[propertyName];
1828
};
1829
1830
1831
/**
1832
* Raises a JsUnit exception with the given comment. If the exception is
1833
* unexpectedly caught during a unit test, it will be rethrown so that it is
1834
* seen by the test framework.
1835
* @param {string} comment A summary for the exception.
1836
* @param {string=} opt_message A description of the exception.
1837
*/
1838
goog.testing.asserts.raiseException = function(comment, opt_message) {
1839
'use strict';
1840
var e = new goog.testing.JsUnitException(comment, opt_message);
1841
1842
var testCase = _getCurrentTestCase();
1843
if (testCase) {
1844
testCase.raiseAssertionException(e);
1845
} else {
1846
goog.global.console.error(
1847
'Failed to save thrown exception: no test case is installed.');
1848
throw e;
1849
}
1850
};
1851
1852
1853
/**
1854
* Helper function for assertObjectEquals.
1855
* @param {string} prop A property name.
1856
* @return {boolean} If the property name is an array index.
1857
* @private
1858
*/
1859
goog.testing.asserts.isArrayIndexProp_ = function(prop) {
1860
'use strict';
1861
return prop === '0' || /^[1-9][0-9]*$/.test(prop);
1862
};
1863
1864
/** @define {boolean} */
1865
goog.EXPORT_ASSERTIONS = goog.define('goog.EXPORT_ASSERTIONS', true);
1866
/*
1867
* These symbols are both exported in the global namespace (for legacy
1868
* reasons) and as part of the goog.testing.asserts namespace. Although they
1869
* can be used globally in tests, these symbols are allowed to be imported for
1870
* cleaner typing.
1871
*/
1872
if (goog.EXPORT_ASSERTIONS) {
1873
goog.exportSymbol('fail', fail);
1874
goog.exportSymbol('assert', assert);
1875
goog.exportSymbol('assertThrows', assertThrows);
1876
goog.exportSymbol('assertNotThrows', assertNotThrows);
1877
goog.exportSymbol('assertThrowsJsUnitException', assertThrowsJsUnitException);
1878
goog.exportSymbol('assertRejects', assertRejects);
1879
goog.exportSymbol('assertTrue', assertTrue);
1880
goog.exportSymbol('assertFalse', assertFalse);
1881
goog.exportSymbol('assertEquals', assertEquals);
1882
goog.exportSymbol('assertNotEquals', assertNotEquals);
1883
goog.exportSymbol('assertNull', assertNull);
1884
goog.exportSymbol('assertNotNull', assertNotNull);
1885
goog.exportSymbol('assertUndefined', assertUndefined);
1886
goog.exportSymbol('assertNotUndefined', assertNotUndefined);
1887
goog.exportSymbol('assertNullOrUndefined', assertNullOrUndefined);
1888
goog.exportSymbol('assertNotNullNorUndefined', assertNotNullNorUndefined);
1889
goog.exportSymbol('assertNonEmptyString', assertNonEmptyString);
1890
goog.exportSymbol('assertNaN', assertNaN);
1891
goog.exportSymbol('assertNotNaN', assertNotNaN);
1892
goog.exportSymbol('assertObjectEquals', assertObjectEquals);
1893
goog.exportSymbol('assertObjectRoughlyEquals', assertObjectRoughlyEquals);
1894
goog.exportSymbol('assertObjectNotEquals', assertObjectNotEquals);
1895
goog.exportSymbol('assertArrayEquals', assertArrayEquals);
1896
goog.exportSymbol('assertElementsEquals', assertElementsEquals);
1897
goog.exportSymbol('assertElementsRoughlyEqual', assertElementsRoughlyEqual);
1898
goog.exportSymbol('assertSameElements', assertSameElements);
1899
goog.exportSymbol('assertEvaluatesToTrue', assertEvaluatesToTrue);
1900
goog.exportSymbol('assertEvaluatesToFalse', assertEvaluatesToFalse);
1901
goog.exportSymbol('assertHTMLEquals', assertHTMLEquals);
1902
goog.exportSymbol('assertHashEquals', assertHashEquals);
1903
goog.exportSymbol('assertRoughlyEquals', assertRoughlyEquals);
1904
goog.exportSymbol('assertContains', assertContains);
1905
goog.exportSymbol('assertNotContains', assertNotContains);
1906
goog.exportSymbol('assertRegExp', assertRegExp);
1907
}
1908
1909