diff options
Diffstat (limited to 'chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.js')
-rw-r--r-- | chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.js | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.js b/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.js new file mode 100644 index 00000000000..8a26cfeb5d3 --- /dev/null +++ b/chromium/chrome/browser/resources/chromeos/chromevox/common/spannable_test.js @@ -0,0 +1,481 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Include test fixture. +GEN_INCLUDE(['../testing/chromevox_unittest_base.js']); + +UnserializableSpan = function() {}; + +StatelessSerializableSpan = function() {}; + +NonStatelessSerializableSpan = function(value) { + this.value = value; +}; + +/** + * @param {!Object} obj object containing the + * serializable representation. + * @return {!Object} The Spannable. + */ +NonStatelessSerializableSpan.fromJson = function(obj) { + return new NonStatelessSerializableSpan(obj.value / 2); +}; + +/** + * @return {Object} the json serializable form. + */ +NonStatelessSerializableSpan.prototype.toJson = function() { + return {value: this.value * 2}; +}; + +/** + * Test fixture. + * @constructor + * @extends {ChromeVoxUnitTestBase} + */ +function CvoxSpannableUnitTest() {} + +CvoxSpannableUnitTest.prototype = { + __proto__: ChromeVoxUnitTestBase.prototype, + + /** @override */ + closureModuleDeps: [ + 'cvox.Spannable', + ], + + /** @override */ + setUp: function() { + cvox.Spannable.registerStatelessSerializableSpan( + StatelessSerializableSpan, 'StatelessSerializableSpan'); + + cvox.Spannable.registerSerializableSpan( + NonStatelessSerializableSpan, 'NonStatelessSerializableSpan', + NonStatelessSerializableSpan.fromJson, + NonStatelessSerializableSpan.prototype.toJson); + } +}; + +TEST_F('CvoxSpannableUnitTest', 'ToStringUnannotated', function() { + assertEquals('', new cvox.Spannable().toString()); + assertEquals('hello world', new cvox.Spannable('hello world').toString()); +}); + +/** Tests that toString works correctly on annotated strings. */ +TEST_F('CvoxSpannableUnitTest', 'ToStringAnnotated', function() { + var spannable = new cvox.Spannable('Hello Google'); + spannable.setSpan('http://www.google.com/', 6, 12); + assertEquals('Hello Google', spannable.toString()); +}); + +/** Tests the length calculation. */ +TEST_F('CvoxSpannableUnitTest', 'GetLength', function() { + var spannable = new cvox.Spannable('Hello'); + spannable.setSpan({}, 0, 3); + assertEquals(5, spannable.getLength()); + spannable.append(' world'); + assertEquals(11, spannable.getLength()); + spannable.append(new cvox.Spannable(' from cvox.Spannable')); + assertEquals(31, spannable.getLength()); +}); + +/** Tests that a span can be added and retrieved at the beginning. */ +TEST_F('CvoxSpannableUnitTest', 'SpanBeginning', function() { + var annotation = {}; + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(annotation, 0, 5); + assertSame(annotation, spannable.getSpan(0)); + assertSame(annotation, spannable.getSpan(3)); + assertUndefined(spannable.getSpan(5)); + assertUndefined(spannable.getSpan(8)); +}); + +/** Tests that a span can be added and retrieved at the beginning. */ +TEST_F('CvoxSpannableUnitTest', 'SpanEnd', function() { + var annotation = {}; + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(annotation, 6, 11); + assertUndefined(spannable.getSpan(3)); + assertUndefined(spannable.getSpan(5)); + assertSame(annotation, spannable.getSpan(6)); + assertSame(annotation, spannable.getSpan(10)); +}); + +/** Tests that a zero-length span is not retrieved. */ +TEST_F('CvoxSpannableUnitTest', 'SpanZeroLength', function() { + var annotation = {}; + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(annotation, 3, 3); + assertUndefined(spannable.getSpan(2)); + assertUndefined(spannable.getSpan(3)); + assertUndefined(spannable.getSpan(4)); +}); + +/** Tests that a removed span is not returned. */ +TEST_F('CvoxSpannableUnitTest', 'RemoveSpan', function() { + var annotation = {}; + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(annotation, 0, 3); + assertSame(annotation, spannable.getSpan(1)); + spannable.removeSpan(annotation); + assertUndefined(spannable.getSpan(1)); +}); + +/** Tests that adding a span in one place removes it from another. */ +TEST_F('CvoxSpannableUnitTest', 'SetSpanMoves', function() { + var annotation = {}; + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(annotation, 0, 3); + assertSame(annotation, spannable.getSpan(1)); + assertUndefined(spannable.getSpan(4)); + spannable.setSpan(annotation, 3, 6); + assertUndefined(spannable.getSpan(1)); + assertSame(annotation, spannable.getSpan(4)); +}); + +/** Tests that setSpan objects to out-of-range arguments. */ +TEST_F('CvoxSpannableUnitTest', 'SetSpanRangeError', function() { + var spannable = new cvox.Spannable('Hello world'); + + // Start index out of range. + assertException('expected range error', function() { + spannable.setSpan({}, -1, 0); + }, 'RangeError'); + + // End index out of range. + assertException('expected range error', function() { + spannable.setSpan({}, 0, 12); + }, 'RangeError'); + + // End before start. + assertException('expected range error', function() { + spannable.setSpan({}, 1, 0); + }, 'RangeError'); +}); + +/** + * Tests that multiple spans can be retrieved at one point. + * The first one added which applies should be returned by getSpan. + */ +TEST_F('CvoxSpannableUnitTest', 'MultipleSpans', function() { + var annotation1 = { number: 1 }; + var annotation2 = { number: 2 }; + assertNotSame(annotation1, annotation2); + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(annotation1, 1, 4); + spannable.setSpan(annotation2, 2, 7); + assertSame(annotation1, spannable.getSpan(1)); + assertThat([annotation1], eqJSON(spannable.getSpans(1))); + assertSame(annotation1, spannable.getSpan(3)); + assertThat([annotation1, annotation2], eqJSON(spannable.getSpans(3))); + assertSame(annotation2, spannable.getSpan(6)); + assertThat([annotation2], eqJSON(spannable.getSpans(6))); +}); + +/** Tests that appending appends the strings. */ +TEST_F('CvoxSpannableUnitTest', 'AppendToString', function() { + var spannable = new cvox.Spannable('Google'); + assertEquals('Google', spannable.toString()); + spannable.append(' Chrome'); + assertEquals('Google Chrome', spannable.toString()); + spannable.append(new cvox.Spannable('Vox')); + assertEquals('Google ChromeVox', spannable.toString()); +}); + +/** + * Tests that appending Spannables combines annotations. + */ +TEST_F('CvoxSpannableUnitTest', 'AppendAnnotations', function() { + var annotation1 = { number: 1 }; + var annotation2 = { number: 2 }; + assertNotSame(annotation1, annotation2); + var left = new cvox.Spannable('hello'); + left.setSpan(annotation1, 0, 3); + var right = new cvox.Spannable(' world'); + right.setSpan(annotation2, 0, 3); + left.append(right); + assertSame(annotation1, left.getSpan(1)); + assertSame(annotation2, left.getSpan(6)); +}); + +/** + * Tests that a span's bounds can be retrieved. + */ +TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEnd', function() { + var annotation = {}; + var spannable = new cvox.Spannable('potato wedges'); + spannable.setSpan(annotation, 8, 12); + assertEquals(8, spannable.getSpanStart(annotation)); + assertEquals(12, spannable.getSpanEnd(annotation)); +}); + +/** + * Tests that an absent span's bounds are reported correctly. + */ +TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEndAbsent', function() { + var annotation = {}; + var spannable = new cvox.Spannable('potato wedges'); + assertUndefined(spannable.getSpanStart(annotation)); + assertUndefined(spannable.getSpanEnd(annotation)); +}); + +/** + * Test that a zero length span can still be found. + */ +TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEndZeroLength', function() { + var annotation = {}; + var spannable = new cvox.Spannable('potato wedges'); + spannable.setSpan(annotation, 8, 8); + assertEquals(8, spannable.getSpanStart(annotation)); + assertEquals(8, spannable.getSpanEnd(annotation)); +}); + +/** + * Tests that == (but not ===) objects are treated distinctly when getting + * span bounds. + */ +TEST_F('CvoxSpannableUnitTest', 'GetSpanStartAndEndEquality', function() { + // Note that 0 == '' and '' == 0 in JavaScript. + var spannable = new cvox.Spannable('wat'); + spannable.setSpan(0, 0, 0); + spannable.setSpan('', 1, 3); + assertEquals(0, spannable.getSpanStart(0)); + assertEquals(0, spannable.getSpanEnd(0)); + assertEquals(1, spannable.getSpanStart('')); + assertEquals(3, spannable.getSpanEnd('')); +}); + +/** + * Tests that substrings have the correct character sequence. + */ +TEST_F('CvoxSpannableUnitTest', 'Substring', function() { + var assertSubstringResult = function(expected, initial, start, opt_end) { + var spannable = new cvox.Spannable(initial); + var substring = spannable.substring(start, opt_end); + assertEquals(expected, substring.toString()); + }; + assertSubstringResult('Page', 'Google PageRank', 7, 11); + assertSubstringResult('Goog', 'Google PageRank', 0, 4); + assertSubstringResult('Rank', 'Google PageRank', 11, 15); + assertSubstringResult('Rank', 'Google PageRank', 11); +}); + +/** + * Tests that substring arguments are validated properly. + */ +TEST_F('CvoxSpannableUnitTest', 'SubstringRangeError', function() { + var assertRangeError = function(initial, start, opt_end) { + var spannable = new cvox.Spannable(initial); + assertException('expected range error', function() { + spannable.substring(start, opt_end); + }, 'RangeError'); + }; + assertRangeError('Google PageRank', -1, 5); + assertRangeError('Google PageRank', 0, 99); + assertRangeError('Google PageRank', 5, 2); +}); + +/** + * Tests that spans in the substring range are preserved. + */ +TEST_F('CvoxSpannableUnitTest', 'SubstringSpansIncluded', function() { + var assertSpanIncluded = function(expectedSpanStart, expectedSpanEnd, + initial, initialSpanStart, initialSpanEnd, start, opt_end) { + var annotation = {}; + var spannable = new cvox.Spannable(initial); + spannable.setSpan(annotation, initialSpanStart, initialSpanEnd); + var substring = spannable.substring(start, opt_end); + assertEquals(expectedSpanStart, substring.getSpanStart(annotation)); + assertEquals(expectedSpanEnd, substring.getSpanEnd(annotation)); + }; + assertSpanIncluded(1, 5, 'potato wedges', 8, 12, 7); + assertSpanIncluded(1, 5, 'potato wedges', 8, 12, 7, 13); + assertSpanIncluded(1, 5, 'potato wedges', 8, 12, 7, 12); + assertSpanIncluded(0, 4, 'potato wedges', 8, 12, 8, 12); + assertSpanIncluded(0, 3, 'potato wedges', 0, 3, 0); + assertSpanIncluded(0, 3, 'potato wedges', 0, 3, 0, 3); + assertSpanIncluded(0, 3, 'potato wedges', 0, 3, 0, 6); + assertSpanIncluded(0, 5, 'potato wedges', 8, 13, 8); + assertSpanIncluded(0, 5, 'potato wedges', 8, 13, 8, 13); + assertSpanIncluded(1, 6, 'potato wedges', 8, 13, 7, 13); + + // Note: we should keep zero-length spans, even at the edges of the range. + assertSpanIncluded(0, 0, 'potato wedges', 0, 0, 0, 0); + assertSpanIncluded(0, 0, 'potato wedges', 0, 0, 0, 6); + assertSpanIncluded(1, 1, 'potato wedges', 8, 8, 7, 13); + assertSpanIncluded(6, 6, 'potato wedges', 6, 6, 0, 6); +}); + +/** + * Tests that spans outside the range are omitted. + * It's fine to keep zero-length spans at the ends, though. + */ +TEST_F('CvoxSpannableUnitTest', 'SubstringSpansExcluded', function() { + var assertSpanExcluded = function(initial, spanStart, spanEnd, + start, opt_end) { + var annotation = {}; + var spannable = new cvox.Spannable(initial); + spannable.setSpan(annotation, spanStart, spanEnd); + var substring = spannable.substring(start, opt_end); + assertUndefined(substring.getSpanStart(annotation)); + assertUndefined(substring.getSpanEnd(annotation)); + }; + assertSpanExcluded('potato wedges', 8, 12, 0, 6); + assertSpanExcluded('potato wedges', 7, 12, 0, 6); + assertSpanExcluded('potato wedges', 0, 6, 8); + assertSpanExcluded('potato wedges', 6, 6, 8); +}); + +/** + * Tests that spans which cross the boundary are clipped. + */ +TEST_F('CvoxSpannableUnitTest', 'SubstringSpansClipped', function() { + var assertSpanIncluded = function(expectedSpanStart, expectedSpanEnd, + initial, initialSpanStart, initialSpanEnd, start, opt_end) { + var annotation = {}; + var spannable = new cvox.Spannable(initial); + spannable.setSpan(annotation, initialSpanStart, initialSpanEnd); + var substring = spannable.substring(start, opt_end); + assertEquals(expectedSpanStart, substring.getSpanStart(annotation)); + assertEquals(expectedSpanEnd, substring.getSpanEnd(annotation)); + }; + assertSpanIncluded(0, 4, 'potato wedges', 7, 13, 8, 12); + assertSpanIncluded(0, 0, 'potato wedges', 0, 6, 0, 0); + assertSpanIncluded(0, 0, 'potato wedges', 0, 6, 6, 6); + + // The first of the above should produce "edge". + assertEquals('edge', + new cvox.Spannable('potato wedges').substring(8, 12).toString()); +}); + +/** + * Tests that whitespace is trimmed. + */ +TEST_F('CvoxSpannableUnitTest', 'Trim', function() { + var assertTrimResult = function(expected, initial) { + assertEquals(expected, new cvox.Spannable(initial).trim().toString()); + }; + assertTrimResult('John F. Kennedy', 'John F. Kennedy'); + assertTrimResult('John F. Kennedy', ' John F. Kennedy'); + assertTrimResult('John F. Kennedy', 'John F. Kennedy '); + assertTrimResult('John F. Kennedy', ' \r\t \nJohn F. Kennedy\n\n \n'); + assertTrimResult('', ''); + assertTrimResult('', ' \t\t \n\r'); +}); + +/** + * Tests that trim keeps, drops and clips spans. + */ +TEST_F('CvoxSpannableUnitTest', 'TrimSpans', function() { + var spannable = new cvox.Spannable(' \t Kennedy\n'); + spannable.setSpan('tab', 1, 2); + spannable.setSpan('jfk', 3, 10); + spannable.setSpan('jfk-newline', 3, 11); + var trimmed = spannable.trim(); + assertUndefined(trimmed.getSpanStart('tab')); + assertUndefined(trimmed.getSpanEnd('tab')); + assertEquals(0, trimmed.getSpanStart('jfk')); + assertEquals(7, trimmed.getSpanEnd('jfk')); + assertEquals(0, trimmed.getSpanStart('jfk-newline')); + assertEquals(7, trimmed.getSpanEnd('jfk-newline')); +}); + +/** + * Tests that when a string is all whitespace, we trim off the *end*. + */ +TEST_F('CvoxSpannableUnitTest', 'TrimAllWhitespace', function() { + var spannable = new cvox.Spannable(' '); + spannable.setSpan('cursor 1', 0, 0); + spannable.setSpan('cursor 2', 2, 2); + var trimmed = spannable.trim(); + assertEquals(0, trimmed.getSpanStart('cursor 1')); + assertEquals(0, trimmed.getSpanEnd('cursor 1')); + assertUndefined(trimmed.getSpanStart('cursor 2')); + assertUndefined(trimmed.getSpanEnd('cursor 2')); +}); + +/** + * Tests finding a span which is an instance of a given class. + */ +TEST_F('CvoxSpannableUnitTest', 'GetSpanInstanceOf', function() { + function ExampleConstructorBase() {} + function ExampleConstructor1() {} + function ExampleConstructor2() {} + function ExampleConstructor3() {} + ExampleConstructor1.prototype = new ExampleConstructorBase(); + ExampleConstructor2.prototype = new ExampleConstructorBase(); + ExampleConstructor3.prototype = new ExampleConstructorBase(); + var ex1 = new ExampleConstructor1(); + var ex2 = new ExampleConstructor2(); + var spannable = new cvox.Spannable('Hello world'); + spannable.setSpan(ex1, 0, 0); + spannable.setSpan(ex2, 1, 1); + assertEquals(ex1, spannable.getSpanInstanceOf(ExampleConstructor1)); + assertEquals(ex2, spannable.getSpanInstanceOf(ExampleConstructor2)); + assertUndefined(spannable.getSpanInstanceOf(ExampleConstructor3)); + assertEquals(ex1, spannable.getSpanInstanceOf(ExampleConstructorBase)); +}); + +/** Tests trimming only left or right. */ +TEST_F('CvoxSpannableUnitTest', 'TrimLeftOrRight', function() { + var spannable = new cvox.Spannable(' '); + spannable.setSpan('cursor 1', 0, 0); + spannable.setSpan('cursor 2', 2, 2); + var trimmed = spannable.trimLeft(); + assertEquals(0, trimmed.getSpanStart('cursor 1')); + assertEquals(0, trimmed.getSpanEnd('cursor 1')); + assertUndefined(trimmed.getSpanStart('cursor 2')); + assertUndefined(trimmed.getSpanEnd('cursor 2')); + + var spannable2 = new cvox.Spannable('0 '); + spannable2.setSpan('cursor 1', 0, 0); + spannable2.setSpan('cursor 2', 2, 2); + var trimmed2 = spannable2.trimLeft(); + assertEquals(0, trimmed2.getSpanStart('cursor 1')); + assertEquals(0, trimmed2.getSpanEnd('cursor 1')); + assertEquals(2, trimmed2.getSpanStart('cursor 2')); + assertEquals(2, trimmed2.getSpanEnd('cursor 2')); + trimmed2 = trimmed2.trimRight(); + assertEquals(0, trimmed2.getSpanStart('cursor 1')); + assertEquals(0, trimmed2.getSpanEnd('cursor 1')); + assertUndefined(trimmed2.getSpanStart('cursor 2')); + assertUndefined(trimmed2.getSpanEnd('cursor 2')); + + var spannable3 = new cvox.Spannable(' 0'); + spannable3.setSpan('cursor 1', 0, 0); + spannable3.setSpan('cursor 2', 2, 2); + var trimmed3 = spannable3.trimRight(); + assertEquals(0, trimmed3.getSpanStart('cursor 1')); + assertEquals(0, trimmed3.getSpanEnd('cursor 1')); + assertEquals(2, trimmed3.getSpanStart('cursor 2')); + assertEquals(2, trimmed3.getSpanEnd('cursor 2')); + trimmed3 = trimmed3.trimLeft(); + assertUndefined(trimmed3.getSpanStart('cursor 1')); + assertUndefined(trimmed3.getSpanEnd('cursor 1')); + assertEquals(0, trimmed3.getSpanStart('cursor 2')); + assertEquals(0, trimmed3.getSpanEnd('cursor 2')); +}); + +TEST_F('CvoxSpannableUnitTest', 'Serialize', function() { + var fresh = new cvox.Spannable('text'); + var freshStatelessSerializable = new StatelessSerializableSpan(); + var freshNonStatelessSerializable = new NonStatelessSerializableSpan(14); + fresh.setSpan(new UnserializableSpan(), 0, 1); + fresh.setSpan(freshStatelessSerializable, 0, 2); + fresh.setSpan(freshNonStatelessSerializable, 3, 4); + var thawn = cvox.Spannable.fromJson(fresh.toJson()); + var thawnStatelessSerializable = thawn.getSpanInstanceOf( + StatelessSerializableSpan); + var thawnNonStatelessSerializable = thawn.getSpanInstanceOf( + NonStatelessSerializableSpan); + assertThat('text', eqJSON(thawn.toString())); + assertUndefined(thawn.getSpanInstanceOf(UnserializableSpan)); + assertThat( + fresh.getSpanStart(freshStatelessSerializable), + eqJSON(thawn.getSpanStart(thawnStatelessSerializable))); + assertThat( + fresh.getSpanEnd(freshStatelessSerializable), + eqJSON(thawn.getSpanEnd(thawnStatelessSerializable))); + assertThat(freshNonStatelessSerializable, + eqJSON(thawnNonStatelessSerializable)); +}); |