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

5 6
// @dart = 2.8

7 8 9 10 11 12 13 14 15 16 17 18 19
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('AppBarTheme copyWith, ==, hashCode basics', () {
    expect(const AppBarTheme(), const AppBarTheme().copyWith());
    expect(const AppBarTheme().hashCode, const AppBarTheme().copyWith().hashCode);
  });

  testWidgets('Passing no AppBarTheme returns defaults', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
20 21
      home: Scaffold(appBar: AppBar(
        actions: <Widget>[
22
          IconButton(icon: const Icon(Icons.share), onPressed: () { }),
23 24
        ],
      )),
25 26 27 28
    ));

    final Material widget = _getAppBarMaterial(tester);
    final IconTheme iconTheme = _getAppBarIconTheme(tester);
29 30
    final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
    final RichText actionIconText = _getAppBarIconRichText(tester);
31 32 33 34 35
    final DefaultTextStyle text = _getAppBarText(tester);

    expect(SystemChrome.latestStyle.statusBarBrightness, Brightness.dark);
    expect(widget.color, Colors.blue);
    expect(widget.elevation, 4.0);
36
    expect(widget.shadowColor, Colors.black);
37
    expect(iconTheme.data, const IconThemeData(color: Colors.white));
38 39
    expect(actionsIconTheme.data, const IconThemeData(color: Colors.white));
    expect(actionIconText.text.style.color, Colors.white);
40
    expect(text.style, Typography.material2014().englishLike.bodyText2.merge(Typography.material2014().white.bodyText2));
41 42 43 44 45 46 47
  });

  testWidgets('AppBar uses values from AppBarTheme', (WidgetTester tester) async {
    final AppBarTheme appBarTheme = _appBarTheme();

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(appBarTheme: appBarTheme),
48 49 50
      home: Scaffold(appBar: AppBar(
        title: const Text('App Bar Title'),
        actions: <Widget>[
51
          IconButton(icon: const Icon(Icons.share), onPressed: () { }),
52 53
        ],
      )),
54 55 56 57
    ));

    final Material widget = _getAppBarMaterial(tester);
    final IconTheme iconTheme = _getAppBarIconTheme(tester);
58 59
    final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
    final RichText actionIconText = _getAppBarIconRichText(tester);
60 61 62 63 64
    final DefaultTextStyle text = _getAppBarText(tester);

    expect(SystemChrome.latestStyle.statusBarBrightness, appBarTheme.brightness);
    expect(widget.color, appBarTheme.color);
    expect(widget.elevation, appBarTheme.elevation);
65
    expect(widget.shadowColor, appBarTheme.shadowColor);
66
    expect(iconTheme.data, appBarTheme.iconTheme);
67 68
    expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
    expect(actionIconText.text.style.color, appBarTheme.actionsIconTheme.color);
69
    expect(text.style, appBarTheme.textTheme.bodyText2);
70 71 72 73 74 75
  });

  testWidgets('AppBar widget properties take priority over theme', (WidgetTester tester) async {
    const Brightness brightness = Brightness.dark;
    const Color color = Colors.orange;
    const double elevation = 3.0;
76
    const Color shadowColor = Colors.red;
77
    const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
78
    const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
79
    const TextTheme textTheme = TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink));
80 81 82 83 84 85 86 87 88

    final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());

    await tester.pumpWidget(MaterialApp(
      theme: themeData,
      home: Scaffold(appBar: AppBar(
        backgroundColor: color,
        brightness: brightness,
        elevation: elevation,
89
        shadowColor: shadowColor,
90
        iconTheme: iconThemeData,
91 92 93
        actionsIconTheme: actionsIconThemeData,
        textTheme: textTheme,
        actions: <Widget>[
94
          IconButton(icon: const Icon(Icons.share), onPressed: () { }),
95 96
        ],
      )),
97 98 99 100
    ));

    final Material widget = _getAppBarMaterial(tester);
    final IconTheme iconTheme = _getAppBarIconTheme(tester);
101 102
    final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
    final RichText actionIconText = _getAppBarIconRichText(tester);
