blob: 54ae7dd33c6cb53260d31ba49fbc178eb8d76c01 [file] [log] [blame]
// 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/test.dart';
import 'package:ui/src/engine.dart';
void main() {
group('$WordBreaker', () {
test('Does not go beyond the ends of a string', () {
expect(WordBreaker.prevBreakIndex('foo', 0), 0);
expect(WordBreaker.nextBreakIndex('foo', 'foo'.length), '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);
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);
strIndex -= word.length;
}
}