Don't crash when TextField w/ explicit controller is activated via a11y (#17892)

Fixes #17801.
This commit is contained in:
Michael Goderbauer 2018-05-25 09:56:24 -07:00 committed by GitHub
parent c4d6311a29
commit 1361071a21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 2 deletions

View file

@ -506,8 +506,8 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
return new Semantics(
onTap: () {
if (!_controller.selection.isValid)
_controller.selection = new TextSelection.collapsed(offset: _controller.text.length);
if (!_effectiveController.selection.isValid)
_effectiveController.selection = new TextSelection.collapsed(offset: _effectiveController.text.length);
_requestKeyboard();
},
child: new IgnorePointer(

View file

@ -2059,6 +2059,76 @@ void main() {
semantics.dispose();
});
testWidgets('Can activate TextField with explicit controller via semantics ', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/17801
const String textInTextField = 'Hello';
final SemanticsTester semantics = new SemanticsTester(tester);
final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner;
final TextEditingController controller = new TextEditingController()
..text = textInTextField;
final Key key = new UniqueKey();
await tester.pumpWidget(
overlay(
child: new TextField(
key: key,
controller: controller,
),
),
);
const int inputFieldId = 1;
expect(semantics, hasSemantics(
new TestSemantics.root(
children: <TestSemantics>[
new TestSemantics(
id: inputFieldId,
flags: <SemanticsFlag>[SemanticsFlag.isTextField],
actions: <SemanticsAction>[SemanticsAction.tap],
value: textInTextField,
textDirection: TextDirection.ltr,
),
],
),
ignoreRect: true, ignoreTransform: true,
));
semanticsOwner.performAction(inputFieldId, SemanticsAction.tap);
await tester.pump();
expect(semantics, hasSemantics(
new TestSemantics.root(
children: <TestSemantics>[
new TestSemantics(
id: inputFieldId,
flags: <SemanticsFlag>[
SemanticsFlag.isTextField,
SemanticsFlag.isFocused,
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.setSelection,
SemanticsAction.paste,
],
value: textInTextField,
textDirection: TextDirection.ltr,
textSelection: const TextSelection(
baseOffset: textInTextField.length,
extentOffset: textInTextField.length,
),
),
],
),
ignoreRect: true, ignoreTransform: true,
));
semantics.dispose();
});
testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async {
const Widget textField = const TextField();
await tester.pumpWidget(textField);