chromevox_unittest_base.js revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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
5GEN_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 */
13function $(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 */
27function ChromeVoxUnitTestBase() {}
28
29ChromeVoxUnitTestBase.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