// 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_test/flutter_test.dart'; import 'package:flutter/material.dart'; void main() { testWidgets('Dialog interaction', (WidgetTester tester) async { expect(tester.testTextInput.isVisible, isFalse); final FocusNode focusNode = FocusNode(debugLabel: 'Editable Text Node'); await tester.pumpWidget( MaterialApp( home: Material( child: Center( child: TextField( focusNode: focusNode, autofocus: true, ), ), ), ), ); expect(tester.testTextInput.isVisible, isTrue); expect(focusNode.hasPrimaryFocus, isTrue); final BuildContext context = tester.element(find.byType(TextField)); showDialog<void>( context: context, builder: (BuildContext context) => const SimpleDialog(title: Text('Dialog')), ); await tester.pump(); expect(tester.testTextInput.isVisible, isFalse); Navigator.of(tester.element(find.text('Dialog'))).pop(); await tester.pump(); expect(focusNode.hasPrimaryFocus, isTrue); expect(tester.testTextInput.isVisible, isTrue); await tester.pumpWidget(Container()); expect(tester.testTextInput.isVisible, isFalse); }); testWidgets('Request focus shows keyboard', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( MaterialApp( home: Material( child: Center( child: TextField( focusNode: focusNode, ), ), ), ), ); expect(tester.testTextInput.isVisible, isFalse); FocusScope.of(tester.element(find.byType(TextField))).requestFocus(focusNode); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.pumpWidget(Container()); expect(tester.testTextInput.isVisible, isFalse); }); testWidgets('Autofocus shows keyboard', (WidgetTester tester) async { expect(tester.testTextInput.isVisible, isFalse); await tester.pumpWidget( const MaterialApp( home: Material( child: Center( child: TextField( autofocus: true, ), ), ), ), ); expect(tester.testTextInput.isVisible, isTrue); await tester.pumpWidget(Container()); expect(tester.testTextInput.isVisible, isFalse); }); testWidgets('Tap shows keyboard', (WidgetTester tester) async { expect(tester.testTextInput.isVisible, isFalse); await tester.pumpWidget( const MaterialApp( home: Material( child: Center( child: TextField(), ), ), ), ); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byType(TextField)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); tester.testTextInput.hide(); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byType(TextField)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.pumpWidget(Container()); expect(tester.testTextInput.isVisible, isFalse); }); testWidgets('Focus triggers keep-alive', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( MaterialApp( home: Material( child: ListView( children: <Widget>[ TextField( focusNode: focusNode, ), Container( height: 1000.0, ), ], ), ), ), ); expect(find.byType(TextField), findsOneWidget); expect(tester.testTextInput.isVisible, isFalse); FocusScope.of(tester.element(find.byType(TextField))).requestFocus(focusNode); await tester.pump(); expect(find.byType(TextField), findsOneWidget); expect(tester.testTextInput.isVisible, isTrue); await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0)); await tester.pump(); expect(find.byType(TextField, skipOffstage: false), findsOneWidget); expect(tester.testTextInput.isVisible, isTrue); focusNode.unfocus(); await tester.pump(); expect(find.byType(TextField), findsNothing); expect(tester.testTextInput.isVisible, isFalse); }); testWidgets('Focus keep-alive works with GlobalKey reparenting', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); Widget makeTest(String? prefix) { return MaterialApp( home: Material( child: ListView( children: <Widget>[ TextField( focusNode: focusNode, decoration: InputDecoration( prefixText: prefix, ), ), Container( height: 1000.0, ), ], ), ), ); } await tester.pumpWidget(makeTest(null)); FocusScope.of(tester.element(find.byType(TextField))).requestFocus(focusNode); await tester.pump(); expect(find.byType(TextField), findsOneWidget); await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0)); await tester.pump(); expect(find.byType(TextField, skipOffstage: false), findsOneWidget); await tester.pumpWidget(makeTest('test')); await tester.pump(); // in case the AutomaticKeepAlive widget thinks it needs a cleanup frame expect(find.byType(TextField, skipOffstage: false), findsOneWidget); }); testWidgets('TextField with decoration:null', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/16880 await tester.pumpWidget( const MaterialApp( home: Material( child: Center( child: TextField( decoration: null ), ), ), ), ); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byType(TextField)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); }); testWidgets('Sibling FocusScopes', (WidgetTester tester) async { expect(tester.testTextInput.isVisible, isFalse); final FocusScopeNode focusScopeNode0 = FocusScopeNode(); final FocusScopeNode focusScopeNode1 = FocusScopeNode(); final Key textField0 = UniqueKey(); final Key textField1 = UniqueKey(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ FocusScope( node: focusScopeNode0, child: Builder( builder: (BuildContext context) => TextField(key: textField0) ), ), FocusScope( node: focusScopeNode1, child: Builder( builder: (BuildContext context) => TextField(key: textField1), ), ), ], ), ), ), ), ); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byKey(textField0)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); tester.testTextInput.hide(); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byKey(textField1)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.tap(find.byKey(textField0)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.tap(find.byKey(textField1)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); tester.testTextInput.hide(); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byKey(textField0)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.pumpWidget(Container()); expect(tester.testTextInput.isVisible, isFalse); }); testWidgets('Sibling Navigators', (WidgetTester tester) async { expect(tester.testTextInput.isVisible, isFalse); final Key textField0 = UniqueKey(); final Key textField1 = UniqueKey(); await tester.pumpWidget( MaterialApp( home: Scaffold( body: Center( child: Column( children: <Widget>[ Expanded( child: Navigator( onGenerateRoute: (RouteSettings settings) { return MaterialPageRoute<void>( builder: (BuildContext context) { return TextField(key: textField0); }, settings: settings, ); }, ), ), Expanded( child: Navigator( onGenerateRoute: (RouteSettings settings) { return MaterialPageRoute<void>( builder: (BuildContext context) { return TextField(key: textField1); }, settings: settings, ); }, ), ), ], ), ), ), ), ); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byKey(textField0)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); tester.testTextInput.hide(); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byKey(textField1)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.tap(find.byKey(textField0)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.tap(find.byKey(textField1)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); tester.testTextInput.hide(); expect(tester.testTextInput.isVisible, isFalse); await tester.tap(find.byKey(textField0)); await tester.idle(); expect(tester.testTextInput.isVisible, isTrue); await tester.pumpWidget(Container()); expect(tester.testTextInput.isVisible, isFalse); }); }