Home | History | Annotate | Download | only in testing
      1 // Copyright 2014 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 GEN_INCLUDE([
      6     'chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js']);
      7 
      8 /**
      9  * Shortcut for document.getElementById.
     10  * @param {string} id of the element.
     11  * @return {HTMLElement} with the id.
     12  */
     13 function $(id) {
     14   return document.getElementById(id);
     15 }
     16 
     17 /**
     18  * Base test fixture for ChromeVox unit tests.
     19  *
     20  * Note that while conceptually these are unit tests, these tests need
     21  * to run in a full web page, so they're actually run as WebUI browser
     22  * tests.
     23  *
     24  * @constructor
     25  * @extends {testing.Test}
     26  */
     27 function ChromeVoxUnitTestBase() {}
     28 
     29 ChromeVoxUnitTestBase.prototype = {
     30   __proto__: testing.Test.prototype,
     31 
     32   /** @override */
     33   closureModuleDeps: [
     34     'cvox.ChromeVoxTester',
     35     'cvox.ChromeVoxUserCommands',
     36     'cvox.SpokenListBuilder',
     37   ],
     38 
     39   /** @override */
     40   browsePreload: DUMMY_URL,
     41 
     42   /**
     43    * @override
     44    * It doesn't make sense to run the accessibility audit on these tests,
     45    * since many of them are deliberately testing inaccessible html.
     46    */
     47   runAccessibilityChecks: false,
     48 
     49   /**
     50    * Loads some inlined html into the body of the current document, replacing
     51    * whatever was there previously.
     52    * @param {string} html The html to load as a string.
     53    */
     54   loadHtml: function(html) {
     55     while (document.head.firstChild) {
     56       document.head.removeChild(document.head.firstChild);
     57     }
     58     while (document.body.firstChild) {
     59       document.body.removeChild(document.body.firstChild);
     60     }
     61     this.appendHtml(html);
     62   },
     63 
     64   /**
     65    * Loads some inlined html into the current document, replacing
     66    * whatever was there previously. This version takes the html
     67    * encoded as a comment inside a function, so you can use it like this:
     68    *
     69    * this.loadDoc(function() {/*!
     70    *     <p>Html goes here</p>
     71    * * /});
     72    *
     73    * @param {Function} commentEncodedHtml The html to load, embedded as a
     74    *     comment inside an anonymous function - see example, above.
     75    */
     76   loadDoc: function(commentEncodedHtml) {
     77     var html = this.extractHtmlFromCommentEncodedString_(commentEncodedHtml);
     78     this.loadHtml(html);
     79   },
     80 
     81   /**
     82    * Appends some inlined html into the current document, at the end of
     83    * the body element. Takes the html encoded as a comment inside a function,
     84    * so you can use it like this:
     85    *
     86    * this.appendDoc(function() {/*!
     87    *     <p>Html goes here</p>
     88    * * /});
     89    *
     90    * @param {Function} commentEncodedHtml The html to load, embedded as a
     91    *     comment inside an anonymous function - see example, above.
     92    */
     93   appendDoc: function(commentEncodedHtml) {
     94     var html = this.extractHtmlFromCommentEncodedString_(commentEncodedHtml);
     95     this.appendHtml(html);
     96   },
     97 
     98   /**
     99    * Appends some inlined html into the current document, at the end of
    100    * the body element.
    101    * @param {string} html The html to load as a string.
    102    */
    103   appendHtml: function(html) {
    104     var div = document.createElement('div');
    105     div.innerHTML = html;
    106     var fragment = document.createDocumentFragment();
    107     while (div.firstChild) {
    108       fragment.appendChild(div.firstChild);
    109     }
    110     document.body.appendChild(fragment);
    111   },
    112 
    113   /**
    114    * Extracts some inlined html encoded as a comment inside a function,
    115    * so you can use it like this:
    116    *
    117    * this.appendDoc(function() {/*!
    118    *     <p>Html goes here</p>
    119    * * /});
    120    *
    121    * @param {Function} commentEncodedHtml The html , embedded as a
    122    *     comment inside an anonymous function - see example, above.
    123    @ @return {String} The html text.
    124    */
    125   extractHtmlFromCommentEncodedString_: function(commentEncodedHtml) {
    126     return commentEncodedHtml.toString().
    127         replace(/^[^\/]+\/\*!?/, '').
    128         replace(/\*\/[^\/]+$/, '');
    129   },
    130 
    131   /**
    132    * Waits for the queued events in ChromeVoxEventWatcher to be
    133    * handled, then calls a callback function with provided arguments
    134    * in the test case scope. Very useful for asserting the results of events.
    135    *
    136    * @param {function()} func A function to call when ChromeVox is ready.
    137    * @param {*} var_args Additional arguments to pass through to the function.
    138    * @return {ChromeVoxUnitTestBase} this.
    139    */
    140   waitForCalm: function(func, var_args) {
    141     var me = this;
    142     var calmArguments = Array.prototype.slice.call(arguments);
    143     calmArguments.shift();
    144     cvox.ChromeVoxEventWatcher.addReadyCallback(function() {
    145       func.apply(me, calmArguments);
    146     });
    147     return this; // for chaining.
    148   },
    149 
    150   /**
    151    * Asserts the TTS engine spoke a certain string. Clears the TTS buffer.
    152    * @param {string} expectedText The expected text.
    153    * @return {ChromeVoxUnitTestBase} this.
    154    */
    155   assertSpoken: function(expectedText) {
    156     assertEquals(expectedText,
    157                  cvox.ChromeVoxTester.testTts().getUtterancesAsString());
    158     cvox.ChromeVoxTester.clearUtterances();
    159     return this; // for chaining.
    160   },
    161 
    162   /**
    163    * Asserts a list of utterances are in the correct queue mode.
    164    * @param {cvox.SpokenListBuilder|Array} expectedList A list
    165    *     of [text, queueMode] tuples OR a SpokenListBuilder with the expected
    166    *     utterances.
    167    * @return {ChromeVoxUnitTestBase} this.
    168    */
    169   assertSpokenList: function(expectedList) {
    170     if (expectedList instanceof cvox.SpokenListBuilder) {
    171       expectedList = expectedList.build();
    172     }
    173 
    174     var ulist = cvox.ChromeVoxTester.testTts().getUtteranceInfoList();
    175     for (var i = 0; i < expectedList.length; i++) {
    176       var text = expectedList[i][0];
    177       var queueMode = expectedList[i][1];
    178       this.assertSingleUtterance_(text, queueMode,
    179                                   ulist[i].text, ulist[i].queueMode);
    180     }
    181     cvox.ChromeVoxTester.clearUtterances();
    182     return this; // for chaining.
    183   },
    184 
    185   assertSingleUtterance_: function(
    186       expectedText, expectedQueueMode, text, queueMode) {
    187     assertEquals(expectedQueueMode, queueMode);
    188     assertEquals(expectedText, text);
    189   },
    190 
    191   /**
    192    * Focuses an element.
    193    * @param {string} id The id of the element to focus.
    194    * @return {ChromeVoxUnitTestBase} this.
    195    */
    196   setFocus: function(id) {
    197     $(id).focus();
    198     return this; // for chaining.
    199   },
    200 
    201   /**
    202    * Executes a ChromeVox user command.
    203    * @param {string} command The name of the command to run.
    204    * @return {ChromeVoxUnitTestBase} this.
    205    */
    206   userCommand: function(command) {
    207     cvox.ChromeVoxUserCommands.commands[command]();
    208     return this; // for chaining.
    209   },
    210 
    211   /**
    212    * @return {cvox.SpokenListBuilder} A new builder.
    213    */
    214   spokenList: function() {
    215     return new cvox.SpokenListBuilder();
    216   }
    217 };
    218