| // 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 'dart:convert' show jsonDecode; |
| |
| import 'package:flutter/services.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| void main() { |
| group('TextEditingDeltaInsertion', () { |
| test('Verify creation of insertion delta when inserting at a collapsed selection.', () { |
| const String jsonInsertionDelta = '{' |
| '"oldText": "",' |
| ' "deltaText": "let there be text",' |
| ' "deltaStart": 0,' |
| ' "deltaEnd": 0,' |
| ' "selectionBase": 17,' |
| ' "selectionExtent": 17,' |
| ' "selectionAffinity" : "TextAffinity.downstream" ,' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": -1,' |
| ' "composingExtent": -1}'; |
| final TextEditingDeltaInsertion delta = TextEditingDelta.fromJSON(jsonDecode(jsonInsertionDelta) as Map<String, dynamic>) as TextEditingDeltaInsertion; |
| const TextRange expectedComposing = TextRange.empty; |
| const int expectedInsertionOffset = 0; |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 17); |
| |
| expect(delta.oldText, ''); |
| expect(delta.textInserted, 'let there be text'); |
| expect(delta.insertionOffset, expectedInsertionOffset); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify creation of insertion delta when inserting at end of composing region.', () { |
| const String jsonInsertionDelta = '{' |
| '"oldText": "hello worl",' |
| ' "deltaText": "world",' |
| ' "deltaStart": 6,' |
| ' "deltaEnd": 10,' |
| ' "selectionBase": 11,' |
| ' "selectionExtent": 11,' |
| ' "selectionAffinity" : "TextAffinity.downstream",' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": 6,' |
| ' "composingExtent": 11}'; |
| |
| final TextEditingDeltaInsertion delta = TextEditingDelta.fromJSON(jsonDecode(jsonInsertionDelta) as Map<String, dynamic>) as TextEditingDeltaInsertion; |
| const TextRange expectedComposing = TextRange(start: 6, end: 11); |
| const int expectedInsertionOffset = 10; |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 11); |
| |
| expect(delta.oldText, 'hello worl'); |
| expect(delta.textInserted, 'd'); |
| expect(delta.insertionOffset, expectedInsertionOffset); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify invalid TextEditingDeltaInsertion fails to apply', () { |
| const TextEditingDeltaInsertion delta = |
| TextEditingDeltaInsertion( |
| oldText: 'hello worl', |
| textInserted: 'd', |
| insertionOffset: 11, |
| selection: TextSelection.collapsed(offset: 11), |
| composing: TextRange.empty, |
| ); |
| |
| expect(() { delta.apply(TextEditingValue.empty); }, throwsAssertionError); |
| }); |
| }); |
| |
| group('TextEditingDeltaDeletion', () { |
| test('Verify creation of deletion delta when deleting.', () { |
| const String jsonDeletionDelta = '{' |
| '"oldText": "let there be text.",' |
| ' "deltaText": "",' |
| ' "deltaStart": 1,' |
| ' "deltaEnd": 2,' |
| ' "selectionBase": 1,' |
| ' "selectionExtent": 1,' |
| ' "selectionAffinity" : "TextAffinity.downstream" ,' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": -1,' |
| ' "composingExtent": -1}'; |
| |
| final TextEditingDeltaDeletion delta = TextEditingDelta.fromJSON(jsonDecode(jsonDeletionDelta) as Map<String, dynamic>) as TextEditingDeltaDeletion; |
| const TextRange expectedComposing = TextRange.empty; |
| const TextRange expectedDeletedRange = TextRange(start: 1, end: 2); |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 1); |
| |
| expect(delta.oldText, 'let there be text.'); |
| expect(delta.textDeleted, 'e'); |
| expect(delta.deletedRange, expectedDeletedRange); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify creation of deletion delta when deleting at end of composing region.', () { |
| const String jsonDeletionDelta = '{' |
| '"oldText": "hello world",' |
| ' "deltaText": "worl",' |
| ' "deltaStart": 6,' |
| ' "deltaEnd": 11,' |
| ' "selectionBase": 10,' |
| ' "selectionExtent": 10,' |
| ' "selectionAffinity" : "TextAffinity.downstream",' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": 6,' |
| ' "composingExtent": 10}'; |
| |
| final TextEditingDeltaDeletion delta = TextEditingDelta.fromJSON(jsonDecode(jsonDeletionDelta) as Map<String, dynamic>) as TextEditingDeltaDeletion; |
| const TextRange expectedComposing = TextRange(start: 6, end: 10); |
| const TextRange expectedDeletedRange = TextRange(start: 10, end: 11); |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 10); |
| |
| expect(delta.oldText, 'hello world'); |
| expect(delta.textDeleted, 'd'); |
| expect(delta.deletedRange, expectedDeletedRange); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify invalid TextEditingDeltaDeletion fails to apply', () { |
| const TextEditingDeltaDeletion delta = |
| TextEditingDeltaDeletion( |
| oldText: 'hello world', |
| deletedRange: TextRange(start: 5, end: 12), |
| selection: TextSelection.collapsed(offset: 5), |
| composing: TextRange.empty, |
| ); |
| |
| expect(() { delta.apply(TextEditingValue.empty); }, throwsAssertionError); |
| }); |
| }); |
| |
| group('TextEditingDeltaReplacement', () { |
| test('Verify creation of replacement delta when replacing with longer.', () { |
| const String jsonReplacementDelta = '{' |
| '"oldText": "hello worfi",' |
| ' "deltaText": "working",' |
| ' "deltaStart": 6,' |
| ' "deltaEnd": 11,' |
| ' "selectionBase": 13,' |
| ' "selectionExtent": 13,' |
| ' "selectionAffinity" : "TextAffinity.downstream",' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": 6,' |
| ' "composingExtent": 13}'; |
| |
| final TextEditingDeltaReplacement delta = TextEditingDelta.fromJSON(jsonDecode(jsonReplacementDelta) as Map<String, dynamic>) as TextEditingDeltaReplacement; |
| const TextRange expectedComposing = TextRange(start: 6, end: 13); |
| const TextRange expectedReplacedRange = TextRange(start: 6, end: 11); |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 13); |
| |
| expect(delta.oldText, 'hello worfi'); |
| expect(delta.textReplaced, 'worfi'); |
| expect(delta.replacementText, 'working'); |
| expect(delta.replacedRange, expectedReplacedRange); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify creation of replacement delta when replacing with shorter.', () { |
| const String jsonReplacementDelta = '{' |
| '"oldText": "hello world",' |
| ' "deltaText": "h",' |
| ' "deltaStart": 6,' |
| ' "deltaEnd": 11,' |
| ' "selectionBase": 7,' |
| ' "selectionExtent": 7,' |
| ' "selectionAffinity" : "TextAffinity.downstream",' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": 6,' |
| ' "composingExtent": 7}'; |
| |
| final TextEditingDeltaReplacement delta = TextEditingDelta.fromJSON(jsonDecode(jsonReplacementDelta) as Map<String, dynamic>) as TextEditingDeltaReplacement; |
| const TextRange expectedComposing = TextRange(start: 6, end: 7); |
| const TextRange expectedReplacedRange = TextRange(start: 6, end: 11); |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 7); |
| |
| expect(delta.oldText, 'hello world'); |
| expect(delta.textReplaced, 'world'); |
| expect(delta.replacementText, 'h'); |
| expect(delta.replacedRange, expectedReplacedRange); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify creation of replacement delta when replacing with same.', () { |
| const String jsonReplacementDelta = '{' |
| '"oldText": "hello world",' |
| ' "deltaText": "words",' |
| ' "deltaStart": 6,' |
| ' "deltaEnd": 11,' |
| ' "selectionBase": 11,' |
| ' "selectionExtent": 11,' |
| ' "selectionAffinity" : "TextAffinity.downstream",' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": 6,' |
| ' "composingExtent": 11}'; |
| |
| final TextEditingDeltaReplacement delta = TextEditingDelta.fromJSON(jsonDecode(jsonReplacementDelta) as Map<String, dynamic>) as TextEditingDeltaReplacement; |
| const TextRange expectedComposing = TextRange(start: 6, end: 11); |
| const TextRange expectedReplacedRange = TextRange(start: 6, end: 11); |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 11); |
| |
| expect(delta.oldText, 'hello world'); |
| expect(delta.textReplaced, 'world'); |
| expect(delta.replacementText, 'words'); |
| expect(delta.replacedRange, expectedReplacedRange); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify invalid TextEditingDeltaReplacement fails to apply', () { |
| const TextEditingDeltaReplacement delta = |
| TextEditingDeltaReplacement( |
| oldText: 'hello worl', |
| replacementText: 'world', |
| replacedRange: TextRange(start: 5, end: 11), |
| selection: TextSelection.collapsed(offset: 11), |
| composing: TextRange.empty, |
| ); |
| |
| expect(() { delta.apply(TextEditingValue.empty); }, throwsAssertionError); |
| }); |
| }); |
| |
| group('TextEditingDeltaNonTextUpdate', () { |
| test('Verify non text update delta created.', () { |
| const String jsonNonTextUpdateDelta = '{' |
| '"oldText": "hello world",' |
| ' "deltaText": "",' |
| ' "deltaStart": -1,' |
| ' "deltaEnd": -1,' |
| ' "selectionBase": 10,' |
| ' "selectionExtent": 10,' |
| ' "selectionAffinity" : "TextAffinity.downstream",' |
| ' "selectionIsDirectional": false,' |
| ' "composingBase": 6,' |
| ' "composingExtent": 11}'; |
| |
| final TextEditingDeltaNonTextUpdate delta = TextEditingDelta.fromJSON(jsonDecode(jsonNonTextUpdateDelta) as Map<String, dynamic>) as TextEditingDeltaNonTextUpdate; |
| const TextRange expectedComposing = TextRange(start: 6, end: 11); |
| const TextSelection expectedSelection = TextSelection.collapsed(offset: 10); |
| |
| expect(delta.oldText, 'hello world'); |
| expect(delta.selection, expectedSelection); |
| expect(delta.composing, expectedComposing); |
| }); |
| |
| test('Verify invalid TextEditingDeltaNonTextUpdate fails to apply', () { |
| const TextEditingDeltaNonTextUpdate delta = |
| TextEditingDeltaNonTextUpdate( |
| oldText: 'hello world', |
| selection: TextSelection.collapsed(offset: 12), |
| composing: TextRange.empty, |
| ); |
| |
| expect(() { delta.apply(TextEditingValue.empty); }, throwsAssertionError); |
| }); |
| }); |
| } |