Migrate even more Material framework tests to null safety. (#67849)

This commit is contained in:
Darren Austin 2020-10-12 11:30:26 -07:00 committed by GitHub
parent fda735cf31
commit 7ce0dce2e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 489 additions and 522 deletions

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui';
import 'package:flutter_test/flutter_test.dart';
@ -14,13 +12,13 @@ import 'semantics_tester.dart';
class TestFocus extends StatefulWidget {
const TestFocus({
Key key,
Key? key,
this.debugLabel,
this.name = 'a',
this.autofocus = false,
}) : super(key: key);
final String debugLabel;
final String? debugLabel;
final String name;
final bool autofocus;
@ -29,14 +27,14 @@ class TestFocus extends StatefulWidget {
}
class TestFocusState extends State<TestFocus> {
FocusNode focusNode;
String _label;
late FocusNode focusNode;
late String _label;
bool built = false;
@override
void dispose() {
focusNode.removeListener(_updateLabel);
focusNode?.dispose();
focusNode.dispose();
super.dispose();
}
@ -85,12 +83,12 @@ void main() {
TestFocus(key: key, name: 'a'),
);
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
FocusScope.of(key.currentContext).requestFocus(key.currentState.focusNode);
FocusScope.of(key.currentContext!).requestFocus(key.currentState!.focusNode);
await tester.pumpAndSettle();
expect(key.currentState.focusNode.hasFocus, isTrue);
expect(key.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
});
@ -106,26 +104,26 @@ void main() {
),
);
expect(keyA.currentState.focusNode.hasFocus, isFalse);
expect(keyA.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
// Set focus to the "B" node to unfocus the "A" node.
FocusScope.of(keyB.currentContext).requestFocus(keyB.currentState.focusNode);
FocusScope.of(keyB.currentContext!).requestFocus(keyB.currentState!.focusNode);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isFalse);
expect(keyA.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
});
@ -143,9 +141,9 @@ void main() {
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isFalse);
expect(keyA.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
});
@ -171,27 +169,27 @@ void main() {
// Autofocus is delayed one frame.
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.tap(find.text('A FOCUSED'));
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.tap(find.text('b'));
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isFalse);
expect(keyA.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
await tester.tap(find.text('a'));
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
});
@ -220,12 +218,12 @@ void main() {
),
);
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
FocusScope.of(key.currentContext).requestFocus(key.currentState.focusNode);
FocusScope.of(key.currentContext!).requestFocus(key.currentState!.focusNode);
await tester.pumpAndSettle();
expect(key.currentState.focusNode.hasFocus, isTrue);
expect(key.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(parentFocusScope, hasAGoodToStringDeep);
@ -260,7 +258,7 @@ void main() {
);
// Add the child focus scope to the focus tree.
final FocusAttachment childAttachment = childFocusScope.attach(key.currentContext);
final FocusAttachment childAttachment = childFocusScope.attach(key.currentContext!);
parentFocusScope.setFirstFocus(childFocusScope);
await tester.pumpAndSettle();
expect(childFocusScope.isFirstFocus, isTrue);
@ -286,7 +284,7 @@ void main() {
),
);
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
// Now move the existing focus node into the child focus scope.
@ -311,7 +309,7 @@ void main() {
await tester.pumpAndSettle();
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
// Now remove the child focus scope.
@ -331,7 +329,7 @@ void main() {
);
await tester.pumpAndSettle();
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
// Must detach the child because we had to attach it in order to call
@ -388,25 +386,25 @@ void main() {
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
parentFocusScope.setFirstFocus(childFocusScope2);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isFalse);
expect(keyA.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('a'), findsOneWidget);
parentFocusScope.setFirstFocus(childFocusScope1);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
keyB.currentState.focusNode.requestFocus();
keyB.currentState!.focusNode.requestFocus();
await tester.pumpAndSettle();
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
expect(parentFocusScope.isFirstFocus, isTrue);
expect(childFocusScope1.isFirstFocus, isTrue);
@ -414,18 +412,18 @@ void main() {
parentFocusScope.setFirstFocus(childFocusScope2);
await tester.pumpAndSettle();
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
expect(parentFocusScope.isFirstFocus, isTrue);
expect(childFocusScope1.isFirstFocus, isFalse);
expect(childFocusScope2.isFirstFocus, isTrue);
keyC.currentState.focusNode.requestFocus();
keyC.currentState!.focusNode.requestFocus();
await tester.pumpAndSettle();
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
expect(keyC.currentState.focusNode.hasFocus, isTrue);
expect(keyC.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('C FOCUSED'), findsOneWidget);
expect(parentFocusScope.isFirstFocus, isTrue);
expect(childFocusScope1.isFirstFocus, isFalse);
@ -433,9 +431,9 @@ void main() {
childFocusScope1.requestFocus();
await tester.pumpAndSettle();
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
expect(keyC.currentState.focusNode.hasFocus, isFalse);
expect(keyC.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('c'), findsOneWidget);
expect(parentFocusScope.isFirstFocus, isTrue);
expect(childFocusScope1.isFirstFocus, isTrue);
@ -461,13 +459,13 @@ void main() {
),
);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.pumpWidget(
@ -483,7 +481,7 @@ void main() {
await tester.pump();
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
});
@ -502,14 +500,14 @@ void main() {
),
);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
expect(FocusScope.of(keyA.currentContext), equals(childFocusScope));
expect(Focus.of(keyA.currentContext, scopeOk: true), equals(childFocusScope));
FocusManager.instance.rootScope.setFirstFocus(FocusScope.of(keyA.currentContext));
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
expect(FocusScope.of(keyA.currentContext!), equals(childFocusScope));
expect(Focus.of(keyA.currentContext!, scopeOk: true), equals(childFocusScope));
FocusManager.instance.rootScope.setFirstFocus(FocusScope.of(keyA.currentContext!));
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(childFocusScope.isFirstFocus, isTrue);
@ -529,7 +527,7 @@ void main() {
await tester.pump();
expect(childFocusScope.isFirstFocus, isTrue);
// Node keeps it's focus when moved to the new scope.
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
});
@ -561,15 +559,15 @@ void main() {
),
);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
final FocusScopeNode scope = FocusScope.of(keyA.currentContext);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
final FocusScopeNode scope = FocusScope.of(keyA.currentContext!);
FocusManager.instance.rootScope.setFirstFocus(scope);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.pumpWidget(
@ -588,7 +586,7 @@ void main() {
await tester.pump();
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
});
@ -635,19 +633,19 @@ void main() {
),
);
FocusScope.of(keyB.currentContext).requestFocus(keyB.currentState.focusNode);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext);
final FocusScopeNode bScope = FocusScope.of(keyB.currentContext);
FocusScope.of(keyB.currentContext!).requestFocus(keyB.currentState!.focusNode);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext!);
final FocusScopeNode bScope = FocusScope.of(keyB.currentContext!);
FocusManager.instance.rootScope.setFirstFocus(bScope);
FocusManager.instance.rootScope.setFirstFocus(aScope);
await tester.pumpAndSettle();
expect(FocusScope.of(keyA.currentContext).isFirstFocus, isTrue);
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(FocusScope.of(keyA.currentContext!).isFirstFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.pumpWidget(Container());
@ -699,19 +697,19 @@ void main() {
),
);
FocusScope.of(keyB.currentContext).requestFocus(keyB.currentState.focusNode);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
final FocusScopeNode bScope = FocusScope.of(keyB.currentContext);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext);
FocusScope.of(keyB.currentContext!).requestFocus(keyB.currentState!.focusNode);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
final FocusScopeNode bScope = FocusScope.of(keyB.currentContext!);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext!);
FocusManager.instance.rootScope.setFirstFocus(bScope);
FocusManager.instance.rootScope.setFirstFocus(aScope);
await tester.pumpAndSettle();
expect(FocusScope.of(keyA.currentContext).isFirstFocus, isTrue);
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(FocusScope.of(keyA.currentContext!).isFirstFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.pumpWidget(
@ -739,7 +737,7 @@ void main() {
await tester.pump();
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
});
@ -782,19 +780,19 @@ void main() {
),
);
FocusScope.of(keyB.currentContext).requestFocus(keyB.currentState.focusNode);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
final FocusScopeNode bScope = FocusScope.of(keyB.currentContext);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext);
FocusScope.of(keyB.currentContext!).requestFocus(keyB.currentState!.focusNode);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
final FocusScopeNode bScope = FocusScope.of(keyB.currentContext!);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext!);
FocusManager.instance.rootScope.setFirstFocus(bScope);
FocusManager.instance.rootScope.setFirstFocus(aScope);
await tester.pumpAndSettle();
expect(FocusScope.of(keyA.currentContext).isFirstFocus, isTrue);
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(FocusScope.of(keyA.currentContext!).isFirstFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.pumpWidget(
@ -820,7 +818,7 @@ void main() {
);
await tester.pump();
expect(keyB.currentState.focusNode.hasFocus, isTrue);
expect(keyB.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('B FOCUSED'), findsOneWidget);
});
@ -859,15 +857,15 @@ void main() {
),
);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext!);
FocusManager.instance.rootScope.setFirstFocus(aScope);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
await tester.pumpWidget(
@ -901,9 +899,9 @@ void main() {
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
});
@ -944,15 +942,15 @@ void main() {
),
);
FocusScope.of(keyA.currentContext).requestFocus(keyA.currentState.focusNode);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext);
FocusScope.of(keyA.currentContext!).requestFocus(keyA.currentState!.focusNode);
final FocusScopeNode aScope = FocusScope.of(keyA.currentContext!);
FocusManager.instance.rootScope.setFirstFocus(aScope);
await tester.pumpAndSettle();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
// This just swaps the FocusScopeNodes that the FocusScopes have in them.
@ -989,9 +987,9 @@ void main() {
await tester.pump();
expect(keyA.currentState.focusNode.hasFocus, isTrue);
expect(keyA.currentState!.focusNode.hasFocus, isTrue);
expect(find.text('A FOCUSED'), findsOneWidget);
expect(keyB.currentState.focusNode.hasFocus, isFalse);
expect(keyB.currentState!.focusNode.hasFocus, isFalse);
expect(find.text('b'), findsOneWidget);
});
@ -1011,7 +1009,7 @@ void main() {
await tester.pump();
expect(rootNode.hasFocus, isTrue);
expect(rootNode, equals(firstElement.owner.focusManager.rootScope));
expect(rootNode, equals(firstElement.owner!.focusManager.rootScope));
});
testWidgets('Can autofocus a node.', (WidgetTester tester) async {
@ -1117,14 +1115,14 @@ void main() {
final Element element4 = tester.element(find.byKey(key4));
final Element element5 = tester.element(find.byKey(key5));
final Element element6 = tester.element(find.byKey(key6));
final FocusNode root = element1.owner.focusManager.rootScope;
final FocusNode root = element1.owner!.focusManager.rootScope;
expect(Focus.of(element1, nullOk: true), isNull);
expect(Focus.of(element2, nullOk: true), isNull);
expect(Focus.of(element3, nullOk: true), isNull);
expect(Focus.of(element4).parent.parent, equals(root));
expect(Focus.of(element5).parent.parent, equals(root));
expect(Focus.of(element6).parent.parent.parent, equals(root));
expect(Focus.of(element4)!.parent!.parent, equals(root));
expect(Focus.of(element5)!.parent!.parent, equals(root));
expect(Focus.of(element6)!.parent!.parent!.parent, equals(root));
});
testWidgets('Can traverse Focus children.', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
@ -1183,13 +1181,13 @@ void main() {
final List<Key> keys = <Key>[];
bool visitor(FocusNode node) {
nodes.add(node);
keys.add(node.context.widget.key);
keys.add(node.context!.widget.key!);
return true;
}
await tester.pump();
Focus.of(firstScope).descendants.forEach(visitor);
Focus.of(firstScope)!.descendants.forEach(visitor);
expect(nodes.length, equals(7));
expect(keys.length, equals(7));
// Depth first.
@ -1199,14 +1197,14 @@ void main() {
final Element secondScope = tester.element(find.byKey(key7));
nodes.clear();
keys.clear();
Focus.of(secondScope).descendants.forEach(visitor);
Focus.of(secondScope)!.descendants.forEach(visitor);
expect(nodes.length, equals(2));
expect(keys, equals(<Key>[key7, key8]));
});
testWidgets('Can set focus.', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
bool gotFocus;
late bool gotFocus;
await tester.pumpWidget(
Focus(
onFocusChange: (bool focused) => gotFocus = focused,
@ -1215,7 +1213,7 @@ void main() {
);
final Element firstNode = tester.element(find.byKey(key1));
final FocusNode node = Focus.of(firstNode);
final FocusNode node = Focus.of(firstNode)!;
node.requestFocus();
await tester.pump();
@ -1226,7 +1224,7 @@ void main() {
testWidgets('Focus is ignored when set to not focusable.', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
bool gotFocus;
bool? gotFocus;
await tester.pumpWidget(
Focus(
canRequestFocus: false,
@ -1236,7 +1234,7 @@ void main() {
);
final Element firstNode = tester.element(find.byKey(key1));
final FocusNode node = Focus.of(firstNode);
final FocusNode node = Focus.of(firstNode)!;
node.requestFocus();
await tester.pump();
@ -1247,7 +1245,7 @@ void main() {
testWidgets('Focus is lost when set to not focusable.', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
bool gotFocus;
bool? gotFocus;
await tester.pumpWidget(
Focus(
autofocus: true,
@ -1258,7 +1256,7 @@ void main() {
);
Element firstNode = tester.element(find.byKey(key1));
FocusNode node = Focus.of(firstNode);
FocusNode node = Focus.of(firstNode)!;
node.requestFocus();
await tester.pump();
@ -1276,7 +1274,7 @@ void main() {
);
firstNode = tester.element(find.byKey(key1));
node = Focus.of(firstNode);
node = Focus.of(firstNode)!;
node.requestFocus();
await tester.pump();
@ -1289,7 +1287,7 @@ void main() {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
final GlobalKey key2 = GlobalKey(debugLabel: '2');
final FocusNode focusNode = FocusNode();
bool gotFocus;
bool? gotFocus;
await tester.pumpWidget(
Focus(
canRequestFocus: false,
@ -1299,7 +1297,7 @@ void main() {
);
final Element childWidget = tester.element(find.byKey(key1));
final FocusNode unfocusableNode = Focus.of(childWidget);
final FocusNode unfocusableNode = Focus.of(childWidget)!;
unfocusableNode.requestFocus();
await tester.pump();
@ -1308,7 +1306,7 @@ void main() {
expect(unfocusableNode.hasFocus, isFalse);
final Element containerWidget = tester.element(find.byKey(key2));
final FocusNode focusableNode = Focus.of(containerWidget);
final FocusNode focusableNode = Focus.of(containerWidget)!;
focusableNode.requestFocus();
await tester.pump();
@ -1319,7 +1317,7 @@ void main() {
testWidgets('Nodes are removed when all Focuses are removed.', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
bool gotFocus;
late bool gotFocus;
await tester.pumpWidget(
FocusScope(
child: Focus(
@ -1330,7 +1328,7 @@ void main() {
);
final Element firstNode = tester.element(find.byKey(key1));
final FocusNode node = Focus.of(firstNode);
final FocusNode node = Focus.of(firstNode)!;
node.requestFocus();
await tester.pump();
@ -1352,22 +1350,22 @@ void main() {
final SemanticsNode semantics = tester.getSemantics(find.byKey(key));
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
expect(semantics.hasFlag(SemanticsFlag.isFocused), isFalse);
expect(semantics.hasFlag(SemanticsFlag.isFocusable), isTrue);
FocusScope.of(key.currentContext).requestFocus(key.currentState.focusNode);
FocusScope.of(key.currentContext!).requestFocus(key.currentState!.focusNode);
await tester.pumpAndSettle();
expect(key.currentState.focusNode.hasFocus, isTrue);
expect(key.currentState!.focusNode.hasFocus, isTrue);
expect(semantics.hasFlag(SemanticsFlag.isFocused), isTrue);
expect(semantics.hasFlag(SemanticsFlag.isFocusable), isTrue);
key.currentState.focusNode.canRequestFocus = false;
key.currentState!.focusNode.canRequestFocus = false;
await tester.pumpAndSettle();
expect(key.currentState.focusNode.hasFocus, isFalse);
expect(key.currentState.focusNode.canRequestFocus, isFalse);
expect(key.currentState!.focusNode.hasFocus, isFalse);
expect(key.currentState!.focusNode.canRequestFocus, isFalse);
expect(semantics.hasFlag(SemanticsFlag.isFocused), isFalse);
expect(semantics.hasFlag(SemanticsFlag.isFocusable), isFalse);
});
@ -1381,12 +1379,12 @@ void main() {
);
await tester.pumpAndSettle();
key.currentState.built = false;
key.currentState.focusNode.canRequestFocus = false;
key.currentState!.built = false;
key.currentState!.focusNode.canRequestFocus = false;
await tester.pumpAndSettle();
key.currentState.built = true;
key.currentState!.built = true;
expect(key.currentState.focusNode.canRequestFocus, isFalse);
expect(key.currentState!.focusNode.canRequestFocus, isFalse);
});
testWidgets('canRequestFocus causes descendants of scope to be skipped.', (WidgetTester tester) async {
@ -1427,75 +1425,75 @@ void main() {
// Check childless node (focus2).
await pumpTest();
Focus.of(container1.currentContext).requestFocus();
Focus.of(container1.currentContext!)!.requestFocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue);
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue);
await pumpTest(allowFocus2: false);
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
Focus.of(container1.currentContext).requestFocus();
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
Focus.of(container1.currentContext!)!.requestFocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
await pumpTest();
Focus.of(container1.currentContext).requestFocus();
Focus.of(container1.currentContext!)!.requestFocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue);
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue);
// Check FocusNode with child (focus1). Shouldn't affect children.
await pumpTest(allowFocus1: false);
expect(Focus.of(container1.currentContext).hasFocus, isTrue); // focus2 has focus.
Focus.of(focus2.currentContext).requestFocus(); // Try to focus focus1
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue); // focus2 has focus.
Focus.of(focus2.currentContext!)!.requestFocus(); // Try to focus focus1
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue); // focus2 still has focus.
Focus.of(container1.currentContext).requestFocus(); // Now try to focus focus2
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue); // focus2 still has focus.
Focus.of(container1.currentContext!)!.requestFocus(); // Now try to focus focus2
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue);
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue);
await pumpTest();
// Try again, now that we've set focus1's canRequestFocus to true again.
Focus.of(container1.currentContext).unfocus();
Focus.of(container1.currentContext!)!.unfocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
Focus.of(container1.currentContext).requestFocus();
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
Focus.of(container1.currentContext!)!.requestFocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue);
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue);
// Check FocusScopeNode with only FocusNode children (scope2). Should affect children.
await pumpTest(allowScope2: false);
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
FocusScope.of(focus1.currentContext).requestFocus(); // Try to focus scope2
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
FocusScope.of(focus1.currentContext!).requestFocus(); // Try to focus scope2
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
Focus.of(focus2.currentContext).requestFocus(); // Try to focus focus1
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
Focus.of(focus2.currentContext!)!.requestFocus(); // Try to focus focus1
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
Focus.of(container1.currentContext).requestFocus(); // Try to focus focus2
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
Focus.of(container1.currentContext!)!.requestFocus(); // Try to focus focus2
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
await pumpTest();
// Try again, now that we've set scope2's canRequestFocus to true again.
Focus.of(container1.currentContext).requestFocus();
Focus.of(container1.currentContext!)!.requestFocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue);
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue);
// Check FocusScopeNode with both FocusNode children and FocusScope children (scope1). Should affect children.
await pumpTest(allowScope1: false);
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
FocusScope.of(scope2.currentContext).requestFocus(); // Try to focus scope1
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
FocusScope.of(scope2.currentContext!).requestFocus(); // Try to focus scope1
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
FocusScope.of(focus1.currentContext).requestFocus(); // Try to focus scope2
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
FocusScope.of(focus1.currentContext!).requestFocus(); // Try to focus scope2
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
Focus.of(focus2.currentContext).requestFocus(); // Try to focus focus1
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
Focus.of(focus2.currentContext!)!.requestFocus(); // Try to focus focus1
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
Focus.of(container1.currentContext).requestFocus(); // Try to focus focus2
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
Focus.of(container1.currentContext!)!.requestFocus(); // Try to focus focus2
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isFalse);
expect(Focus.of(container1.currentContext!)!.hasFocus, isFalse);
await pumpTest();
// Try again, now that we've set scope1's canRequestFocus to true again.
Focus.of(container1.currentContext).requestFocus();
Focus.of(container1.currentContext!)!.requestFocus();
await tester.pump();
expect(Focus.of(container1.currentContext).hasFocus, isTrue);
expect(Focus.of(container1.currentContext!)!.hasFocus, isTrue);
});
testWidgets('skipTraversal works as expected.', (WidgetTester tester) async {
@ -1555,7 +1553,7 @@ void main() {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
final GlobalKey key2 = GlobalKey(debugLabel: '2');
final FocusNode focusNode = FocusNode();
bool gotFocus;
bool? gotFocus;
await tester.pumpWidget(
Focus(
descendantsAreFocusable: false,
@ -1571,9 +1569,9 @@ void main() {
);
final Element childWidget = tester.element(find.byKey(key1));
final FocusNode unfocusableNode = Focus.of(childWidget);
final FocusNode unfocusableNode = Focus.of(childWidget)!;
final Element containerWidget = tester.element(find.byKey(key2));
final FocusNode containerNode = Focus.of(containerWidget);
final FocusNode containerNode = Focus.of(containerWidget)!;
unfocusableNode.requestFocus();
await tester.pump();
@ -1601,7 +1599,7 @@ void main() {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
final GlobalKey key2 = GlobalKey(debugLabel: '2');
final FocusNode focusNode = FocusNode();
bool gotFocus;
bool? gotFocus;
await tester.pumpWidget(
ExcludeFocus(
excluding: true,
@ -1617,9 +1615,9 @@ void main() {
);
final Element childWidget = tester.element(find.byKey(key1));
final FocusNode unfocusableNode = Focus.of(childWidget);
final FocusNode unfocusableNode = Focus.of(childWidget)!;
final Element containerWidget = tester.element(find.byKey(key2));
final FocusNode containerNode = Focus.of(containerWidget);
final FocusNode containerNode = Focus.of(containerWidget)!;
unfocusableNode.requestFocus();
await tester.pump();
@ -1703,7 +1701,7 @@ void main() {
expect(focusNode1.hasFocus, isFalse);
expect(focusNode2.hasFocus, isFalse);
expect(parentFocusNode.hasFocus, isFalse);
expect(parentFocusNode.enclosingScope.hasPrimaryFocus, isTrue);
expect(parentFocusNode.enclosingScope!.hasPrimaryFocus, isTrue);
});
testWidgets("ExcludeFocus doesn't introduce a Semantics node", (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui';
import 'package:flutter/painting.dart';
@ -55,9 +53,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key3));
final Element secondChild = tester.element(find.byKey(key5));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
secondFocusNode.nextFocus();
await tester.pump();
@ -94,9 +92,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key3));
final Element secondChild = tester.element(find.byKey(key5));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
expect(firstFocusNode.hasFocus, isFalse);
expect(secondFocusNode.hasFocus, isFalse);
@ -117,10 +115,10 @@ void main() {
final GlobalKey key4 = GlobalKey(debugLabel: '4');
final GlobalKey key5 = GlobalKey(debugLabel: '5');
final GlobalKey key6 = GlobalKey(debugLabel: '6');
bool focus1;
bool focus2;
bool focus3;
bool focus5;
bool? focus1;
bool? focus2;
bool? focus3;
bool? focus5;
await tester.pumpWidget(
FocusTraversalGroup(
policy: WidgetOrderTraversalPolicy(),
@ -159,9 +157,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key4));
final Element secondChild = tester.element(find.byKey(key6));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
firstFocusNode.requestFocus();
await tester.pump();
@ -179,7 +177,7 @@ void main() {
focus3 = null;
focus5 = null;
Focus.of(firstChild).nextFocus();
Focus.of(firstChild)!.nextFocus();
await tester.pump();
@ -196,7 +194,7 @@ void main() {
focus3 = null;
focus5 = null;
Focus.of(firstChild).nextFocus();
Focus.of(firstChild)!.nextFocus();
await tester.pump();
@ -214,7 +212,7 @@ void main() {
focus5 = null;
// Tests that can still move back to original node.
Focus.of(firstChild).previousFocus();
Focus.of(firstChild)!.previousFocus();
await tester.pump();
@ -264,9 +262,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key4));
final Element secondChild = tester.element(find.byKey(key6));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
secondFocusNode.requestFocus();
await tester.pump();
@ -275,7 +273,7 @@ void main() {
expect(secondFocusNode.hasFocus, isTrue);
expect(scope.hasFocus, isTrue);
Focus.of(firstChild).previousFocus();
Focus.of(firstChild)!.previousFocus();
await tester.pump();
@ -283,7 +281,7 @@ void main() {
expect(secondFocusNode.hasFocus, isFalse);
expect(scope.hasFocus, isTrue);
Focus.of(firstChild).previousFocus();
Focus.of(firstChild)!.previousFocus();
await tester.pump();
@ -292,7 +290,7 @@ void main() {
expect(scope.hasFocus, isTrue);
// Tests that can still move back to original node.
Focus.of(firstChild).nextFocus();
Focus.of(firstChild)!.nextFocus();
await tester.pump();
@ -324,12 +322,12 @@ void main() {
expect(nodes[2].hasPrimaryFocus, isTrue);
primaryFocus.nextFocus();
primaryFocus!.nextFocus();
await tester.pump();
expect(nodes[6].hasPrimaryFocus, isTrue);
primaryFocus.previousFocus();
primaryFocus!.previousFocus();
await tester.pump();
expect(nodes[0].hasPrimaryFocus, isTrue);
@ -351,7 +349,7 @@ void main() {
focusNode: testNode1,
autofocus: true,
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) {
return Center(
@ -360,7 +358,7 @@ void main() {
focusNode: testNode2,
autofocus: true,
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context)!.pop();
},
child: const Text('Go Back'),
),
@ -378,8 +376,8 @@ void main() {
);
final Element firstChild = tester.element(find.text('Go Forward'));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
await tester.pump();
expect(firstFocusNode.hasFocus, isTrue);
@ -389,7 +387,7 @@ void main() {
await tester.pumpAndSettle();
final Element secondChild = tester.element(find.text('Go Back'));
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode secondFocusNode = Focus.of(secondChild)!;
expect(firstFocusNode.hasFocus, isFalse);
expect(secondFocusNode.hasFocus, isTrue);
@ -430,9 +428,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key3));
final Element secondChild = tester.element(find.byKey(key5));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
secondFocusNode.nextFocus();
await tester.pump();
@ -449,10 +447,10 @@ void main() {
final GlobalKey key4 = GlobalKey(debugLabel: '4');
final GlobalKey key5 = GlobalKey(debugLabel: '5');
final GlobalKey key6 = GlobalKey(debugLabel: '6');
bool focus1;
bool focus2;
bool focus3;
bool focus5;
bool? focus1;
bool? focus2;
bool? focus3;
bool? focus5;
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -501,9 +499,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key4));
final Element secondChild = tester.element(find.byKey(key6));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
firstFocusNode.requestFocus();
await tester.pump();
@ -517,7 +515,7 @@ void main() {
expect(scope.hasFocus, isTrue);
clear();
Focus.of(firstChild).nextFocus();
Focus.of(firstChild)!.nextFocus();
await tester.pump();
@ -530,7 +528,7 @@ void main() {
expect(scope.hasFocus, isTrue);
clear();
Focus.of(firstChild).nextFocus();
Focus.of(firstChild)!.nextFocus();
await tester.pump();
@ -544,7 +542,7 @@ void main() {
clear();
// Tests that can still move back to original node.
Focus.of(firstChild).previousFocus();
Focus.of(firstChild)!.previousFocus();
await tester.pump();
@ -594,9 +592,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key4));
final Element secondChild = tester.element(find.byKey(key6));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
secondFocusNode.requestFocus();
await tester.pump();
@ -605,7 +603,7 @@ void main() {
expect(secondFocusNode.hasFocus, isTrue);
expect(scope.hasFocus, isTrue);
Focus.of(firstChild).previousFocus();
Focus.of(firstChild)!.previousFocus();
await tester.pump();
@ -613,7 +611,7 @@ void main() {
expect(secondFocusNode.hasFocus, isFalse);
expect(scope.hasFocus, isTrue);
Focus.of(firstChild).previousFocus();
Focus.of(firstChild)!.previousFocus();
await tester.pump();
@ -622,7 +620,7 @@ void main() {
expect(scope.hasFocus, isTrue);
// Tests that can still move back to original node.
Focus.of(firstChild).nextFocus();
Focus.of(firstChild)!.nextFocus();
await tester.pump();
@ -731,7 +729,7 @@ void main() {
for (int i = 0; i < nodeCount; ++i) {
nodes.first.nextFocus();
await tester.pump();
order.add(nodes.indexOf(primaryFocus));
order.add(nodes.indexOf(primaryFocus!));
}
expect(order, orderedEquals(<int>[0, 1, 2, 4, 3, 5, 6, 7, 8, 9]));
@ -741,7 +739,7 @@ void main() {
for (int i = 0; i < nodeCount; ++i) {
nodes.first.nextFocus();
await tester.pump();
order.add(nodes.indexOf(primaryFocus));
order.add(nodes.indexOf(primaryFocus!));
}
expect(order, orderedEquals(<int>[0, 1, 2, 4, 3, 5, 6, 8, 7, 9]));
});
@ -772,7 +770,7 @@ void main() {
for (int i = 0; i < nodeCount; ++i) {
nodes.first.nextFocus();
await tester.pump();
order.add(nodes.indexOf(primaryFocus));
order.add(nodes.indexOf(primaryFocus!));
}
expect(order, orderedEquals(<int>[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]));
@ -799,7 +797,7 @@ void main() {
for (int i = 0; i < nodeCount; ++i) {
nodes.first.nextFocus();
await tester.pump();
order.add(nodes.indexOf(primaryFocus));
order.add(nodes.indexOf(primaryFocus!));
}
expect(order, orderedEquals(<int>[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]));
@ -835,7 +833,7 @@ void main() {
for (int i = 0; i < nodeCount; ++i) {
nodes.first.nextFocus();
await tester.pump();
order.add(nodes.indexOf(primaryFocus));
order.add(nodes.indexOf(primaryFocus!));
}
expect(order, orderedEquals(<int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]));
});
@ -869,9 +867,9 @@ void main() {
final Element firstChild = tester.element(find.byKey(key1));
final Element secondChild = tester.element(find.byKey(key2));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode secondFocusNode = Focus.of(secondChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
secondFocusNode.nextFocus();
await tester.pump();
@ -1127,7 +1125,7 @@ void main() {
for (int i = 0; i < nodeCount; ++i) {
nodes.first.nextFocus();
await tester.pump();
order.add(nodes.indexOf(primaryFocus));
order.add(nodes.indexOf(primaryFocus!));
}
expect(order, orderedEquals(expectedOrder));
});
@ -1150,7 +1148,7 @@ void main() {
focusNode: testNode1,
autofocus: true,
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) {
return Center(
@ -1161,7 +1159,7 @@ void main() {
focusNode: testNode2,
autofocus: true,
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context)!.pop();
},
child: const Text('Go Back'),
),
@ -1181,8 +1179,8 @@ void main() {
);
final Element firstChild = tester.element(find.text('Go Forward'));
final FocusNode firstFocusNode = Focus.of(firstChild);
final FocusNode scope = Focus.of(firstChild).enclosingScope;
final FocusNode firstFocusNode = Focus.of(firstChild)!;
final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
await tester.pump();
expect(firstFocusNode.hasFocus, isTrue);
@ -1192,7 +1190,7 @@ void main() {
await tester.pumpAndSettle();
final Element secondChild = tester.element(find.text('Go Back'));
final FocusNode secondFocusNode = Focus.of(secondChild);
final FocusNode secondFocusNode = Focus.of(secondChild)!;
expect(firstFocusNode.hasFocus, isFalse);
expect(secondFocusNode.hasFocus, isTrue);
@ -1211,10 +1209,10 @@ void main() {
final GlobalKey upperRightKey = GlobalKey(debugLabel: 'upperRightKey');
final GlobalKey lowerLeftKey = GlobalKey(debugLabel: 'lowerLeftKey');
final GlobalKey lowerRightKey = GlobalKey(debugLabel: 'lowerRightKey');
bool focusUpperLeft;
bool focusUpperRight;
bool focusLowerLeft;
bool focusLowerRight;
bool? focusUpperLeft;
bool? focusUpperRight;
bool? focusLowerLeft;
bool? focusLowerRight;
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1266,11 +1264,11 @@ void main() {
focusLowerRight = null;
}
final FocusNode upperLeftNode = Focus.of(tester.element(find.byKey(upperLeftKey)));
final FocusNode upperRightNode = Focus.of(tester.element(find.byKey(upperRightKey)));
final FocusNode lowerLeftNode = Focus.of(tester.element(find.byKey(lowerLeftKey)));
final FocusNode lowerRightNode = Focus.of(tester.element(find.byKey(lowerRightKey)));
final FocusNode scope = upperLeftNode.enclosingScope;
final FocusNode upperLeftNode = Focus.of(tester.element(find.byKey(upperLeftKey)))!;
final FocusNode upperRightNode = Focus.of(tester.element(find.byKey(upperRightKey)))!;
final FocusNode lowerLeftNode = Focus.of(tester.element(find.byKey(lowerLeftKey)))!;
final FocusNode lowerRightNode = Focus.of(tester.element(find.byKey(lowerRightKey)))!;
final FocusNode scope = upperLeftNode.enclosingScope!;
upperLeftNode.requestFocus();
await tester.pump();
@ -1355,7 +1353,7 @@ void main() {
GlobalKey(debugLabel: 'row 3:2'),
GlobalKey(debugLabel: 'row 3:3'),
];
List<bool> focus = List<bool>.generate(keys.length, (int _) => null);
List<bool?> focus = List<bool?>.generate(keys.length, (int _) => null);
Focus makeFocus(int index) {
return Focus(
debugLabel: keys[index].toString(),
@ -1407,16 +1405,16 @@ void main() {
);
void clear() {
focus = List<bool>.generate(keys.length, (int _) => null);
focus = List<bool?>.generate(keys.length, (int _) => null);
}
final List<FocusNode> nodes = keys.map<FocusNode>((GlobalKey key) => Focus.of(tester.element(find.byKey(key)))).toList();
final FocusNode scope = nodes[0].enclosingScope;
final List<FocusNode> nodes = keys.map<FocusNode>((GlobalKey key) => Focus.of(tester.element(find.byKey(key)))!).toList();
final FocusNode scope = nodes[0].enclosingScope!;
nodes[4].requestFocus();
void expectState(List<bool> states) {
void expectState(List<bool?> states) {
for (int index = 0; index < states.length; ++index) {
expect(focus[index], states[index] == null ? isNull : (states[index] ? isTrue : isFalse));
expect(focus[index], states[index] == null ? isNull : (states[index]! ? isTrue : isFalse));
if (states[index] == null) {
expect(nodes[index].hasFocus, isFalse);
} else {
@ -1428,59 +1426,59 @@ void main() {
// Test to make sure that the same path is followed backwards and forwards.
await tester.pump();
expectState(<bool>[null, null, null, null, true, null]);
expectState(<bool?>[null, null, null, null, true, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.up), isTrue);
await tester.pump();
expectState(<bool>[null, null, true, null, false, null]);
expectState(<bool?>[null, null, true, null, false, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.up), isTrue);
await tester.pump();
expectState(<bool>[true, null, false, null, null, null]);
expectState(<bool?>[true, null, false, null, null, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.down), isTrue);
await tester.pump();
expectState(<bool>[false, null, true, null, null, null]);
expectState(<bool?>[false, null, true, null, null, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.down), isTrue);
await tester.pump();
expectState(<bool>[null, null, false, null, true, null]);
expectState(<bool?>[null, null, false, null, true, null]);
clear();
// Make sure that moving in a different axis clears the history.
expect(scope.focusInDirection(TraversalDirection.left), isTrue);
await tester.pump();
expectState(<bool>[null, null, null, true, false, null]);
expectState(<bool?>[null, null, null, true, false, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.up), isTrue);
await tester.pump();
expectState(<bool>[null, true, null, false, null, null]);
expectState(<bool?>[null, true, null, false, null, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.up), isTrue);
await tester.pump();
expectState(<bool>[true, false, null, null, null, null]);
expectState(<bool?>[true, false, null, null, null, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.down), isTrue);
await tester.pump();
expectState(<bool>[false, true, null, null, null, null]);
expectState(<bool?>[false, true, null, null, null, null]);
clear();
expect(scope.focusInDirection(TraversalDirection.down), isTrue);
await tester.pump();
expectState(<bool>[null, false, null, true, null, null]);
expectState(<bool?>[null, false, null, true, null, null]);
clear();
});
@ -1529,14 +1527,14 @@ void main() {
),
);
final FocusNode upperLeftNode = Focus.of(tester.element(find.byKey(upperLeftKey)));
final FocusNode upperRightNode = Focus.of(tester.element(find.byKey(upperRightKey)));
final FocusNode lowerLeftNode = Focus.of(tester.element(find.byKey(lowerLeftKey)));
final FocusNode scope = upperLeftNode.enclosingScope;
final FocusNode upperLeftNode = Focus.of(tester.element(find.byKey(upperLeftKey)))!;
final FocusNode upperRightNode = Focus.of(tester.element(find.byKey(upperRightKey)))!;
final FocusNode lowerLeftNode = Focus.of(tester.element(find.byKey(lowerLeftKey)))!;
final FocusNode scope = upperLeftNode.enclosingScope!;
await tester.pump();
final FocusTraversalPolicy policy = FocusTraversalGroup.of(upperLeftKey.currentContext);
final FocusTraversalPolicy policy = FocusTraversalGroup.of(upperLeftKey.currentContext!)!;
expect(policy.findFirstFocusInDirection(scope, TraversalDirection.up), equals(lowerLeftNode));
expect(policy.findFirstFocusInDirection(scope, TraversalDirection.down), equals(upperLeftNode));
@ -1565,7 +1563,7 @@ void main() {
));
focusTop.requestFocus();
final FocusNode scope = focusTop.enclosingScope;
final FocusNode scope = focusTop.enclosingScope!;
scope.focusInDirection(TraversalDirection.down);
scope.focusInDirection(TraversalDirection.down);
@ -1646,42 +1644,42 @@ void main() {
),
);
expect(Focus.of(upperLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
expect(Focus.of(upperRightKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
expect(Focus.of(lowerLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(lowerLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
expect(Focus.of(lowerRightKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(lowerRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
expect(Focus.of(upperLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(Focus.of(lowerRightKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(lowerRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(Focus.of(lowerLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(lowerLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(Focus.of(upperRightKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
expect(Focus.of(upperLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
// Traverse in a direction
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
expect(Focus.of(upperRightKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
expect(Focus.of(lowerRightKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(lowerRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
expect(Focus.of(lowerLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(lowerLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
expect(Focus.of(upperLeftKey.currentContext).hasPrimaryFocus, isTrue);
expect(Focus.of(upperLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
testWidgets('Focus traversal inside a vertical scrollable scrolls to stay visible.', (WidgetTester tester) async {
@ -2056,7 +2054,7 @@ void main() {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
final GlobalKey key2 = GlobalKey(debugLabel: '2');
final FocusNode focusNode = FocusNode();
bool gotFocus;
bool? gotFocus;
await tester.pumpWidget(
FocusTraversalGroup(
descendantsAreFocusable: false,
@ -2072,9 +2070,9 @@ void main() {
);
final Element childWidget = tester.element(find.byKey(key1));
final FocusNode unfocusableNode = Focus.of(childWidget);
final FocusNode unfocusableNode = Focus.of(childWidget)!;
final Element containerWidget = tester.element(find.byKey(key2));
final FocusNode containerNode = Focus.of(containerWidget);
final FocusNode containerNode = Focus.of(containerWidget)!;
unfocusableNode.requestFocus();
await tester.pump();
@ -2134,7 +2132,7 @@ void main() {
}
class TestRoute extends PageRouteBuilder<void> {
TestRoute({Widget child})
TestRoute({required Widget child})
: super(
pageBuilder: (BuildContext _, Animation<double> __, Animation<double> ___) {
return child;

View file

@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
void main() {
testWidgets('onSaved callback is called', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String fieldValue;
String? fieldValue;
Widget builder() {
return MaterialApp(
@ -23,7 +21,7 @@ void main() {
child: Form(
key: formKey,
child: TextFormField(
onSaved: (String value) { fieldValue = value; },
onSaved: (String? value) { fieldValue = value; },
),
),
),
@ -39,7 +37,7 @@ void main() {
Future<void> checkText(String testValue) async {
await tester.enterText(find.byType(TextFormField), testValue);
formKey.currentState.save();
formKey.currentState!.save();
// Pumping is unnecessary because callback happens regardless of frames.
expect(fieldValue, equals(testValue));
}
@ -49,7 +47,7 @@ void main() {
});
testWidgets('onChanged callback is called', (WidgetTester tester) async {
String fieldValue;
String? fieldValue;
Widget builder() {
return MaterialApp(
@ -87,7 +85,7 @@ void main() {
testWidgets('Validator sets the error text only when validate is called', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String errorText(String value) => value + '/error';
String? errorText(String? value) => (value ?? '') + '/error';
Widget builder(AutovalidateMode autovalidateMode) {
return MaterialApp(
@ -115,24 +113,24 @@ void main() {
await tester.pumpWidget(builder(AutovalidateMode.disabled));
Future<void> checkErrorText(String testValue) async {
formKey.currentState.reset();
formKey.currentState!.reset();
await tester.pumpWidget(builder(AutovalidateMode.disabled));
await tester.enterText(find.byType(TextFormField), testValue);
await tester.pump();
// We have to manually validate if we're not autovalidating.
expect(find.text(errorText(testValue)), findsNothing);
formKey.currentState.validate();
expect(find.text(errorText(testValue)!), findsNothing);
formKey.currentState!.validate();
await tester.pump();
expect(find.text(errorText(testValue)), findsOneWidget);
expect(find.text(errorText(testValue)!), findsOneWidget);
// Try again with autovalidation. Should validate immediately.
formKey.currentState.reset();
formKey.currentState!.reset();
await tester.pumpWidget(builder(AutovalidateMode.always));
await tester.enterText(find.byType(TextFormField), testValue);
await tester.pump();
expect(find.text(errorText(testValue)), findsOneWidget);
expect(find.text(errorText(testValue)!), findsOneWidget);
}
await checkErrorText('Test');
@ -143,7 +141,7 @@ void main() {
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>();
const String validString = 'Valid string';
String validator(String s) => s == validString ? null : 'Error text';
String? validator(String? s) => s == validString ? null : 'Error text';
Widget builder() {
return MaterialApp(
@ -180,8 +178,8 @@ void main() {
await tester.pumpWidget(builder());
expect(fieldKey1.currentState.isValid, isTrue);
expect(fieldKey2.currentState.isValid, isTrue);
expect(fieldKey1.currentState!.isValid, isTrue);
expect(fieldKey2.currentState!.isValid, isTrue);
});
testWidgets(
@ -190,7 +188,7 @@ void main() {
final GlobalKey<FormFieldState<String>> fieldKey1 = GlobalKey<FormFieldState<String>>();
final GlobalKey<FormFieldState<String>> fieldKey2 = GlobalKey<FormFieldState<String>>();
const String validString = 'Valid string';
String validator(String s) => s == validString ? null : 'Error text';
String? validator(String? s) => s == validString ? null : 'Error text';
Widget builder() {
return MaterialApp(
@ -227,9 +225,9 @@ void main() {
await tester.pumpWidget(builder());
expect(fieldKey1.currentState.isValid, isTrue);
expect(fieldKey2.currentState.isValid, isFalse);
expect(fieldKey2.currentState.hasError, isFalse);
expect(fieldKey1.currentState!.isValid, isTrue);
expect(fieldKey2.currentState!.isValid, isFalse);
expect(fieldKey2.currentState!.hasError, isFalse);
},
);
@ -237,7 +235,7 @@ void main() {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final GlobalKey<FormFieldState<String>> fieldKey = GlobalKey<FormFieldState<String>>();
// Input 2's validator depends on a input 1's value.
String errorText(String input) => '${fieldKey.currentState.value}/error';
String? errorText(String? input) => '${fieldKey.currentState!.value}/error';
Widget builder() {
return MaterialApp(
@ -313,17 +311,17 @@ void main() {
// initial value should be loaded into keyboard editing state
expect(tester.testTextInput.editingState, isNotNull);
expect(tester.testTextInput.editingState['text'], equals(initialValue));
expect(tester.testTextInput.editingState!['text'], equals(initialValue));
// initial value should also be visible in the raw input line
final EditableTextState editableText = tester.state(find.byType(EditableText));
expect(editableText.widget.controller.text, equals(initialValue));
// sanity check, make sure we can still edit the text and everything updates
expect(inputKey.currentState.value, equals(initialValue));
expect(inputKey.currentState!.value, equals(initialValue));
await tester.enterText(find.byType(TextFormField), 'world');
await tester.pump();
expect(inputKey.currentState.value, equals('world'));
expect(inputKey.currentState!.value, equals('world'));
expect(editableText.widget.controller.text, equals('world'));
});
@ -358,7 +356,7 @@ void main() {
// initial value should be loaded into keyboard editing state
expect(tester.testTextInput.editingState, isNotNull);
expect(tester.testTextInput.editingState['text'], equals(initialValue));
expect(tester.testTextInput.editingState!['text'], equals(initialValue));
// initial value should also be visible in the raw input line
final EditableTextState editableText = tester.state(find.byType(EditableText));
@ -366,10 +364,10 @@ void main() {
expect(controller.text, equals(initialValue));
// sanity check, make sure we can still edit the text and everything updates
expect(inputKey.currentState.value, equals(initialValue));
expect(inputKey.currentState!.value, equals(initialValue));
await tester.enterText(find.byType(TextFormField), 'world');
await tester.pump();
expect(inputKey.currentState.value, equals('world'));
expect(inputKey.currentState!.value, equals('world'));
expect(editableText.widget.controller.text, equals('world'));
expect(controller.text, equals('world'));
});
@ -409,13 +407,13 @@ void main() {
controller.text = 'Xyzzy';
await tester.idle();
expect(editableText.widget.controller.text, equals('Xyzzy'));
expect(inputKey.currentState.value, equals('Xyzzy'));
expect(inputKey.currentState!.value, equals('Xyzzy'));
expect(controller.text, equals('Xyzzy'));
// verify value resets to initialValue on reset.
formKey.currentState.reset();
formKey.currentState!.reset();
await tester.idle();
expect(inputKey.currentState.value, equals('Plover'));
expect(inputKey.currentState!.value, equals('Plover'));
expect(editableText.widget.controller.text, equals('Plover'));
expect(controller.text, equals('Plover'));
});
@ -425,8 +423,8 @@ void main() {
final TextEditingController controller2 = TextEditingController(text: 'Bar');
final GlobalKey<FormFieldState<String>> inputKey = GlobalKey<FormFieldState<String>>();
TextEditingController currentController;
StateSetter setState;
TextEditingController? currentController;
late StateSetter setState;
Widget builder() {
return StatefulBuilder(
@ -459,7 +457,7 @@ void main() {
// verify initially empty.
expect(tester.testTextInput.editingState, isNotNull);
expect(tester.testTextInput.editingState['text'], isEmpty);
expect(tester.testTextInput.editingState!['text'], isEmpty);
final EditableTextState editableText = tester.state(find.byType(EditableText));
expect(editableText.widget.controller.text, isEmpty);
@ -469,18 +467,18 @@ void main() {
});
await tester.pump();
expect(editableText.widget.controller.text, equals('Foo'));
expect(inputKey.currentState.value, equals('Foo'));
expect(inputKey.currentState!.value, equals('Foo'));
// verify changes to controller1 text are visible in text field and set in form value.
controller1.text = 'Wobble';
await tester.idle();
expect(editableText.widget.controller.text, equals('Wobble'));
expect(inputKey.currentState.value, equals('Wobble'));
expect(inputKey.currentState!.value, equals('Wobble'));
// verify changes to the field text update the form value and controller1.
await tester.enterText(find.byType(TextFormField), 'Wibble');
await tester.pump();
expect(inputKey.currentState.value, equals('Wibble'));
expect(inputKey.currentState!.value, equals('Wibble'));
expect(editableText.widget.controller.text, equals('Wibble'));
expect(controller1.text, equals('Wibble'));
@ -489,7 +487,7 @@ void main() {
currentController = controller2;
});
await tester.pump();
expect(inputKey.currentState.value, equals('Bar'));
expect(inputKey.currentState!.value, equals('Bar'));
expect(editableText.widget.controller.text, equals('Bar'));
expect(controller2.text, equals('Bar'));
expect(controller1.text, equals('Wibble'));
@ -498,14 +496,14 @@ void main() {
controller2.text = 'Xyzzy';
await tester.idle();
expect(editableText.widget.controller.text, equals('Xyzzy'));
expect(inputKey.currentState.value, equals('Xyzzy'));
expect(inputKey.currentState!.value, equals('Xyzzy'));
expect(controller1.text, equals('Wibble'));
// verify changes to controller1 text are not visible in text field or set in form value.
controller1.text = 'Plugh';
await tester.idle();
expect(editableText.widget.controller.text, equals('Xyzzy'));
expect(inputKey.currentState.value, equals('Xyzzy'));
expect(inputKey.currentState!.value, equals('Xyzzy'));
expect(controller1.text, equals('Plugh'));
// verify that switching from controller2 to null is handled.
@ -513,7 +511,7 @@ void main() {
currentController = null;
});
await tester.pump();
expect(inputKey.currentState.value, equals('Xyzzy'));
expect(inputKey.currentState!.value, equals('Xyzzy'));
expect(editableText.widget.controller.text, equals('Xyzzy'));
expect(controller2.text, equals('Xyzzy'));
expect(controller1.text, equals('Plugh'));
@ -521,7 +519,7 @@ void main() {
// verify that changes to the field text update the form value but not the previous controllers.
await tester.enterText(find.byType(TextFormField), 'Plover');
await tester.pump();
expect(inputKey.currentState.value, equals('Plover'));
expect(inputKey.currentState!.value, equals('Plover'));
expect(editableText.widget.controller.text, equals('Plover'));
expect(controller1.text, equals('Plugh'));
expect(controller2.text, equals('Xyzzy'));
@ -529,7 +527,7 @@ void main() {
testWidgets('No crash when a TextFormField is removed from the tree', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String fieldValue;
String? fieldValue;
Widget builder(bool remove) {
return MaterialApp(
@ -543,8 +541,8 @@ void main() {
key: formKey,
child: remove ? Container() : TextFormField(
autofocus: true,
onSaved: (String value) { fieldValue = value; },
validator: (String value) { return value.isEmpty ? null : 'yes'; },
onSaved: (String? value) { fieldValue = value; },
validator: (String? value) { return (value == null || value.isEmpty) ? null : 'yes'; },
),
),
),
@ -557,34 +555,34 @@ void main() {
await tester.pumpWidget(builder(false));
expect(fieldValue, isNull);
expect(formKey.currentState.validate(), isTrue);
expect(formKey.currentState!.validate(), isTrue);
await tester.enterText(find.byType(TextFormField), 'Test');
await tester.pumpWidget(builder(false));
// Form wasn't saved yet.
expect(fieldValue, null);
expect(formKey.currentState.validate(), isFalse);
expect(formKey.currentState!.validate(), isFalse);
formKey.currentState.save();
formKey.currentState!.save();
// Now fieldValue is saved.
expect(fieldValue, 'Test');
expect(formKey.currentState.validate(), isFalse);
expect(formKey.currentState!.validate(), isFalse);
// Now remove the field with an error.
await tester.pumpWidget(builder(true));
// Reset the form. Should not crash.
formKey.currentState.reset();
formKey.currentState.save();
expect(formKey.currentState.validate(), isTrue);
formKey.currentState!.reset();
formKey.currentState!.save();
expect(formKey.currentState!.validate(), isTrue);
});
testWidgets('Does not auto-validate before value changes when autovalidateMode is set to onUserInteraction', (WidgetTester tester) async {
FormFieldState<String> formFieldState;
late FormFieldState<String> formFieldState;
String errorText(String value) => '$value/error';
String? errorText(String? value) => '$value/error';
Widget builder() {
return MaterialApp(
@ -614,13 +612,13 @@ void main() {
// The form field has no error.
expect(formFieldState.hasError, isFalse);
// No error widget is visible.
expect(find.text(errorText('foo')), findsNothing);
expect(find.text(errorText('foo')!), findsNothing);
});
testWidgets('auto-validate before value changes if autovalidateMode was set to always', (WidgetTester tester) async {
FormFieldState<String> formFieldState;
late FormFieldState<String> formFieldState;
String errorText(String value) => '$value/error';
String? errorText(String? value) => '$value/error';
Widget builder() {
return MaterialApp(
@ -652,7 +650,7 @@ void main() {
testWidgets('Form auto-validates form fields only after one of them changes if autovalidateMode is onUserInteraction', (WidgetTester tester) async {
const String initialValue = 'foo';
String errorText(String value) => 'error/$value';
String? errorText(String? value) => 'error/$value';
Widget builder() {
return MaterialApp(
@ -691,7 +689,7 @@ void main() {
await tester.pumpWidget(builder());
// We expect no validation error text being shown.
expect(find.text(errorText(initialValue)), findsNothing);
expect(find.text(errorText(initialValue)!), findsNothing);
// Set a empty string into the first form field to
// trigger the fields validators.
@ -700,12 +698,12 @@ void main() {
// Now we expect the errors to be shown for the first Text Field and
// for the next two form fields that have their contents unchanged.
expect(find.text(errorText('')), findsOneWidget);
expect(find.text(errorText(initialValue)), findsNWidgets(2));
expect(find.text(errorText('')!), findsOneWidget);
expect(find.text(errorText(initialValue)!), findsNWidgets(2));
});
testWidgets('Form auto-validates form fields even before any have changed if autovalidateMode is set to always', (WidgetTester tester) async {
String errorText(String value) => 'error/$value';
String? errorText(String? value) => 'error/$value';
Widget builder() {
return MaterialApp(
@ -731,12 +729,12 @@ void main() {
await tester.pumpWidget(builder());
// We expect validation error text being shown.
expect(find.text(errorText('')), findsOneWidget);
expect(find.text(errorText('')!), findsOneWidget);
});
testWidgets('autovalidate parameter is still used if true', (WidgetTester tester) async {
FormFieldState<String> formFieldState;
String errorText(String value) => '$value/error';
late FormFieldState<String> formFieldState;
String? errorText(String? value) => '$value/error';
Widget builder() {
return MaterialApp(
@ -768,7 +766,7 @@ void main() {
testWidgets('Form.reset() resets form fields, and auto validation will only happen on the next user interaction if autovalidateMode is onUserInteraction', (WidgetTester tester) async {
final GlobalKey<FormState> formState = GlobalKey<FormState>();
String errorText(String value) => '$value/error';
String? errorText(String? value) => '$value/error';
Widget builder() {
return MaterialApp(
@ -797,17 +795,17 @@ void main() {
await tester.pumpWidget(builder());
// No error text is visible yet.
expect(find.text(errorText('foo')), findsNothing);
expect(find.text(errorText('foo')!), findsNothing);
await tester.enterText(find.byType(TextFormField), 'bar');
await tester.pumpAndSettle();
await tester.pump();
expect(find.text(errorText('bar')), findsOneWidget);
expect(find.text(errorText('bar')!), findsOneWidget);
// Resetting the form state should remove the error text.
formState.currentState.reset();
formState.currentState!.reset();
await tester.pump();
expect(find.text(errorText('bar')), findsNothing);
expect(find.text(errorText('bar')!), findsNothing);
});
testWidgets('Form.autovalidateMode and Form.autovalidate should not be used at the same time', (WidgetTester tester) async {
@ -853,7 +851,7 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/65374.
testWidgets('Validate form should return correct validation if the value is composing', (WidgetTester tester) async {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
String fieldValue;
String? fieldValue;
final Widget widget = MaterialApp(
home: MediaQuery(
@ -866,8 +864,8 @@ void main() {
key: formKey,
child: TextFormField(
maxLength: 5,
onSaved: (String value) { fieldValue = value; },
validator: (String value) => value.length > 5 ? 'Exceeded' : null,
onSaved: (String? value) { fieldValue = value; },
validator: (String? value) => (value != null && value.length > 5) ? 'Exceeded' : null,
),
),
),
@ -882,16 +880,16 @@ void main() {
editableText.updateEditingValue(const TextEditingValue(text: '123456', composing: TextRange(start: 2, end: 5)));
expect(editableText.currentTextEditingValue.composing, const TextRange(start: 2, end: 5));
formKey.currentState.save();
formKey.currentState!.save();
expect(fieldValue, '123456');
expect(formKey.currentState.validate(), isFalse);
expect(formKey.currentState!.validate(), isFalse);
});
testWidgets('FormField.autovalidate parameter is passed into class the property', (WidgetTester tester) async {
String errorText(String value) => '$value/error';
String? errorText(String? value) => '$value/error';
const ObjectKey widgetKey = ObjectKey('key');
Widget builder({@required bool autovalidate}) {
Widget builder({required bool autovalidate}) {
return MaterialApp(
home: MediaQuery(
data: const MediaQueryData(devicePixelRatio: 1.0),
@ -934,7 +932,7 @@ void main() {
testWidgets('Form.autovalidate parameter is passed into class the property', (WidgetTester tester) async {
const ObjectKey widgetKey = ObjectKey('key');
Widget builder({@required bool autovalidate}) {
Widget builder({required bool autovalidate}) {
return MaterialApp(
home: MediaQuery(
data: const MediaQueryData(devicePixelRatio: 1.0),

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
@ -27,7 +25,7 @@ void main() {
),
),
));
final RenderBox box = inner.currentContext.findRenderObject() as RenderBox;
final RenderBox box = inner.currentContext!.findRenderObject()! as RenderBox;
expect(box.size, equals(const Size(50.0, 25.0)));
expect(box.localToGlobal(Offset.zero), equals(const Offset(25.0, 37.5)));
});
@ -43,7 +41,7 @@ void main() {
child: Placeholder(key: inner),
),
));
final RenderBox box = inner.currentContext.findRenderObject() as RenderBox;
final RenderBox box = inner.currentContext!.findRenderObject()! as RenderBox;
expect(box.size, equals(const Size(400.0, 300.0)));
expect(box.localToGlobal(box.size.center(Offset.zero)), equals(const Offset(800.0 - 400.0 / 2.0, 0.0 + 300.0 / 2.0)));
});
@ -59,7 +57,7 @@ void main() {
child: Placeholder(key: inner),
),
));
final RenderBox box = inner.currentContext.findRenderObject() as RenderBox;
final RenderBox box = inner.currentContext!.findRenderObject()! as RenderBox;
expect(box.size, equals(const Size(400.0, 300.0)));
expect(box.localToGlobal(box.size.center(Offset.zero)), equals(const Offset(0.0 + 400.0 / 2.0, 0.0 + 300.0 / 2.0)));
});
@ -85,7 +83,7 @@ void main() {
),
),
));
final RenderBox box = inner.currentContext.findRenderObject() as RenderBox;
final RenderBox box = inner.currentContext!.findRenderObject()! as RenderBox;
expect(box.size, equals(const Size(50.0, 25.0)));
expect(box.localToGlobal(Offset.zero), equals(const Offset(25.0, 37.5)));
});

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart';
@ -13,7 +11,7 @@ typedef ElementRebuildCallback = void Function(StatefulElement element);
class TestState extends State<StatefulWidget> {
@override
Widget build(BuildContext context) => null;
Widget build(BuildContext context) => const SizedBox();
}
@optionalTypeArgs
@ -138,9 +136,9 @@ void main() {
testWidgets('GlobalKey correct case 3 - can deal with early rebuild in layoutbuilder - move backward', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2');
Key rebuiltKeyOfSecondChildBeforeLayout;
Key rebuiltKeyOfFirstChildAfterLayout;
Key rebuiltKeyOfSecondChildAfterLayout;
Key? rebuiltKeyOfSecondChildBeforeLayout;
Key? rebuiltKeyOfFirstChildAfterLayout;
Key? rebuiltKeyOfSecondChildAfterLayout;
await tester.pumpWidget(
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
@ -228,9 +226,9 @@ void main() {
const Key key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2');
const Key key3 = GlobalObjectKey('Text3');
Key rebuiltKeyOfSecondChildBeforeLayout;
Key rebuiltKeyOfSecondChildAfterLayout;
Key rebuiltKeyOfThirdChildAfterLayout;
Key? rebuiltKeyOfSecondChildBeforeLayout;
Key? rebuiltKeyOfSecondChildAfterLayout;
Key? rebuiltKeyOfThirdChildAfterLayout;
await tester.pumpWidget(
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
@ -329,8 +327,8 @@ void main() {
testWidgets('GlobalKey correct case 5 - can deal with early rebuild in layoutbuilder - only one global key', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
Key rebuiltKeyOfSecondChildBeforeLayout;
Key rebuiltKeyOfThirdChildAfterLayout;
Key? rebuiltKeyOfSecondChildBeforeLayout;
Key? rebuiltKeyOfThirdChildAfterLayout;
await tester.pumpWidget(
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
@ -844,7 +842,7 @@ void main() {
],
));
int count = 0;
final FlutterExceptionHandler oldHandler = FlutterError.onError;
final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails details) {
expect(details.exception, isFlutterError);
count += 1;
@ -929,9 +927,9 @@ void main() {
testWidgets('GlobalKey duplication 20 - real duplication with early rebuild in layoutbuilder will throw', (WidgetTester tester) async {
const Key key1 = GlobalObjectKey('Text1');
const Key key2 = GlobalObjectKey('Text2');
Key rebuiltKeyOfSecondChildBeforeLayout;
Key rebuiltKeyOfFirstChildAfterLayout;
Key rebuiltKeyOfSecondChildAfterLayout;
Key? rebuiltKeyOfSecondChildBeforeLayout;
Key? rebuiltKeyOfFirstChildAfterLayout;
Key? rebuiltKeyOfSecondChildAfterLayout;
await tester.pumpWidget(
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
@ -1047,18 +1045,18 @@ void main() {
),
));
final SliverMultiBoxAdaptorElement element = tester.element(find.byType(SliverList));
Element childElement;
late Element childElement;
// Removing and recreating child with same Global Key should not trigger
// duplicate key error.
element.visitChildren((Element e) {
childElement = e;
});
element.removeChild(childElement.renderObject as RenderBox);
element.removeChild(childElement.renderObject! as RenderBox);
element.createChild(0, after: null);
element.visitChildren((Element e) {
childElement = e;
});
element.removeChild(childElement.renderObject as RenderBox);
element.removeChild(childElement.renderObject! as RenderBox);
element.createChild(0, after: null);
});
@ -1066,7 +1064,7 @@ void main() {
// This is a regression test for https://github.com/flutter/flutter/issues/62055
const Key key1 = GlobalObjectKey('key1');
const Key key2 = GlobalObjectKey('key2');
StateSetter setState;
late StateSetter setState;
int tabBarViewCnt = 2;
TabController tabController = TabController(length: tabBarViewCnt, vsync: const TestVSync(),);
@ -1109,7 +1107,7 @@ void main() {
});
testWidgets('Defunct setState throws exception', (WidgetTester tester) async {
StateSetter setState;
late StateSetter setState;
await tester.pumpWidget(StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
@ -1138,8 +1136,8 @@ void main() {
debugPrintGlobalKeyedWidgetLifecycle = true;
final List<String> log = <String>[];
debugPrint = (String message, { int wrapWidth }) {
log.add(message);
debugPrint = (String? message, { int? wrapWidth }) {
log.add(message!);
};
final GlobalKey key = GlobalKey();
@ -1166,10 +1164,10 @@ void main() {
Container(),
],
));
final MultiChildRenderObjectElement element = key0.currentContext as MultiChildRenderObjectElement;
final MultiChildRenderObjectElement element = key0.currentContext! as MultiChildRenderObjectElement;
expect(
element.children.map((Element element) => element.widget.key),
<Key>[null, key1, null, key2, null],
<Key?>[null, key1, null, key2, null],
);
});
@ -1185,7 +1183,7 @@ void main() {
Container(),
],
));
final MultiChildRenderObjectElement element = key0.currentContext as MultiChildRenderObjectElement;
final MultiChildRenderObjectElement element = key0.currentContext! as MultiChildRenderObjectElement;
expect(element, hasAGoodToStringDeep);
expect(
@ -1216,14 +1214,13 @@ void main() {
/// ignore here is required for testing purpose because changing the flag properly is hard
// ignore: invalid_use_of_protected_member
tester.binding.debugBuildingDirtyElements = true;
FlutterError error;
late FlutterError error;
try {
tester.binding.buildOwner.scheduleBuildFor(
DirtyElementWithCustomBuildOwner(tester.binding.buildOwner, Container()));
tester.binding.buildOwner!.scheduleBuildFor(
DirtyElementWithCustomBuildOwner(tester.binding.buildOwner!, Container()));
} on FlutterError catch (e) {
error = e;
} finally {
expect(error, isNotNull);
expect(error.diagnostics.length, 3);
expect(error.diagnostics.last.level, DiagnosticLevel.hint);
expect(
@ -1270,7 +1267,7 @@ void main() {
/// Initial build - should call didChangeDependencies, not deactivate
await tester.pumpWidget(Inherited(1, child: DependentStatefulWidget(key: key)));
final DependentState state = key.currentState;
final DependentState state = key.currentState!;
expect(key.currentState, isNotNull);
expect(state.didChangeDependenciesCount, 1);
expect(state.deactivatedCount, 0);
@ -1295,8 +1292,8 @@ void main() {
});
testWidgets('StatefulElement subclass can decorate State.build', (WidgetTester tester) async {
bool isDidChangeDependenciesDecorated;
bool isBuildDecorated;
late bool isDidChangeDependenciesDecorated;
late bool isBuildDecorated;
final Widget child = Decorate(
didChangeDependencies: (bool value) {
@ -1319,7 +1316,7 @@ void main() {
});
group('BuildContext.debugDoingbuild', () {
testWidgets('StatelessWidget', (WidgetTester tester) async {
bool debugDoingBuildOnBuild;
late bool debugDoingBuildOnBuild;
await tester.pumpWidget(
StatelessWidgetSpy(
onBuild: (BuildContext context) {
@ -1334,12 +1331,12 @@ void main() {
expect(debugDoingBuildOnBuild, isTrue);
});
testWidgets('StatefulWidget', (WidgetTester tester) async {
bool debugDoingBuildOnBuild;
bool debugDoingBuildOnInitState;
bool debugDoingBuildOnDidChangeDependencies;
bool debugDoingBuildOnDidUpdateWidget;
bool debugDoingBuildOnDispose;
bool debugDoingBuildOnDeactivate;
late bool debugDoingBuildOnBuild;
late bool debugDoingBuildOnInitState;
late bool debugDoingBuildOnDidChangeDependencies;
late bool debugDoingBuildOnDidUpdateWidget;
bool? debugDoingBuildOnDispose;
bool? debugDoingBuildOnDeactivate;
await tester.pumpWidget(
Inherited(
@ -1403,18 +1400,18 @@ void main() {
expect(debugDoingBuildOnDeactivate, isFalse);
});
testWidgets('RenderObjectWidget', (WidgetTester tester) async {
bool debugDoingBuildOnCreateRenderObject;
bool debugDoingBuildOnUpdateRenderObject;
bool debugDoingBuildOnDidUnmountRenderObject;
late bool debugDoingBuildOnCreateRenderObject;
bool? debugDoingBuildOnUpdateRenderObject;
bool? debugDoingBuildOnDidUnmountRenderObject;
final ValueNotifier<int> notifier = ValueNotifier<int>(0);
BuildContext spyContext;
late BuildContext spyContext;
Widget build() {
return ValueListenableBuilder<int>(
valueListenable: notifier,
builder: (BuildContext context, int value, Widget child) {
return Inherited(value, child: child);
builder: (BuildContext context, int? value, Widget? child) {
return Inherited(value, child: child!);
},
child: RenderObjectWidgetSpy(
onCreateRenderObject: (BuildContext context) {
@ -1465,7 +1462,7 @@ void main() {
testWidgets('A widget whose element has an invalid visitChildren implementation triggers a useful error message', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
await tester.pumpWidget(Container(child: _WidgetWithNoVisitChildren(_StatefulLeaf(key: key))));
(key.currentState as _StatefulLeafState).markNeedsBuild();
(key.currentState! as _StatefulLeafState).markNeedsBuild();
await tester.pumpWidget(Container());
final dynamic exception = tester.takeException();
expect(
@ -1489,7 +1486,7 @@ void main() {
}
class _WidgetWithNoVisitChildren extends StatelessWidget {
const _WidgetWithNoVisitChildren(this.child, { Key key }) :
const _WidgetWithNoVisitChildren(this.child, { Key? key }) :
super(key: key);
final Widget child;
@ -1514,7 +1511,7 @@ class _WidgetWithNoVisitChildrenElement extends StatelessElement {
}
class _StatefulLeaf extends StatefulWidget {
const _StatefulLeaf({ Key key }) : super(key: key);
const _StatefulLeaf({ Key? key }) : super(key: key);
@override
State<_StatefulLeaf> createState() => _StatefulLeafState();
@ -1533,9 +1530,9 @@ class _StatefulLeafState extends State<_StatefulLeaf> {
class Decorate extends StatefulWidget {
const Decorate({
Key key,
@required this.didChangeDependencies,
@required this.build
Key? key,
required this.didChangeDependencies,
required this.build
}) :
assert(didChangeDependencies != null),
assert(build != null),
@ -1601,16 +1598,16 @@ class DirtyElementWithCustomBuildOwner extends Element {
}
class Inherited extends InheritedWidget {
const Inherited(this.value, {Widget child, Key key}) : super(key: key, child: child);
const Inherited(this.value, {Key? key, required Widget child}) : super(key: key, child: child);
final int value;
final int? value;
@override
bool updateShouldNotify(Inherited oldWidget) => oldWidget.value != value;
}
class DependentStatefulWidget extends StatefulWidget {
const DependentStatefulWidget({Key key}) : super(key: key);
const DependentStatefulWidget({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => DependentState();
@ -1642,13 +1639,13 @@ class DependentState extends State<DependentStatefulWidget> {
class SwapKeyWidget extends StatefulWidget {
const SwapKeyWidget({this.childKey}): super();
final Key childKey;
final Key? childKey;
@override
SwapKeyWidgetState createState() => SwapKeyWidgetState();
}
class SwapKeyWidgetState extends State<SwapKeyWidget> {
Key key;
Key? key;
@override
void initState() {
@ -1669,9 +1666,9 @@ class SwapKeyWidgetState extends State<SwapKeyWidget> {
}
class _Stateful extends StatefulWidget {
const _Stateful({Key key, this.child, this.onElementRebuild}) : super(key: key);
const _Stateful({Key? key, required this.child, this.onElementRebuild}) : super(key: key);
final Text child;
final ElementRebuildCallback onElementRebuild;
final ElementRebuildCallback? onElementRebuild;
@override
State<StatefulWidget> createState() => _StatefulState();
@ -1695,17 +1692,15 @@ class StatefulElementSpy extends StatefulElement {
@override
void rebuild() {
if (_statefulWidget.onElementRebuild != null) {
_statefulWidget.onElementRebuild(this);
}
_statefulWidget.onElementRebuild?.call(this);
super.rebuild();
}
}
class StatelessWidgetSpy extends StatelessWidget {
const StatelessWidgetSpy({
Key key,
@required this.onBuild,
Key? key,
required this.onBuild,
}) : assert(onBuild != null),
super(key: key);
@ -1720,7 +1715,7 @@ class StatelessWidgetSpy extends StatelessWidget {
class StatefulWidgetSpy extends StatefulWidget {
const StatefulWidgetSpy({
Key key,
Key? key,
this.onBuild,
this.onInitState,
this.onDidChangeDependencies,
@ -1729,12 +1724,12 @@ class StatefulWidgetSpy extends StatefulWidget {
this.onDidUpdateWidget,
}) : super(key: key);
final void Function(BuildContext) onBuild;
final void Function(BuildContext) onInitState;
final void Function(BuildContext) onDidChangeDependencies;
final void Function(BuildContext) onDispose;
final void Function(BuildContext) onDeactivate;
final void Function(BuildContext) onDidUpdateWidget;
final void Function(BuildContext)? onBuild;
final void Function(BuildContext)? onInitState;
final void Function(BuildContext)? onDidChangeDependencies;
final void Function(BuildContext)? onDispose;
final void Function(BuildContext)? onDeactivate;
final void Function(BuildContext)? onDidUpdateWidget;
@override
_StatefulWidgetSpyState createState() => _StatefulWidgetSpyState();
@ -1780,15 +1775,15 @@ class _StatefulWidgetSpyState extends State<StatefulWidgetSpy> {
class RenderObjectWidgetSpy extends LeafRenderObjectWidget {
const RenderObjectWidgetSpy({
Key key,
Key? key,
this.onCreateRenderObject,
this.onUpdateRenderObject,
this.onDidUnmountRenderObject,
}) : super(key: key);
final void Function(BuildContext) onCreateRenderObject;
final void Function(BuildContext) onUpdateRenderObject;
final void Function() onDidUnmountRenderObject;
final void Function(BuildContext)? onCreateRenderObject;
final void Function(BuildContext)? onUpdateRenderObject;
final void Function()? onDidUnmountRenderObject;
@override
RenderObject createRenderObject(BuildContext context) {

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
@ -34,13 +32,13 @@ void main() {
actions: <SemanticsAction>[SemanticsAction.scrollUp, SemanticsAction.scrollDown]),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollRight);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollRight);
expect(callCount, 0);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollUp);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollUp);
expect(callCount, 1);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollDown);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollDown);
expect(callCount, 2);
semantics.dispose();
@ -68,13 +66,13 @@ void main() {
actions: <SemanticsAction>[SemanticsAction.scrollLeft, SemanticsAction.scrollRight]),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollUp);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollDown);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollUp);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollDown);
expect(callCount, 0);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
expect(callCount, 1);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollRight);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollRight);
expect(callCount, 2);
semantics.dispose();
@ -97,8 +95,8 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
expect(logs, <String>{'horizontal', 'pan'});
semantics.dispose();
@ -120,7 +118,7 @@ void main() {
final Set<String> logs = <String>{};
final GlobalKey<RawGestureDetectorState> detectorKey = GlobalKey();
final VoidCallback performLayout = () {
detectorKey.currentState.replaceGestureRecognizers(<Type, GestureRecognizerFactory>{
detectorKey.currentState!.replaceGestureRecognizers(<Type, GestureRecognizerFactory>{
TapGestureRecognizer: GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
() => TapGestureRecognizer(),
(TapGestureRecognizer instance) {
@ -131,7 +129,7 @@ void main() {
};
bool hasLayoutPerformer = false;
VoidCallback introduceLayoutPerformer;
late VoidCallback introduceLayoutPerformer;
await tester.pumpWidget(
StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
@ -158,16 +156,16 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
expect(logs, <String>{'horizontal'});
logs.clear();
introduceLayoutPerformer();
await tester.pumpAndSettle();
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.tap);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.tap);
expect(logs, <String>{'tap'});
logs.clear();
@ -301,20 +299,20 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.tap);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.tap);
expect(logs, <String>['tap']);
logs.clear();
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.longPress);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.longPress);
expect(logs, <String>['longPress']);
logs.clear();
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
expect(logs, <String>['horizontal']);
logs.clear();
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollUp);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollUp);
expect(logs, <String>['vertical']);
logs.clear();
@ -388,8 +386,8 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.tap);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.tap);
expect(logs, <String>['tapDown', 'tapUp', 'tap']);
semantics.dispose();
@ -460,8 +458,8 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.longPress);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.longPress);
expect(logs, <String>['LPStart', 'LP', 'LPEnd', 'LPUp']);
semantics.dispose();
@ -560,13 +558,13 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
expect(logs, <String>['HDown', 'HStart', 'HUpdate', 'HEnd',
'PDown', 'PStart', 'PUpdate', 'PEnd',]);
logs.clear();
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollLeft);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollLeft);
expect(logs, <String>['HDown', 'HStart', 'HUpdate', 'HEnd',
'PDown', 'PStart', 'PUpdate', 'PEnd',]);
@ -651,13 +649,13 @@ void main() {
),
);
final int detectorId = detectorKey.currentContext.findRenderObject().debugSemantics.id;
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollUp);
final int detectorId = detectorKey.currentContext!.findRenderObject()!.debugSemantics!.id;
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollUp);
expect(logs, <String>['VDown', 'VStart', 'VUpdate', 'VEnd',
'PDown', 'PStart', 'PUpdate', 'PEnd',]);
logs.clear();
tester.binding.pipelineOwner.semanticsOwner.performAction(detectorId, SemanticsAction.scrollDown);
tester.binding.pipelineOwner.semanticsOwner!.performAction(detectorId, SemanticsAction.scrollDown);
expect(logs, <String>['VDown', 'VStart', 'VUpdate', 'VEnd',
'PDown', 'PStart', 'PUpdate', 'PEnd',]);
@ -700,8 +698,8 @@ void main() {
class _TestLayoutPerformer extends SingleChildRenderObjectWidget {
const _TestLayoutPerformer({
Key key,
this.performLayout,
Key? key,
required this.performLayout,
}) : super(key: key);
final VoidCallback performLayout;
@ -713,7 +711,7 @@ class _TestLayoutPerformer extends SingleChildRenderObjectWidget {
}
class _RenderTestLayoutPerformer extends RenderBox {
_RenderTestLayoutPerformer({VoidCallback performLayout}) : _performLayout = performLayout;
_RenderTestLayoutPerformer({required VoidCallback performLayout}) : _performLayout = performLayout;
final VoidCallback _performLayout;
@ -726,8 +724,8 @@ class _RenderTestLayoutPerformer extends RenderBox {
}
Map<Type, GestureRecognizerFactory> _buildGestureMap<T extends GestureRecognizer>(
GestureRecognizerFactoryConstructor<T> constructor,
GestureRecognizerFactoryInitializer<T> initializer,
GestureRecognizerFactoryConstructor<T>? constructor,
GestureRecognizerFactoryInitializer<T>? initializer,
) {
if (constructor == null)
return <Type, GestureRecognizerFactory>{};
@ -747,10 +745,10 @@ class _TestSemanticsGestureDelegate extends SemanticsGestureDelegate {
this.onVerticalDragUpdate,
});
final GestureTapCallback onTap;
final GestureLongPressCallback onLongPress;
final GestureDragUpdateCallback onHorizontalDragUpdate;
final GestureDragUpdateCallback onVerticalDragUpdate;
final GestureTapCallback? onTap;
final GestureLongPressCallback? onLongPress;
final GestureDragUpdateCallback? onHorizontalDragUpdate;
final GestureDragUpdateCallback? onVerticalDragUpdate;
@override
void assignSemantics(RenderSemanticsGestureHandler renderObject) {

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
@ -14,7 +12,7 @@ void main() {
testWidgets('Uncontested scrolls start immediately', (WidgetTester tester) async {
bool didStartDrag = false;
double updatedDragDelta;
double? updatedDragDelta;
bool didEndDrag = false;
final Widget widget = GestureDetector(
@ -69,7 +67,7 @@ void main() {
final Widget widget = GestureDetector(
dragStartBehavior: DragStartBehavior.down,
onVerticalDragUpdate: (DragUpdateDetails details) { dragDistance += details.primaryDelta; },
onVerticalDragUpdate: (DragUpdateDetails details) { dragDistance += details.primaryDelta ?? 0; },
onVerticalDragEnd: (DragEndDetails details) { gestureCount += 1; },
onHorizontalDragUpdate: (DragUpdateDetails details) { fail('gesture should not match'); },
onHorizontalDragEnd: (DragEndDetails details) { fail('gesture should not match'); },
@ -95,7 +93,7 @@ void main() {
testWidgets("Pan doesn't crash", (WidgetTester tester) async {
bool didStartPan = false;
Offset panDelta;
Offset? panDelta;
bool didEndPan = false;
await tester.pumpWidget(
@ -104,7 +102,7 @@ void main() {
didStartPan = true;
},
onPanUpdate: (DragUpdateDetails details) {
panDelta = panDelta == null ? details.delta : panDelta + details.delta;
panDelta = (panDelta ?? Offset.zero) + details.delta;
},
onPanEnd: (DragEndDetails details) {
didEndPan = true;
@ -122,8 +120,8 @@ void main() {
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0));
expect(didStartPan, isTrue);
expect(panDelta.dx, 20.0);
expect(panDelta.dy, 30.0);
expect(panDelta!.dx, 20.0);
expect(panDelta!.dy, 30.0);
expect(didEndPan, isTrue);
});
@ -141,7 +139,7 @@ void main() {
bool didReceivePointerDown;
bool didTap;
Future<void> pumpWidgetTree(HitTestBehavior behavior) {
Future<void> pumpWidgetTree(HitTestBehavior? behavior) {
return tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -732,7 +730,7 @@ void main() {
await tester.pumpWidget(RawGestureDetector(
key: key,
));
key.currentState.debugFillProperties(builder);
key.currentState!.debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
@ -767,7 +765,7 @@ void main() {
child: Container(),
semantics: _EmptySemanticsGestureDelegate(),
));
key.currentState.debugFillProperties(builder);
key.currentState!.debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
@ -791,7 +789,7 @@ void main() {
semantics: _EmptySemanticsGestureDelegate(),
excludeFromSemantics: true,
));
key.currentState.debugFillProperties(builder);
key.currentState!.debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
@ -806,13 +804,12 @@ void main() {
group('error control test', () {
test('constructor redundant pan and scale', () {
FlutterError error;
late FlutterError error;
try {
GestureDetector(onScaleStart: (_) {}, onPanStart: (_) {},);
} on FlutterError catch (e) {
error = e;
} finally {
expect(error, isNotNull);
expect(
error.toStringDeep(),
'FlutterError\n'
@ -832,7 +829,7 @@ void main() {
});
test('constructor duplicate drag recognizer', () {
FlutterError error;
late FlutterError error;
try {
GestureDetector(
onVerticalDragStart: (_) {},
@ -842,7 +839,6 @@ void main() {
} on FlutterError catch (e) {
error = e;
} finally {
expect(error, isNotNull);
expect(
error.toStringDeep(),
'FlutterError\n'
@ -868,14 +864,13 @@ void main() {
),
),
);
FlutterError error;
late FlutterError error;
try {
key.currentState.replaceGestureRecognizers(
key.currentState!.replaceGestureRecognizers(
<Type, GestureRecognizerFactory>{});
} on FlutterError catch (e) {
error = e;
} finally {
expect(error, isNotNull);
expect(error.diagnostics.last.level, DiagnosticLevel.hint);
expect(
error.diagnostics.last.toStringDeep(),
@ -913,8 +908,8 @@ class _EmptySemanticsGestureDelegate extends SemanticsGestureDelegate {
/// A [TestVariant] that runs tests multiple times with different buttons.
class ButtonVariant extends TestVariant<int> {
const ButtonVariant({
@required this.values,
@required this.descriptions,
required this.values,
required this.descriptions,
}) : assert(values.length != 0); // ignore: prefer_is_empty
@override
@ -922,12 +917,12 @@ class ButtonVariant extends TestVariant<int> {
final Map<int, String> descriptions;
static int button;
static int button = 0;
@override
String describeValue(int value) {
assert(descriptions.containsKey(value), 'Unknown button');
return descriptions[value];
return descriptions[value]!;
}
@override

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/gestures.dart';

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
@ -61,7 +59,7 @@ void main() {
});
testWidgets('GlobalKey children of two nodes', (WidgetTester tester) async {
StateSetter nestedSetState;
late StateSetter nestedSetState;
bool flag = false;
await tester.pumpWidget(Stack(
textDirection: TextDirection.ltr,

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
@ -17,7 +15,7 @@ class Item {
List<Item> items = <Item>[Item(), Item()];
class StatefulLeaf extends StatefulWidget {
const StatefulLeaf({ GlobalKey key }) : super(key: key);
const StatefulLeaf({ GlobalKey? key }) : super(key: key);
@override
StatefulLeafState createState() => StatefulLeafState();
@ -31,7 +29,7 @@ class StatefulLeafState extends State<StatefulLeaf> {
}
class KeyedWrapper extends StatelessWidget {
const KeyedWrapper(this.key1, this.key2, { Key key }) : super(key: key);
const KeyedWrapper(this.key1, this.key2, { Key? key }) : super(key: key);
final Key key1;
final GlobalKey key2;

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

View file

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
@ -578,8 +576,7 @@ void main() {
itemCount: 1000,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
counters[index] ??= 0;
counters[index] += 1;
counters[index] = (counters[index] ?? 0) + 1;
return SizedBox(
key: ValueKey<int>(index),
width: 200,