Home | History | Annotate | Download | only in new
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * Tests that an observation matches the expected value.
      7  * @param {Object} expected The expected value.
      8  * @param {Object} observed The actual value.
      9  * @param {string=} opt_message Optional message to include with a test
     10  *     failure.
     11  */
     12 function assertEquals(expected, observed, opt_message) {
     13   if (observed !== expected) {
     14     var message = 'Assertion Failed\n  Observed: ' + observed +
     15       '\n  Expected: ' + expected;
     16     if (opt_message)
     17       message = message + '\n  ' + opt_message;
     18     throw new Error(message);
     19   }
     20 }
     21 
     22 /**
     23  * Verifies that a test result is true.
     24  * @param {boolean} observed The observed value.
     25  * @param {string=} opt_message Optional message to include with a test
     26  *     failure.
     27  */
     28 function assertTrue(observed, opt_message) {
     29   assertEquals(true, observed, opt_message);
     30 }
     31 
     32 /**
     33  * Verifies that a test result is false.
     34  * @param {boolean} observed The observed value.
     35  * @param {string=} opt_message Optional message to include with a test
     36  *     failure.
     37  */
     38 function assertFalse(observed, opt_message) {
     39   assertEquals(false, observed, opt_message);
     40 }
     41 
     42 /**
     43  * Verifies that the observed and reference values differ.
     44  * @param {Object} reference The target value for comparison.
     45  * @param {Object} observed The test result.
     46  * @param {string=} opt_message Optional message to include with a test
     47  *     failure.
     48  */
     49 function assertNotEqual(reference, observed, opt_message) {
     50   if (observed === reference) {
     51     var message = 'Assertion Failed\n  Observed: ' + observed +
     52       '\n  Reference: ' + reference;
     53     if (opt_message)
     54       message = message + '\n  ' + opt_message;
     55     throw new Error(message);
     56   }
     57 }
     58 
     59 /**
     60  * Verifies that a test evaluation results in an exception.
     61  * @param {!Function} f The test function.
     62  */
     63 function assertThrows(f) {
     64   var triggeredError = false;
     65   try {
     66     f();
     67   } catch (err) {
     68     triggeredError = true;
     69   }
     70   if (!triggeredError)
     71     throw new Error('Assertion Failed: throw expected.');
     72 }
     73 
     74 /**
     75  * Verifies that the contents of the expected and observed arrays match.
     76  * @param {!Array} expected The expected result.
     77  * @param {!Array} observed The actual result.
     78  */
     79 function assertArrayEquals(expected, observed) {
     80   var v1 = Array.prototype.slice.call(expected);
     81   var v2 = Array.prototype.slice.call(observed);
     82   var equal = v1.length == v2.length;
     83   if (equal) {
     84     for (var i = 0; i < v1.length; i++) {
     85       if (v1[i] !== v2[i]) {
     86         equal = false;
     87         break;
     88       }
     89     }
     90   }
     91   if (!equal) {
     92     var message =
     93       ['Assertion Failed', 'Observed: ' + v2, 'Expected: ' + v1].join('\n  ');
     94     throw new Error(message);
     95   }
     96 }
     97 
     98 /**
     99  * Verifies that the expected and observed result have the same content.
    100  * @param {*} expected The expected result.
    101  * @param {*} observed The actual result.
    102  */
    103 function assertDeepEquals(expected, observed, opt_message) {
    104   if (typeof expected == 'object' && expected != null) {
    105     assertNotEqual(null, observed);
    106     for (var key in expected) {
    107       assertTrue(key in observed, opt_message);
    108       assertDeepEquals(expected[key], observed[key], opt_message);
    109     }
    110     for (var key in observed) {
    111       assertTrue(key in expected, opt_message);
    112     }
    113   } else {
    114     assertEquals(expected, observed, opt_message);
    115   }
    116 }
    117 
    118 /**
    119  * Defines runTests.
    120  */
    121 (function(exports) {
    122   /**
    123    * List of test cases.
    124    * @type {Array.<string>} List of function names for tests to run.
    125    */
    126   var testCases = [];
    127 
    128   /**
    129    * Indicates if all tests have run successfully.
    130    * @type {boolean}
    131    */
    132   var cleanTestRun = true;
    133 
    134   /**
    135    * Armed during setup of a test to call the matching tear down code.
    136    * @type {Function}
    137    */
    138   var pendingTearDown = null;
    139 
    140   /**
    141    * Runs all functions starting with test and reports success or
    142    * failure of the test suite.
    143    */
    144   function runTests() {
    145     for (var name in window) {
    146       if (typeof window[name] == 'function' && /^test/.test(name))
    147         testCases.push(name);
    148     }
    149     if (!testCases.length) {
    150       console.error('Failed to find test cases.');
    151       cleanTestRun = false;
    152     }
    153     continueTesting();
    154   }
    155 
    156   function reportPass(name) {
    157     'use strict';
    158     var text = document.createTextNode(name + ': PASSED');
    159     var span = document.createElement('span');
    160     span.appendChild(text);
    161     document.body.appendChild(span);
    162     document.body.appendChild(document.createElement('br'));
    163   }
    164 
    165   function reportFail(name) {
    166     'use strict';
    167     var text = document.createTextNode(name + ': =========FAILED=======');
    168     var span = document.createElement('span');
    169     span.appendChild(text);
    170     document.body.appendChild(span);
    171     document.body.appendChild(document.createElement('br'));
    172   }
    173 
    174   /**
    175    * Runs the next test in the queue. Reports the test results if the queue is
    176    * empty.
    177    */
    178   function continueTesting() {
    179     if (pendingTearDown) {
    180       pendingTearDown();
    181       pendingTearDown = null;
    182     }
    183     if (testCases.length > 0) {
    184       var fn = testCases.pop();
    185       var isAsyncTest = window[fn].length;
    186       try {
    187         if (window.setUp)
    188           window.setUp();
    189         pendingTearDown = window.tearDown;
    190         window[fn](continueTesting);
    191         reportPass(fn);
    192       } catch (err) {
    193         reportFail(fn);
    194         console.error('Failure in test ' + fn + '\n' + err);
    195         console.log(err.stack);
    196         cleanTestRun = false;
    197       }
    198       // Asynchronous tests must manually call continueTesting when complete.
    199       if (!isAsyncTest)
    200         continueTesting();
    201     }
    202     if (testCases.length) {
    203       domAutomationController.setAutomationId(1);
    204       domAutomationController.send('PENDING');
    205     }
    206   };
    207 
    208   exports.runTests = runTests;
    209 })(this);
    210 
    211