blob: 8c42981807585183b2d291cdfdf19360f2e94a01 [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/material.dart';
import 'package:flutter_test/flutter_test.dart';
final Matcher _matchesCommit = isMethodCall('TextInput.finishAutofillContext', arguments: true);
final Matcher _matchesCancel = isMethodCall('TextInput.finishAutofillContext', arguments: false);
void main() {
testWidgets('AutofillGroup has the right clients', (WidgetTester tester) async {
const Key outerKey = Key('outer');
const Key innerKey = Key('inner');
const TextField client1 = TextField(autofillHints: <String>['1']);
const TextField client2 = TextField(autofillHints: <String>['2']);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: AutofillGroup(
key: outerKey,
child: Column(children: <Widget>[
client1,
AutofillGroup(
key: innerKey,
child: Column(children: const <Widget>[client2, TextField(autofillHints: null)]),
),
]),
),
),
),
);
final AutofillGroupState innerState = tester.state<AutofillGroupState>(find.byKey(innerKey));
final AutofillGroupState outerState = tester.state<AutofillGroupState>(find.byKey(outerKey));
final State<TextField> clientState1 = tester.state<State<TextField>>(find.byWidget(client1));
final State<TextField> clientState2 = tester.state<State<TextField>>(find.byWidget(client2));
expect(outerState.autofillClients.toList(), <State<TextField>>[clientState1]);
// The second TextField in the AutofillGroup doesn't have autofill enabled.
expect(innerState.autofillClients.toList(), <State<TextField>>[clientState2]);
});
testWidgets('new clients can be added & removed to a scope', (WidgetTester tester) async {
const Key scopeKey = Key('scope');
const TextField client1 = TextField(autofillHints: <String>['1']);
TextField client2 = const TextField(autofillHints: null);
late StateSetter setState;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: AutofillGroup(
key: scopeKey,
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
setState = setter;
return Column(children: <Widget>[client1, client2]);
},
),
),
),
),
);
final AutofillGroupState scopeState = tester.state<AutofillGroupState>(find.byKey(scopeKey));
final State<TextField> clientState1 = tester.state<State<TextField>>(find.byWidget(client1));
final State<TextField> clientState2 = tester.state<State<TextField>>(find.byWidget(client2));
expect(scopeState.autofillClients.toList(), <State<TextField>>[clientState1]);
// Add to scope.
setState(() { client2 = const TextField(autofillHints: <String>['2']); });
await tester.pump();
expect(scopeState.autofillClients, contains(clientState1));
expect(scopeState.autofillClients, contains(clientState2));
expect(scopeState.autofillClients.length, 2);
// Remove from scope again.
setState(() { client2 = const TextField(autofillHints: null); });
await tester.pump();
expect(scopeState.autofillClients, <State<TextField>>[clientState1]);
});
testWidgets('AutofillGroup has the right clients after reparenting', (WidgetTester tester) async {
const Key outerKey = Key('outer');
const Key innerKey = Key('inner');
final GlobalKey keyClient3 = GlobalKey();
const TextField client1 = TextField(autofillHints: <String>['1']);
const TextField client2 = TextField(autofillHints: <String>['2']);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: AutofillGroup(
key: outerKey,
child: Column(children: <Widget>[
client1,
AutofillGroup(
key: innerKey,
child: Column(children: <Widget>[
client2,
TextField(key: keyClient3, autofillHints: const <String>['3']),
]),
),
]),
),
),
),
);
final AutofillGroupState innerState = tester.state<AutofillGroupState>(find.byKey(innerKey));
final AutofillGroupState outerState = tester.state<AutofillGroupState>(find.byKey(outerKey));
final State<TextField> clientState1 = tester.state<State<TextField>>(find.byWidget(client1));
final State<TextField> clientState2 = tester.state<State<TextField>>(find.byWidget(client2));
final State<TextField> clientState3 = tester.state<State<TextField>>(find.byKey(keyClient3));
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: AutofillGroup(
key: outerKey,
child: Column(children: <Widget>[
client1,
TextField(key: keyClient3, autofillHints: const <String>['3']),
AutofillGroup(
key: innerKey,
child: Column(children: const <Widget>[client2]),
),
]),
),
),
),
);
expect(outerState.autofillClients.length, 2);
expect(outerState.autofillClients, contains(clientState1));
expect(outerState.autofillClients, contains(clientState3));
expect(innerState.autofillClients, <State<TextField>>[clientState2]);
});
testWidgets('disposing AutofillGroups', (WidgetTester tester) async {
late StateSetter setState;
const Key group1 = Key('group1');
const Key group2 = Key('group2');
const Key group3 = Key('group3');
const TextField placeholder = TextField(autofillHints: <String>[AutofillHints.name]);
List<Widget> children = const <Widget> [
AutofillGroup(
key: group1,
child: AutofillGroup(child: placeholder),
),
AutofillGroup(key: group2, onDisposeAction: AutofillContextAction.cancel, child: placeholder),
AutofillGroup(
key: group3,
child: AutofillGroup(child: placeholder),
),
];
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
setState = setter;
return Column(children: children);
},
),
),
),
);
expect(
tester.testTextInput.log,
isNot(contains(_matchesCommit)),
);
tester.testTextInput.log.clear();
// Remove the first topmost group group1. Should commit.
setState(() {
children = const <Widget> [
AutofillGroup(key: group2, onDisposeAction: AutofillContextAction.cancel, child: placeholder),
AutofillGroup(
key: group3,
child: AutofillGroup(child: placeholder),
),
];
});
await tester.pump();
expect(
tester.testTextInput.log.single,
_matchesCommit,
);
tester.testTextInput.log.clear();
// Remove the topmost group group2. Should cancel.
setState(() {
children = const <Widget> [
AutofillGroup(
key: group3,
child: AutofillGroup(child: placeholder),
),
];
});
await tester.pump();
expect(
tester.testTextInput.log.single,
_matchesCancel,
);
tester.testTextInput.log.clear();
// Remove the inner group within group3. No action.
setState(() {
children = const <Widget> [
AutofillGroup(
key: group3,
child: placeholder,
),
];
});
await tester.pump();
expect(
tester.testTextInput.log,
isNot(contains('TextInput.finishAutofillContext')),
);
tester.testTextInput.log.clear();
// Remove the topmosts group group3. Should commit.
setState(() {
children = const <Widget> [];
});
await tester.pump();
expect(
tester.testTextInput.log.single,
_matchesCommit,
);
});
}