@@ -96,6 +96,113 @@ void main() {
9696 expect (scope.hasFocus, isTrue);
9797 });
9898
99+ testWidgetsWithLeakTracking ('focus traversal should work case 1' , (WidgetTester tester) async {
100+ final FocusNode outer1 = FocusNode (debugLabel: 'outer1' , skipTraversal: true );
101+ final FocusNode outer2 = FocusNode (debugLabel: 'outer2' , skipTraversal: true );
102+ final FocusNode inner1 = FocusNode (debugLabel: 'inner1' , );
103+ final FocusNode inner2 = FocusNode (debugLabel: 'inner2' , );
104+ addTearDown (() {
105+ outer1.dispose ();
106+ outer2.dispose ();
107+ inner1.dispose ();
108+ inner2.dispose ();
109+ });
110+
111+ await tester.pumpWidget (
112+ Directionality (
113+ textDirection: TextDirection .ltr,
114+ child: FocusTraversalGroup (
115+ child: Row (
116+ children: < Widget > [
117+ FocusScope (
118+ child: Focus (
119+ focusNode: outer1,
120+ child: Focus (
121+ focusNode: inner1,
122+ child: const SizedBox (width: 10 , height: 10 ),
123+ ),
124+ ),
125+ ),
126+ FocusScope (
127+ child: Focus (
128+ focusNode: outer2,
129+ // Add a padding to ensure both Focus widgets have different
130+ // sizes.
131+ child: Padding (
132+ padding: const EdgeInsets .all (5 ),
133+ child: Focus (
134+ focusNode: inner2,
135+ child: const SizedBox (width: 10 , height: 10 ),
136+ ),
137+ ),
138+ ),
139+ ),
140+ ],
141+ ),
142+ ),
143+ ),
144+ );
145+
146+ expect (FocusManager .instance.primaryFocus, isNull);
147+ inner1.requestFocus ();
148+ await tester.pump ();
149+ expect (FocusManager .instance.primaryFocus, inner1);
150+ outer2.nextFocus ();
151+ await tester.pump ();
152+ expect (FocusManager .instance.primaryFocus, inner2);
153+ });
154+
155+ testWidgetsWithLeakTracking ('focus traversal should work case 2' , (WidgetTester tester) async {
156+ final FocusNode outer1 = FocusNode (debugLabel: 'outer1' , skipTraversal: true );
157+ final FocusNode outer2 = FocusNode (debugLabel: 'outer2' , skipTraversal: true );
158+ final FocusNode inner1 = FocusNode (debugLabel: 'inner1' , );
159+ final FocusNode inner2 = FocusNode (debugLabel: 'inner2' , );
160+ addTearDown (() {
161+ outer1.dispose ();
162+ outer2.dispose ();
163+ inner1.dispose ();
164+ inner2.dispose ();
165+ });
166+
167+ await tester.pumpWidget (
168+ Directionality (
169+ textDirection: TextDirection .ltr,
170+ child: FocusTraversalGroup (
171+ child: Row (
172+ children: < Widget > [
173+ FocusScope (
174+ child: Focus (
175+ focusNode: outer1,
176+ child: Focus (
177+ focusNode: inner1,
178+ child: const SizedBox (width: 10 , height: 10 ),
179+ ),
180+ ),
181+ ),
182+ FocusScope (
183+ child: Focus (
184+ focusNode: outer2,
185+ child: Focus (
186+ focusNode: inner2,
187+ child: const SizedBox (width: 10 , height: 10 ),
188+ ),
189+ ),
190+ ),
191+ ],
192+ ),
193+ ),
194+ ),
195+ );
196+
197+ expect (FocusManager .instance.primaryFocus, isNull);
198+ inner1.requestFocus ();
199+ await tester.pump ();
200+ expect (FocusManager .instance.primaryFocus, inner1);
201+ outer2.nextFocus ();
202+ await tester.pump ();
203+ expect (FocusManager .instance.primaryFocus, inner2);
204+ });
205+
99206 testWidgetsWithLeakTracking ('Move focus to next node.' , (WidgetTester tester) async {
100207 final GlobalKey key1 = GlobalKey (debugLabel: '1' );
101208 final GlobalKey key2 = GlobalKey (debugLabel: '2' );
@@ -716,8 +823,13 @@ void main() {
716823 final bool didFindNode = node1.nextFocus ();
717824 await tester.pump ();
718825 expect (didFindNode, isTrue);
719- expect (node1.hasPrimaryFocus, isFalse);
720- expect (node2.hasPrimaryFocus, isTrue);
826+ if (canRequestFocus) {
827+ expect (node1.hasPrimaryFocus, isTrue);
828+ expect (node2.hasPrimaryFocus, isFalse);
829+ } else {
830+ expect (node1.hasPrimaryFocus, isFalse);
831+ expect (node2.hasPrimaryFocus, isTrue);
832+ }
721833 }
722834 });
723835
0 commit comments