|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 var EXPORTED_SYMBOLS = ['Assert', 'Expect']; |
|
6 |
|
7 const Cu = Components.utils; |
|
8 |
|
9 Cu.import("resource://gre/modules/Services.jsm"); |
|
10 |
|
11 var broker = {}; Cu.import('resource://mozmill/driver/msgbroker.js', broker); |
|
12 var errors = {}; Cu.import('resource://mozmill/modules/errors.js', errors); |
|
13 var stack = {}; Cu.import('resource://mozmill/modules/stack.js', stack); |
|
14 |
|
15 /** |
|
16 * @name assertions |
|
17 * @namespace Defines expect and assert methods to be used for assertions. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * The Assert class implements fatal assertions, and can be used in cases |
|
22 * when a failing test has to directly abort the current test function. All |
|
23 * remaining tasks will not be performed. |
|
24 * |
|
25 */ |
|
26 var Assert = function () {} |
|
27 |
|
28 Assert.prototype = { |
|
29 |
|
30 // The following deepEquals implementation is from Narwhal under this license: |
|
31 |
|
32 // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 |
|
33 // |
|
34 // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! |
|
35 // |
|
36 // Originally from narwhal.js (http://narwhaljs.org) |
|
37 // Copyright (c) 2009 Thomas Robinson <280north.com> |
|
38 // |
|
39 // Permission is hereby granted, free of charge, to any person obtaining a copy |
|
40 // of this software and associated documentation files (the 'Software'), to |
|
41 // deal in the Software without restriction, including without limitation the |
|
42 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
|
43 // sell copies of the Software, and to permit persons to whom the Software is |
|
44 // furnished to do so, subject to the following conditions: |
|
45 // |
|
46 // The above copyright notice and this permission notice shall be included in |
|
47 // all copies or substantial portions of the Software. |
|
48 // |
|
49 // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
50 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
51 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
52 // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
53 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
54 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
55 |
|
56 _deepEqual: function (actual, expected) { |
|
57 // 7.1. All identical values are equivalent, as determined by ===. |
|
58 if (actual === expected) { |
|
59 return true; |
|
60 |
|
61 // 7.2. If the expected value is a Date object, the actual value is |
|
62 // equivalent if it is also a Date object that refers to the same time. |
|
63 } else if (actual instanceof Date && expected instanceof Date) { |
|
64 return actual.getTime() === expected.getTime(); |
|
65 |
|
66 // 7.3. Other pairs that do not both pass typeof value == 'object', |
|
67 // equivalence is determined by ==. |
|
68 } else if (typeof actual != 'object' && typeof expected != 'object') { |
|
69 return actual == expected; |
|
70 |
|
71 // 7.4. For all other Object pairs, including Array objects, equivalence is |
|
72 // determined by having the same number of owned properties (as verified |
|
73 // with Object.prototype.hasOwnProperty.call), the same set of keys |
|
74 // (although not necessarily the same order), equivalent values for every |
|
75 // corresponding key, and an identical 'prototype' property. Note: this |
|
76 // accounts for both named and indexed properties on Arrays. |
|
77 } else { |
|
78 return this._objEquiv(actual, expected); |
|
79 } |
|
80 }, |
|
81 |
|
82 _objEquiv: function (a, b) { |
|
83 if (a == null || a == undefined || b == null || b == undefined) |
|
84 return false; |
|
85 // an identical 'prototype' property. |
|
86 if (a.prototype !== b.prototype) return false; |
|
87 |
|
88 function isArguments(object) { |
|
89 return Object.prototype.toString.call(object) == '[object Arguments]'; |
|
90 } |
|
91 |
|
92 //~~~I've managed to break Object.keys through screwy arguments passing. |
|
93 // Converting to array solves the problem. |
|
94 if (isArguments(a)) { |
|
95 if (!isArguments(b)) { |
|
96 return false; |
|
97 } |
|
98 a = pSlice.call(a); |
|
99 b = pSlice.call(b); |
|
100 return _deepEqual(a, b); |
|
101 } |
|
102 try { |
|
103 var ka = Object.keys(a), |
|
104 kb = Object.keys(b), |
|
105 key, i; |
|
106 } catch (e) {//happens when one is a string literal and the other isn't |
|
107 return false; |
|
108 } |
|
109 // having the same number of owned properties (keys incorporates |
|
110 // hasOwnProperty) |
|
111 if (ka.length != kb.length) |
|
112 return false; |
|
113 //the same set of keys (although not necessarily the same order), |
|
114 ka.sort(); |
|
115 kb.sort(); |
|
116 //~~~cheap key test |
|
117 for (i = ka.length - 1; i >= 0; i--) { |
|
118 if (ka[i] != kb[i]) |
|
119 return false; |
|
120 } |
|
121 //equivalent values for every corresponding key, and |
|
122 //~~~possibly expensive deep test |
|
123 for (i = ka.length - 1; i >= 0; i--) { |
|
124 key = ka[i]; |
|
125 if (!this._deepEqual(a[key], b[key])) return false; |
|
126 } |
|
127 return true; |
|
128 }, |
|
129 |
|
130 _expectedException : function Assert__expectedException(actual, expected) { |
|
131 if (!actual || !expected) { |
|
132 return false; |
|
133 } |
|
134 |
|
135 if (expected instanceof RegExp) { |
|
136 return expected.test(actual); |
|
137 } else if (actual instanceof expected) { |
|
138 return true; |
|
139 } else if (expected.call({}, actual) === true) { |
|
140 return true; |
|
141 } else if (actual.name === expected.name) { |
|
142 return true; |
|
143 } |
|
144 |
|
145 return false; |
|
146 }, |
|
147 |
|
148 /** |
|
149 * Log a test as failing by throwing an AssertionException. |
|
150 * |
|
151 * @param {object} aResult |
|
152 * Test result details used for reporting. |
|
153 * <dl> |
|
154 * <dd>fileName</dd> |
|
155 * <dt>Name of the file in which the assertion failed.</dt> |
|
156 * <dd>functionName</dd> |
|
157 * <dt>Function in which the assertion failed.</dt> |
|
158 * <dd>lineNumber</dd> |
|
159 * <dt>Line number of the file in which the assertion failed.</dt> |
|
160 * <dd>message</dd> |
|
161 * <dt>Message why the assertion failed.</dt> |
|
162 * </dl> |
|
163 * @throws {errors.AssertionError} |
|
164 * |
|
165 */ |
|
166 _logFail: function Assert__logFail(aResult) { |
|
167 throw new errors.AssertionError(aResult.message, |
|
168 aResult.fileName, |
|
169 aResult.lineNumber, |
|
170 aResult.functionName, |
|
171 aResult.name); |
|
172 }, |
|
173 |
|
174 /** |
|
175 * Log a test as passing by adding a pass frame. |
|
176 * |
|
177 * @param {object} aResult |
|
178 * Test result details used for reporting. |
|
179 * <dl> |
|
180 * <dd>fileName</dd> |
|
181 * <dt>Name of the file in which the assertion failed.</dt> |
|
182 * <dd>functionName</dd> |
|
183 * <dt>Function in which the assertion failed.</dt> |
|
184 * <dd>lineNumber</dd> |
|
185 * <dt>Line number of the file in which the assertion failed.</dt> |
|
186 * <dd>message</dd> |
|
187 * <dt>Message why the assertion failed.</dt> |
|
188 * </dl> |
|
189 */ |
|
190 _logPass: function Assert__logPass(aResult) { |
|
191 broker.pass({pass: aResult}); |
|
192 }, |
|
193 |
|
194 /** |
|
195 * Test the condition and mark test as passed or failed |
|
196 * |
|
197 * @param {boolean} aCondition |
|
198 * Condition to test. |
|
199 * @param {string} aMessage |
|
200 * Message to show for the test result |
|
201 * @param {string} aDiagnosis |
|
202 * Diagnose message to show for the test result |
|
203 * @throws {errors.AssertionError} |
|
204 * |
|
205 * @returns {boolean} Result of the test. |
|
206 */ |
|
207 _test: function Assert__test(aCondition, aMessage, aDiagnosis) { |
|
208 let diagnosis = aDiagnosis || ""; |
|
209 let message = aMessage || ""; |
|
210 |
|
211 if (diagnosis) |
|
212 message = aMessage ? message + " - " + diagnosis : diagnosis; |
|
213 |
|
214 // Build result data |
|
215 let frame = stack.findCallerFrame(Components.stack); |
|
216 |
|
217 let result = { |
|
218 'fileName' : frame.filename.replace(/(.*)-> /, ""), |
|
219 'functionName' : frame.name, |
|
220 'lineNumber' : frame.lineNumber, |
|
221 'message' : message |
|
222 }; |
|
223 |
|
224 // Log test result |
|
225 if (aCondition) { |
|
226 this._logPass(result); |
|
227 } |
|
228 else { |
|
229 result.stack = Components.stack; |
|
230 this._logFail(result); |
|
231 } |
|
232 |
|
233 return aCondition; |
|
234 }, |
|
235 |
|
236 /** |
|
237 * Perform an always passing test |
|
238 * |
|
239 * @param {string} aMessage |
|
240 * Message to show for the test result. |
|
241 * @returns {boolean} Always returns true. |
|
242 */ |
|
243 pass: function Assert_pass(aMessage) { |
|
244 return this._test(true, aMessage, undefined); |
|
245 }, |
|
246 |
|
247 /** |
|
248 * Perform an always failing test |
|
249 * |
|
250 * @param {string} aMessage |
|
251 * Message to show for the test result. |
|
252 * @throws {errors.AssertionError} |
|
253 * |
|
254 * @returns {boolean} Always returns false. |
|
255 */ |
|
256 fail: function Assert_fail(aMessage) { |
|
257 return this._test(false, aMessage, undefined); |
|
258 }, |
|
259 |
|
260 /** |
|
261 * Test if the value pass |
|
262 * |
|
263 * @param {boolean|string|number|object} aValue |
|
264 * Value to test. |
|
265 * @param {string} aMessage |
|
266 * Message to show for the test result. |
|
267 * @throws {errors.AssertionError} |
|
268 * |
|
269 * @returns {boolean} Result of the test. |
|
270 */ |
|
271 ok: function Assert_ok(aValue, aMessage) { |
|
272 let condition = !!aValue; |
|
273 let diagnosis = "got '" + aValue + "'"; |
|
274 |
|
275 return this._test(condition, aMessage, diagnosis); |
|
276 }, |
|
277 |
|
278 /** |
|
279 * Test if both specified values are identical. |
|
280 * |
|
281 * @param {boolean|string|number|object} aValue |
|
282 * Value to test. |
|
283 * @param {boolean|string|number|object} aExpected |
|
284 * Value to strictly compare with. |
|
285 * @param {string} aMessage |
|
286 * Message to show for the test result |
|
287 * @throws {errors.AssertionError} |
|
288 * |
|
289 * @returns {boolean} Result of the test. |
|
290 */ |
|
291 equal: function Assert_equal(aValue, aExpected, aMessage) { |
|
292 let condition = (aValue === aExpected); |
|
293 let diagnosis = "'" + aValue + "' should equal '" + aExpected + "'"; |
|
294 |
|
295 return this._test(condition, aMessage, diagnosis); |
|
296 }, |
|
297 |
|
298 /** |
|
299 * Test if both specified values are not identical. |
|
300 * |
|
301 * @param {boolean|string|number|object} aValue |
|
302 * Value to test. |
|
303 * @param {boolean|string|number|object} aExpected |
|
304 * Value to strictly compare with. |
|
305 * @param {string} aMessage |
|
306 * Message to show for the test result |
|
307 * @throws {errors.AssertionError} |
|
308 * |
|
309 * @returns {boolean} Result of the test. |
|
310 */ |
|
311 notEqual: function Assert_notEqual(aValue, aExpected, aMessage) { |
|
312 let condition = (aValue !== aExpected); |
|
313 let diagnosis = "'" + aValue + "' should not equal '" + aExpected + "'"; |
|
314 |
|
315 return this._test(condition, aMessage, diagnosis); |
|
316 }, |
|
317 |
|
318 /** |
|
319 * Test if an object equals another object |
|
320 * |
|
321 * @param {object} aValue |
|
322 * The object to test. |
|
323 * @param {object} aExpected |
|
324 * The object to strictly compare with. |
|
325 * @param {string} aMessage |
|
326 * Message to show for the test result |
|
327 * @throws {errors.AssertionError} |
|
328 * |
|
329 * @returns {boolean} Result of the test. |
|
330 */ |
|
331 deepEqual: function equal(aValue, aExpected, aMessage) { |
|
332 let condition = this._deepEqual(aValue, aExpected); |
|
333 try { |
|
334 var aValueString = JSON.stringify(aValue); |
|
335 } catch (e) { |
|
336 var aValueString = String(aValue); |
|
337 } |
|
338 try { |
|
339 var aExpectedString = JSON.stringify(aExpected); |
|
340 } catch (e) { |
|
341 var aExpectedString = String(aExpected); |
|
342 } |
|
343 |
|
344 let diagnosis = "'" + aValueString + "' should equal '" + |
|
345 aExpectedString + "'"; |
|
346 |
|
347 return this._test(condition, aMessage, diagnosis); |
|
348 }, |
|
349 |
|
350 /** |
|
351 * Test if an object does not equal another object |
|
352 * |
|
353 * @param {object} aValue |
|
354 * The object to test. |
|
355 * @param {object} aExpected |
|
356 * The object to strictly compare with. |
|
357 * @param {string} aMessage |
|
358 * Message to show for the test result |
|
359 * @throws {errors.AssertionError} |
|
360 * |
|
361 * @returns {boolean} Result of the test. |
|
362 */ |
|
363 notDeepEqual: function notEqual(aValue, aExpected, aMessage) { |
|
364 let condition = !this._deepEqual(aValue, aExpected); |
|
365 try { |
|
366 var aValueString = JSON.stringify(aValue); |
|
367 } catch (e) { |
|
368 var aValueString = String(aValue); |
|
369 } |
|
370 try { |
|
371 var aExpectedString = JSON.stringify(aExpected); |
|
372 } catch (e) { |
|
373 var aExpectedString = String(aExpected); |
|
374 } |
|
375 |
|
376 let diagnosis = "'" + aValueString + "' should not equal '" + |
|
377 aExpectedString + "'"; |
|
378 |
|
379 return this._test(condition, aMessage, diagnosis); |
|
380 }, |
|
381 |
|
382 /** |
|
383 * Test if the regular expression matches the string. |
|
384 * |
|
385 * @param {string} aString |
|
386 * String to test. |
|
387 * @param {RegEx} aRegex |
|
388 * Regular expression to use for testing that a match exists. |
|
389 * @param {string} aMessage |
|
390 * Message to show for the test result |
|
391 * @throws {errors.AssertionError} |
|
392 * |
|
393 * @returns {boolean} Result of the test. |
|
394 */ |
|
395 match: function Assert_match(aString, aRegex, aMessage) { |
|
396 // XXX Bug 634948 |
|
397 // Regex objects are transformed to strings when evaluated in a sandbox |
|
398 // For now lets re-create the regex from its string representation |
|
399 let pattern = flags = ""; |
|
400 try { |
|
401 let matches = aRegex.toString().match(/\/(.*)\/(.*)/); |
|
402 |
|
403 pattern = matches[1]; |
|
404 flags = matches[2]; |
|
405 } catch (e) { |
|
406 } |
|
407 |
|
408 let regex = new RegExp(pattern, flags); |
|
409 let condition = (aString.match(regex) !== null); |
|
410 let diagnosis = "'" + regex + "' matches for '" + aString + "'"; |
|
411 |
|
412 return this._test(condition, aMessage, diagnosis); |
|
413 }, |
|
414 |
|
415 /** |
|
416 * Test if the regular expression does not match the string. |
|
417 * |
|
418 * @param {string} aString |
|
419 * String to test. |
|
420 * @param {RegEx} aRegex |
|
421 * Regular expression to use for testing that a match does not exist. |
|
422 * @param {string} aMessage |
|
423 * Message to show for the test result |
|
424 * @throws {errors.AssertionError} |
|
425 * |
|
426 * @returns {boolean} Result of the test. |
|
427 */ |
|
428 notMatch: function Assert_notMatch(aString, aRegex, aMessage) { |
|
429 // XXX Bug 634948 |
|
430 // Regex objects are transformed to strings when evaluated in a sandbox |
|
431 // For now lets re-create the regex from its string representation |
|
432 let pattern = flags = ""; |
|
433 try { |
|
434 let matches = aRegex.toString().match(/\/(.*)\/(.*)/); |
|
435 |
|
436 pattern = matches[1]; |
|
437 flags = matches[2]; |
|
438 } catch (e) { |
|
439 } |
|
440 |
|
441 let regex = new RegExp(pattern, flags); |
|
442 let condition = (aString.match(regex) === null); |
|
443 let diagnosis = "'" + regex + "' doesn't match for '" + aString + "'"; |
|
444 |
|
445 return this._test(condition, aMessage, diagnosis); |
|
446 }, |
|
447 |
|
448 |
|
449 /** |
|
450 * Test if a code block throws an exception. |
|
451 * |
|
452 * @param {string} block |
|
453 * function to call to test for exception |
|
454 * @param {RegEx} error |
|
455 * the expected error class |
|
456 * @param {string} message |
|
457 * message to present if assertion fails |
|
458 * @throws {errors.AssertionError} |
|
459 * |
|
460 * @returns {boolean} Result of the test. |
|
461 */ |
|
462 throws : function Assert_throws(block, /*optional*/error, /*optional*/message) { |
|
463 return this._throws.apply(this, [true].concat(Array.prototype.slice.call(arguments))); |
|
464 }, |
|
465 |
|
466 /** |
|
467 * Test if a code block doesn't throw an exception. |
|
468 * |
|
469 * @param {string} block |
|
470 * function to call to test for exception |
|
471 * @param {RegEx} error |
|
472 * the expected error class |
|
473 * @param {string} message |
|
474 * message to present if assertion fails |
|
475 * @throws {errors.AssertionError} |
|
476 * |
|
477 * @returns {boolean} Result of the test. |
|
478 */ |
|
479 doesNotThrow : function Assert_doesNotThrow(block, /*optional*/error, /*optional*/message) { |
|
480 return this._throws.apply(this, [false].concat(Array.prototype.slice.call(arguments))); |
|
481 }, |
|
482 |
|
483 /* Tests whether a code block throws the expected exception |
|
484 class. helper for throws() and doesNotThrow() |
|
485 |
|
486 adapted from node.js's assert._throws() |
|
487 https://github.com/joyent/node/blob/master/lib/assert.js |
|
488 */ |
|
489 _throws : function Assert__throws(shouldThrow, block, expected, message) { |
|
490 var actual; |
|
491 |
|
492 if (typeof expected === 'string') { |
|
493 message = expected; |
|
494 expected = null; |
|
495 } |
|
496 |
|
497 try { |
|
498 block(); |
|
499 } catch (e) { |
|
500 actual = e; |
|
501 } |
|
502 |
|
503 message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + |
|
504 (message ? ' ' + message : '.'); |
|
505 |
|
506 if (shouldThrow && !actual) { |
|
507 return this._test(false, message, 'Missing expected exception'); |
|
508 } |
|
509 |
|
510 if (!shouldThrow && this._expectedException(actual, expected)) { |
|
511 return this._test(false, message, 'Got unwanted exception'); |
|
512 } |
|
513 |
|
514 if ((shouldThrow && actual && expected && |
|
515 !this._expectedException(actual, expected)) || (!shouldThrow && actual)) { |
|
516 throw actual; |
|
517 } |
|
518 |
|
519 return this._test(true, message); |
|
520 }, |
|
521 |
|
522 /** |
|
523 * Test if the string contains the pattern. |
|
524 * |
|
525 * @param {String} aString String to test. |
|
526 * @param {String} aPattern Pattern to look for in the string |
|
527 * @param {String} aMessage Message to show for the test result |
|
528 * @throws {errors.AssertionError} |
|
529 * |
|
530 * @returns {Boolean} Result of the test. |
|
531 */ |
|
532 contain: function Assert_contain(aString, aPattern, aMessage) { |
|
533 let condition = (aString.indexOf(aPattern) !== -1); |
|
534 let diagnosis = "'" + aString + "' should contain '" + aPattern + "'"; |
|
535 |
|
536 return this._test(condition, aMessage, diagnosis); |
|
537 }, |
|
538 |
|
539 /** |
|
540 * Test if the string does not contain the pattern. |
|
541 * |
|
542 * @param {String} aString String to test. |
|
543 * @param {String} aPattern Pattern to look for in the string |
|
544 * @param {String} aMessage Message to show for the test result |
|
545 * @throws {errors.AssertionError} |
|
546 * |
|
547 * @returns {Boolean} Result of the test. |
|
548 */ |
|
549 notContain: function Assert_notContain(aString, aPattern, aMessage) { |
|
550 let condition = (aString.indexOf(aPattern) === -1); |
|
551 let diagnosis = "'" + aString + "' should not contain '" + aPattern + "'"; |
|
552 |
|
553 return this._test(condition, aMessage, diagnosis); |
|
554 }, |
|
555 |
|
556 /** |
|
557 * Waits for the callback evaluates to true |
|
558 * |
|
559 * @param {Function} aCallback |
|
560 * Callback for evaluation |
|
561 * @param {String} aMessage |
|
562 * Message to show for result |
|
563 * @param {Number} aTimeout |
|
564 * Timeout in waiting for evaluation |
|
565 * @param {Number} aInterval |
|
566 * Interval between evaluation attempts |
|
567 * @param {Object} aThisObject |
|
568 * this object |
|
569 * @throws {errors.AssertionError} |
|
570 * |
|
571 * @returns {Boolean} Result of the test. |
|
572 */ |
|
573 waitFor: function Assert_waitFor(aCallback, aMessage, aTimeout, aInterval, aThisObject) { |
|
574 var timeout = aTimeout || 5000; |
|
575 var interval = aInterval || 100; |
|
576 |
|
577 var self = { |
|
578 timeIsUp: false, |
|
579 result: aCallback.call(aThisObject) |
|
580 }; |
|
581 var deadline = Date.now() + timeout; |
|
582 |
|
583 function wait() { |
|
584 if (self.result !== true) { |
|
585 self.result = aCallback.call(aThisObject); |
|
586 self.timeIsUp = Date.now() > deadline; |
|
587 } |
|
588 } |
|
589 |
|
590 var hwindow = Services.appShell.hiddenDOMWindow; |
|
591 var timeoutInterval = hwindow.setInterval(wait, interval); |
|
592 var thread = Services.tm.currentThread; |
|
593 |
|
594 while (self.result !== true && !self.timeIsUp) { |
|
595 thread.processNextEvent(true); |
|
596 |
|
597 let type = typeof(self.result); |
|
598 if (type !== 'boolean') |
|
599 throw TypeError("waitFor() callback has to return a boolean" + |
|
600 " instead of '" + type + "'"); |
|
601 } |
|
602 |
|
603 hwindow.clearInterval(timeoutInterval); |
|
604 |
|
605 if (self.result !== true && self.timeIsUp) { |
|
606 aMessage = aMessage || arguments.callee.name + ": Timeout exceeded for '" + aCallback + "'"; |
|
607 throw new errors.TimeoutError(aMessage); |
|
608 } |
|
609 |
|
610 broker.pass({'function':'assert.waitFor()'}); |
|
611 return true; |
|
612 } |
|
613 } |
|
614 |
|
615 /* non-fatal assertions */ |
|
616 var Expect = function () {} |
|
617 |
|
618 Expect.prototype = new Assert(); |
|
619 |
|
620 /** |
|
621 * Log a test as failing by adding a fail frame. |
|
622 * |
|
623 * @param {object} aResult |
|
624 * Test result details used for reporting. |
|
625 * <dl> |
|
626 * <dd>fileName</dd> |
|
627 * <dt>Name of the file in which the assertion failed.</dt> |
|
628 * <dd>functionName</dd> |
|
629 * <dt>Function in which the assertion failed.</dt> |
|
630 * <dd>lineNumber</dd> |
|
631 * <dt>Line number of the file in which the assertion failed.</dt> |
|
632 * <dd>message</dd> |
|
633 * <dt>Message why the assertion failed.</dt> |
|
634 * </dl> |
|
635 */ |
|
636 Expect.prototype._logFail = function Expect__logFail(aResult) { |
|
637 broker.fail({fail: aResult}); |
|
638 } |
|
639 |
|
640 /** |
|
641 * Waits for the callback evaluates to true |
|
642 * |
|
643 * @param {Function} aCallback |
|
644 * Callback for evaluation |
|
645 * @param {String} aMessage |
|
646 * Message to show for result |
|
647 * @param {Number} aTimeout |
|
648 * Timeout in waiting for evaluation |
|
649 * @param {Number} aInterval |
|
650 * Interval between evaluation attempts |
|
651 * @param {Object} aThisObject |
|
652 * this object |
|
653 */ |
|
654 Expect.prototype.waitFor = function Expect_waitFor(aCallback, aMessage, aTimeout, aInterval, aThisObject) { |
|
655 let condition = true; |
|
656 let message = aMessage; |
|
657 |
|
658 try { |
|
659 Assert.prototype.waitFor.apply(this, arguments); |
|
660 } |
|
661 catch (ex if ex instanceof errors.AssertionError) { |
|
662 message = ex.message; |
|
663 condition = false; |
|
664 } |
|
665 |
|
666 return this._test(condition, message); |
|
667 } |