blob: 3a83eba8b2b1e9d2a93e93cd71691c57272e421d [file] [log] [blame]
// 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 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.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(
home: Scaffold(appBar: AppBar(
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
],
)),
));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, Brightness.dark);
expect(widget.color, Colors.blue);
expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black);
expect(iconTheme.data, const IconThemeData(color: Colors.white));
expect(actionsIconTheme.data, const IconThemeData(color: Colors.white));
expect(actionIconText.text.style!.color, Colors.white);
expect(text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().white.bodyText2));
});
testWidgets('AppBar uses values from AppBarTheme', (WidgetTester tester) async {
final AppBarTheme appBarTheme = _appBarTheme();
await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: appBarTheme),
home: Scaffold(appBar: AppBar(
title: const Text('App Bar Title'),
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
],
)),
));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, appBarTheme.brightness);
expect(widget.color, appBarTheme.color);
expect(widget.elevation, appBarTheme.elevation);
expect(widget.shadowColor, appBarTheme.shadowColor);
expect(iconTheme.data, appBarTheme.iconTheme);
expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
expect(actionIconText.text.style!.color, appBarTheme.actionsIconTheme!.color);
expect(text.style, appBarTheme.textTheme!.bodyText2);
});
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;
const Color shadowColor = Colors.red;
const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
const TextTheme textTheme = TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink));
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
await tester.pumpWidget(MaterialApp(
theme: themeData,
home: Scaffold(appBar: AppBar(
backgroundColor: color,
brightness: brightness,
elevation: elevation,
shadowColor: shadowColor,
iconTheme: iconThemeData,
actionsIconTheme: actionsIconThemeData,
textTheme: textTheme,
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
],
)),
));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, brightness);
expect(widget.color, color);
expect(widget.elevation, elevation);
expect(widget.shadowColor, shadowColor);
expect(iconTheme.data, iconThemeData);
expect(actionsIconTheme.data, actionsIconThemeData);
expect(actionIconText.text.style!.color, actionsIconThemeData.color);
expect(text.style, textTheme.bodyText2);
});
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>[
IconButton(icon: const Icon(Icons.share), color: color, onPressed: () { }),
],
)),
));
final RichText actionIconText = _getAppBarIconRichText(tester);
expect(actionIconText.text.style!.color, color);
});
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,
home: Scaffold(appBar: AppBar(
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
],
)),
));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, appBarTheme.brightness);
expect(widget.color, appBarTheme.color);
expect(widget.elevation, appBarTheme.elevation);
expect(widget.shadowColor, appBarTheme.shadowColor);
expect(iconTheme.data, appBarTheme.iconTheme);
expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
expect(actionIconText.text.style!.color, appBarTheme.actionsIconTheme!.color);
expect(text.style, appBarTheme.textTheme!.bodyText2);
});
testWidgets('ThemeData properties are used when no AppBarTheme is set', (WidgetTester tester) async {
final ThemeData themeData = _themeData();
await tester.pumpWidget(MaterialApp(
theme: themeData,
home: Scaffold(appBar: AppBar(
actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
],
)),
));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, themeData.brightness);
expect(widget.color, themeData.primaryColor);
expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black);
expect(iconTheme.data, themeData.primaryIconTheme);
expect(actionsIconTheme.data, themeData.primaryIconTheme);
expect(actionIconText.text.style!.color, themeData.primaryIconTheme.color);
// Default value for ThemeData.typography is Typography.material2014()
expect(text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().white.bodyText2).merge(themeData.primaryTextTheme.bodyText2));
});
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(
appBar: AppBar(
title: const Text('Title'),
centerTitle: false,
),
),
));
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);
});
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);
});
testWidgets('AppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async {
const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
home: Scaffold(
appBar: AppBar(
title: const Text('Title'),
),
),
));
final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
expect(navToolBar.middleSpacing, kTitleSpacing);
});
testWidgets('AppBar.titleSpacing takes priority over AppBarTheme.titleSpacing', (WidgetTester tester) async {
const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
home: Scaffold(
appBar: AppBar(
title: const Text('Title'),
titleSpacing: 40,
),
),
));
final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
expect(navToolBar.middleSpacing, 40);
});
testWidgets('SliverAppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async {
const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
home: const CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Title'),
),
],
),
));
final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar));
expect(navToolBar.middleSpacing, kTitleSpacing);
});
testWidgets('SliverAppBar.titleSpacing takes priority over AppBarTheme.titleSpacing ', (WidgetTester tester) async {
const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
home: const CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Title'),
titleSpacing: 40,
),
],
),
));
final NavigationToolbar navToolbar = tester.widget(find.byType(NavigationToolbar));
expect(navToolbar.middleSpacing, 40);
});
testWidgets('Default AppBarTheme debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const AppBarTheme().debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description, <String>[]);
});
testWidgets('AppBarTheme implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const AppBarTheme(
brightness: Brightness.dark,
color: Color(0xff000001),
elevation: 8.0,
shadowColor: Color(0xff000002),
centerTitle: true,
titleSpacing: 40.0,
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description, <String>[
'brightness: Brightness.dark',
'color: Color(0xff000001)',
'elevation: 8.0',
'shadowColor: Color(0xff000002)',
'centerTitle: true',
'titleSpacing: 40.0',
]);
// On the web, Dart doubles and ints are backed by the same kind of object because
// JavaScript does not support integers. So, the Dart double "4.0" is identical
// to "4", which results in the web evaluating to the value "4" regardless of which
// one is used. This results in a difference for doubles in debugFillProperties between
// the web and the rest of Flutter's target platforms.
}, skip: kIsWeb);
}
AppBarTheme _appBarTheme() {
const Brightness brightness = Brightness.light;
const Color color = Colors.lightBlue;
const double elevation = 6.0;
const Color shadowColor = Colors.red;
const IconThemeData iconThemeData = IconThemeData(color: Colors.black);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.pink);
const TextTheme textTheme = TextTheme(bodyText2: TextStyle(color: Colors.yellow));
return const AppBarTheme(
actionsIconTheme: actionsIconThemeData,
brightness: brightness,
color: color,
elevation: elevation,
shadowColor: shadowColor,
iconTheme: iconThemeData,
textTheme: textTheme,
);
}
ThemeData _themeData() {
return ThemeData(
primaryColor: Colors.purple,
brightness: Brightness.dark,
primaryIconTheme: const IconThemeData(color: Colors.green),
primaryTextTheme: const TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink)),
);
}
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),
).first,
);
}
IconTheme _getAppBarActionsIconTheme(WidgetTester tester) {
return tester.widget<IconTheme>(
find.descendant(
of: find.byType(NavigationToolbar),
matching: find.byType(IconTheme),
).first,
);
}
RichText _getAppBarIconRichText(WidgetTester tester) {
return tester.widget<RichText>(
find.descendant(
of: find.byType(Icon),
matching: find.byType(RichText),
).first,
);
}
DefaultTextStyle _getAppBarText(WidgetTester tester) {
return tester.widget<DefaultTextStyle>(
find.descendant(
of: find.byType(CustomSingleChildLayout),
matching: find.byType(DefaultTextStyle),
).first,
);
}