mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[web] text_editing_test.dart nnbd; bump test dep (flutter/engine#26709)
This commit is contained in:
parent
11ff18234d
commit
7a60f2fb7f
@ -10,8 +10,6 @@ import 'package:pedantic/pedantic.dart';
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
import 'package:typed_data/typed_buffers.dart';
|
||||
|
||||
import 'package:test_api/src/utils.dart' show getErrorMessage;
|
||||
|
||||
/// An interface for running browser instances.
|
||||
///
|
||||
/// This is intentionally coarse-grained: browsers are controlled primary from
|
||||
@ -123,8 +121,9 @@ abstract class Browser {
|
||||
return;
|
||||
}
|
||||
_onExitCompleter.completeError(
|
||||
Exception('Failed to run $name: ${getErrorMessage(error)}.'),
|
||||
stackTrace);
|
||||
Exception('Failed to run $name: $error.'),
|
||||
stackTrace,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ dev_dependencies:
|
||||
image: 3.0.1
|
||||
path: 1.8.0
|
||||
quiver: 3.0.0
|
||||
test: 1.16.6
|
||||
test: 1.17.7
|
||||
yaml: 3.0.0
|
||||
watcher: 1.0.0
|
||||
web_test_utils:
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.9
|
||||
import 'dart:async';
|
||||
import 'dart:html';
|
||||
import 'dart:js_util' as js_util;
|
||||
@ -23,9 +22,9 @@ const MethodCodec codec = JSONMethodCodec();
|
||||
/// Add unit tests for [FirefoxTextEditingStrategy].
|
||||
/// TODO(nurhan): https://github.com/flutter/flutter/issues/46891
|
||||
|
||||
DefaultTextEditingStrategy editingStrategy;
|
||||
EditingState lastEditingState;
|
||||
String lastInputAction;
|
||||
DefaultTextEditingStrategy? editingStrategy;
|
||||
EditingState? lastEditingState;
|
||||
String? lastInputAction;
|
||||
|
||||
final InputConfiguration singlelineConfig = InputConfiguration(
|
||||
inputType: EngineInputType.text,
|
||||
@ -40,11 +39,11 @@ final InputConfiguration multilineConfig = InputConfiguration(
|
||||
final Map<String, dynamic> flutterMultilineConfig =
|
||||
createFlutterConfig('multiline');
|
||||
|
||||
void trackEditingState(EditingState editingState) {
|
||||
void trackEditingState(EditingState? editingState) {
|
||||
lastEditingState = editingState;
|
||||
}
|
||||
|
||||
void trackInputAction(String inputAction) {
|
||||
void trackInputAction(String? inputAction) {
|
||||
lastInputAction = inputAction;
|
||||
}
|
||||
|
||||
@ -62,7 +61,7 @@ void testMain() {
|
||||
});
|
||||
|
||||
group('$GloballyPositionedTextEditingStrategy', () {
|
||||
HybridTextEditing testTextEditing;
|
||||
late HybridTextEditing testTextEditing;
|
||||
|
||||
setUp(() {
|
||||
testTextEditing = HybridTextEditing();
|
||||
@ -82,7 +81,7 @@ void testMain() {
|
||||
expect(document.activeElement, document.body);
|
||||
expect(defaultTextEditingRoot.activeElement, null);
|
||||
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
singlelineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -92,19 +91,19 @@ void testMain() {
|
||||
defaultTextEditingRoot.querySelectorAll('input'),
|
||||
hasLength(1),
|
||||
);
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
final Element input = defaultTextEditingRoot.querySelector('input')!;
|
||||
// Now the editing element should have focus.
|
||||
|
||||
expect(document.activeElement, domRenderer.glassPaneElement);
|
||||
expect(defaultTextEditingRoot.activeElement, input);
|
||||
|
||||
expect(editingStrategy.domElement, input);
|
||||
expect(editingStrategy!.domElement, input);
|
||||
expect(input.getAttribute('type'), null);
|
||||
|
||||
// Input is appended to the right point of the DOM.
|
||||
expect(defaultTextEditingRoot.contains(editingStrategy.domElement), isTrue);
|
||||
expect(defaultTextEditingRoot.contains(editingStrategy!.domElement), isTrue);
|
||||
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
expect(
|
||||
defaultTextEditingRoot.querySelectorAll('input'),
|
||||
hasLength(0),
|
||||
@ -118,78 +117,78 @@ void testMain() {
|
||||
final InputConfiguration config = InputConfiguration(
|
||||
readOnly: true,
|
||||
);
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
config,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
expect(defaultTextEditingRoot.querySelectorAll('input'), hasLength(1));
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
expect(editingStrategy.domElement, input);
|
||||
final Element input = defaultTextEditingRoot.querySelector('input')!;
|
||||
expect(editingStrategy!.domElement, input);
|
||||
expect(input.getAttribute('readonly'), 'readonly');
|
||||
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
});
|
||||
|
||||
test('Knows how to create password fields', () {
|
||||
final InputConfiguration config = InputConfiguration(
|
||||
obscureText: true,
|
||||
);
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
config,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
expect(defaultTextEditingRoot.querySelectorAll('input'), hasLength(1));
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
expect(editingStrategy.domElement, input);
|
||||
final Element input = defaultTextEditingRoot.querySelector('input')!;
|
||||
expect(editingStrategy!.domElement, input);
|
||||
expect(input.getAttribute('type'), 'password');
|
||||
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
});
|
||||
|
||||
test('Knows to turn autocorrect off', () {
|
||||
final InputConfiguration config = InputConfiguration(
|
||||
autocorrect: false,
|
||||
);
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
config,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
expect(defaultTextEditingRoot.querySelectorAll('input'), hasLength(1));
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
expect(editingStrategy.domElement, input);
|
||||
final Element input = defaultTextEditingRoot.querySelector('input')!;
|
||||
expect(editingStrategy!.domElement, input);
|
||||
expect(input.getAttribute('autocorrect'), 'off');
|
||||
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
});
|
||||
|
||||
test('Knows to turn autocorrect on', () {
|
||||
final InputConfiguration config = InputConfiguration(
|
||||
autocorrect: true,
|
||||
);
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
config,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
expect(defaultTextEditingRoot.querySelectorAll('input'), hasLength(1));
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
expect(editingStrategy.domElement, input);
|
||||
final Element input = defaultTextEditingRoot.querySelector('input')!;
|
||||
expect(editingStrategy!.domElement, input);
|
||||
expect(input.getAttribute('autocorrect'), 'on');
|
||||
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
});
|
||||
|
||||
test('Can read editing state correctly', () {
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
singlelineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
|
||||
final InputElement input = editingStrategy.domElement;
|
||||
final InputElement input = editingStrategy!.domElement as InputElement;
|
||||
input.value = 'foo bar';
|
||||
input.dispatchEvent(Event.eventType('Event', 'input'));
|
||||
expect(
|
||||
@ -209,15 +208,15 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('Can set editing state correctly', () {
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
singlelineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
editingStrategy.setEditingState(
|
||||
editingStrategy!.setEditingState(
|
||||
EditingState(text: 'foo bar baz', baseOffset: 2, extentOffset: 7));
|
||||
|
||||
checkInputEditingState(editingStrategy.domElement, 'foo bar baz', 2, 7);
|
||||
checkInputEditingState(editingStrategy!.domElement!, 'foo bar baz', 2, 7);
|
||||
|
||||
// There should be no input action.
|
||||
expect(lastInputAction, isNull);
|
||||
@ -226,7 +225,7 @@ void testMain() {
|
||||
test('Multi-line mode also works', () {
|
||||
// The textarea element is created lazily.
|
||||
expect(document.getElementsByTagName('textarea'), hasLength(0));
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
multilineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -234,10 +233,10 @@ void testMain() {
|
||||
expect(defaultTextEditingRoot.querySelectorAll('textarea'), hasLength(1));
|
||||
|
||||
final TextAreaElement textarea =
|
||||
defaultTextEditingRoot.querySelector('textarea');
|
||||
defaultTextEditingRoot.querySelector('textarea') as TextAreaElement;
|
||||
// Now the textarea should have focus.
|
||||
expect(defaultTextEditingRoot.activeElement, textarea);
|
||||
expect(editingStrategy.domElement, textarea);
|
||||
expect(editingStrategy!.domElement, textarea);
|
||||
|
||||
textarea.value = 'foo\nbar';
|
||||
textarea.dispatchEvent(Event.eventType('Event', 'input'));
|
||||
@ -250,11 +249,11 @@ void testMain() {
|
||||
);
|
||||
|
||||
// Can set textarea state correctly (and preserves new lines).
|
||||
editingStrategy.setEditingState(
|
||||
editingStrategy!.setEditingState(
|
||||
EditingState(text: 'bar\nbaz', baseOffset: 2, extentOffset: 7));
|
||||
checkTextAreaEditingState(textarea, 'bar\nbaz', 2, 7);
|
||||
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
// The textarea should be cleaned up.
|
||||
expect(defaultTextEditingRoot.querySelectorAll('textarea'), hasLength(0));
|
||||
// The focus is back to the body.
|
||||
@ -270,7 +269,7 @@ void testMain() {
|
||||
expect(document.getElementsByTagName('textarea'), hasLength(0));
|
||||
|
||||
// Use single-line config and expect an `<input>` to be created.
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
singlelineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -279,12 +278,12 @@ void testMain() {
|
||||
expect(defaultTextEditingRoot.querySelectorAll('textarea'), hasLength(0));
|
||||
|
||||
// Disable and check that all DOM elements were removed.
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
expect(defaultTextEditingRoot.querySelectorAll('input'), hasLength(0));
|
||||
expect(defaultTextEditingRoot.querySelectorAll('textarea'), hasLength(0));
|
||||
|
||||
// Use multi-line config and expect an `<textarea>` to be created.
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
multilineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -293,7 +292,7 @@ void testMain() {
|
||||
expect(defaultTextEditingRoot.querySelectorAll('textarea'), hasLength(1));
|
||||
|
||||
// Disable again and check that all DOM elements were removed.
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
expect(defaultTextEditingRoot.querySelectorAll('input'), hasLength(0));
|
||||
expect(defaultTextEditingRoot.querySelectorAll('textarea'), hasLength(0));
|
||||
|
||||
@ -305,7 +304,7 @@ void testMain() {
|
||||
final InputConfiguration config = InputConfiguration(
|
||||
inputAction: 'TextInputAction.done',
|
||||
);
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
config,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -315,7 +314,7 @@ void testMain() {
|
||||
expect(lastInputAction, isNull);
|
||||
|
||||
dispatchKeyboardEvent(
|
||||
editingStrategy.domElement,
|
||||
editingStrategy!.domElement!,
|
||||
'keydown',
|
||||
keyCode: _kReturnKeyCode,
|
||||
);
|
||||
@ -329,7 +328,7 @@ void testMain() {
|
||||
inputType: EngineInputType.multiline,
|
||||
inputAction: 'TextInputAction.done',
|
||||
);
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
config,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -339,7 +338,7 @@ void testMain() {
|
||||
expect(lastInputAction, isNull);
|
||||
|
||||
final KeyboardEvent event = dispatchKeyboardEvent(
|
||||
editingStrategy.domElement,
|
||||
editingStrategy!.domElement!,
|
||||
'keydown',
|
||||
keyCode: _kReturnKeyCode,
|
||||
);
|
||||
@ -351,17 +350,17 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('globally positions and sizes its DOM element', () {
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
singlelineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
expect(editingStrategy.isEnabled, isTrue);
|
||||
expect(editingStrategy!.isEnabled, isTrue);
|
||||
|
||||
// No geometry should be set until setEditableSizeAndTransform is called.
|
||||
expect(editingStrategy.domElement.style.transform, '');
|
||||
expect(editingStrategy.domElement.style.width, '');
|
||||
expect(editingStrategy.domElement.style.height, '');
|
||||
expect(editingStrategy!.domElement!.style.transform, '');
|
||||
expect(editingStrategy!.domElement!.style.width, '');
|
||||
expect(editingStrategy!.domElement!.style.height, '');
|
||||
|
||||
testTextEditing.acceptCommand(TextInputSetEditableSizeAndTransform(geometry: EditableTextGeometry(
|
||||
width: 13,
|
||||
@ -370,30 +369,33 @@ void testMain() {
|
||||
)), () {});
|
||||
|
||||
// setEditableSizeAndTransform calls placeElement, so expecting geometry to be applied.
|
||||
expect(editingStrategy.domElement.style.transform,
|
||||
expect(editingStrategy!.domElement!.style.transform,
|
||||
'matrix(1, 0, 0, 1, 14, 15)');
|
||||
expect(editingStrategy.domElement.style.width, '13px');
|
||||
expect(editingStrategy.domElement.style.height, '12px');
|
||||
expect(editingStrategy!.domElement!.style.width, '13px');
|
||||
expect(editingStrategy!.domElement!.style.height, '12px');
|
||||
});
|
||||
});
|
||||
|
||||
group('$HybridTextEditing', () {
|
||||
HybridTextEditing textEditing;
|
||||
HybridTextEditing? textEditing;
|
||||
final PlatformMessagesSpy spy = PlatformMessagesSpy();
|
||||
|
||||
int clientId = 0;
|
||||
|
||||
/// Emulates sending of a message by the framework to the engine.
|
||||
void sendFrameworkMessage(dynamic message) {
|
||||
textEditing.channel.handleTextInput(message, (ByteData data) {});
|
||||
textEditing!.channel.handleTextInput(message, (ByteData? data) {});
|
||||
}
|
||||
|
||||
/// Sends the necessary platform messages to activate a text field and show
|
||||
/// the keyboard.
|
||||
///
|
||||
/// Returns the `clientId` used in the platform message.
|
||||
int showKeyboard(
|
||||
{String inputType, String inputAction, bool decimal = false}) {
|
||||
int showKeyboard({
|
||||
required String inputType,
|
||||
String? inputAction,
|
||||
bool decimal = false,
|
||||
}) {
|
||||
final MethodCall setClient = MethodCall(
|
||||
'TextInput.setClient',
|
||||
<dynamic>[
|
||||
@ -419,7 +421,7 @@ void testMain() {
|
||||
}
|
||||
|
||||
String getEditingInputMode() {
|
||||
return textEditing.strategy.domElement.getAttribute('inputmode');
|
||||
return textEditing!.strategy.domElement!.getAttribute('inputmode')!;
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
@ -429,8 +431,8 @@ void testMain() {
|
||||
|
||||
tearDown(() {
|
||||
spy.tearDown();
|
||||
if (textEditing.isEditing) {
|
||||
textEditing.stopEditing();
|
||||
if (textEditing!.isEditing) {
|
||||
textEditing!.stopEditing();
|
||||
}
|
||||
textEditing = null;
|
||||
});
|
||||
@ -453,7 +455,7 @@ void testMain() {
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
checkInputEditingState(textEditing.strategy.domElement, '', 0, 0);
|
||||
checkInputEditingState(textEditing!.strategy.domElement, '', 0, 0);
|
||||
|
||||
const MethodCall setEditingState =
|
||||
MethodCall('TextInput.setEditingState', <String, dynamic>{
|
||||
@ -464,7 +466,7 @@ void testMain() {
|
||||
sendFrameworkMessage(codec.encodeMethodCall(setEditingState));
|
||||
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
const MethodCall hide = MethodCall('TextInput.hide');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(hide));
|
||||
@ -496,7 +498,7 @@ void testMain() {
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
const MethodCall clearClient = MethodCall('TextInput.clearClient');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(clearClient));
|
||||
@ -527,7 +529,7 @@ void testMain() {
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
final HtmlElement element = textEditing.strategy.domElement;
|
||||
final Element element = textEditing!.strategy.domElement!;
|
||||
expect(element.getAttribute('readonly'), 'readonly');
|
||||
|
||||
// Update the read-only config.
|
||||
@ -569,11 +571,11 @@ void testMain() {
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
expect(textEditing.isEditing, isTrue);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
expect(textEditing!.isEditing, isTrue);
|
||||
|
||||
// DOM element is blurred.
|
||||
textEditing.strategy.domElement.blur();
|
||||
textEditing!.strategy.domElement!.blur();
|
||||
|
||||
// For ios-safari the connection is closed.
|
||||
if (browserEngine == BrowserEngine.webkit &&
|
||||
@ -591,7 +593,7 @@ void testMain() {
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
// DOM element still keeps the focus.
|
||||
expect(defaultTextEditingRoot.activeElement,
|
||||
textEditing.strategy.domElement);
|
||||
textEditing!.strategy.domElement);
|
||||
}
|
||||
},
|
||||
// TODO(nurhan): https://github.com/flutter/flutter/issues/50769
|
||||
@ -618,7 +620,7 @@ void testMain() {
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
const MethodCall finishAutofillContext =
|
||||
MethodCall('TextInput.finishAutofillContext', false);
|
||||
@ -733,7 +735,7 @@ void testMain() {
|
||||
|
||||
// Form is added to DOM.
|
||||
expect(defaultTextEditingRoot.querySelectorAll('form'), isNotEmpty);
|
||||
FormElement formElement = defaultTextEditingRoot.querySelector('form');
|
||||
FormElement formElement = defaultTextEditingRoot.querySelector('form') as FormElement;
|
||||
final Completer<bool> submittedForm = Completer<bool>();
|
||||
formElement.addEventListener(
|
||||
'submit', (event) => submittedForm.complete(true));
|
||||
@ -786,7 +788,7 @@ void testMain() {
|
||||
|
||||
// Form is added to DOM.
|
||||
expect(defaultTextEditingRoot.querySelectorAll('form'), isNotEmpty);
|
||||
FormElement formElement = defaultTextEditingRoot.querySelector('form');
|
||||
FormElement formElement = defaultTextEditingRoot.querySelector('form') as FormElement;
|
||||
final Completer<bool> submittedForm = Completer<bool>();
|
||||
formElement.addEventListener(
|
||||
'submit', (event) => submittedForm.complete(true));
|
||||
@ -830,7 +832,7 @@ void testMain() {
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
final MethodCall setClient2 = MethodCall(
|
||||
'TextInput.setClient', <dynamic>[567, flutterSinglelineConfig]);
|
||||
@ -872,7 +874,7 @@ void testMain() {
|
||||
|
||||
// The second [setEditingState] should override the first one.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'xyz', 0, 2);
|
||||
textEditing!.strategy.domElement, 'xyz', 0, 2);
|
||||
|
||||
const MethodCall clearClient = MethodCall('TextInput.clearClient');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(clearClient));
|
||||
@ -909,9 +911,9 @@ void testMain() {
|
||||
|
||||
// The second [setEditingState] should override the first one.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
final FormElement formElement = defaultTextEditingRoot.querySelector('form');
|
||||
final FormElement formElement = defaultTextEditingRoot.querySelector('form') as FormElement;
|
||||
// The form has one input element and one submit button.
|
||||
expect(formElement.childNodes, hasLength(2));
|
||||
|
||||
@ -947,7 +949,7 @@ void testMain() {
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
final InputElement inputElement =
|
||||
textEditing.strategy.domElement as InputElement;
|
||||
textEditing!.strategy.domElement as InputElement;
|
||||
expect(inputElement.value, 'abcd');
|
||||
if (!(browserEngine == BrowserEngine.webkit &&
|
||||
operatingSystem == OperatingSystem.macOs)) {
|
||||
@ -968,11 +970,11 @@ void testMain() {
|
||||
|
||||
// Check the element still has focus. User can keep editing.
|
||||
expect(defaultTextEditingRoot.activeElement,
|
||||
textEditing.strategy.domElement);
|
||||
textEditing!.strategy.domElement);
|
||||
|
||||
// Check the cursor location is the same.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
const MethodCall clearClient = MethodCall('TextInput.clearClient');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(clearClient));
|
||||
@ -1019,9 +1021,9 @@ void testMain() {
|
||||
|
||||
// The second [setEditingState] should override the first one.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
final FormElement formElement = defaultTextEditingRoot.querySelector('form');
|
||||
final FormElement formElement = defaultTextEditingRoot.querySelector('form') as FormElement;
|
||||
// The form has 4 input elements and one submit button.
|
||||
expect(formElement.childNodes, hasLength(5));
|
||||
|
||||
@ -1061,12 +1063,12 @@ void testMain() {
|
||||
if (browserEngine == BrowserEngine.webkit &&
|
||||
operatingSystem == OperatingSystem.iOs) {
|
||||
expect(
|
||||
textEditing.strategy.domElement
|
||||
textEditing!.strategy.domElement!
|
||||
.getAttribute('autocapitalize'),
|
||||
'off');
|
||||
} else {
|
||||
expect(
|
||||
textEditing.strategy.domElement
|
||||
textEditing!.strategy.domElement!
|
||||
.getAttribute('autocapitalize'),
|
||||
isNull);
|
||||
}
|
||||
@ -1100,7 +1102,7 @@ void testMain() {
|
||||
if (browserEngine == BrowserEngine.webkit &&
|
||||
operatingSystem == OperatingSystem.iOs) {
|
||||
expect(
|
||||
textEditing.strategy.domElement
|
||||
textEditing!.strategy.domElement!
|
||||
.getAttribute('autocapitalize'),
|
||||
'characters');
|
||||
}
|
||||
@ -1136,7 +1138,7 @@ void testMain() {
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
final HtmlElement domElement = textEditing.strategy.domElement;
|
||||
final Element domElement = textEditing!.strategy.domElement!;
|
||||
|
||||
checkInputEditingState(domElement, 'abcd', 2, 3);
|
||||
|
||||
@ -1147,7 +1149,7 @@ void testMain() {
|
||||
const Point<double>(160.0, 70.0)));
|
||||
expect(domElement.style.transform,
|
||||
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 20, 30, 1)');
|
||||
expect(textEditing.strategy.domElement.style.font,
|
||||
expect(textEditing!.strategy.domElement!.style.font,
|
||||
'500 12px sans-serif');
|
||||
|
||||
const MethodCall clearClient = MethodCall('TextInput.clearClient');
|
||||
@ -1192,7 +1194,7 @@ void testMain() {
|
||||
});
|
||||
sendFrameworkMessage(codec.encodeMethodCall(setEditingState));
|
||||
|
||||
final HtmlElement domElement = textEditing.strategy.domElement;
|
||||
final HtmlElement domElement = textEditing!.strategy.domElement!;
|
||||
|
||||
checkInputEditingState(domElement, 'abcd', 2, 3);
|
||||
|
||||
@ -1207,7 +1209,7 @@ void testMain() {
|
||||
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 20, 30, 1)',
|
||||
);
|
||||
expect(
|
||||
textEditing.strategy.domElement.style.font,
|
||||
textEditing!.strategy.domElement!.style.font,
|
||||
'500 12px sans-serif',
|
||||
);
|
||||
|
||||
@ -1215,11 +1217,11 @@ void testMain() {
|
||||
if (browserEngine == BrowserEngine.blink ||
|
||||
browserEngine == BrowserEngine.samsung ||
|
||||
browserEngine == BrowserEngine.webkit) {
|
||||
expect(textEditing.strategy.domElement.classes,
|
||||
expect(textEditing!.strategy.domElement!.classes,
|
||||
contains('transparentTextEditing'));
|
||||
} else {
|
||||
expect(
|
||||
textEditing.strategy.domElement.classes.any(
|
||||
textEditing!.strategy.domElement!.classes.any(
|
||||
(element) => element.toString() == 'transparentTextEditing'),
|
||||
isFalse);
|
||||
}
|
||||
@ -1255,7 +1257,7 @@ void testMain() {
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
final HtmlElement domElement = textEditing.strategy.domElement;
|
||||
final HtmlElement domElement = textEditing!.strategy.domElement!;
|
||||
|
||||
checkInputEditingState(domElement, 'abcd', 2, 3);
|
||||
|
||||
@ -1267,7 +1269,7 @@ void testMain() {
|
||||
expect(domElement.style.transform,
|
||||
'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 10, 20, 30, 1)');
|
||||
expect(
|
||||
textEditing.strategy.domElement.style.font, '12px sans-serif');
|
||||
textEditing!.strategy.domElement!.style.font, '12px sans-serif');
|
||||
|
||||
hideKeyboard();
|
||||
},
|
||||
@ -1275,9 +1277,9 @@ void testMain() {
|
||||
skip: browserEngine == BrowserEngine.webkit);
|
||||
|
||||
test('Canonicalizes font family', () {
|
||||
showKeyboard();
|
||||
showKeyboard(inputType: 'text');
|
||||
|
||||
final HtmlElement input = textEditing.strategy.domElement;
|
||||
final HtmlElement input = textEditing!.strategy.domElement!;
|
||||
|
||||
MethodCall setStyle;
|
||||
|
||||
@ -1316,7 +1318,7 @@ void testMain() {
|
||||
|
||||
// Check if the selection range is correct.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'xyz', 1, 2);
|
||||
textEditing!.strategy.domElement, 'xyz', 1, 2);
|
||||
|
||||
const MethodCall setEditingState2 =
|
||||
MethodCall('TextInput.setEditingState', <String, dynamic>{
|
||||
@ -1328,7 +1330,7 @@ void testMain() {
|
||||
|
||||
// The negative offset values are applied to the dom element as 0.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'xyz', 0, 0);
|
||||
textEditing!.strategy.domElement, 'xyz', 0, 0);
|
||||
|
||||
hideKeyboard();
|
||||
});
|
||||
@ -1349,7 +1351,7 @@ void testMain() {
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
final InputElement input = textEditing.strategy.domElement;
|
||||
final InputElement input = textEditing!.strategy.domElement as InputElement;
|
||||
|
||||
input.value = 'something';
|
||||
input.dispatchEvent(Event.eventType('Event', 'input'));
|
||||
@ -1373,7 +1375,7 @@ void testMain() {
|
||||
input.setSelectionRange(2, 5);
|
||||
if (browserEngine == BrowserEngine.firefox) {
|
||||
Event keyup = KeyboardEvent('keyup');
|
||||
textEditing.strategy.domElement.dispatchEvent(keyup);
|
||||
textEditing!.strategy.domElement!.dispatchEvent(keyup);
|
||||
} else {
|
||||
document.dispatchEvent(Event.eventType('Event', 'selectionchange'));
|
||||
}
|
||||
@ -1431,14 +1433,14 @@ void testMain() {
|
||||
|
||||
// The second [setEditingState] should override the first one.
|
||||
checkInputEditingState(
|
||||
textEditing.strategy.domElement, 'abcd', 2, 3);
|
||||
textEditing!.strategy.domElement, 'abcd', 2, 3);
|
||||
|
||||
final FormElement formElement = defaultTextEditingRoot.querySelector('form');
|
||||
final FormElement formElement = defaultTextEditingRoot.querySelector('form') as FormElement;
|
||||
// The form has 4 input elements and one submit button.
|
||||
expect(formElement.childNodes, hasLength(5));
|
||||
|
||||
// Autofill one of the form elements.
|
||||
InputElement element = formElement.childNodes.first;
|
||||
InputElement element = formElement.childNodes.first as InputElement;
|
||||
if (browserEngine == BrowserEngine.firefox) {
|
||||
expect(element.name,
|
||||
BrowserAutofillHints.instance.flutterToEngine(hintForFirstElement));
|
||||
@ -1482,7 +1484,7 @@ void testMain() {
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
final TextAreaElement textarea = textEditing.strategy.domElement;
|
||||
final TextAreaElement textarea = textEditing!.strategy.domElement as TextAreaElement;
|
||||
checkTextAreaEditingState(textarea, '', 0, 0);
|
||||
|
||||
// Can set editing state and preserve new lines.
|
||||
@ -1500,7 +1502,7 @@ void testMain() {
|
||||
textarea.dispatchEvent(Event.eventType('Event', 'input'));
|
||||
textarea.setSelectionRange(2, 5);
|
||||
if (browserEngine == BrowserEngine.firefox) {
|
||||
textEditing.strategy.domElement
|
||||
textEditing!.strategy.domElement!
|
||||
.dispatchEvent(KeyboardEvent('keyup'));
|
||||
} else {
|
||||
document.dispatchEvent(Event.eventType('Event', 'selectionchange'));
|
||||
@ -1624,7 +1626,7 @@ void testMain() {
|
||||
expect(lastInputAction, isNull);
|
||||
|
||||
dispatchKeyboardEvent(
|
||||
textEditing.strategy.domElement,
|
||||
textEditing!.strategy.domElement!,
|
||||
'keydown',
|
||||
keyCode: _kReturnKeyCode,
|
||||
);
|
||||
@ -1647,7 +1649,7 @@ void testMain() {
|
||||
);
|
||||
|
||||
final KeyboardEvent event = dispatchKeyboardEvent(
|
||||
textEditing.strategy.domElement,
|
||||
textEditing!.strategy.domElement!,
|
||||
'keydown',
|
||||
keyCode: _kReturnKeyCode,
|
||||
);
|
||||
@ -1670,7 +1672,7 @@ void testMain() {
|
||||
['field1', 'field2', 'field3']);
|
||||
final EngineAutofillForm autofillForm =
|
||||
EngineAutofillForm.fromFrameworkMessage(
|
||||
createAutofillInfo('username', 'field1'), fields);
|
||||
createAutofillInfo('username', 'field1'), fields)!;
|
||||
|
||||
// Number of elements if number of fields sent to the constructor minus
|
||||
// one (for the focused text element).
|
||||
@ -1685,7 +1687,7 @@ void testMain() {
|
||||
// 3 child nodes.
|
||||
expect(form.childNodes, hasLength(3));
|
||||
|
||||
final InputElement firstElement = form.childNodes.first;
|
||||
final InputElement firstElement = form.childNodes.first as InputElement;
|
||||
// Autofill value is applied to the element.
|
||||
expect(firstElement.name,
|
||||
BrowserAutofillHints.instance.flutterToEngine('password'));
|
||||
@ -1729,7 +1731,7 @@ void testMain() {
|
||||
['zzyyxx', 'aabbcc', 'jjkkll']);
|
||||
final EngineAutofillForm autofillForm =
|
||||
EngineAutofillForm.fromFrameworkMessage(
|
||||
createAutofillInfo('username', 'field1'), fields);
|
||||
createAutofillInfo('username', 'field1'), fields)!;
|
||||
|
||||
expect(autofillForm.formIdentifier, 'aabbcc*jjkkll*zzyyxx');
|
||||
});
|
||||
@ -1742,7 +1744,7 @@ void testMain() {
|
||||
['field1', 'fields2', 'field3']);
|
||||
final EngineAutofillForm autofillForm =
|
||||
EngineAutofillForm.fromFrameworkMessage(
|
||||
createAutofillInfo('username', 'field1'), fields);
|
||||
createAutofillInfo('username', 'field1'), fields)!;
|
||||
|
||||
final InputElement testInputElement = InputElement();
|
||||
autofillForm.placeForm(testInputElement);
|
||||
@ -1752,7 +1754,7 @@ void testMain() {
|
||||
final FormElement form = autofillForm.formElement;
|
||||
expect(form.childNodes, hasLength(4));
|
||||
|
||||
final FormElement formOnDom = defaultTextEditingRoot.querySelector('form');
|
||||
final FormElement formOnDom = defaultTextEditingRoot.querySelector('form') as FormElement;
|
||||
// Form is attached to the DOM.
|
||||
expect(form, equals(formOnDom));
|
||||
|
||||
@ -1765,7 +1767,7 @@ void testMain() {
|
||||
final List<dynamic> fields = createFieldValues(['username'], ['field1']);
|
||||
final EngineAutofillForm autofillForm =
|
||||
EngineAutofillForm.fromFrameworkMessage(
|
||||
createAutofillInfo('username', 'field1'), fields);
|
||||
createAutofillInfo('username', 'field1'), fields)!;
|
||||
|
||||
// The focused element is the only field. Form should be empty after
|
||||
// the initialization (focus element is appended later).
|
||||
@ -1776,7 +1778,7 @@ void testMain() {
|
||||
final FormElement form = autofillForm.formElement;
|
||||
// Submit button is added to the form.
|
||||
expect(form.childNodes, isNotEmpty);
|
||||
final InputElement inputElement = form.childNodes.first;
|
||||
final InputElement inputElement = form.childNodes.first as InputElement;
|
||||
expect(inputElement.type, 'submit');
|
||||
|
||||
// The submit button should have class `submitBtn`.
|
||||
@ -1785,7 +1787,7 @@ void testMain() {
|
||||
|
||||
test('Return null if no focused element', () {
|
||||
final List<dynamic> fields = createFieldValues(['username'], ['field1']);
|
||||
final EngineAutofillForm autofillForm =
|
||||
final EngineAutofillForm? autofillForm =
|
||||
EngineAutofillForm.fromFrameworkMessage(null, fields);
|
||||
|
||||
expect(autofillForm, isNull);
|
||||
@ -1877,7 +1879,7 @@ void testMain() {
|
||||
setUp(() {
|
||||
editingStrategy =
|
||||
GloballyPositionedTextEditingStrategy(HybridTextEditing());
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
singlelineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
@ -1903,7 +1905,7 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('Configure input element from the editing state', () {
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input') as InputElement;
|
||||
_editingState =
|
||||
EditingState(text: 'Test', baseOffset: 1, extentOffset: 2);
|
||||
|
||||
@ -1916,14 +1918,14 @@ void testMain() {
|
||||
|
||||
test('Configure text area element from the editing state', () {
|
||||
cleanTextEditingStrategy();
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
multilineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
|
||||
final TextAreaElement textArea =
|
||||
defaultTextEditingRoot.querySelector('textarea');
|
||||
defaultTextEditingRoot.querySelector('textarea') as TextAreaElement;
|
||||
_editingState =
|
||||
EditingState(text: 'Test', baseOffset: 1, extentOffset: 2);
|
||||
|
||||
@ -1935,7 +1937,7 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('Get Editing State from input element', () {
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input') as InputElement;
|
||||
input.value = 'Test';
|
||||
input.selectionStart = 1;
|
||||
input.selectionEnd = 2;
|
||||
@ -1949,13 +1951,13 @@ void testMain() {
|
||||
|
||||
test('Get Editing State from text area element', () {
|
||||
cleanTextEditingStrategy();
|
||||
editingStrategy.enable(
|
||||
editingStrategy!.enable(
|
||||
multilineConfig,
|
||||
onChange: trackEditingState,
|
||||
onAction: trackInputAction,
|
||||
);
|
||||
|
||||
final TextAreaElement input = defaultTextEditingRoot.querySelector('textarea');
|
||||
final TextAreaElement input = defaultTextEditingRoot.querySelector('textarea') as TextAreaElement;
|
||||
input.value = 'Test';
|
||||
input.selectionStart = 1;
|
||||
input.selectionEnd = 2;
|
||||
@ -1968,7 +1970,7 @@ void testMain() {
|
||||
});
|
||||
|
||||
test('Compare two editing states', () {
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input');
|
||||
final InputElement input = defaultTextEditingRoot.querySelector('input') as InputElement;
|
||||
input.value = 'Test';
|
||||
input.selectionStart = 1;
|
||||
input.selectionEnd = 2;
|
||||
@ -1989,7 +1991,7 @@ void testMain() {
|
||||
KeyboardEvent dispatchKeyboardEvent(
|
||||
EventTarget target,
|
||||
String type, {
|
||||
int keyCode,
|
||||
required int keyCode,
|
||||
}) {
|
||||
final Function jsKeyboardEvent = js_util.getProperty(window, 'KeyboardEvent');
|
||||
final List<dynamic> eventArgs = <dynamic>[
|
||||
@ -2007,7 +2009,7 @@ KeyboardEvent dispatchKeyboardEvent(
|
||||
}
|
||||
|
||||
MethodCall configureSetStyleMethodCall(int fontSize, String fontFamily,
|
||||
int textAlignIndex, int fontWeightIndex, int textDirectionIndex) {
|
||||
int textAlignIndex, int? fontWeightIndex, int textDirectionIndex) {
|
||||
return MethodCall('TextInput.setStyle', <String, dynamic>{
|
||||
'fontSize': fontSize,
|
||||
'fontFamily': fontFamily,
|
||||
@ -2029,9 +2031,9 @@ MethodCall configureSetSizeAndTransformMethodCall(
|
||||
/// Will disable editing element which will also clean the backup DOM
|
||||
/// element from the page.
|
||||
void cleanTextEditingStrategy() {
|
||||
if (editingStrategy != null && editingStrategy.isEnabled) {
|
||||
if (editingStrategy != null && editingStrategy!.isEnabled) {
|
||||
// Clean up all the DOM elements and event listeners.
|
||||
editingStrategy.disable();
|
||||
editingStrategy!.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2041,7 +2043,10 @@ void cleanTestFlags() {
|
||||
}
|
||||
|
||||
void checkInputEditingState(
|
||||
InputElement input, String text, int start, int end) {
|
||||
Element? element, String text, int start, int end) {
|
||||
expect(element, isNotNull);
|
||||
expect(element, isA<InputElement>());
|
||||
final InputElement input = element as InputElement;
|
||||
expect(defaultTextEditingRoot.activeElement, input);
|
||||
expect(input.value, text);
|
||||
expect(input.selectionStart, start);
|
||||
@ -2082,9 +2087,9 @@ Map<String, dynamic> createFlutterConfig(
|
||||
bool obscureText = false,
|
||||
bool autocorrect = true,
|
||||
String textCapitalization = 'TextCapitalization.none',
|
||||
String inputAction,
|
||||
String autofillHint,
|
||||
List<String> autofillHintsForFields,
|
||||
String? inputAction,
|
||||
String? autofillHint,
|
||||
List<String>? autofillHintsForFields,
|
||||
bool decimal = false,
|
||||
}) {
|
||||
return <String, dynamic>{
|
||||
|
||||
@ -6,7 +6,7 @@ environment:
|
||||
dependencies:
|
||||
js: 0.6.3
|
||||
stream_channel: 2.1.0
|
||||
test: 1.16.6
|
||||
test: 1.17.7
|
||||
webkit_inspection_protocol: 1.0.0
|
||||
ui:
|
||||
path: ../../lib/web_ui
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user