From aafdbc6d12cd800450722543b4f6262a892ddfd4 Mon Sep 17 00:00:00 2001 From: hangyu Date: Fri, 21 Jul 2023 03:38:54 -0700 Subject: [PATCH] Add tests for navigation_drawer_theme_test.dart (#130465) fixes: https://github.com/flutter/flutter/issues/129618 --- .../lib/src/material/navigation_drawer.dart | 9 +- .../navigation_drawer_theme_test.dart | 291 ++++++++++++++++++ 2 files changed, 296 insertions(+), 4 deletions(-) diff --git a/packages/flutter/lib/src/material/navigation_drawer.dart b/packages/flutter/lib/src/material/navigation_drawer.dart index f52e20274f..611a2d51d7 100644 --- a/packages/flutter/lib/src/material/navigation_drawer.dart +++ b/packages/flutter/lib/src/material/navigation_drawer.dart @@ -165,12 +165,13 @@ class NavigationDrawer extends StatelessWidget { destinationIndex += 1; } } + final NavigationDrawerThemeData navigationDrawerTheme = NavigationDrawerTheme.of(context); return Drawer( - backgroundColor: backgroundColor, - shadowColor: shadowColor, - surfaceTintColor: surfaceTintColor, - elevation: elevation, + backgroundColor: backgroundColor ?? navigationDrawerTheme.backgroundColor, + shadowColor: shadowColor ?? navigationDrawerTheme.shadowColor, + surfaceTintColor: surfaceTintColor ?? navigationDrawerTheme.surfaceTintColor, + elevation: elevation ?? navigationDrawerTheme.elevation, child: SafeArea( bottom: false, child: ListView( diff --git a/packages/flutter/test/material/navigation_drawer_theme_test.dart b/packages/flutter/test/material/navigation_drawer_theme_test.dart index 411ad46d8e..2df6b7edf2 100644 --- a/packages/flutter/test/material/navigation_drawer_theme_test.dart +++ b/packages/flutter/test/material/navigation_drawer_theme_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -16,4 +17,294 @@ void main() { const NavigationDrawerThemeData data = NavigationDrawerThemeData(); expect(identical(NavigationDrawerThemeData.lerp(data, data, 0.5), data), true); }); + + testWidgets('Default debugFillProperties', (WidgetTester tester) async { + final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); + const NavigationDrawerThemeData().debugFillProperties(builder); + + final List description = builder.properties + .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) + .map((DiagnosticsNode node) => node.toString()) + .toList(); + + expect(description, []); + }); + + testWidgets('NavigationDrawerThemeData implements debugFillProperties', (WidgetTester tester) async { + final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); + const NavigationDrawerThemeData( + tileHeight: 50, + backgroundColor: Color(0x00000099), + elevation: 5.0, + shadowColor: Color(0x00000098), + surfaceTintColor: Color(0x00000097), + indicatorColor: Color(0x00000096), + indicatorShape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))), + indicatorSize: Size(10, 10), + labelTextStyle: MaterialStatePropertyAll(TextStyle(fontSize: 7.0)), + iconTheme: MaterialStatePropertyAll(IconThemeData(color: Color(0x00000095))), + ).debugFillProperties(builder); + + final List description = builder.properties + .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) + .map((DiagnosticsNode node) => node.toString()) + .toList(); + + expect(description, equalsIgnoringHashCodes( + [ + 'tileHeight: 50.0', + 'backgroundColor: Color(0x00000099)', + 'elevation: 5.0', + 'shadowColor: Color(0x00000098)', + 'surfaceTintColor: Color(0x00000097)', + 'indicatorColor: Color(0x00000096)', + 'indicatorShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))', + 'indicatorSize: Size(10.0, 10.0)', + 'labelTextStyle: MaterialStatePropertyAll(TextStyle(inherit: true, size: 7.0))', + 'iconTheme: MaterialStatePropertyAll(IconThemeData#00000(color: Color(0x00000095)))' + ], + )); + }); + + testWidgets( + 'NavigationDrawerThemeData values are used when no NavigationDrawer properties are specified', + (WidgetTester tester) async { + final GlobalKey scaffoldKey = GlobalKey(); + const NavigationDrawerThemeData navigationDrawerTheme = NavigationDrawerThemeData( + backgroundColor: Color(0x00000001), + elevation: 7.0, + shadowColor: Color(0x00000002), + surfaceTintColor: Color(0x00000003), + indicatorColor: Color(0x00000004), + indicatorShape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topRight: Radius.circular(16.0))), + labelTextStyle:MaterialStatePropertyAll(TextStyle(fontSize: 7.0)), + iconTheme: MaterialStatePropertyAll(IconThemeData(color: Color(0x00000005))), + ); + + await tester.pumpWidget( + _buildWidget( + scaffoldKey, + NavigationDrawer( + children: const [ + Text('Headline'), + NavigationDrawerDestination( + icon: Icon(Icons.ac_unit), + label: Text('AC'), + ), + NavigationDrawerDestination( + icon: Icon(Icons.access_alarm), + label: Text('Alarm'), + ), + ], + onDestinationSelected: (int i) {}, + ), + theme: ThemeData( + navigationDrawerTheme: navigationDrawerTheme, + ), + ), + ); + scaffoldKey.currentState!.openDrawer(); + await tester.pump(const Duration(seconds: 1)); + + // Test drawer Material. + expect(_getMaterial(tester).color, navigationDrawerTheme.backgroundColor); + expect(_getMaterial(tester).surfaceTintColor, navigationDrawerTheme.surfaceTintColor); + expect(_getMaterial(tester).shadowColor, navigationDrawerTheme.shadowColor); + expect(_getMaterial(tester).elevation, 7); + // Test indicator decoration. + expect(_getIndicatorDecoration(tester)?.color, navigationDrawerTheme.indicatorColor); + expect(_getIndicatorDecoration(tester)?.shape, navigationDrawerTheme.indicatorShape); + // Test icon. + expect( + _iconStyle(tester, Icons.ac_unit)?.color, + navigationDrawerTheme.iconTheme?.resolve({})?.color, + ); + expect( + _iconStyle(tester, Icons.access_alarm)?.color, + navigationDrawerTheme.iconTheme?.resolve({})?.color, + ); + // Test label. + expect( + _labelStyle(tester, 'AC'), + navigationDrawerTheme.labelTextStyle?.resolve({}) + ); + expect( + _labelStyle(tester, 'Alarm'), + navigationDrawerTheme.labelTextStyle?.resolve({}) + ); + }); + + testWidgets( + 'NavigationDrawer values take priority over NavigationDrawerThemeData values when both properties are specified', + (WidgetTester tester) async { + final GlobalKey scaffoldKey = GlobalKey(); + const NavigationDrawerThemeData navigationDrawerTheme = NavigationDrawerThemeData( + backgroundColor: Color(0x00000001), + elevation: 7.0, + shadowColor: Color(0x00000002), + surfaceTintColor: Color(0x00000003), + indicatorColor: Color(0x00000004), + indicatorShape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topRight: Radius.circular(16.0))), + labelTextStyle:MaterialStatePropertyAll(TextStyle(fontSize: 7.0)), + iconTheme: MaterialStatePropertyAll(IconThemeData(color: Color(0x00000005))), + ); + const Color backgroundColor = Color(0x00000009); + const double elevation = 14.0; + const Color shadowColor = Color(0x00000008); + const Color surfaceTintColor = Color(0x00000007); + const RoundedRectangleBorder indicatorShape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(32.0))); + const Color indicatorColor = Color(0x00000006); + + await tester.pumpWidget( + _buildWidget( + scaffoldKey, + NavigationDrawer( + backgroundColor: backgroundColor, + elevation: elevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, + indicatorShape: indicatorShape, + indicatorColor: indicatorColor, + children: const [ + Text('Headline'), + NavigationDrawerDestination( + icon: Icon(Icons.ac_unit), + label: Text('AC'), + ), + NavigationDrawerDestination( + icon: Icon(Icons.access_alarm), + label: Text('Alarm'), + ), + ], + onDestinationSelected: (int i) {}, + ), + theme: ThemeData( + navigationDrawerTheme: navigationDrawerTheme, + ), + ), + ); + scaffoldKey.currentState!.openDrawer(); + await tester.pump(const Duration(seconds: 1)); + + // Test drawer Material. + expect(_getMaterial(tester).color, backgroundColor); + expect(_getMaterial(tester).surfaceTintColor, surfaceTintColor); + expect(_getMaterial(tester).shadowColor, shadowColor); + expect(_getMaterial(tester).elevation, elevation); + // Test indicator decoration. + expect(_getIndicatorDecoration(tester)?.color, indicatorColor); + expect(_getIndicatorDecoration(tester)?.shape, indicatorShape); + }); + + testWidgets('Local NavigationDrawerTheme takes priority over ThemeData.navigationDrawerTheme', (WidgetTester tester) async { + final GlobalKey scaffoldKey = GlobalKey(); + const Color backgroundColor = Color(0x00000009); + const double elevation = 7.0; + const Color shadowColor = Color(0x00000008); + const Color surfaceTintColor = Color(0x00000007); + const Color iconColor = Color(0x00000006); + const TextStyle labelStyle = TextStyle(fontSize: 7.0); + const ShapeBorder indicatorShape = CircleBorder(); + const Color indicatorColor = Color(0x00000005); + + await tester.pumpWidget( + _buildWidget( + scaffoldKey, + NavigationDrawerTheme( + data: const NavigationDrawerThemeData( + backgroundColor: backgroundColor, + elevation: elevation, + shadowColor: shadowColor, + surfaceTintColor: surfaceTintColor, + indicatorShape: indicatorShape, + indicatorColor: indicatorColor, + labelTextStyle:MaterialStatePropertyAll(TextStyle(fontSize: 7.0)), + iconTheme: MaterialStatePropertyAll(IconThemeData(color: iconColor)), + ), + child: NavigationDrawer( + children: const [ + Text('Headline'), + NavigationDrawerDestination( + icon: Icon(Icons.ac_unit), + label: Text('AC'), + ), + NavigationDrawerDestination( + icon: Icon(Icons.access_alarm), + label: Text('Alarm'), + ), + ], + onDestinationSelected: (int i) {}, + ), + ), + theme: ThemeData( + navigationDrawerTheme: const NavigationDrawerThemeData( + backgroundColor: Color(0x00000001), + elevation: 7.0, + shadowColor: Color(0x00000002), + surfaceTintColor: Color(0x00000003), + indicatorColor: Color(0x00000004), + indicatorShape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topRight: Radius.circular(16.0))), + labelTextStyle:MaterialStatePropertyAll(TextStyle(fontSize: 7.0)), + iconTheme: MaterialStatePropertyAll(IconThemeData(color: Color(0x00000005))), + ), + ), + ), + ); + scaffoldKey.currentState!.openDrawer(); + await tester.pump(const Duration(seconds: 1)); + + // Test drawer Material. + expect(_getMaterial(tester).color, backgroundColor); + expect(_getMaterial(tester).surfaceTintColor, surfaceTintColor); + expect(_getMaterial(tester).shadowColor, shadowColor); + expect(_getMaterial(tester).elevation, elevation); + // Test indicator decoration. + expect(_getIndicatorDecoration(tester)?.color, indicatorColor); + expect(_getIndicatorDecoration(tester)?.shape, indicatorShape); + // Test icon. + expect(_iconStyle(tester, Icons.ac_unit)?.color, iconColor); + expect(_iconStyle(tester, Icons.access_alarm)?.color, iconColor); + // Test label. + expect(_labelStyle(tester, 'AC'), labelStyle); + expect(_labelStyle(tester, 'Alarm'), labelStyle); + }); +} + +Widget _buildWidget(GlobalKey scaffoldKey, Widget child, { ThemeData? theme }) { + return MaterialApp( + theme: theme, + home: Scaffold( + key: scaffoldKey, + drawer: child, + body: Container(), + ), + ); +} + +Material _getMaterial(WidgetTester tester) { + return tester.firstWidget(find.descendant( + of: find.byType(NavigationDrawer), + matching: find.byType(Material), + )); +} + +ShapeDecoration? _getIndicatorDecoration(WidgetTester tester) { + return tester.firstWidget(find.descendant( + of: find.byType(FadeTransition), + matching: find.byType(Container), + )).decoration as ShapeDecoration?; +} + +TextStyle? _iconStyle(WidgetTester tester, IconData icon) { + return tester.widget( + find.descendant(of: find.byIcon(icon), + matching: find.byType(RichText)), + ).text.style; +} + +TextStyle? _labelStyle(WidgetTester tester, String label) { + return tester.widget(find.descendant( + of: find.text(label), + matching: find.byType(RichText), + )).text.style; }