back_button_test.dart 6.77 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('BackButton control test', (WidgetTester tester) async {
    await tester.pumpWidget(
11
      MaterialApp(
12
        home: const Material(child: Text('Home')),
13 14
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
15
            return const Material(
16 17
              child: Center(
                child: BackButton(),
18
              ),
19 20
            );
          },
21
        },
22
      ),
23 24 25 26
    );

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');

27
    await tester.pumpAndSettle();
28 29 30

    await tester.tap(find.byType(BackButton));

31
    await tester.pumpAndSettle();
32 33 34

    expect(find.text('Home'), findsOneWidget);
  });
35

36
  testWidgets('BackButton onPressed overrides default pop behavior', (WidgetTester tester) async {
37
    bool customCallbackWasCalled = false;
38 39 40 41 42 43 44
    await tester.pumpWidget(
      MaterialApp(
        home: const Material(child: Text('Home')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return Material(
              child: Center(
45
                child: BackButton(onPressed: () => customCallbackWasCalled = true),
46 47
              ),
            );
48
          },
49
        },
50
      ),
51
    );
52

53
    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');
54

55
    await tester.pumpAndSettle();
56

57 58
    expect(find.text('Home'), findsNothing); // Start off on the second page.
    expect(customCallbackWasCalled, false); // customCallbackWasCalled should still be false.
59
    await tester.tap(find.byType(BackButton));
60

61
    await tester.pumpAndSettle();
62

63 64 65
    // We're still on the second page.
    expect(find.text('Home'), findsNothing);
    // But the custom callback is called.
66
    expect(customCallbackWasCalled, true);
67 68
  });

69
  testWidgets('BackButton icon', (WidgetTester tester) async {
70
    final Key androidKey = UniqueKey();
Dan Field's avatar
Dan Field committed
71
    final Key iOSKey = UniqueKey();
72
    final Key linuxKey = UniqueKey();
Dan Field's avatar
Dan Field committed
73
    final Key macOSKey = UniqueKey();
74
    final Key windowsKey = UniqueKey();
75

76
    await tester.pumpWidget(
77 78
      MaterialApp(
        home: Column(
79
          children: <Widget>[
Dan Field's avatar
Dan Field committed
80 81 82 83
            Theme(
              data: ThemeData(platform: TargetPlatform.android),
              child: BackButtonIcon(key: androidKey),
            ),
84 85 86
            Theme(
              data: ThemeData(platform: TargetPlatform.iOS),
              child: BackButtonIcon(key: iOSKey),
87
            ),
88 89 90 91
            Theme(
              data: ThemeData(platform: TargetPlatform.linux),
              child: BackButtonIcon(key: linuxKey),
            ),
92
            Theme(
Dan Field's avatar
Dan Field committed
93 94
              data: ThemeData(platform: TargetPlatform.macOS),
              child: BackButtonIcon(key: macOSKey),
95
            ),
96 97 98 99
            Theme(
              data: ThemeData(platform: TargetPlatform.windows),
              child: BackButtonIcon(key: windowsKey),
            ),
100 101 102 103 104
          ],
        ),
      ),
    );

105
    final Icon androidIcon = tester.widget(find.descendant(of: find.byKey(androidKey), matching: find.byType(Icon)));
Dan Field's avatar
Dan Field committed
106
    final Icon iOSIcon = tester.widget(find.descendant(of: find.byKey(iOSKey), matching: find.byType(Icon)));
107
    final Icon linuxIcon = tester.widget(find.descendant(of: find.byKey(linuxKey), matching: find.byType(Icon)));
Dan Field's avatar
Dan Field committed
108
    final Icon macOSIcon = tester.widget(find.descendant(of: find.byKey(macOSKey), matching: find.byType(Icon)));
109
    final Icon windowsIcon = tester.widget(find.descendant(of: find.byKey(windowsKey), matching: find.byType(Icon)));
Dan Field's avatar
Dan Field committed
110
    expect(iOSIcon.icon == androidIcon.icon, isFalse);
111
    expect(linuxIcon.icon == androidIcon.icon, isTrue);
Dan Field's avatar
Dan Field committed
112 113
    expect(macOSIcon.icon == androidIcon.icon, isFalse);
    expect(macOSIcon.icon == iOSIcon.icon, isTrue);
114
    expect(windowsIcon.icon == androidIcon.icon, isTrue);
115
  });
116

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
  testWidgets('BackButton color', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: BackButton(
            color: Colors.blue,
          ),
        ),
      ),
    );

    final RichText iconText = tester.firstWidget(find.descendant(
        of: find.byType(BackButton),
        matching: find.byType(RichText)
    ));
132
    expect(iconText.text.style!.color, Colors.blue);
133 134
  });

135 136 137
  testWidgets('BackButton semantics', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
138
      MaterialApp(
139
        home: const Material(child: Text('Home')),
140 141 142
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return const Material(
143 144
              child: Center(
                child: BackButton(),
145 146 147 148 149 150 151 152 153 154 155
              ),
            );
          },
        },
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');

    await tester.pumpAndSettle();

156
    expect(tester.getSemantics(find.byType(BackButton)), matchesSemantics(
157 158 159 160 161
      label: 'Back',
      isButton: true,
      hasEnabledState: true,
      isEnabled: true,
      hasTapAction: true,
162
      isFocusable: true,
163 164 165
    ));
    handle.dispose();
  });
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181

  testWidgets('CloseButton color', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: CloseButton(
            color: Colors.red,
          ),
        ),
      ),
    );

    final RichText iconText = tester.firstWidget(find.descendant(
        of: find.byType(CloseButton),
        matching: find.byType(RichText)
    ));
182
    expect(iconText.text.style!.color, Colors.red);
183
  });
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

  testWidgets('CloseButton onPressed overrides default pop behavior', (WidgetTester tester) async {
    bool customCallbackWasCalled = false;
    await tester.pumpWidget(
      MaterialApp(
        home: const Material(child: Text('Home')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return Material(
              child: Center(
                child: CloseButton(onPressed: () => customCallbackWasCalled = true),
              ),
            );
          },
        },
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');

    await tester.pumpAndSettle();
    expect(find.text('Home'), findsNothing); // Start off on the second page.
    expect(customCallbackWasCalled, false); // customCallbackWasCalled should still be false.
    await tester.tap(find.byType(CloseButton));

    await tester.pumpAndSettle();

    // We're still on the second page.
    expect(find.text('Home'), findsNothing);
    // The custom callback is called, setting customCallbackWasCalled to true.
    expect(customCallbackWasCalled, true);
  });
216
}