103 104 105 106 107
    final DefaultTextStyle text = _getAppBarText(tester);

    expect(SystemChrome.latestStyle.statusBarBrightness, brightness);
    expect(widget.color, color);
    expect(widget.elevation, elevation);
108
    expect(widget.shadowColor, shadowColor);
109
    expect(iconTheme.data, iconThemeData);
110 111
    expect(actionsIconTheme.data, actionsIconThemeData);
    expect(actionIconText.text.style.color, actionsIconThemeData.color);
112
    expect(text.style, textTheme.bodyText2);
113 114
  });

115 116 117 118 119 120 121 122 123 124 125 126 127
  testWidgets('AppBar icon color takes priority over everything', (WidgetTester tester) async {
    const Color color = Colors.lime;
    const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
    const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);

    final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());

    await tester.pumpWidget(MaterialApp(
      theme: themeData,
      home: Scaffold(appBar: AppBar(
        iconTheme: iconThemeData,
        actionsIconTheme: actionsIconThemeData,
        actions: <Widget>[
128
          IconButton(icon: const Icon(Icons.share), color: color, onPressed: () { }),
129 130 131 132 133 134 135 136
        ],
      )),
    ));

    final RichText actionIconText = _getAppBarIconRichText(tester);
    expect(actionIconText.text.style.color, color);
  });

137 138 139 140 141 142
  testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
    final AppBarTheme appBarTheme = _appBarTheme();
    final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());

    await tester.pumpWidget(MaterialApp(
      theme: themeData,
143 144
      home: Scaffold(appBar: AppBar(
        actions: <Widget>[
145
          IconButton(icon: const Icon(Icons.share), onPressed: () { }),
146 147
        ],
      )),
148 149 150 151
    ));

    final Material widget = _getAppBarMaterial(tester);
    final IconTheme iconTheme = _getAppBarIconTheme(tester);
152 153
    final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
    final RichText actionIconText = _getAppBarIconRichText(tester);
154 155 156 157 158
    final DefaultTextStyle text = _getAppBarText(tester);

    expect(SystemChrome.latestStyle.statusBarBrightness, appBarTheme.brightness);
    expect(widget.color, appBarTheme.color);
    expect(widget.elevation, appBarTheme.elevation);
159
    expect(widget.shadowColor, appBarTheme.shadowColor);
160
    expect(iconTheme.data, appBarTheme.iconTheme);
161 162
    expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
    expect(actionIconText.text.style.color, appBarTheme.actionsIconTheme.color);
163
    expect(text.style, appBarTheme.textTheme.bodyText2);
