content_editable_extractor_test.unitjs 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
5// Include test fixture.
6GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
7
8/**
9 * Test fixture.
10 * @constructor
11 * @extends {ChromeVoxUnitTestBase}
12 */
13function CvoxContentEditableExtractorUnitTest() {}
14
15CvoxContentEditableExtractorUnitTest.prototype = {
16  __proto__: ChromeVoxUnitTestBase.prototype,
17
18  /** @override */
19  closureModuleDeps: [
20    'cvox.ContentEditableExtractor',
21  ]
22};
23
24/**
25 * Helper function to set the selection
26 * @param {Node} startNode The base/start node of the range.
27 * @param {number} startOffset The 0-based character index of the start.
28 * @param {Node} endNode The extent/end node of the range.
29 * @param {number} endOffset The 0-based character index of the end.
30 */
31function setSelection(startNode, startOffset, endNode, endOffset) {
32  var r = document.createRange();
33  r.setStart(startNode, startOffset);
34  r.setEnd(endNode, endOffset);
35  var sel = window.getSelection();
36  sel.removeAllRanges();
37  sel.addRange(r);
38}
39
40TEST_F('CvoxContentEditableExtractorUnitTest', 'EmptyElement', function() {
41  this.loadDoc(function() {/*!
42    <div>
43      <div id="textbox" contentEditable="true"></div>
44    </div>
45  */});
46
47  var textbox = $('textbox');
48  var extractor = new cvox.ContentEditableExtractor();
49  extractor.update(textbox);
50  assertEquals('', extractor.getText());
51  assertEquals(0, extractor.getStartIndex());
52  assertEquals(0, extractor.getEndIndex(0));
53  assertEquals(0, extractor.getLineIndex(0));
54  assertEquals(0, extractor.getLineStart(0));
55  assertEquals(0, extractor.getLineEnd(0));
56});
57
58/**
59 * Test getting text and selections from a single contenteditable node.
60 */
61TEST_F('CvoxContentEditableExtractorUnitTest', 'SingleTextNode', function() {
62  this.loadDoc(function() {/*!
63    <div>
64      <div id="textbox" contentEditable="true">Hello</div>
65    </div>
66  */});
67  var textbox = $('textbox');
68
69  var extractor = new cvox.ContentEditableExtractor();
70  extractor.update(textbox);
71  assertEquals('Hello', extractor.getText());
72  assertEquals(0, extractor.getLineIndex(0));
73  assertEquals(0, extractor.getLineStart(0));
74  assertEquals(5, extractor.getLineEnd(0));
75  assertEquals(5, extractor.getStartIndex());
76  assertEquals(5, extractor.getEndIndex());
77
78  // Test all possible cursor positions.
79  for (var i = 0; i <= 5; i++) {
80    setSelection(textbox.firstChild, i, textbox.firstChild, i);
81    extractor.update(textbox);
82    assertEquals(i, extractor.getStartIndex());
83    assertEquals(i, extractor.getEndIndex());
84  }
85
86  // Test all possible ways to select one character.
87  for (i = 0; i < 5; i++) {
88    setSelection(textbox.firstChild, i, textbox.firstChild, i + 1);
89    extractor.update(textbox);
90    assertEquals(i, extractor.getStartIndex());
91    assertEquals(i + 1, extractor.getEndIndex());
92  }
93
94  // Test selecting everything.
95  setSelection(textbox.firstChild, 0, textbox.firstChild, 5);
96  extractor.update(textbox);
97  assertEquals(0, extractor.getStartIndex());
98  assertEquals(5, extractor.getEndIndex());
99});
100
101/**
102 * Test getting text and selections from a contenteditable node with
103 * nonprinted whitespace.
104 */
105TEST_F('CvoxContentEditableExtractorUnitTest', 'TextWithWhitespace',
106    function() {
107  this.loadDoc(function() {/*!
108    <div>
109      <div id="textbox" contentEditable="true"> Hello  World </div>
110    </div>
111  */});
112  var textbox = $('textbox');
113
114  var extractor = new cvox.ContentEditableExtractor();
115  extractor.update(textbox);
116  assertEquals('Hello World', extractor.getText());
117  assertEquals(0, extractor.getLineIndex(0));
118  assertEquals(0, extractor.getLineStart(0));
119  assertEquals(11, extractor.getLineEnd(0));
120  assertEquals(11, extractor.getStartIndex());
121  assertEquals(11, extractor.getEndIndex());
122
123  // Test all *reasonable* indexes of a selection into this text node
124  // and the logical index into the text that these should result in.
125  var expectedIndexMap = {
126    0: 0,
127    1: 0,
128    2: 1,
129    3: 2,
130    4: 3,
131    5: 4,
132    6: 5,
133    // Note: index=7 should never happen
134    8: 6,
135    9: 7,
136    10: 8,
137    11: 9,
138    12: 10,
139    13: 11,
140    14: 11
141  };
142  for (var srcIndex in expectedIndexMap) {
143    var dstIndex = expectedIndexMap[srcIndex];
144    setSelection(textbox.firstChild, srcIndex, textbox.firstChild, srcIndex);
145    extractor.update(textbox);
146    assertEquals(dstIndex, extractor.getStartIndex());
147    assertEquals(dstIndex, extractor.getEndIndex());
148  }
149});
150
151/**
152 * Test getting text and selections from a contenteditable node with
153 * preformatted text.
154 */
155TEST_F('CvoxContentEditableExtractorUnitTest', 'Preformatted', function() {
156  this.loadDoc(function() {/*!
157    <div>
158      <pre id="textbox" contentEditable="true">aaaaaaaaaa
159bbbbbbbbbb
160cccccccccc</pre>
161    </div>
162  */});
163  var textbox = $('textbox');
164
165  var extractor = new cvox.ContentEditableExtractor();
166  extractor.update(textbox);
167  assertEquals('aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc', extractor.getText());
168  assertEquals(0, extractor.getLineStart(0));
169  assertEquals(11, extractor.getLineEnd(0));
170  assertEquals(11, extractor.getLineStart(1));
171  assertEquals(22, extractor.getLineEnd(1));
172  assertEquals(22, extractor.getLineStart(2));
173  assertEquals(32, extractor.getLineEnd(2));
174
175  // Test all possible cursor positions.
176  for (var i = 0; i <= 32; i++) {
177    setSelection(textbox.firstChild, i, textbox.firstChild, i);
178    extractor.update(textbox);
179    assertEquals(i, extractor.getStartIndex());
180    assertEquals(i, extractor.getEndIndex());
181  }
182});
183
184/**
185 * Test getting text and selections from a contenteditable node with
186 * wrapping.
187 */
188TEST_F('CvoxContentEditableExtractorUnitTest', 'WordWrap', function() {
189  this.loadDoc(function() {/*!
190    <div>
191      <div id="textbox"
192           style="width: 1em; word-wrap: normal"
193           contentEditable="true">One two three</div>
194    </div>
195  */});
196  var textbox = $('textbox');
197
198  var extractor = new cvox.ContentEditableExtractor();
199  extractor.update(textbox);
200  assertEquals('One\ntwo\nthree', extractor.getText());
201  assertEquals(0, extractor.getLineStart(0));
202  assertEquals(4, extractor.getLineEnd(0));
203  assertEquals(4, extractor.getLineStart(1));
204  assertEquals(8, extractor.getLineEnd(1));
205  assertEquals(8, extractor.getLineStart(2));
206  assertEquals(13, extractor.getLineEnd(2));
207
208  // Test all possible cursor positions.
209  for (var i = 0; i <= 13; i++) {
210    setSelection(textbox.firstChild, i, textbox.firstChild, i);
211    extractor.update(textbox);
212    assertEquals(i, extractor.getStartIndex());
213    assertEquals(i, extractor.getEndIndex());
214  }
215});
216
217/**
218 * Test getting text and lines from a contenteditable region
219 * containing two paragraphs and an explicit line break.
220 */
221TEST_F('CvoxContentEditableExtractorUnitTest', 'TwoParas', function() {
222  this.loadDoc(function() {/*!
223    <div>
224      <div id="textbox" contentEditable="true">
225        <p>One</p>
226        <p>Two<br>Three</p>
227      </div>
228    </div>
229  */});
230  var textbox = $('textbox');
231
232  var extractor = new cvox.ContentEditableExtractor();
233  extractor.update(textbox);
234  assertEquals('One\nTwo\nThree',
235               extractor.getText());
236  assertEquals(0, extractor.getLineStart(0));
237  assertEquals(4, extractor.getLineEnd(0));
238  assertEquals(4, extractor.getLineStart(1));
239  assertEquals(8, extractor.getLineEnd(1));
240  assertEquals(8, extractor.getLineStart(2));
241  assertEquals(13, extractor.getLineEnd(2));
242});
243
244/**
245 * Test getting text and lines from a contenteditable region
246 * containing two paragraphs, this time with added whitespace.
247 */
248TEST_F('CvoxContentEditableExtractorUnitTest', 'TwoParasWithWhitespace',
249    function() {
250  this.loadDoc(function() {/*!
251    <div>
252      <div id="textbox" contentEditable="true">
253        <p> One </p>
254        <p> Two <br> Three </p>
255      </div>
256    </div>
257  */});
258  var textbox = $('textbox');
259
260  var extractor = new cvox.ContentEditableExtractor();
261  extractor.update(textbox);
262  assertEquals('One\nTwo Three',
263               extractor.getText());
264  assertEquals(0, extractor.getLineStart(0));
265  assertEquals(4, extractor.getLineEnd(0));
266  assertEquals(4, extractor.getLineStart(1));
267  assertEquals(8, extractor.getLineEnd(1));
268  assertEquals(8, extractor.getLineStart(2));
269  assertEquals(13, extractor.getLineEnd(2));
270});
271
272/**
273 * Test getting text and lines from a contenteditable region
274 * containing some raw text and then some text in a block-level element.
275 */
276TEST_F('CvoxContentEditableExtractorUnitTest', 'NodePlusElement', function() {
277  this.loadDoc(function() {/*!
278    <div>
279      <div id="textbox"
280           contentEditable="true">One<div>Two<br>Three</div></div>
281    </div>
282  */});
283  var textbox = $('textbox');
284
285  var extractor = new cvox.ContentEditableExtractor();
286  extractor.update(textbox);
287  assertEquals('One\nTwo\nThree',
288               extractor.getText());
289  assertEquals(0, extractor.getLineStart(0));
290  assertEquals(4, extractor.getLineEnd(0));
291  assertEquals(4, extractor.getLineStart(1));
292  assertEquals(8, extractor.getLineEnd(1));
293  assertEquals(8, extractor.getLineStart(2));
294  assertEquals(13, extractor.getLineEnd(2));
295
296  var oneTextNode = textbox.firstChild;
297  assertEquals('One', oneTextNode.data);
298  var twoTextNode = textbox.firstElementChild.firstChild;
299  assertEquals('Two', twoTextNode.data);
300  var threeTextNode = twoTextNode.nextSibling.nextSibling;
301  assertEquals('Three', threeTextNode.data);
302
303  // End of first line.
304  setSelection(oneTextNode, 3, oneTextNode, 3);
305  extractor.update(textbox);
306  assertEquals(3, extractor.getStartIndex());
307  assertEquals(3, extractor.getEndIndex());
308
309  // Beginning of second line.
310  setSelection(twoTextNode, 0, twoTextNode, 0);
311  extractor.update(textbox);
312  assertEquals(4, extractor.getStartIndex());
313  assertEquals(4, extractor.getEndIndex());
314
315  // End of second line.
316  setSelection(twoTextNode, 3, twoTextNode, 3);
317  extractor.update(textbox);
318  assertEquals(7, extractor.getStartIndex());
319  assertEquals(7, extractor.getEndIndex());
320
321  // Beginning of third line.
322  setSelection(threeTextNode, 0, threeTextNode, 0);
323  extractor.update(textbox);
324  assertEquals(8, extractor.getStartIndex());
325  assertEquals(8, extractor.getEndIndex());
326});
327