// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui';

import 'package:flutter/painting.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

import 'semantics_tester.dart';

/// Used to test removal of nodes while sorting.
class SkipAllButFirstAndLastPolicy extends FocusTraversalPolicy with DirectionalFocusTraversalPolicyMixin {
  @override
  Iterable<FocusNode> sortDescendants(Iterable<FocusNode> descendants, FocusNode currentNode) {
    return <FocusNode>[
      descendants.first,
      if (currentNode != descendants.first && currentNode != descendants.last) currentNode,
      descendants.last,
    ];
  }
}

void main() {
  group(WidgetOrderTraversalPolicy, () {
    testWidgets('Find the initial focus if there is none yet.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      final GlobalKey key4 = GlobalKey(debugLabel: '4');
      final GlobalKey key5 = GlobalKey(debugLabel: '5');
      await tester.pumpWidget(FocusTraversalGroup(
        policy: WidgetOrderTraversalPolicy(),
        child: FocusScope(
          key: key1,
          child: Column(
            children: <Widget>[
              Focus(
                key: key2,
                child: Container(key: key3, width: 100, height: 100),
              ),
              Focus(
                key: key4,
                child: Container(key: key5, width: 100, height: 100),
              ),
            ],
          ),
        ),
      ));

      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!;
      secondFocusNode.nextFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Find the initial focus if there is none yet and traversing backwards.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      final GlobalKey key4 = GlobalKey(debugLabel: '4');
      final GlobalKey key5 = GlobalKey(debugLabel: '5');
      await tester.pumpWidget(FocusTraversalGroup(
        policy: WidgetOrderTraversalPolicy(),
        child: FocusScope(
          key: key1,
          child: Column(
            children: <Widget>[
              Focus(
                key: key2,
                child: Container(key: key3, width: 100, height: 100),
              ),
              Focus(
                key: key4,
                child: Container(key: key5, width: 100, height: 100),
              ),
            ],
          ),
        ),
      ));

      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!;

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isFalse);

      secondFocusNode.previousFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Move focus to next node.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      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;
      await tester.pumpWidget(
        FocusTraversalGroup(
          policy: WidgetOrderTraversalPolicy(),
          child: FocusScope(
            debugLabel: 'key1',
            key: key1,
            onFocusChange: (bool focus) => focus1 = focus,
            child: Column(
              children: <Widget>[
                FocusScope(
                  debugLabel: 'key2',
                  key: key2,
                  onFocusChange: (bool focus) => focus2 = focus,
                  child: Column(
                    children: <Widget>[
                      Focus(
                        debugLabel: 'key3',
                        key: key3,
                        onFocusChange: (bool focus) => focus3 = focus,
                        child: Container(key: key4),
                      ),
                      Focus(
                        debugLabel: 'key5',
                        key: key5,
                        onFocusChange: (bool focus) => focus5 = focus,
                        child: Container(key: key6),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );

      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!;
      firstFocusNode.requestFocus();

      await tester.pump();

      expect(focus1, isTrue);
      expect(focus2, isTrue);
      expect(focus3, isTrue);
      expect(focus5, isNull);
      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);

      focus1 = null;
      focus2 = null;
      focus3 = null;
      focus5 = null;

      Focus.of(firstChild)!.nextFocus();

      await tester.pump();

      expect(focus1, isNull);
      expect(focus2, isNull);
      expect(focus3, isFalse);
      expect(focus5, isTrue);
      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      focus1 = null;
      focus2 = null;
      focus3 = null;
      focus5 = null;

      Focus.of(firstChild)!.nextFocus();

      await tester.pump();

      expect(focus1, isNull);
      expect(focus2, isNull);
      expect(focus3, isTrue);
      expect(focus5, isFalse);
      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);

      focus1 = null;
      focus2 = null;
      focus3 = null;
      focus5 = null;

      // Tests that can still move back to original node.
      Focus.of(firstChild)!.previousFocus();

      await tester.pump();

      expect(focus1, isNull);
      expect(focus2, isNull);
      expect(focus3, isFalse);
      expect(focus5, isTrue);
      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Move focus to previous node.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      final GlobalKey key4 = GlobalKey(debugLabel: '4');
      final GlobalKey key5 = GlobalKey(debugLabel: '5');
      final GlobalKey key6 = GlobalKey(debugLabel: '6');
      await tester.pumpWidget(
        FocusTraversalGroup(
          policy: WidgetOrderTraversalPolicy(),
          child: FocusScope(
            key: key1,
            child: Column(
              children: <Widget>[
                FocusScope(
                  key: key2,
                  child: Column(
                    children: <Widget>[
                      Focus(
                        key: key3,
                        child: Container(key: key4),
                      ),
                      Focus(
                        key: key5,
                        child: Container(key: key6),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );

      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!;
      secondFocusNode.requestFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      Focus.of(firstChild)!.previousFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);

      Focus.of(firstChild)!.previousFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      // Tests that can still move back to original node.
      Focus.of(firstChild)!.nextFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Move focus to next/previous node while skipping nodes in policy', (WidgetTester tester) async {
      final List<FocusNode> nodes =
      List<FocusNode>.generate(7, (int index) => FocusNode(debugLabel: 'Node $index'));
      await tester.pumpWidget(
        FocusTraversalGroup(
          policy: SkipAllButFirstAndLastPolicy(),
          child: Column(
            children: List<Widget>.generate(
              nodes.length,
              (int index) => Focus(
                focusNode: nodes[index],
                child: const SizedBox(),
              ),
            ),
          ),
        ),
      );

      nodes[2].requestFocus();
      await tester.pump();

      expect(nodes[2].hasPrimaryFocus, isTrue);

      primaryFocus!.nextFocus();
      await tester.pump();

      expect(nodes[6].hasPrimaryFocus, isTrue);

      primaryFocus!.previousFocus();
      await tester.pump();

      expect(nodes[0].hasPrimaryFocus, isTrue);
    });

    testWidgets('Find the initial focus when a route is pushed or popped.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final FocusNode testNode1 = FocusNode(debugLabel: 'First Focus Node');
      final FocusNode testNode2 = FocusNode(debugLabel: 'Second Focus Node');
      await tester.pumpWidget(
        MaterialApp(
          home: FocusTraversalGroup(
            policy: WidgetOrderTraversalPolicy(),
            child: Center(
              child: Builder(builder: (BuildContext context) {
                return MaterialButton(
                  key: key1,
                  focusNode: testNode1,
                  autofocus: true,
                  onPressed: () {
                    Navigator.of(context)!.push<void>(
                      MaterialPageRoute<void>(
                        builder: (BuildContext context) {
                          return Center(
                            child: MaterialButton(
                              key: key2,
                              focusNode: testNode2,
                              autofocus: true,
                              onPressed: () {
                                Navigator.of(context)!.pop();
                              },
                              child: const Text('Go Back'),
                            ),
                          );
                        },
                      ),
                    );
                  },
                  child: const Text('Go Forward'),
                );
              }),
            ),
          ),
        ),
      );

      final Element firstChild = tester.element(find.text('Go Forward'));
      final FocusNode firstFocusNode = Focus.of(firstChild)!;
      final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      await tester.tap(find.text('Go Forward'));
      await tester.pumpAndSettle();

      final Element secondChild = tester.element(find.text('Go Back'));
      final FocusNode secondFocusNode = Focus.of(secondChild)!;

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);

      await tester.tap(find.text('Go Back'));
      await tester.pumpAndSettle();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
    });
  });

  group(ReadingOrderTraversalPolicy, () {
    testWidgets('Find the initial focus if there is none yet.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      final GlobalKey key4 = GlobalKey(debugLabel: '4');
      final GlobalKey key5 = GlobalKey(debugLabel: '5');
      await tester.pumpWidget(FocusTraversalGroup(
        policy: ReadingOrderTraversalPolicy(),
        child: FocusScope(
          key: key1,
          child: Column(
            children: <Widget>[
              Focus(
                key: key2,
                child: Container(key: key3, width: 100, height: 100),
              ),
              Focus(
                key: key4,
                child: Container(key: key5, width: 100, height: 100),
              ),
            ],
          ),
        ),
      ));

      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!;
      secondFocusNode.nextFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Move reading focus to next node.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      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;
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: ReadingOrderTraversalPolicy(),
            child: FocusScope(
              debugLabel: 'key1',
              key: key1,
              onFocusChange: (bool focus) => focus1 = focus,
              child: Column(
                children: <Widget>[
                  FocusScope(
                    debugLabel: 'key2',
                    key: key2,
                    onFocusChange: (bool focus) => focus2 = focus,
                    child: Row(
                      children: <Widget>[
                        Focus(
                          debugLabel: 'key3',
                          key: key3,
                          onFocusChange: (bool focus) => focus3 = focus,
                          child: Container(key: key4),
                        ),
                        Focus(
                          debugLabel: 'key5',
                          key: key5,
                          onFocusChange: (bool focus) => focus5 = focus,
                          child: Container(key: key6),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      );

      void clear() {
        focus1 = null;
        focus2 = null;
        focus3 = null;
        focus5 = null;
      }

      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!;
      firstFocusNode.requestFocus();

      await tester.pump();

      expect(focus1, isTrue);
      expect(focus2, isTrue);
      expect(focus3, isTrue);
      expect(focus5, isNull);
      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
      clear();

      Focus.of(firstChild)!.nextFocus();

      await tester.pump();

      expect(focus1, isNull);
      expect(focus2, isNull);
      expect(focus3, isFalse);
      expect(focus5, isTrue);
      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
      clear();

      Focus.of(firstChild)!.nextFocus();

      await tester.pump();

      expect(focus1, isNull);
      expect(focus2, isNull);
      expect(focus3, isTrue);
      expect(focus5, isFalse);
      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
      clear();

      // Tests that can still move back to original node.
      Focus.of(firstChild)!.previousFocus();

      await tester.pump();

      expect(focus1, isNull);
      expect(focus2, isNull);
      expect(focus3, isFalse);
      expect(focus5, isTrue);
      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Move reading focus to previous node.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final GlobalKey key3 = GlobalKey(debugLabel: '3');
      final GlobalKey key4 = GlobalKey(debugLabel: '4');
      final GlobalKey key5 = GlobalKey(debugLabel: '5');
      final GlobalKey key6 = GlobalKey(debugLabel: '6');
      await tester.pumpWidget(
        FocusTraversalGroup(
          policy: ReadingOrderTraversalPolicy(),
          child: FocusScope(
            key: key1,
            child: Column(
              children: <Widget>[
                FocusScope(
                  key: key2,
                  child: Column(
                    children: <Widget>[
                      Focus(
                        key: key3,
                        child: Container(key: key4),
                      ),
                      Focus(
                        key: key5,
                        child: Container(key: key6),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );

      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!;
      secondFocusNode.requestFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      Focus.of(firstChild)!.previousFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);

      Focus.of(firstChild)!.previousFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      // Tests that can still move back to original node.
      Focus.of(firstChild)!.nextFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(secondFocusNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Focus order is correct in the presence of different directionalities.', (WidgetTester tester) async {
      const int nodeCount = 10;
      final FocusScopeNode scopeNode = FocusScopeNode();
      final List<FocusNode> nodes = List<FocusNode>.generate(nodeCount, (int index) => FocusNode(debugLabel: 'Node $index'));
      Widget buildTest(TextDirection topDirection) {
        return Directionality(
          textDirection: topDirection,
          child: FocusTraversalGroup(
            policy: ReadingOrderTraversalPolicy(),
            child: FocusScope(
              node: scopeNode,
              child: Column(
                children: <Widget>[
                  Directionality(
                    textDirection: TextDirection.ltr,
                    child: Row(children: <Widget>[
                      Focus(
                        focusNode: nodes[0],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                      Focus(
                        focusNode: nodes[1],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                      Focus(
                        focusNode: nodes[2],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                    ]),
                  ),
                  Directionality(
                    textDirection: TextDirection.ltr,
                    child: Row(children: <Widget>[
                      Directionality(
                        textDirection: TextDirection.rtl,
                        child: Focus(
                          focusNode: nodes[3],
                          child: const SizedBox(width: 10, height: 10),
                        ),
                      ),
                      Directionality(
                        textDirection: TextDirection.rtl,
                        child: Focus(
                          focusNode: nodes[4],
                          child: const SizedBox(width: 10, height: 10),
                        ),
                      ),
                      Directionality(
                        textDirection: TextDirection.ltr,
                        child: Focus(
                          focusNode: nodes[5],
                          child: const SizedBox(width: 10, height: 10),
                        ),
                      ),
                    ]),
                  ),
                  Row(children: <Widget>[
                    Directionality(
                      textDirection: TextDirection.ltr,
                      child: Focus(
                        focusNode: nodes[6],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                    ),
                    Directionality(
                      textDirection: TextDirection.rtl,
                      child: Focus(
                        focusNode: nodes[7],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                    ),
                    Directionality(
                      textDirection: TextDirection.rtl,
                      child: Focus(
                        focusNode: nodes[8],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                    ),
                    Directionality(
                      textDirection: TextDirection.ltr,
                      child: Focus(
                        focusNode: nodes[9],
                        child: const SizedBox(width: 10, height: 10),
                      ),
                    ),
                  ]),
                ],
              ),
            ),
          ),
        );
      }
      await tester.pumpWidget(buildTest(TextDirection.rtl));

      // The last four *are* correct: the Row is sensitive to the directionality
      // too, so it swaps the positions of 7 and 8.
      final List<int> order = <int>[];
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        order.add(nodes.indexOf(primaryFocus!));
      }
      expect(order, orderedEquals(<int>[0, 1, 2, 4, 3, 5, 6, 7, 8, 9]));

      await tester.pumpWidget(buildTest(TextDirection.ltr));

      order.clear();
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        order.add(nodes.indexOf(primaryFocus!));
      }
      expect(order, orderedEquals(<int>[0, 1, 2, 4, 3, 5, 6, 8, 7, 9]));
    });

    testWidgets('Focus order is reading order regardless of widget order, even when overlapping.', (WidgetTester tester) async {
      const int nodeCount = 10;
      final List<FocusNode> nodes = List<FocusNode>.generate(nodeCount, (int index) => FocusNode(debugLabel: 'Node $index'));
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.rtl,
          child: FocusTraversalGroup(
            policy: ReadingOrderTraversalPolicy(),
            child: Stack(
              alignment: const Alignment(-1, -1),
              children: List<Widget>.generate(nodeCount, (int index) {
                // Boxes that all have the same upper left origin corner.
                return Focus(
                  focusNode: nodes[index],
                  child: SizedBox(width: 10.0 * (index + 1), height: 10.0 * (index + 1)),
                );
              }),
            ),
          ),
        ),
      );

      final List<int> order = <int>[];
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        order.add(nodes.indexOf(primaryFocus!));
      }
      expect(order, orderedEquals(<int>[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]));

      // Concentric boxes.
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.rtl,
          child: FocusTraversalGroup(
            policy: ReadingOrderTraversalPolicy(),
            child: Stack(
              alignment: const Alignment(0, 0),
              children: List<Widget>.generate(nodeCount, (int index) {
                return Focus(
                  focusNode: nodes[index],
                  child: SizedBox(width: 10.0 * (index + 1), height: 10.0 * (index + 1)),
                );
              }),
            ),
          ),
        ),
      );

      order.clear();
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        order.add(nodes.indexOf(primaryFocus!));
      }
      expect(order, orderedEquals(<int>[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]));

      // Stacked (vertically) and centered (horizontally, on each other)
      // widgets, not overlapping.
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.rtl,
          child: FocusTraversalGroup(
            policy: ReadingOrderTraversalPolicy(),
            child: Stack(
              alignment: const Alignment(0, 0),
              children: List<Widget>.generate(nodeCount, (int index) {
                return Positioned(
                  top: 5.0 * index * (index + 1),
                  left: 5.0 * (9 - index),
                  child: Focus(
                    focusNode: nodes[index],
                    child: Container(
                      decoration: BoxDecoration(border: Border.all()),
                      width: 10.0 * (index + 1),
                      height: 10.0 * (index + 1),
                    ),
                  ),
                );
              }),
            ),
          ),
        ),
      );

      order.clear();
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        order.add(nodes.indexOf(primaryFocus!));
      }
      expect(order, orderedEquals(<int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]));
    });
  });

  group(OrderedTraversalPolicy, () {
    testWidgets('Find the initial focus if there is none yet.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      await tester.pumpWidget(FocusTraversalGroup(
        policy: OrderedTraversalPolicy(secondary: ReadingOrderTraversalPolicy()),
        child: FocusScope(
          child: Column(
            children: <Widget>[
              FocusTraversalOrder(
                order: const NumericFocusOrder(2),
                child: Focus(
                  child: Container(key: key1, width: 100, height: 100),
                ),
              ),
              FocusTraversalOrder(
                order: const NumericFocusOrder(1),
                child: Focus(
                  child: Container(key: key2, width: 100, height: 100),
                ),
              ),
            ],
          ),
        ),
      ));

      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!;
      secondFocusNode.nextFocus();

      await tester.pump();

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Fall back to the secondary sort if no FocusTraversalOrder exists.', (WidgetTester tester) async {
      const int nodeCount = 10;
      final List<FocusNode> nodes = List<FocusNode>.generate(nodeCount, (int index) => FocusNode(debugLabel: 'Node $index'));
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.rtl,
          child: FocusTraversalGroup(
            policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
            child: FocusScope(
              child: Row(
                children: List<Widget>.generate(
                  nodeCount,
                  (int index) => Focus(
                    focusNode: nodes[index],
                    child: const SizedBox(width: 10, height: 10),
                  ),
                ),
              ),
            ),
          ),
        ),
      );

      // Because it should be using widget order, this shouldn't be affected by
      // the directionality.
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        expect(nodes[i].hasPrimaryFocus, isTrue, reason: "node $i doesn't have focus, but should");
      }

      // Now check backwards.
      for (int i = nodeCount - 1; i > 0; --i) {
        nodes.first.previousFocus();
        await tester.pump();
        expect(nodes[i - 1].hasPrimaryFocus, isTrue, reason: "node ${i - 1} doesn't have focus, but should");
      }
    });

    testWidgets('Move focus to next/previous node using numerical order.', (WidgetTester tester) async {
      const int nodeCount = 10;
      final List<FocusNode> nodes = List<FocusNode>.generate(nodeCount, (int index) => FocusNode(debugLabel: 'Node $index'));
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
            child: FocusScope(
              child: Row(
                children: List<Widget>.generate(
                  nodeCount,
                  (int index) => FocusTraversalOrder(
                    order: NumericFocusOrder(nodeCount - index.toDouble()),
                    child: Focus(
                      focusNode: nodes[index],
                      child: const SizedBox(width: 10, height: 10),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      );

      // The orders are assigned to be backwards from normal, so should go backwards.
      for (int i = nodeCount - 1; i >= 0; --i) {
        nodes.first.nextFocus();
        await tester.pump();
        expect(nodes[i].hasPrimaryFocus, isTrue, reason: "node $i doesn't have focus, but should");
      }

      // Now check backwards.
      for (int i = 1; i < nodeCount; ++i) {
        nodes.first.previousFocus();
        await tester.pump();
        expect(nodes[i].hasPrimaryFocus, isTrue, reason: "node $i doesn't have focus, but should");
      }
    });

    testWidgets('Move focus to next/previous node using lexical order.', (WidgetTester tester) async {
      const int nodeCount = 10;

      /// Generate ['J' ... 'A'];
      final List<String> keys = List<String>.generate(nodeCount, (int index) => String.fromCharCode('A'.codeUnits[0] + nodeCount - index - 1));
      final List<FocusNode> nodes = List<FocusNode>.generate(nodeCount, (int index) => FocusNode(debugLabel: 'Node ${keys[index]}'));
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
            child: FocusScope(
              child: Row(
                children: List<Widget>.generate(
                  nodeCount,
                  (int index) => FocusTraversalOrder(
                    order: LexicalFocusOrder(keys[index]),
                    child: Focus(
                      focusNode: nodes[index],
                      child: const SizedBox(width: 10, height: 10),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      );

      // The orders are assigned to be backwards from normal, so should go backwards.
      for (int i = nodeCount - 1; i >= 0; --i) {
        nodes.first.nextFocus();
        await tester.pump();
        expect(nodes[i].hasPrimaryFocus, isTrue, reason: "node $i doesn't have focus, but should");
      }

      // Now check backwards.
      for (int i = 1; i < nodeCount; ++i) {
        nodes.first.previousFocus();
        await tester.pump();
        expect(nodes[i].hasPrimaryFocus, isTrue, reason: "node $i doesn't have focus, but should");
      }
    });

    testWidgets('Focus order is correct in the presence of FocusTraversalPolicyGroups.', (WidgetTester tester) async {
      const int nodeCount = 10;
      final FocusScopeNode scopeNode = FocusScopeNode();
      final List<FocusNode> nodes = List<FocusNode>.generate(nodeCount, (int index) => FocusNode(debugLabel: 'Node $index'));
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: WidgetOrderTraversalPolicy(),
            child: FocusScope(
              node: scopeNode,
              child: FocusTraversalGroup(
                policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
                child: Row(
                  children: <Widget>[
                    FocusTraversalOrder(
                      order: const NumericFocusOrder(0),
                      child: FocusTraversalGroup(
                        policy: WidgetOrderTraversalPolicy(),
                        child: Row(children: <Widget>[
                          FocusTraversalOrder(
                            order: const NumericFocusOrder(9),
                            child: Focus(
                              focusNode: nodes[9],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const NumericFocusOrder(8),
                            child: Focus(
                              focusNode: nodes[8],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const NumericFocusOrder(7),
                            child: Focus(
                              focusNode: nodes[7],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                        ]),
                      ),
                    ),
                    FocusTraversalOrder(
                      order: const NumericFocusOrder(1),
                      child: FocusTraversalGroup(
                        policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
                        child: Row(children: <Widget>[
                          FocusTraversalOrder(
                            order: const NumericFocusOrder(4),
                            child: Focus(
                              focusNode: nodes[4],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const NumericFocusOrder(5),
                            child: Focus(
                              focusNode: nodes[5],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const NumericFocusOrder(6),
                            child: Focus(
                              focusNode: nodes[6],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                        ]),
                      ),
                    ),
                    FocusTraversalOrder(
                      order: const NumericFocusOrder(2),
                      child: FocusTraversalGroup(
                        policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
                        child: Row(children: <Widget>[
                          FocusTraversalOrder(
                            order: const LexicalFocusOrder('D'),
                            child: Focus(
                              focusNode: nodes[3],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const LexicalFocusOrder('C'),
                            child: Focus(
                              focusNode: nodes[2],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const LexicalFocusOrder('B'),
                            child: Focus(
                              focusNode: nodes[1],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                          FocusTraversalOrder(
                            order: const LexicalFocusOrder('A'),
                            child: Focus(
                              focusNode: nodes[0],
                              child: const SizedBox(width: 10, height: 10),
                            ),
                          ),
                        ]),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      );

      final List<int> expectedOrder = <int>[9, 8, 7, 4, 5, 6, 0, 1, 2, 3];
      final List<int> order = <int>[];
      for (int i = 0; i < nodeCount; ++i) {
        nodes.first.nextFocus();
        await tester.pump();
        order.add(nodes.indexOf(primaryFocus!));
      }
      expect(order, orderedEquals(expectedOrder));
    });

    testWidgets('Find the initial focus when a route is pushed or popped.', (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final FocusNode testNode1 = FocusNode(debugLabel: 'First Focus Node');
      final FocusNode testNode2 = FocusNode(debugLabel: 'Second Focus Node');
      await tester.pumpWidget(
        MaterialApp(
          home: FocusTraversalGroup(
            policy: OrderedTraversalPolicy(secondary: WidgetOrderTraversalPolicy()),
            child: Center(
              child: Builder(builder: (BuildContext context) {
                return FocusTraversalOrder(
                  order: const NumericFocusOrder(0),
                  child: MaterialButton(
                    key: key1,
                    focusNode: testNode1,
                    autofocus: true,
                    onPressed: () {
                      Navigator.of(context)!.push<void>(
                        MaterialPageRoute<void>(
                          builder: (BuildContext context) {
                            return Center(
                              child: FocusTraversalOrder(
                                order: const NumericFocusOrder(0),
                                child: MaterialButton(
                                  key: key2,
                                  focusNode: testNode2,
                                  autofocus: true,
                                  onPressed: () {
                                    Navigator.of(context)!.pop();
                                  },
                                  child: const Text('Go Back'),
                                ),
                              ),
                            );
                          },
                        ),
                      );
                    },
                    child: const Text('Go Forward'),
                  ),
                );
              }),
            ),
          ),
        ),
      );

      final Element firstChild = tester.element(find.text('Go Forward'));
      final FocusNode firstFocusNode = Focus.of(firstChild)!;
      final FocusNode scope = Focus.of(firstChild)!.enclosingScope!;
      await tester.pump();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);

      await tester.tap(find.text('Go Forward'));
      await tester.pumpAndSettle();

      final Element secondChild = tester.element(find.text('Go Back'));
      final FocusNode secondFocusNode = Focus.of(secondChild)!;

      expect(firstFocusNode.hasFocus, isFalse);
      expect(secondFocusNode.hasFocus, isTrue);

      await tester.tap(find.text('Go Back'));
      await tester.pumpAndSettle();

      expect(firstFocusNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
    });
  });

  group(DirectionalFocusTraversalPolicyMixin, () {
    testWidgets('Move focus in all directions.', (WidgetTester tester) async {
      final GlobalKey upperLeftKey = GlobalKey(debugLabel: 'upperLeftKey');
      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;
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: WidgetOrderTraversalPolicy(),
            child: FocusScope(
              debugLabel: 'Scope',
              child: Column(
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      Focus(
                        debugLabel: 'upperLeft',
                        onFocusChange: (bool focus) => focusUpperLeft = focus,
                        child: Container(width: 100, height: 100, key: upperLeftKey),
                      ),
                      Focus(
                        debugLabel: 'upperRight',
                        onFocusChange: (bool focus) => focusUpperRight = focus,
                        child: Container(width: 100, height: 100, key: upperRightKey),
                      ),
                    ],
                  ),
                  Row(
                    children: <Widget>[
                      Focus(
                        debugLabel: 'lowerLeft',
                        onFocusChange: (bool focus) => focusLowerLeft = focus,
                        child: Container(width: 100, height: 100, key: lowerLeftKey),
                      ),
                      Focus(
                        debugLabel: 'lowerRight',
                        onFocusChange: (bool focus) => focusLowerRight = focus,
                        child: Container(width: 100, height: 100, key: lowerRightKey),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      );

      void clear() {
        focusUpperLeft = null;
        focusUpperRight = null;
        focusLowerLeft = null;
        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!;
      upperLeftNode.requestFocus();

      await tester.pump();

      expect(focusUpperLeft, isTrue);
      expect(focusUpperRight, isNull);
      expect(focusLowerLeft, isNull);
      expect(focusLowerRight, isNull);
      expect(upperLeftNode.hasFocus, isTrue);
      expect(upperRightNode.hasFocus, isFalse);
      expect(lowerLeftNode.hasFocus, isFalse);
      expect(lowerRightNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
      clear();

      expect(scope.focusInDirection(TraversalDirection.right), isTrue);

      await tester.pump();

      expect(focusUpperLeft, isFalse);
      expect(focusUpperRight, isTrue);
      expect(focusLowerLeft, isNull);
      expect(focusLowerRight, isNull);
      expect(upperLeftNode.hasFocus, isFalse);
      expect(upperRightNode.hasFocus, isTrue);
      expect(lowerLeftNode.hasFocus, isFalse);
      expect(lowerRightNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
      clear();

      expect(scope.focusInDirection(TraversalDirection.down), isTrue);

      await tester.pump();

      expect(focusUpperLeft, isNull);
      expect(focusUpperRight, isFalse);
      expect(focusLowerLeft, isNull);
      expect(focusLowerRight, isTrue);
      expect(upperLeftNode.hasFocus, isFalse);
      expect(upperRightNode.hasFocus, isFalse);
      expect(lowerLeftNode.hasFocus, isFalse);
      expect(lowerRightNode.hasFocus, isTrue);
      expect(scope.hasFocus, isTrue);
      clear();

      expect(scope.focusInDirection(TraversalDirection.left), isTrue);

      await tester.pump();

      expect(focusUpperLeft, isNull);
      expect(focusUpperRight, isNull);
      expect(focusLowerLeft, isTrue);
      expect(focusLowerRight, isFalse);
      expect(upperLeftNode.hasFocus, isFalse);
      expect(upperRightNode.hasFocus, isFalse);
      expect(lowerLeftNode.hasFocus, isTrue);
      expect(lowerRightNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
      clear();

      expect(scope.focusInDirection(TraversalDirection.up), isTrue);

      await tester.pump();

      expect(focusUpperLeft, isTrue);
      expect(focusUpperRight, isNull);
      expect(focusLowerLeft, isFalse);
      expect(focusLowerRight, isNull);
      expect(upperLeftNode.hasFocus, isTrue);
      expect(upperRightNode.hasFocus, isFalse);
      expect(lowerLeftNode.hasFocus, isFalse);
      expect(lowerRightNode.hasFocus, isFalse);
      expect(scope.hasFocus, isTrue);
    });

    testWidgets('Directional focus avoids hysteresis.', (WidgetTester tester) async {
      final List<GlobalKey> keys = <GlobalKey>[
        GlobalKey(debugLabel: 'row 1:1'),
        GlobalKey(debugLabel: 'row 2:1'),
        GlobalKey(debugLabel: 'row 2:2'),
        GlobalKey(debugLabel: 'row 3:1'),
        GlobalKey(debugLabel: 'row 3:2'),
        GlobalKey(debugLabel: 'row 3:3'),
      ];
      List<bool?> focus = List<bool?>.generate(keys.length, (int _) => null);
      Focus makeFocus(int index) {
        return Focus(
          debugLabel: keys[index].toString(),
          onFocusChange: (bool isFocused) => focus[index] = isFocused,
          child: Container(width: 100, height: 100, key: keys[index]),
        );
      }

      /// Layout is:
      ///           keys[0]
      ///       keys[1] keys[2]
      ///    keys[3] keys[4] keys[5]
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: WidgetOrderTraversalPolicy(),
            child: FocusScope(
              debugLabel: 'Scope',
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      makeFocus(0),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      makeFocus(1),
                      makeFocus(2),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      makeFocus(3),
                      makeFocus(4),
                      makeFocus(5),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      );

      void clear() {
        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!;
      nodes[4].requestFocus();

      void expectState(List<bool?> states) {
        for (int index = 0; index < states.length; ++index) {
          expect(focus[index], states[index] == null ? isNull : (states[index]! ? isTrue : isFalse));
          if (states[index] == null) {
            expect(nodes[index].hasFocus, isFalse);
          } else {
            expect(nodes[index].hasFocus, states[index]);
          }
          expect(scope.hasFocus, isTrue);
        }
      }

      // Test to make sure that the same path is followed backwards and forwards.
      await tester.pump();
      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]);
      clear();

      expect(scope.focusInDirection(TraversalDirection.up), isTrue);
      await tester.pump();

      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]);
      clear();

      expect(scope.focusInDirection(TraversalDirection.down), isTrue);
      await tester.pump();
      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]);
      clear();

      expect(scope.focusInDirection(TraversalDirection.up), isTrue);
      await tester.pump();

      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]);
      clear();

      expect(scope.focusInDirection(TraversalDirection.down), isTrue);
      await tester.pump();

      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]);
      clear();
    });

    testWidgets('Can find first focus in all directions.', (WidgetTester tester) async {
      final GlobalKey upperLeftKey = GlobalKey(debugLabel: 'upperLeftKey');
      final GlobalKey upperRightKey = GlobalKey(debugLabel: 'upperRightKey');
      final GlobalKey lowerLeftKey = GlobalKey(debugLabel: 'lowerLeftKey');

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: FocusTraversalGroup(
            policy: WidgetOrderTraversalPolicy(),
            child: FocusScope(
              debugLabel: 'scope',
              child: Column(
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      Focus(
                        debugLabel: 'upperLeft',
                        child: Container(width: 100, height: 100, key: upperLeftKey),
                      ),
                      Focus(
                        debugLabel: 'upperRight',
                        child: Container(width: 100, height: 100, key: upperRightKey),
                      ),
                    ],
                  ),
                  Row(
                    children: <Widget>[
                      Focus(
                        debugLabel: 'lowerLeft',
                        child: Container(width: 100, height: 100, key: lowerLeftKey),
                      ),
                      const Focus(
                        debugLabel: 'lowerRight',
                        child: SizedBox(width: 100, height: 100),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      );

      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!)!;

      expect(policy.findFirstFocusInDirection(scope, TraversalDirection.up), equals(lowerLeftNode));
      expect(policy.findFirstFocusInDirection(scope, TraversalDirection.down), equals(upperLeftNode));
      expect(policy.findFirstFocusInDirection(scope, TraversalDirection.left), equals(upperRightNode));
      expect(policy.findFirstFocusInDirection(scope, TraversalDirection.right), equals(upperLeftNode));
    });

    testWidgets('Can find focus when policy data dirty', (WidgetTester tester) async {
      final FocusNode focusTop = FocusNode(debugLabel: 'top');
      final FocusNode focusCenter = FocusNode(debugLabel: 'center');
      final FocusNode focusBottom = FocusNode(debugLabel: 'bottom');

      final FocusTraversalPolicy policy = ReadingOrderTraversalPolicy();
      await tester.pumpWidget(FocusTraversalGroup(
        policy: policy,
        child: FocusScope(
          debugLabel: 'Scope',
          child: Column(
            children: <Widget>[
              Focus(focusNode: focusTop, child: const SizedBox(width: 100, height: 100)),
              Focus(focusNode: focusCenter, child: const SizedBox(width: 100, height: 100)),
              Focus(focusNode: focusBottom, child: const SizedBox(width: 100, height: 100)),
            ],
          ),
        ),
      ));

      focusTop.requestFocus();
      final FocusNode scope = focusTop.enclosingScope!;

      scope.focusInDirection(TraversalDirection.down);
      scope.focusInDirection(TraversalDirection.down);

      await tester.pump();
      expect(focusBottom.hasFocus, isTrue);

      // Remove center focus node.
      await tester.pumpWidget(FocusTraversalGroup(
        policy: policy,
        child: FocusScope(
          debugLabel: 'Scope',
          child: Column(
            children: <Widget>[
              Focus(focusNode: focusTop, child: const SizedBox(width: 100, height: 100)),
              Focus(focusNode: focusBottom, child: const SizedBox(width: 100, height: 100)),
            ],
          ),
        ),
      ));

      expect(focusBottom.hasFocus, isTrue);
      scope.focusInDirection(TraversalDirection.up);
      await tester.pump();

      expect(focusCenter.hasFocus, isFalse);
      expect(focusTop.hasFocus, isTrue);
    });

    testWidgets('Focus traversal actions are invoked when shortcuts are used.', (WidgetTester tester) async {
      final GlobalKey upperLeftKey = GlobalKey(debugLabel: 'upperLeftKey');
      final GlobalKey upperRightKey = GlobalKey(debugLabel: 'upperRightKey');
      final GlobalKey lowerLeftKey = GlobalKey(debugLabel: 'lowerLeftKey');
      final GlobalKey lowerRightKey = GlobalKey(debugLabel: 'lowerRightKey');

      await tester.pumpWidget(
        WidgetsApp(
          color: const Color(0xFFFFFFFF),
          onGenerateRoute: (RouteSettings settings) {
            return TestRoute(
              child: Directionality(
                textDirection: TextDirection.ltr,
                child: FocusScope(
                  debugLabel: 'scope',
                  child: Column(
                    children: <Widget>[
                      Row(
                        children: <Widget>[
                          Focus(
                            autofocus: true,
                            debugLabel: 'upperLeft',
                            child: Container(width: 100, height: 100, key: upperLeftKey),
                          ),
                          Focus(
                            debugLabel: 'upperRight',
                            child: Container(width: 100, height: 100, key: upperRightKey),
                          ),
                        ],
                      ),
                      Row(
                        children: <Widget>[
                          Focus(
                            debugLabel: 'lowerLeft',
                            child: Container(width: 100, height: 100, key: lowerLeftKey),
                          ),
                          Focus(
                            debugLabel: 'lowerRight',
                            child: Container(width: 100, height: 100, key: lowerRightKey),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
        ),
      );

      expect(Focus.of(upperLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      expect(Focus.of(upperRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      expect(Focus.of(lowerLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      expect(Focus.of(lowerRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      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);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      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);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      expect(Focus.of(upperLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);

      // Traverse in a direction
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      expect(Focus.of(upperRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      expect(Focus.of(lowerRightKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      expect(Focus.of(lowerLeftKey.currentContext!)!.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      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 {
      final List<int> items = List<int>.generate(11, (int index) => index).toList();
      final List<FocusNode> nodes = List<FocusNode>.generate(11, (int index) => FocusNode(debugLabel: 'Item ${index + 1}')).toList();
      final FocusNode topNode = FocusNode(debugLabel: 'Header');
      final FocusNode bottomNode = FocusNode(debugLabel: 'Footer');
      final ScrollController controller = ScrollController();
      await tester.pumpWidget(
        MaterialApp(
          home: Column(
            children: <Widget>[
              Focus(focusNode: topNode, child: Container(height: 100)),
              Expanded(
                child: ListView(
                  scrollDirection: Axis.vertical,
                  controller: controller,
                  children: items.map<Widget>((int item) {
                    return Focus(
                      focusNode: nodes[item],
                      child: Container(height: 100),
                    );
                  }).toList(),
                ),
              ),
              Focus(focusNode: bottomNode, child: Container(height: 100)),
            ],
          ),
        ),
      );

      // Start at the top
      expect(controller.offset, equals(0.0));
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(topNode.hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));

      // Enter the list.
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(nodes[0].hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));

      // Go down until we hit the bottom of the visible area.
      for (int i = 1; i <= 4; ++i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
        await tester.pump();
        expect(controller.offset, equals(0.0), reason: 'Focusing item $i caused a scroll');
      }

      // Now keep going down, and the scrollable should scroll automatically.
      for (int i = 5; i <= 10; ++i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
        await tester.pump();
        final double expectedOffset = 100.0 * (i - 5) + 200.0;
        expect(controller.offset, equals(expectedOffset), reason: "Focusing item $i didn't cause a scroll to $expectedOffset");
      }

      // Now go one more, and see that the footer gets focused.

      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(bottomNode.hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(100.0 * (10 - 5) + 200.0));

      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(nodes[10].hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(100.0 * (10 - 5) + 200.0));

      // Now reverse directions and go back to the top.

      // These should not cause a scroll.
      final double lowestOffset = controller.offset;
      for (int i = 10; i >= 8; --i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
        await tester.pump();
        expect(controller.offset, equals(lowestOffset), reason: 'Focusing item $i caused a scroll');
      }

      // These should all cause a scroll.
      for (int i = 7; i >= 1; --i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
        await tester.pump();
        final double expectedOffset = 100.0 * (i - 1);
        expect(controller.offset, equals(expectedOffset), reason: "Focusing item $i didn't cause a scroll");
      }

      // Back at the top.
      expect(nodes[0].hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));

      // Now we jump to the header.
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(topNode.hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));
    }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347

    testWidgets('Focus traversal inside a horizontal scrollable scrolls to stay visible.', (WidgetTester tester) async {
      final List<int> items = List<int>.generate(11, (int index) => index).toList();
      final List<FocusNode> nodes = List<FocusNode>.generate(11, (int index) => FocusNode(debugLabel: 'Item ${index + 1}')).toList();
      final FocusNode leftNode = FocusNode(debugLabel: 'Left Side');
      final FocusNode rightNode = FocusNode(debugLabel: 'Right Side');
      final ScrollController controller = ScrollController();
      await tester.pumpWidget(
        MaterialApp(
          home: Row(
            children: <Widget>[
              Focus(focusNode: leftNode, child: Container(width: 100)),
              Expanded(
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  controller: controller,
                  children: items.map<Widget>((int item) {
                    return Focus(
                      focusNode: nodes[item],
                      child: Container(width: 100),
                    );
                  }).toList(),
                ),
              ),
              Focus(focusNode: rightNode, child: Container(width: 100)),
            ],
          ),
        ),
      );

      // Start at the right
      expect(controller.offset, equals(0.0));
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.pump();
      expect(leftNode.hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));

      // Enter the list.
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.pump();
      expect(nodes[0].hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));

      // Go right until we hit the right of the visible area.
      for (int i = 1; i <= 6; ++i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
        await tester.pump();
        expect(controller.offset, equals(0.0), reason: 'Focusing item $i caused a scroll');
      }

      // Now keep going right, and the scrollable should scroll automatically.
      for (int i = 7; i <= 10; ++i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
        await tester.pump();
        final double expectedOffset = 100.0 * (i - 5);
        expect(controller.offset, equals(expectedOffset), reason: "Focusing item $i didn't cause a scroll to $expectedOffset");
      }

      // Now go one more, and see that the right edge gets focused.

      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.pump();
      expect(rightNode.hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(100.0 * 5));

      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      await tester.pump();
      expect(nodes[10].hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(100.0 * 5));

      // Now reverse directions and go back to the left.

      // These should not cause a scroll.
      final double lowestOffset = controller.offset;
      for (int i = 10; i >= 7; --i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
        await tester.pump();
        expect(controller.offset, equals(lowestOffset), reason: 'Focusing item $i caused a scroll');
      }

      // These should all cause a scroll.
      for (int i = 6; i >= 1; --i) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
        await tester.pump();
        final double expectedOffset = 100.0 * (i - 1);
        expect(controller.offset, equals(expectedOffset), reason: "Focusing item $i didn't cause a scroll");
      }

      // Back at the left side of the scrollable.
      expect(nodes[0].hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));

      // Now we jump to the left edge of the app.
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      await tester.pump();
      expect(leftNode.hasPrimaryFocus, isTrue);
      expect(controller.offset, equals(0.0));
    }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347

    testWidgets('Arrow focus traversal actions can be re-enabled for text fields.', (WidgetTester tester) async {
      final GlobalKey upperLeftKey = GlobalKey(debugLabel: 'upperLeftKey');
      final GlobalKey upperRightKey = GlobalKey(debugLabel: 'upperRightKey');
      final GlobalKey lowerLeftKey = GlobalKey(debugLabel: 'lowerLeftKey');
      final GlobalKey lowerRightKey = GlobalKey(debugLabel: 'lowerRightKey');

      final TextEditingController controller1 = TextEditingController();
      final TextEditingController controller2 = TextEditingController();
      final TextEditingController controller3 = TextEditingController();
      final TextEditingController controller4 = TextEditingController();

      final FocusNode focusNodeUpperLeft = FocusNode(debugLabel: 'upperLeft');
      final FocusNode focusNodeUpperRight = FocusNode(debugLabel: 'upperRight');
      final FocusNode focusNodeLowerLeft = FocusNode(debugLabel: 'lowerLeft');
      final FocusNode focusNodeLowerRight = FocusNode(debugLabel: 'lowerRight');

      Widget generateTestWidgets(bool ignoreTextFields) {
        final Map<LogicalKeySet, Intent> shortcuts = <LogicalKeySet, Intent>{
          LogicalKeySet(LogicalKeyboardKey.arrowLeft): DirectionalFocusIntent(TraversalDirection.left, ignoreTextFields: ignoreTextFields),
          LogicalKeySet(LogicalKeyboardKey.arrowRight): DirectionalFocusIntent(TraversalDirection.right, ignoreTextFields: ignoreTextFields),
          LogicalKeySet(LogicalKeyboardKey.arrowDown): DirectionalFocusIntent(TraversalDirection.down, ignoreTextFields: ignoreTextFields),
          LogicalKeySet(LogicalKeyboardKey.arrowUp): DirectionalFocusIntent(TraversalDirection.up, ignoreTextFields: ignoreTextFields),
        };

        return MaterialApp(
          home: Shortcuts(
            shortcuts: shortcuts,
            child: FocusScope(
              debugLabel: 'scope',
              child: Column(
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      Container(
                        width: 100,
                        height: 100,
                        child: EditableText(
                          autofocus: true,
                          key: upperLeftKey,
                          controller: controller1,
                          focusNode: focusNodeUpperLeft,
                          cursorColor: const Color(0xffffffff),
                          backgroundCursorColor: const Color(0xff808080),
                          style: const TextStyle(),
                        ),
                      ),
                      Container(
                        width: 100,
                        height: 100,
                        child: EditableText(
                          key: upperRightKey,
                          controller: controller2,
                          focusNode: focusNodeUpperRight,
                          cursorColor: const Color(0xffffffff),
                          backgroundCursorColor: const Color(0xff808080),
                          style: const TextStyle(),
                        ),
                      ),
                    ],
                  ),
                  Row(
                    children: <Widget>[
                      Container(
                        width: 100,
                        height: 100,
                        child: EditableText(
                          key: lowerLeftKey,
                          controller: controller3,
                          focusNode: focusNodeLowerLeft,
                          cursorColor: const Color(0xffffffff),
                          backgroundCursorColor: const Color(0xff808080),
                          style: const TextStyle(),
                        ),
                      ),
                      Container(
                        width: 100,
                        height: 100,
                        child: EditableText(
                          key: lowerRightKey,
                          controller: controller4,
                          focusNode: focusNodeLowerRight,
                          cursorColor: const Color(0xffffffff),
                          backgroundCursorColor: const Color(0xff808080),
                          style: const TextStyle(),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(generateTestWidgets(false));

      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      expect(focusNodeUpperRight.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      expect(focusNodeLowerRight.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      expect(focusNodeLowerLeft.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);

      await tester.pumpWidget(generateTestWidgets(true));

      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      expect(focusNodeUpperRight.hasPrimaryFocus, isFalse);
      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      expect(focusNodeLowerRight.hasPrimaryFocus, isFalse);
      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      expect(focusNodeLowerLeft.hasPrimaryFocus, isFalse);
      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      expect(focusNodeUpperLeft.hasPrimaryFocus, isTrue);
    });

    testWidgets('Focus traversal does not break when no focusable is available on a MaterialApp', (WidgetTester tester) async {
      final List<RawKeyEvent> events = <RawKeyEvent>[];

      await tester.pumpWidget(MaterialApp(home: Container()));

      RawKeyboard.instance.addListener((RawKeyEvent event) {
        events.add(event);
      });

      await tester.idle();
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.idle();

      expect(events.length, 2);
    });

    testWidgets('Focus traversal does not break when no focusable is available on a WidgetsApp', (WidgetTester tester) async {
      final List<RawKeyEvent> events = <RawKeyEvent>[];

      await tester.pumpWidget(
        WidgetsApp(
          color: Colors.white,
          onGenerateRoute: (RouteSettings settings) => PageRouteBuilder<void>(
            settings: settings,
            pageBuilder: (BuildContext context, Animation<double> animation1, Animation<double> animation2) {
              return const Placeholder();
            },
          ),
        ),
      );

      RawKeyboard.instance.addListener((RawKeyEvent event) {
        events.add(event);
      });

      await tester.idle();
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.idle();

      expect(events.length, 2);
    });
  });
  group(FocusTraversalGroup, () {
    testWidgets("Focus traversal group doesn't introduce a Semantics node", (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(FocusTraversalGroup(child: Container()));
      final TestSemantics expectedSemantics = TestSemantics.root();
      expect(semantics, hasSemantics(expectedSemantics));
    });
    testWidgets("Descendants of FocusTraversalGroup aren't focusable if descendantsAreFocusable is false.", (WidgetTester tester) async {
      final GlobalKey key1 = GlobalKey(debugLabel: '1');
      final GlobalKey key2 = GlobalKey(debugLabel: '2');
      final FocusNode focusNode = FocusNode();
      bool? gotFocus;
      await tester.pumpWidget(
        FocusTraversalGroup(
          descendantsAreFocusable: false,
          child: Focus(
            onFocusChange: (bool focused) => gotFocus = focused,
            child: Focus(
              key: key1,
              focusNode: focusNode,
              child: Container(key: key2),
            ),
          ),
        ),
      );

      final Element childWidget = tester.element(find.byKey(key1));
      final FocusNode unfocusableNode = Focus.of(childWidget)!;
      final Element containerWidget = tester.element(find.byKey(key2));
      final FocusNode containerNode = Focus.of(containerWidget)!;

      unfocusableNode.requestFocus();
      await tester.pump();

      expect(gotFocus, isNull);
      expect(containerNode.hasFocus, isFalse);
      expect(unfocusableNode.hasFocus, isFalse);

      containerNode.requestFocus();
      await tester.pump();

      expect(gotFocus, isNull);
      expect(containerNode.hasFocus, isFalse);
      expect(unfocusableNode.hasFocus, isFalse);
    });
  });
  group(RawKeyboardListener, () {
    testWidgets('Raw keyboard listener introduces a Semantics node by default', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      final FocusNode focusNode = FocusNode();
      await tester.pumpWidget(
        RawKeyboardListener(
          focusNode: focusNode,
          child: Container(),
        ),
      );
      final TestSemantics expectedSemantics = TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics.rootChild(
            flags: <SemanticsFlag>[
              SemanticsFlag.isFocusable,
            ],
          ),
        ],
      );
      expect(semantics, hasSemantics(
        expectedSemantics,
        ignoreId: true,
        ignoreRect: true,
        ignoreTransform: true,
      ));
    });
    testWidgets("Raw keyboard listener doesn't introduce a Semantics node when specified", (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      final FocusNode focusNode = FocusNode();
      await tester.pumpWidget(
          RawKeyboardListener(
              focusNode: focusNode,
              includeSemantics: false,
              child: Container(),
          ),
      );
      final TestSemantics expectedSemantics = TestSemantics.root();
      expect(semantics, hasSemantics(expectedSemantics));
    });
  });
}

class TestRoute extends PageRouteBuilder<void> {
  TestRoute({required Widget child})
      : super(
          pageBuilder: (BuildContext _, Animation<double> __, Animation<double> ___) {
            return child;
          },
        );
}