164 165 166 167 168 169 170
  });

  testWidgets('ThemeData properties are used when no AppBarTheme is set', (WidgetTester tester) async {
    final ThemeData themeData = _themeData();

    await tester.pumpWidget(MaterialApp(
      theme: themeData,
171 172
      home: Scaffold(appBar: AppBar(
        actions: <Widget>[
173
          IconButton(icon: const Icon(Icons.share), onPressed: () { }),
174 175
        ],
      )),
176 177 178 179
    ));

    final Material widget = _getAppBarMaterial(tester);
    final IconTheme iconTheme = _getAppBarIconTheme(tester);
180 181
    final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
    final RichText actionIconText = _getAppBarIconRichText(tester);
182 183 184 185 186
    final DefaultTextStyle text = _getAppBarText(tester);

    expect(SystemChrome.latestStyle.statusBarBrightness, themeData.brightness);
    expect(widget.color, themeData.primaryColor);
    expect(widget.elevation, 4.0);
187
    expect(widget.shadowColor, Colors.black);
188
    expect(iconTheme.data, themeData.primaryIconTheme);
189 190
    expect(actionsIconTheme.data, themeData.primaryIconTheme);
    expect(actionIconText.text.style.color, themeData.primaryIconTheme.color);
191 192
    // Default value for ThemeData.typography is Typography.material2014()
    expect(text.style, Typography.material2014().englishLike.bodyText2.merge(Typography.material2014().white.bodyText2).merge(themeData.primaryTextTheme.bodyText2));
193
  });
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

  testWidgets('AppBar uses AppBarTheme.centerTitle when centerTitle is null', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)),
      home: Scaffold(appBar: AppBar(title: const Text('Title'))),
    ));

    final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
    expect(navToolBar.centerMiddle, true);
  });

  testWidgets('AppBar.centerTitle takes priority over AppBarTheme.centerTitle', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)),
      home: Scaffold(
209 210 211 212 213
        appBar: AppBar(
          title: const Text('Title'),
          centerTitle: false,
        ),
      ),
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    ));

    final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
    // The AppBar.centerTitle should be used instead of AppBarTheme.centerTitle.
    expect(navToolBar.centerMiddle, false);
  });

  testWidgets('AppBar.centerTitle adapts to TargetPlatform when AppBarTheme.centerTitle is null', (WidgetTester tester) async{
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(platform: TargetPlatform.iOS),
      home: Scaffold(appBar: AppBar(title: const Text('Title'))),
    ));

    final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
    // When ThemeData.platform is TargetPlatform.iOS, and AppBarTheme is null,
    // the value of NavigationToolBar.centerMiddle should be true.
    expect(navToolBar.centerMiddle, true);
  });
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247

  testWidgets('AppBar.shadowColor takes priority over AppBarTheme.shadowColor', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(appBarTheme: const AppBarTheme(shadowColor: Colors.red)),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Title'),
          shadowColor: Colors.yellow,
        ),
      ),
    ));

    final AppBar appBar = tester.widget(find.byType(AppBar));
    // The AppBar.shadowColor should be used instead of AppBarTheme.shadowColor.
    expect(appBar.shadowColor, Colors.yellow);
  });
248 249 250 251 252 253
}

AppBarTheme _appBarTheme() {
  const Brightness brightness = Brightness.light;
  const Color color = Colors.lightBlue;
  const double elevation = 6.0;
254
  const Color shadowColor = Colors.red;
255
  const IconThemeData iconThemeData = IconThemeData(color: Colors.black);
256
  const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.pink);
257
  const TextTheme textTheme = TextTheme(bodyText2: TextStyle(color: Colors.yellow));
258
  return const AppBarTheme(
259
    actionsIconTheme: actionsIconThemeData,
260 261 262
    brightness: brightness,
    color: color,
    elevation: elevation,
263
    shadowColor: shadowColor,
264
    iconTheme: iconThemeData,
265
    textTheme: textTheme,
266 267 268 269 270 271 272 273
  );
}

ThemeData _themeData() {
  return ThemeData(
    primaryColor: Colors.purple,
    brightness: Brightness.dark,
    primaryIconTheme: const IconThemeData(color: Colors.green),
274
    primaryTextTheme: const TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink)),
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
  );
}

Material _getAppBarMaterial(WidgetTester tester) {
  return tester.widget<Material>(
    find.descendant(
      of: find.byType(AppBar),
      matching: find.byType(Material),
    ),
  );
}

IconTheme _getAppBarIconTheme(WidgetTester tester) {
  return tester.widget<IconTheme>(
    find.descendant(
      of: find.byType(AppBar),
      matching: find.byType(IconTheme),
292 293 294 295 296 297 298 299 300 301
    ).first,
  );
}

IconTheme _getAppBarActionsIconTheme(WidgetTester tester) {
  return tester.widget<IconTheme>(
    find.descendant(
      of: find.byType(NavigationToolbar),
      matching: find.byType(IconTheme),
    ).first,
302 303 304
  );
}

305 306 307 308 309 310 311 312
RichText _getAppBarIconRichText(WidgetTester tester) {
  return tester.widget<RichText>(
    find.descendant(
      of: find.byType(Icon),
      matching: find.byType(RichText),
    ).first,
  );
}
313

314 315 316 317 318 319 320 321
DefaultTextStyle _getAppBarText(WidgetTester tester) {
  return tester.widget<DefaultTextStyle>(
    find.descendant(
      of: find.byType(CustomSingleChildLayout),
      matching: find.byType(DefaultTextStyle),
    ).first,
  );
}