Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / chromevox / common / editable_text_test.unitjs
blob0d00d79d04ffe52744ee25b4900a84973e7dfa7d
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.
5 // Include test fixture.
6 GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
8 /**
9  * A TTS class implementing speak and stop methods intended only for testing.
10  * @constructor
11  * @implements cvox.TtsInterface
12  */
13 function TestTts() {
14   this.strings = [];
17 /**
18  * The strings that were spoken since the last call to get().
19  * @type {Array<string>}
20  */
21 TestTts.prototype.strings;
23 /**
24  * Returns the list of strings spoken since the last time this method was
25  * called, and then clears the list.
26  * @return {Array<string>} The list of strings.
27  */
28 TestTts.prototype.get = function() {
29   var result = this.strings;
30   this.strings = [];
31   return result;
34 /** @override */
35 TestTts.prototype.speak = function(text, queueMode, properties) {
36   this.strings.push(text);
39 /** @override */
40 TestTts.prototype.isSpeaking = function() {
41   return false;
44 /** @override */
45 TestTts.prototype.stop = function() {
46   // Do nothing.
49 /** @override */
50 TestTts.prototype.increaseOrDecreaseProperty =
51     function(propertyName, increase) {
52   // Do nothing.
55 /**
56  * Stores the last braille content.
57  * @constructor
58  * @implements cvox.BrailleInterface
59  */
60 function TestBraille() {
61   this.content = null;
64 /** @override */
65 TestBraille.prototype.write = function(params) {
66   this.content = params;
69 /**
70  * Asserts the current braille content.
71  *
72  * @param {string} text Braille text.
73  * @param {number=} opt_start Selection start.
74  * @param {number=} opt_end Selection end.
75  */
76 TestBraille.assertContent = function(text, opt_start, opt_end) {
77   var c = cvox.ChromeVox.braille.content;
78   assertTrue(c != null);
79   opt_start = opt_start !== undefined ? opt_start : -1;
80   opt_end = opt_end !== undefined ? opt_end : opt_start;
81   assertEquals(text, c.text.toString());
82   assertEquals(opt_start, c.startIndex);
83   assertEquals(opt_end, c.endIndex);
86 /**
87  * Test fixture.
88  * @constructor
89  * @extends {ChromeVoxUnitTestBase}
90  */
91 function CvoxEditableTextUnitTest() {}
93 CvoxEditableTextUnitTest.prototype = {
94   __proto__: ChromeVoxUnitTestBase.prototype,
96   /** @override */
97   closureModuleDeps: [
98     'cvox.ChromeVoxEditableElement',
99     'cvox.ChromeVoxEditableHTMLInput',
100     'cvox.ChromeVoxEditableTextBase',
101     'cvox.ChromeVoxEventWatcher',
102     'cvox.TextChangeEvent',
103     'cvox.TtsInterface',
104     'cvox.TypingEcho',
105   ],
107   /** @override */
108   setUp: function() {
109     // TODO: These tests are all assuming we used the IBeam cursor.
110     // We need to add coverage for block cursor.
111     cvox.ChromeVoxEditableTextBase.useIBeamCursor = true;
112     cvox.ChromeVox.typingEcho = cvox.TypingEcho.CHARACTER_AND_WORD;
113     cvox.ChromeVoxEditableTextBase.eventTypingEcho = false;
114     cvox.ChromeVox.braille = new TestBraille();
116     /** Simple mock. */
117     cvox.ChromeVox.msgs = {};
119     /**
120      * Simply return the message id.
121      * @param {string} msg Message id.
122      * @return {string} Message id.
123      */
124     cvox.ChromeVox.msgs.getMsg = function(msg) {
125       return msg;
126     };
127   },
129   /**
130    * Sets up for a cursor movement test.
131    * @param {string} tagName Desired tag name, "input" or "textarea".
132    * @return {Object} object containing the editable element, and functions
133    *     to prepare, run the test, and tear down.
134    * @private
135    */
136   setUpForCursorTest_: function(tagName) {
137     var element, editable;
138     switch (tagName) {
139       case 'input':
140         element = document.createElement('input');
141         editable = new cvox.ChromeVoxEditableHTMLInput(element, new TestTts());
142         break;
143       case 'textarea':
144         element = document.createElement('textarea');
145         editable = new cvox.ChromeVoxEditableTextArea(element, new TestTts());
146         break;
147       default:
148         throw 'invalid tagName in setUpForCursorTest_';
149     }
150     document.body.appendChild(element);
151     element.focus();
153     var expect = function(str) {
154       assertEquals(element.selectionStart, element.selectionEnd);
155       assertEquals(str, element.value.substring(0, element.selectionStart) +
156           '|' + element.value.substring(element.selectionEnd));
157     };
158     return {
159       editable: editable,
160       expect: expect,
161       prepare: function(str) {
162         var position = str.indexOf('|');
163         var value = str.substring(0, position) + str.substring(position + 1);
164         element.value = value;
165         element.selectionStart = element.selectionEnd = position;
166         editable.update(true /* triggeredByUser */);
167         expect(str);
168       },
169       tearDown: function() {
170         document.body.removeChild(element);
171       }
172     };
173   }
176 TEST_F('CvoxEditableTextUnitTest', 'CursorNavigation', function() {
177   var tts = new TestTts();
178   var obj = new cvox.ChromeVoxEditableTextBase('Hello', 0, 0, false, tts);
180   obj.changed(new cvox.TextChangeEvent('Hello', 1, 1));
181   obj.changed(new cvox.TextChangeEvent('Hello', 2, 2));
182   obj.changed(new cvox.TextChangeEvent('Hello', 3, 3));
183   obj.changed(new cvox.TextChangeEvent('Hello', 4, 4));
184   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
185   obj.changed(new cvox.TextChangeEvent('Hello', 4, 4));
186   obj.changed(new cvox.TextChangeEvent('Hello', 3, 3));
187   assertEqualStringArrays(['H', 'e', 'l', 'l', 'o',
188                             'o', 'l'], tts.get());
189   obj.changed(new cvox.TextChangeEvent('Hello', 0, 0));
190   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
191   assertEqualStringArrays(['Hel', 'Hello'], tts.get());
194 /** Test typing words. */
195 TEST_F('CvoxEditableTextUnitTest', 'TypingWords', function() {
196   var tts = new TestTts();
197   var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
198   obj.changed(new cvox.TextChangeEvent('H', 1, 1));
199   obj.changed(new cvox.TextChangeEvent('He', 2, 2));
200   obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
201   obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
202   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
203   obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
204   obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
205   obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
206   obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
207   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
208   obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
209   obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
210   obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
211   assertEqualStringArrays(['H', 'e', 'l', 'l', 'o', 'Hello,',
212                             ' ',
213                             'W', 'o', 'r', 'l', 'd', 'World.'],
214                            tts.get());
216   // Backspace
217   obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
218   obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
219   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
220   assertEqualStringArrays(['.', 'd', 'l'], tts.get());
222   // Forward-delete
223   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 9, 9));
224   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 8, 8));
225   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 7, 7));
226   obj.changed(new cvox.TextChangeEvent('Hello, or', 7, 7));
227   obj.changed(new cvox.TextChangeEvent('Hello, r', 7, 7));
228   obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
229   assertEqualStringArrays(['r', 'o', 'W', 'W', 'o', 'r'], tts.get());
231   // Clear all
232   obj.changed(new cvox.TextChangeEvent('', 0, 0));
233   assertEqualStringArrays(['Hello, , deleted'], tts.get());
235   // Paste / insert a whole word
236   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
237   assertEqualStringArrays(['Hello'], tts.get());
238   obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
239   assertEqualStringArrays([', World'], tts.get());
242 /** Test selection. */
243 TEST_F('CvoxEditableTextUnitTest', 'Selection', function() {
244   var tts = new TestTts();
245   var obj =
246       new cvox.ChromeVoxEditableTextBase('Hello, world.', 0, 0, false, tts);
247   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 1));
248   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 2));
249   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 3));
250   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 4));
251   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 5));
252   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 6));
253   assertEqualStringArrays(['H', 'selected',
254                             'e', 'added_to_selection',
255                             'l', 'added_to_selection',
256                             'l', 'added_to_selection',
257                             'o', 'added_to_selection',
258                             ',', 'added_to_selection'],
259                            tts.get());
260   obj.changed(new cvox.TextChangeEvent('Hello, world.', 0, 12));
261   assertEqualStringArrays([' world', 'added_to_selection'],
262                            tts.get());
263   obj.changed(new cvox.TextChangeEvent('Hello, world.', 1, 12));
264   assertEqualStringArrays(['H', 'removed_from_selection'],
265                            tts.get());
266   obj.changed(new cvox.TextChangeEvent('Hello, world.', 2, 5));
267   assertEqualStringArrays(['llo', 'selected'],
268                            tts.get());
269   obj.changed(new cvox.TextChangeEvent('Hello, world.', 2, 2));
270   assertEqualStringArrays(['Unselected'],
271                            tts.get());
275 /** Test multi-line text. */
276 TEST_F('CvoxEditableTextUnitTest', 'MultiLineText', function() {
277   var str = 'This string\nspans\nfive lines.\n  \n';
278   var tts = new TestTts();
279   var obj = new cvox.ChromeVoxEditableElement(null, str, 0, 0, false, tts);
280   obj.multiline = true;
281   obj.getLineIndex = function(index) {
282     if (index >= 33) {
283       return 4;
284     } else if (index >= 30) {
285       return 3;
286     } else if (index >= 18) {
287       return 2;
288     } else if (index >= 12) {
289       return 1;
290     } else {
291       return 0;
292     }
293   };
294   obj.getLineStart = function(index) {
295     return [0, 12, 18, 30, 33][index];
296   };
297   obj.getLineEnd = function(index) {
298     return [11, 17, 29, 32, 33][index];
299   };
300   assertEquals('This string', obj.getLine(0));
301   obj.changed(new cvox.TextChangeEvent(str, 12, 12));
302   assertEqualStringArrays(['spans'], tts.get());
303   TestBraille.assertContent('spans', 0);
304   obj.changed(new cvox.TextChangeEvent(str, 18, 18));
305   assertEqualStringArrays(['five lines.'], tts.get());
306   TestBraille.assertContent('five lines.', 0);
307   obj.changed(new cvox.TextChangeEvent(str, 30, 30));
308   assertEqualStringArrays(['text_box_whitespace'], tts.get());
309   TestBraille.assertContent('  ', 0);
310   obj.changed(new cvox.TextChangeEvent(str, 33, 33));
311   assertEqualStringArrays(['text_box_blank'], tts.get());
312   TestBraille.assertContent('', 0);
313   obj.changed(new cvox.TextChangeEvent(str, 0, 1));
314   assertEqualStringArrays(['T', 'selected'], tts.get());
315   TestBraille.assertContent('This string', 0, 1);
316   obj.changed(new cvox.TextChangeEvent(str, 0, 12));
317   assertEqualStringArrays(['his string\n', 'added_to_selection'],
318       tts.get());
319   // Newline stripped, thus 11, not 12.
320   TestBraille.assertContent('This string', 0, 11);
321   obj.changed(new cvox.TextChangeEvent(str, 0, str.length));
322   assertEqualStringArrays([str.substr(12), 'added_to_selection'],
323       tts.get());
324   TestBraille.assertContent('This string', 0, 11);
325   obj.changed(new cvox.TextChangeEvent(str, 12, 19));
326   assertEqualStringArrays(['spans\nf', 'selected'], tts.get());
327   TestBraille.assertContent('spans', 0, 5);
332  * Test autocomplete; suppose a user is typing "google.com/firefox" into an
333  * address bar, and it's being autocompleted. Sometimes it's autocompleted
334  * as they type, sometimes there's a short delay.
335  */
336 TEST_F('CvoxEditableTextUnitTest', 'Autocomplete', function() {
337   var tts = new TestTts();
338   var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
340   // User types 'g'
341   obj.changed(new cvox.TextChangeEvent('g', 1, 1));
342   assertEqualStringArrays(['g'], tts.get());
344   // The rest of 'google.com' is autocompleted and automatically selected.
345   obj.changed(new cvox.TextChangeEvent('google.com', 1, 10));
346   assertEqualStringArrays(['oogle.com, oogle.com'], tts.get());
348   // The user doesn't realize it and types a few more characters of 'google.com'
349   // and this changes the selection (unselecting) as the user types them.
350   obj.changed(new cvox.TextChangeEvent('google.com', 2, 10));
351   assertEqualStringArrays(['o', 'ogle.com'], tts.get());
352   obj.changed(new cvox.TextChangeEvent('google.com', 3, 10));
353   assertEqualStringArrays(['o', 'gle.com'], tts.get());
354   obj.changed(new cvox.TextChangeEvent('google.com', 4, 10));
355   assertEqualStringArrays(['g', 'le.com'], tts.get());
357   // The user presses right-arrow, which fully unselects the remaining text.
358   obj.changed(new cvox.TextChangeEvent('google.com', 10, 10));
359   assertEqualStringArrays(['Unselected'], tts.get());
361   // The user types '/'
362   obj.changed(new cvox.TextChangeEvent('google.com/', 11, 11));
363   assertEqualStringArrays(['com/'], tts.get());
365   // The user types 'f', and 'finance' is autocompleted
366   obj.changed(new cvox.TextChangeEvent('google.com/finance', 12, 18));
367   assertEqualStringArrays(['finance, inance'], tts.get());
369   // The user types 'i'
370   obj.changed(new cvox.TextChangeEvent('google.com/finance', 13, 18));
371   assertEqualStringArrays(['i', 'nance'], tts.get());
373   // The user types 'r', now 'firefox' is autocompleted
374   obj.changed(new cvox.TextChangeEvent('google.com/firefox', 14, 18));
375   assertEqualStringArrays(['refox, efox'], tts.get());
377   // The user presses right-arrow to accept the completion.
378   obj.changed(new cvox.TextChangeEvent('google.com/firefox', 18, 18));
379   assertEqualStringArrays(['Unselected'], tts.get());
384  * Test a few common scenarios where text is replaced.
385  */
386 TEST_F('CvoxEditableTextUnitTest', 'ReplacingText', function() {
387   // Initial value is Alabama.
388   var tts = new TestTts();
389   var obj = new cvox.ChromeVoxEditableTextBase('Alabama', 0, 0, false, tts);
391   // Entire text replaced with Alaska.
392   obj.changed(new cvox.TextChangeEvent('Alaska', 0, 0));
393   assertEqualStringArrays(['Alaska'], tts.get());
395   // Entire text selected.
396   obj.changed(new cvox.TextChangeEvent('Alaska', 0, 6));
397   assertEqualStringArrays(['Alaska', 'selected'], tts.get());
399   // Entire text replaced with Arizona.
400   obj.changed(new cvox.TextChangeEvent('Arizona', 7, 7));
401   assertEqualStringArrays(['Arizona'], tts.get());
403   // Entire text selected.
404   obj.changed(new cvox.TextChangeEvent('Arizona', 0, 7));
405   assertEqualStringArrays(['Arizona', 'selected'], tts.get());
407   // Click between 'r' and 'i'.
408   obj.changed(new cvox.TextChangeEvent('Arizona', 2, 2));
409   assertEqualStringArrays(['Unselected'], tts.get());
411   // Next character removed from selection.
412   obj.changed(new cvox.TextChangeEvent('Arizona', 2, 7));
413   assertEqualStringArrays(['izona', 'selected'], tts.get());
415   // Selection replaced with "kansas" to make Arkansas.  This time it
416   // says "kansas" because the deleted text was selected.
417   obj.changed(new cvox.TextChangeEvent('Arkansas', 8, 8));
418   assertEqualStringArrays(['kansas'], tts.get());
423  * Test feedback when text changes in a long sentence.
424  */
425 TEST_F('CvoxEditableTextUnitTest', 'ReplacingLongText', function() {
426   var tts = new TestTts();
427   var obj = new cvox.ChromeVoxEditableTextBase(
428     'I love deadlines. I like the whooshing sound they make as they fly by.',
429     0, 0, false, tts);
431   // Change the whole sentence without moving the cursor. It should speak
432   // only the part that changed, but it should speak whole words.
433   obj.changed(new cvox.TextChangeEvent(
434     'I love deadlines. I love the whooshing sounds they make as they fly by.',
435     0, 0));
436   assertEqualStringArrays(['love the whooshing sounds'], tts.get());
439 /** Tests character echo. */
440 TEST_F('CvoxEditableTextUnitTest', 'CharacterEcho', function() {
441   cvox.ChromeVox.typingEcho = cvox.TypingEcho.CHARACTER;
442   var tts = new TestTts();
443   var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
444   obj.changed(new cvox.TextChangeEvent('H', 1, 1));
445   obj.changed(new cvox.TextChangeEvent('He', 2, 2));
446   obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
447   obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
448   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
449   obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
450   obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
451   obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
452   obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
453   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
454   obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
455   obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
456   obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
457   assertEqualStringArrays(
458       ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '.'],
459        tts.get());
463 /** Tests word echo. */
464 TEST_F('CvoxEditableTextUnitTest', 'WordEcho', function() {
465   cvox.ChromeVox.typingEcho = cvox.TypingEcho.WORD;
466   var tts = new TestTts();
467   var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
468   obj.changed(new cvox.TextChangeEvent('H', 1, 1));
469   obj.changed(new cvox.TextChangeEvent('He', 2, 2));
470   obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
471   obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
472   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
473   obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
474   obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
475   obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
476   obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
477   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
478   obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
479   obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
480   obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
481   assertEqualStringArrays(
482       ['Hello,', 'World.'],
483        tts.get());
487 /** Tests no echo. */
488 TEST_F('CvoxEditableTextUnitTest', 'NoEcho', function() {
489   cvox.ChromeVox.typingEcho = cvox.TypingEcho.NONE;
490   var tts = new TestTts();
491   var obj = new cvox.ChromeVoxEditableTextBase('', 0, 0, false, tts);
492   obj.changed(new cvox.TextChangeEvent('H', 1, 1));
493   obj.changed(new cvox.TextChangeEvent('He', 2, 2));
494   obj.changed(new cvox.TextChangeEvent('Hel', 3, 3));
495   obj.changed(new cvox.TextChangeEvent('Hell', 4, 4));
496   obj.changed(new cvox.TextChangeEvent('Hello', 5, 5));
497   obj.changed(new cvox.TextChangeEvent('Hello,', 6, 6));
498   obj.changed(new cvox.TextChangeEvent('Hello, ', 7, 7));
499   obj.changed(new cvox.TextChangeEvent('Hello, W', 8, 8));
500   obj.changed(new cvox.TextChangeEvent('Hello, Wo', 9, 9));
501   obj.changed(new cvox.TextChangeEvent('Hello, Wor', 10, 10));
502   obj.changed(new cvox.TextChangeEvent('Hello, Worl', 11, 11));
503   obj.changed(new cvox.TextChangeEvent('Hello, World', 12, 12));
504   obj.changed(new cvox.TextChangeEvent('Hello, World.', 13, 13));
505   assertEqualStringArrays(
506       [],
507        tts.get());
510 /** Tests cursor movement in an input field by character. */
511 TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByCharacter', function() {
512   var test = this.setUpForCursorTest_('input');
513   var editable = test.editable, prepare = test.prepare, expect = test.expect;
514   try {
515     // Moving near the beginning of the text.
516     prepare('|"Hello," says Sally.');
517     editable.moveCursorToPreviousCharacter();
518     expect('|"Hello," says Sally.');
519     editable.moveCursorToNextCharacter();
520     expect('"|Hello," says Sally.');
521     editable.moveCursorToNextCharacter();
522     expect('"H|ello," says Sally.');
524     // Moving near the end of the text.
525     prepare('"Hello," says Sally|.');
526     editable.moveCursorToPreviousCharacter();
527     expect('"Hello," says Sall|y.');
528     editable.moveCursorToNextCharacter();
529     expect('"Hello," says Sally|.');
530     editable.moveCursorToNextCharacter();
531     expect('"Hello," says Sally.|');
532     editable.moveCursorToNextCharacter();
533     expect('"Hello," says Sally.|');
534   } finally {
535     test.tearDown();
536   }
539 /** Tests cursor movement in an input field by word. */
540 TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByWord', function() {
541   var test = this.setUpForCursorTest_('input');
542   var editable = test.editable, prepare = test.prepare, expect = test.expect;
543   try {
544     // Moving forward.
545     prepare('"He|llo," says Sally.');
546     editable.moveCursorToNextWord();
547     expect('"Hello|," says Sally.');
548     editable.moveCursorToNextWord();
549     expect('"Hello," says| Sally.');
550     editable.moveCursorToNextWord();
551     expect('"Hello," says Sally|.');
552     editable.moveCursorToNextWord();
553     expect('"Hello," says Sally.|');
554     editable.moveCursorToNextWord();
555     expect('"Hello," says Sally.|');
557     // Moving backward.
558     prepare('"Hello," says S|ally.');
559     editable.moveCursorToPreviousWord();
560     expect('"Hello," says |Sally.');
561     editable.moveCursorToPreviousWord();
562     expect('"Hello," |says Sally.');
563     editable.moveCursorToPreviousWord();
564     expect('"|Hello," says Sally.');
565     editable.moveCursorToPreviousWord();
566     expect('|"Hello," says Sally.');
567     editable.moveCursorToPreviousWord();
568     expect('|"Hello," says Sally.');
569   } finally {
570     test.tearDown();
571   }
574 /** Tests that character and word movement still work in <textarea>. */
575 TEST_F('CvoxEditableTextUnitTest', 'CursorMovementTextArea', function() {
576   var test = this.setUpForCursorTest_('textarea');
577   var editable = test.editable, prepare = test.prepare, expect = test.expect;
578   try {
579     prepare('|Hello, Larry.\nHello, Sergey.');
580     editable.moveCursorToNextCharacter();
581     expect('H|ello, Larry.\nHello, Sergey.');
582     editable.moveCursorToNextWord();
583     expect('Hello|, Larry.\nHello, Sergey.');
584     editable.moveCursorToNextWord();
585     expect('Hello, Larry|.\nHello, Sergey.');
586     editable.moveCursorToNextWord();
587     expect('Hello, Larry.\nHello|, Sergey.');
588     editable.moveCursorToNextCharacter();
589     expect('Hello, Larry.\nHello,| Sergey.');
590     editable.moveCursorToPreviousWord();
591     expect('Hello, Larry.\n|Hello, Sergey.');
592     editable.moveCursorToPreviousCharacter();
593     expect('Hello, Larry.|\nHello, Sergey.');
594   } finally {
595     test.tearDown();
596   }
599 /** Tests that line navigation works. */
600 TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByLine', function() {
601   var test = this.setUpForCursorTest_('textarea');
602   var editable = test.editable, prepare = test.prepare, expect = test.expect;
603   try {
604     prepare('123\n1234\n1234|5\n\nHi');
605     editable.moveCursorToPreviousLine();
606     expect('123\n1234|\n12345\n\nHi');
607     editable.moveCursorToPreviousLine();
608     expect('123|\n1234\n12345\n\nHi');
609     editable.moveCursorToNextLine();
610     expect('123\n123|4\n12345\n\nHi');
611     editable.moveCursorToNextLine();
612     expect('123\n1234\n123|45\n\nHi');
613     editable.moveCursorToNextLine();
614     expect('123\n1234\n12345\n|\nHi');
615     editable.moveCursorToNextLine();
616     expect('123\n1234\n12345\n\n|Hi');
617     editable.moveCursorToNextLine();
618     expect('123\n1234\n12345\n\nHi|');
620     prepare('foo|bar');
621     editable.moveCursorToPreviousLine();
622     expect('|foobar');
623     editable.moveCursorToPreviousLine();
624     expect('|foobar');
625     editable.moveCursorToNextLine();
626     expect('foobar|');
627     editable.moveCursorToNextLine();
628     expect('foobar|');
629   } finally {
630     test.tearDown();
631   }
634 /** Tests that paragraph navigation works. */
635 TEST_F('CvoxEditableTextUnitTest', 'CursorMovementByParagraph', function() {
636   var test = this.setUpForCursorTest_('textarea');
637   var editable = test.editable, prepare = test.prepare, expect = test.expect;
638   try {
639     prepare('Para|graph 1\nParagraph 2\nParagraph 3');
640     editable.moveCursorToNextParagraph();
641     expect('Paragraph 1\n|Paragraph 2\nParagraph 3');
642     editable.moveCursorToNextParagraph();
643     expect('Paragraph 1\nParagraph 2\n|Paragraph 3');
644     editable.moveCursorToNextParagraph();
645     expect('Paragraph 1\nParagraph 2\nParagraph 3|');
646     editable.moveCursorToPreviousParagraph();
647     expect('Paragraph 1\nParagraph 2\n|Paragraph 3');
648     editable.moveCursorToPreviousParagraph();
649     expect('Paragraph 1\n|Paragraph 2\nParagraph 3');
650     editable.moveCursorToPreviousParagraph();
651     expect('|Paragraph 1\nParagraph 2\nParagraph 3');
652   } finally {
653     test.tearDown();
654   }
657 /** Tests normalization of TextChangeEvent's */
658 TEST_F('CvoxEditableTextUnitTest', 'TextChangeEvent', function() {
659   var event1 = new cvox.TextChangeEvent('foo', 0, 1, true);
660   var event2 = new cvox.TextChangeEvent('foo', 1, 0, true);
661   var event3 = new cvox.TextChangeEvent('foo', 1, 1, true);
663   assertEquals(0, event1.start);
664   assertEquals(1, event1.end);
666   assertEquals(0, event2.start);
667   assertEquals(1, event2.end);
669   assertEquals(1, event3.start);
670   assertEquals(1, event3.end);
673 TEST_F('CvoxEditableTextUnitTest', 'ContentEditableBraille', function() {
674   this.loadDoc(function() {/*!
675     <div id='1' contenteditable='true'>
676       Some &nbsp; text.<br><br>
677       After blank line.
678     </div>
679   */});
680   var element = $('1');
681   element.focus();
682   var editable = new cvox.ChromeVoxEditableContentEditable(
683       element, new TestTts());
684   var firstLine = 'Some   text.\n';
685   for (var i = 0; i < firstLine.length; ++i) {
686     editable.update(true);
687     TestBraille.assertContent(firstLine, i, i);
688     window.getSelection().modify('move', 'forward', 'character');
689   }
690   // We should have crossed the line break to the second line which is blank.
691   editable.update(true);
692   TestBraille.assertContent('', 0, 0);