| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // @dart = 2.6 |
| import 'package:test/bootstrap/browser.dart'; |
| import 'package:test/test.dart'; |
| |
| import 'package:ui/src/engine.dart'; |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| void testMain() { |
| group('$WordBreaker', () { |
| test('Does not go beyond the ends of a string', () { |
| expect(WordBreaker.prevBreakIndex('foo', -1), 0); |
| expect(WordBreaker.prevBreakIndex('foo', 0), 0); |
| expect(WordBreaker.prevBreakIndex('foo', 'foo'.length + 1), 'foo'.length); |
| |
| expect(WordBreaker.nextBreakIndex('foo', -1), 0); |
| expect(WordBreaker.nextBreakIndex('foo', 'foo'.length), 'foo'.length); |
| expect(WordBreaker.nextBreakIndex('foo', 'foo'.length + 1), 'foo'.length); |
| }); |
| |
| test('Words and spaces', () { |
| expectWords('foo bar', <String>['foo', ' ', 'bar']); |
| expectWords('foo bar', <String>['foo', ' ', 'bar']); |
| }); |
| |
| test('Single-letter words', () { |
| expectWords('foo a bar', <String>['foo', ' ', 'a', ' ', 'bar']); |
| expectWords('a b c', <String>['a', ' ', 'b', ' ', 'c']); |
| expectWords(' a b ', <String>[' ', 'a', ' ', 'b', ' ']); |
| }); |
| |
| test('Multiple consecutive spaces', () { |
| // Different types of whitespace: |
| final String oghamSpace = String.fromCharCode(0x1680); |
| final String punctuationSpace = String.fromCharCode(0x2008); |
| final String mathSpace = String.fromCharCode(0x205F); |
| final String ideographicSpace = String.fromCharCode(0x3000); |
| expectWords( |
| 'foo$oghamSpace ${punctuationSpace}bar', |
| <String>['foo', '$oghamSpace $punctuationSpace', 'bar'], |
| ); |
| expectWords( |
| '$mathSpace$ideographicSpace${oghamSpace}foo', |
| <String>['$mathSpace$ideographicSpace$oghamSpace', 'foo'], |
| ); |
| expectWords( |
| 'foo$punctuationSpace$mathSpace ', |
| <String>['foo', '$punctuationSpace$mathSpace '], |
| ); |
| expectWords( |
| '$oghamSpace $punctuationSpace$mathSpace$ideographicSpace', |
| <String>['$oghamSpace $punctuationSpace$mathSpace$ideographicSpace'], |
| ); |
| }); |
| |
| test('Punctuation', () { |
| expectWords('foo,bar.baz', <String>['foo', ',', 'bar.baz']); |
| expectWords('foo_bar', <String>['foo_bar']); |
| expectWords('foo-bar', <String>['foo', '-', 'bar']); |
| }); |
| |
| test('Numeric', () { |
| expectWords('12ab ab12', <String>['12ab', ' ', 'ab12']); |
| expectWords('ab12,34cd', <String>['ab12,34cd']); |
| expectWords('123,456_789.0', <String>['123,456_789.0']); |
| }); |
| |
| test('Quotes', () { |
| expectWords("Mike's bike", <String>["Mike's", ' ', 'bike']); |
| expectWords("Students' grades", <String>['Students', "'", ' ', 'grades']); |
| expectWords( |
| 'Joe said: "I\'m here"', |
| <String>['Joe', ' ', 'said', ':', ' ', '"', "I\'m", ' ', 'here', '"'], |
| ); |
| }); |
| |
| // Hebrew letters have the same rules as other letters, except |
| // when they are around quotes. So we need to test those rules separately. |
| test('Hebrew with quotes', () { |
| // A few hebrew letters: |
| const String h1 = 'א'; |
| const String h2 = 'ל'; |
| const String h3 = 'ט'; |
| |
| // Test the single quote behavior that should be the same as other letters. |
| expectWords("$h1$h2'$h3", <String>["$h1$h2'$h3"]); |
| |
| // Single quote following a hebrew shouldn't break. |
| expectWords("$h1$h2'", <String>["$h1$h2'"]); |
| expectWords("$h1$h2' $h3", <String>["$h1$h2'", ' ', h3]); |
| |
| // Double quotes around hebrew words should break. |
| expectWords('"$h1$h3"', <String>['"', '$h1$h3', '"']); |
| |
| // Double quotes within hebrew words shouldn't break. |
| expectWords('$h3"$h2', <String>['$h3"$h2']); |
| }); |
| |
| test('Newline, CR and LF', () { |
| final String newline = String.fromCharCode(0x000B); |
| // The only sequence of new lines that isn't a word boundary is CR×LF. |
| expectWords('foo\r\nbar', <String>['foo', '\r\n', 'bar']); |
| |
| // All other sequences are considered word boundaries. |
| |
| expectWords('foo\n\nbar', <String>['foo', '\n', '\n', 'bar']); |
| expectWords('foo\r\rbar', <String>['foo', '\r', '\r', 'bar']); |
| expectWords( |
| 'foo$newline${newline}bar', <String>['foo', newline, newline, 'bar']); |
| |
| expectWords('foo\n\rbar', <String>['foo', '\n', '\r', 'bar']); |
| expectWords('foo$newline\rbar', <String>['foo', newline, '\r', 'bar']); |
| expectWords('foo\r${newline}bar', <String>['foo', '\r', newline, 'bar']); |
| expectWords('foo$newline\nbar', <String>['foo', newline, '\n', 'bar']); |
| expectWords('foo\n${newline}bar', <String>['foo', '\n', newline, 'bar']); |
| }); |
| |
| test('katakana', () { |
| // Katakana letters should stick together but not with other letters. |
| expectWords('ナヌ', <String>['ナヌ']); |
| expectWords('ナabcヌ', <String>['ナ', 'abc', 'ヌ']); |
| |
| // Katakana sometimes behaves the same as other letters. |
| expectWords('ナ,ヌ_イ', <String>['ナ', ',', 'ヌ_イ']); |
| |
| // Katakana sometimes behaves differently from other letters. |
| expectWords('ナ.ヌ', <String>['ナ', '.', 'ヌ']); |
| expectWords("ナ'ヌ", <String>['ナ', "'", 'ヌ']); |
| expectWords('ナ12ヌ', <String>['ナ', '12', 'ヌ']); |
| }); |
| }); |
| } |
| |
| void expectWords(String text, List<String> expectedWords) { |
| int strIndex = 0; |
| |
| // Forward word break lookup. |
| for (String word in expectedWords) { |
| final int nextBreak = WordBreaker.nextBreakIndex(text, strIndex); |
| expect( |
| nextBreak, strIndex + word.length, |
| reason: 'Forward word break lookup: expecting to move to the end of "$word" in "$text".' |
| ); |
| strIndex += word.length; |
| } |
| |
| // Backward word break lookup. |
| strIndex = text.length; |
| for (String word in expectedWords.reversed) { |
| final int prevBreak = WordBreaker.prevBreakIndex(text, strIndex); |
| expect( |
| prevBreak, strIndex - word.length, |
| reason: 'Backward word break lookup: expecting to move to the start of "$word" in "$text".' |
| ); |
| strIndex -= word.length; |
| } |
| } |