blob: 67dbc5aff7b1d0d3541ba2e6483b5b50301abf93 [file] [log] [blame]
// Copyright 2014 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.
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('Character boundary works', () {
const CharacterBoundary boundary = CharacterBoundary('abc');
const TextPosition midPosition = TextPosition(offset: 1);
expect(boundary.getLeadingTextBoundaryAt(midPosition), const TextPosition(offset: 1));
expect(boundary.getTrailingTextBoundaryAt(midPosition), const TextPosition(offset: 2, affinity: TextAffinity.upstream));
const TextPosition startPosition = TextPosition(offset: 0);
expect(boundary.getLeadingTextBoundaryAt(startPosition), const TextPosition(offset: 0));
expect(boundary.getTrailingTextBoundaryAt(startPosition), const TextPosition(offset: 1, affinity: TextAffinity.upstream));
const TextPosition endPosition = TextPosition(offset: 3);
expect(boundary.getLeadingTextBoundaryAt(endPosition), const TextPosition(offset: 3, affinity: TextAffinity.upstream));
expect(boundary.getTrailingTextBoundaryAt(endPosition), const TextPosition(offset: 3, affinity: TextAffinity.upstream));
});
test('Character boundary works with grapheme', () {
const String text = 'a❄︎c';
const CharacterBoundary boundary = CharacterBoundary(text);
TextPosition position = const TextPosition(offset: 1);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: 1));
// The `❄` takes two character length.
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: 3, affinity: TextAffinity.upstream));
position = const TextPosition(offset: 2);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: 1));
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: 3, affinity: TextAffinity.upstream));
position = const TextPosition(offset: 0);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: 0));
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: 1, affinity: TextAffinity.upstream));
position = const TextPosition(offset: text.length);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: text.length, affinity: TextAffinity.upstream));
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: text.length, affinity: TextAffinity.upstream));
});
test('word boundary works', () {
final WordBoundary boundary = WordBoundary(TestTextLayoutMetrics());
const TextPosition position = TextPosition(offset: 3);
expect(boundary.getLeadingTextBoundaryAt(position).offset, TestTextLayoutMetrics.wordBoundaryAt3.start);
expect(boundary.getTrailingTextBoundaryAt(position).offset, TestTextLayoutMetrics.wordBoundaryAt3.end);
});
test('line boundary works', () {
final LineBreak boundary = LineBreak(TestTextLayoutMetrics());
const TextPosition position = TextPosition(offset: 3);
expect(boundary.getLeadingTextBoundaryAt(position).offset, TestTextLayoutMetrics.lineAt3.start);
expect(boundary.getTrailingTextBoundaryAt(position).offset, TestTextLayoutMetrics.lineAt3.end);
});
test('document boundary works', () {
const String text = 'abcd efg hi\njklmno\npqrstuv';
const DocumentBoundary boundary = DocumentBoundary(text);
const TextPosition position = TextPosition(offset: 10);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: 0));
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: text.length, affinity: TextAffinity.upstream));
});
test('white space boundary works', () {
const String text = 'abcd efg';
const WhitespaceBoundary boundary = WhitespaceBoundary(text);
TextPosition position = const TextPosition(offset: 1);
// Should return the same position if the position points to a non white space.
expect(boundary.getLeadingTextBoundaryAt(position), position);
expect(boundary.getTrailingTextBoundaryAt(position), position);
position = const TextPosition(offset: 1, affinity: TextAffinity.upstream);
expect(boundary.getLeadingTextBoundaryAt(position), position);
expect(boundary.getTrailingTextBoundaryAt(position), position);
position = const TextPosition(offset: 4, affinity: TextAffinity.upstream);
expect(boundary.getLeadingTextBoundaryAt(position), position);
expect(boundary.getTrailingTextBoundaryAt(position), position);
// white space
position = const TextPosition(offset: 4);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: 4, affinity: TextAffinity.upstream));
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: 8));
// white space
position = const TextPosition(offset: 6);
expect(boundary.getLeadingTextBoundaryAt(position), const TextPosition(offset: 4, affinity: TextAffinity.upstream));
expect(boundary.getTrailingTextBoundaryAt(position), const TextPosition(offset: 8));
position = const TextPosition(offset: 8);
expect(boundary.getLeadingTextBoundaryAt(position), position);
expect(boundary.getTrailingTextBoundaryAt(position), position);
});
test('extended boundary should work', () {
const String text = 'abcd efg';
const WhitespaceBoundary outer = WhitespaceBoundary(text);
const CharacterBoundary inner = CharacterBoundary(text);
final TextBoundary expanded = outer + inner;
TextPosition position = const TextPosition(offset: 1);
expect(expanded.getLeadingTextBoundaryAt(position), position);
expect(expanded.getTrailingTextBoundaryAt(position), const TextPosition(offset: 2, affinity: TextAffinity.upstream));
position = const TextPosition(offset: 5);
// should skip white space
expect(expanded.getLeadingTextBoundaryAt(position), const TextPosition(offset: 3));
expect(expanded.getTrailingTextBoundaryAt(position), const TextPosition(offset: 9, affinity: TextAffinity.upstream));
});
test('push text position works', () {
const String text = 'abcd efg';
const CharacterBoundary inner = CharacterBoundary(text);
final TextBoundary forward = PushTextPosition.forward + inner;
final TextBoundary backward = PushTextPosition.backward + inner;
TextPosition position = const TextPosition(offset: 1, affinity: TextAffinity.upstream);
const TextPosition pushedForward = TextPosition(offset: 1);
// the forward should push position one affinity
expect(forward.getLeadingTextBoundaryAt(position), inner.getLeadingTextBoundaryAt(pushedForward));
expect(forward.getTrailingTextBoundaryAt(position), inner.getTrailingTextBoundaryAt(pushedForward));
position = const TextPosition(offset: 5);
const TextPosition pushedBackward = TextPosition(offset: 5, affinity: TextAffinity.upstream);
// should skip white space
expect(backward.getLeadingTextBoundaryAt(position), inner.getLeadingTextBoundaryAt(pushedBackward));
expect(backward.getTrailingTextBoundaryAt(position), inner.getTrailingTextBoundaryAt(pushedBackward));
});
}
class TestTextLayoutMetrics extends TextLayoutMetrics {
static const TextSelection lineAt3 = TextSelection(baseOffset: 0, extentOffset: 10);
static const TextRange wordBoundaryAt3 = TextRange(start: 4, end: 7);
@override
TextSelection getLineAtOffset(TextPosition position) {
if (position.offset == 3) {
return lineAt3;
}
throw UnimplementedError();
}
@override
TextPosition getTextPositionAbove(TextPosition position) {
throw UnimplementedError();
}
@override
TextPosition getTextPositionBelow(TextPosition position) {
throw UnimplementedError();
}
@override
TextRange getWordBoundary(TextPosition position) {
if (position.offset == 3) {
return wordBoundaryAt3;
}
throw UnimplementedError();
}
}