mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Appbar should update when you add a drawer. (#9755)
Also, I had a question about flutter_test matchers and our style guide says that when I have a question I should update the docs so I did that and then got a bit carried away.
This commit is contained in:
parent
d604791a1c
commit
cbfde9650d
|
@ -319,20 +319,6 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
|||
}
|
||||
|
||||
class _AppBarState extends State<AppBar> {
|
||||
bool _hasDrawer = false;
|
||||
bool _canPop = false;
|
||||
bool _useCloseButton = false;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
|
||||
_hasDrawer = scaffold?.hasDrawer ?? false;
|
||||
final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
|
||||
_canPop = parentRoute?.canPop ?? false;
|
||||
_useCloseButton = parentRoute is MaterialPageRoute<dynamic> && parentRoute.fullscreenDialog;
|
||||
}
|
||||
|
||||
void _handleDrawerButton() {
|
||||
Scaffold.of(context).openDrawer();
|
||||
}
|
||||
|
@ -341,6 +327,12 @@ class _AppBarState extends State<AppBar> {
|
|||
Widget build(BuildContext context) {
|
||||
assert(!widget.primary || debugCheckHasMediaQuery(context));
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
|
||||
final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
|
||||
|
||||
final bool hasDrawer = scaffold?.hasDrawer ?? false;
|
||||
final bool canPop = parentRoute?.canPop ?? false;
|
||||
final bool useCloseButton = parentRoute is MaterialPageRoute<dynamic> && parentRoute.fullscreenDialog;
|
||||
|
||||
IconThemeData appBarIconTheme = widget.iconTheme ?? themeData.primaryIconTheme;
|
||||
TextStyle centerStyle = widget.textTheme?.title ?? themeData.primaryTextTheme.title;
|
||||
|
@ -365,15 +357,15 @@ class _AppBarState extends State<AppBar> {
|
|||
final List<Widget> toolbarChildren = <Widget>[];
|
||||
Widget leading = widget.leading;
|
||||
if (leading == null) {
|
||||
if (_hasDrawer) {
|
||||
if (hasDrawer) {
|
||||
leading = new IconButton(
|
||||
icon: const Icon(Icons.menu),
|
||||
onPressed: _handleDrawerButton,
|
||||
tooltip: 'Open navigation menu' // TODO(ianh): Figure out how to localize this string
|
||||
);
|
||||
} else {
|
||||
if (_canPop)
|
||||
leading = _useCloseButton ? const CloseButton() : const BackButton();
|
||||
if (canPop)
|
||||
leading = useCloseButton ? const CloseButton() : const BackButton();
|
||||
}
|
||||
}
|
||||
if (leading != null) {
|
||||
|
|
|
@ -308,7 +308,6 @@ void main() {
|
|||
expect(find.text('A2'), findsOneWidget);
|
||||
});
|
||||
|
||||
|
||||
testWidgets('AppBar render at zero size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new MaterialApp(
|
||||
|
@ -760,4 +759,24 @@ void main() {
|
|||
expect(appBarTop(tester), 0.0);
|
||||
expect(tester.getTopLeft(find.text('title')).dy, lessThan(100.0));
|
||||
});
|
||||
|
||||
testWidgets('AppBar updates when you add a drawer', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new MaterialApp(
|
||||
home: new Scaffold(
|
||||
appBar: new AppBar(),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byIcon(Icons.menu), findsNothing);
|
||||
await tester.pumpWidget(
|
||||
new MaterialApp(
|
||||
home: new Scaffold(
|
||||
drawer: const Drawer(),
|
||||
appBar: new AppBar(),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byIcon(Icons.menu), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,30 +9,62 @@ import 'finders.dart';
|
|||
|
||||
/// Asserts that the [Finder] matches no widgets in the widget tree.
|
||||
///
|
||||
/// Example:
|
||||
/// ## Sample code
|
||||
///
|
||||
/// expect(find.text('Save'), findsNothing);
|
||||
/// ```dart
|
||||
/// expect(find.text('Save'), findsNothing);
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [findsWidgets], when you want the finder to find one or more widgets.
|
||||
/// * [findsOneWidgets], when you want the finder to find exactly one widget.
|
||||
/// * [findsNWidgets], when you want the finder to find a specific number of widgets.
|
||||
const Matcher findsNothing = const _FindsWidgetMatcher(null, 0);
|
||||
|
||||
/// Asserts that the [Finder] locates at least one widget in the widget tree.
|
||||
///
|
||||
/// Example:
|
||||
/// ## Sample code
|
||||
///
|
||||
/// expect(find.text('Save'), findsWidgets);
|
||||
/// ```dart
|
||||
/// expect(find.text('Save'), findsWidgets);
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [findsNothing], when you want the finder to not find anything.
|
||||
/// * [findsOneWidgets], when you want the finder to find exactly one widget.
|
||||
/// * [findsNWidgets], when you want the finder to find a specific number of widgets.
|
||||
const Matcher findsWidgets = const _FindsWidgetMatcher(1, null);
|
||||
|
||||
/// Asserts that the [Finder] locates at exactly one widget in the widget tree.
|
||||
///
|
||||
/// Example:
|
||||
/// ## Sample code
|
||||
///
|
||||
/// expect(find.text('Save'), findsOneWidget);
|
||||
/// ```dart
|
||||
/// expect(find.text('Save'), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [findsNothing], when you want the finder to not find anything.
|
||||
/// * [findsWidgets], when you want the finder to find one or more widgets.
|
||||
/// * [findsNWidgets], when you want the finder to find a specific number of widgets.
|
||||
const Matcher findsOneWidget = const _FindsWidgetMatcher(1, 1);
|
||||
|
||||
/// Asserts that the [Finder] locates the specified number of widgets in the widget tree.
|
||||
///
|
||||
/// Example:
|
||||
/// ## Sample code
|
||||
///
|
||||
/// expect(find.text('Save'), findsNWidgets(2));
|
||||
/// ```dart
|
||||
/// expect(find.text('Save'), findsNWidgets(2));
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [findsNothing], when you want the finder to not find anything.
|
||||
/// * [findsWidgets], when you want the finder to find one or more widgets.
|
||||
/// * [findsOneWidgets], when you want the finder to find exactly one widget.
|
||||
Matcher findsNWidgets(int n) => new _FindsWidgetMatcher(n, n);
|
||||
|
||||
/// Asserts that the [Finder] locates the a single widget that has at
|
||||
|
@ -41,21 +73,41 @@ Matcher findsNWidgets(int n) => new _FindsWidgetMatcher(n, n);
|
|||
/// It's important to use a full finder, since by default finders exclude
|
||||
/// offstage widgets.
|
||||
///
|
||||
/// Example:
|
||||
/// ## Sample code
|
||||
///
|
||||
/// expect(find.text('Save', skipOffstage: false), isOffstage);
|
||||
/// ```dart
|
||||
/// expect(find.text('Save', skipOffstage: false), isOffstage);
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [isOnStage], the opposite.
|
||||
const Matcher isOffstage = const _IsOffstage();
|
||||
|
||||
/// Asserts that the [Finder] locates the a single widget that has no
|
||||
/// [Offstage] widget ancestors.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [isOffStage], the opposite.
|
||||
const Matcher isOnstage = const _IsOnstage();
|
||||
|
||||
/// Asserts that the [Finder] locates the a single widget that has at
|
||||
/// least one [Card] widget ancestor.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [isNotInCard], the opposite.
|
||||
const Matcher isInCard = const _IsInCard();
|
||||
|
||||
/// Asserts that the [Finder] locates the a single widget that has no
|
||||
/// [Card] widget ancestors.
|
||||
///
|
||||
/// This is equivalent to `isNot(isInCard)`.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [isInCard], the opposite.
|
||||
const Matcher isNotInCard = const _IsNotInCard();
|
||||
|
||||
/// Asserts that an object's toString() is a plausible one-line description.
|
||||
|
@ -66,15 +118,47 @@ const Matcher isNotInCard = const _IsNotInCard();
|
|||
const Matcher hasOneLineDescription = const _HasOneLineDescription();
|
||||
|
||||
/// A matcher for functions that throw [FlutterError].
|
||||
///
|
||||
/// This is equivalent to `throwsA(const isInstanceOf<FlutterError>())`.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [throwsAssertionError], to test if a function throws any [AssertionError].
|
||||
/// * [isFlutterError], to test if any object is a [FlutterError].
|
||||
/// * [isAssertionError], to test if any object is any kind of [AssertionError].
|
||||
Matcher throwsFlutterError = throwsA(isFlutterError);
|
||||
|
||||
/// A matcher for functions that throw [AssertionError].
|
||||
///
|
||||
/// This is equivalent to `throwsA(const isInstanceOf<AssertionError>())`.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [throwsFlutterError], to test if a function throws a [FlutterError].
|
||||
/// * [isFlutterError], to test if any object is a [FlutterError].
|
||||
/// * [isAssertionError], to test if any object is any kind of [AssertionError].
|
||||
Matcher throwsAssertionError = throwsA(isAssertionError);
|
||||
|
||||
/// A matcher for [FlutterError].
|
||||
///
|
||||
/// This is equivalent to `const isInstanceOf<FlutterError>()`.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [throwsFlutterError], to test if a function throws a [FlutterError].
|
||||
/// * [throwsAssertionError], to test if a function throws any [AssertionError].
|
||||
/// * [isAssertionError], to test if any object is any kind of [AssertionError].
|
||||
const Matcher isFlutterError = const isInstanceOf<FlutterError>();
|
||||
|
||||
/// A matcher for [AssertionError].
|
||||
///
|
||||
/// This is equivalent to `const isInstanceOf<AssertionError>()`.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [throwsFlutterError], to test if a function throws a [FlutterError].
|
||||
/// * [throwsAssertionError], to test if a function throws any [AssertionError].
|
||||
/// * [isFlutterError], to test if any object is a [FlutterError].
|
||||
const Matcher isAssertionError = const isInstanceOf<AssertionError>();
|
||||
|
||||
/// Asserts that two [double]s are equal, within some tolerated error.
|
||||
|
@ -84,6 +168,13 @@ const Matcher isAssertionError = const isInstanceOf<AssertionError>();
|
|||
/// using the `epsilon` argument. This matcher is intended to compare floating
|
||||
/// point numbers that are the result of different sequences of operations, such
|
||||
/// that they may have accumulated slightly different errors.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [closeTo], which is identical except that the epsilon argument is
|
||||
/// required and not named.
|
||||
/// * [isInclusiveRange], which matches if the argument is in a specified
|
||||
/// range.
|
||||
Matcher moreOrLessEquals(double value, { double epsilon: 1e-10 }) {
|
||||
return new _MoreOrLessEquals(value, epsilon);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue