Unverified Commit 0ed17dd5 authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Update `TextSelectionTheme`, `ThemeData`, `TimePicker`, and `TimePickerTheme`...

Update `TextSelectionTheme`, `ThemeData`, `TimePicker`, and `TimePickerTheme` tests for M2/M3 (#130547)

Updated unit tests for `TextSelectionTheme`, `ThemeData`, `TimePicker` and `TimePickerTheme` to have M2 and M3 versions.

More info in #127064
parent d4005a87
...@@ -60,12 +60,11 @@ void main() { ...@@ -60,12 +60,11 @@ void main() {
]); ]);
}); });
testWidgetsWithLeakTracking('Empty textSelectionTheme will use defaults', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - Empty textSelectionTheme will use defaults', (WidgetTester tester) async {
final ThemeData theme = ThemeData(); final ThemeData theme = ThemeData(useMaterial3: false);
final bool material3 = theme.useMaterial3; const Color defaultCursorColor = Color(0xff2196f3);
final Color defaultCursorColor = material3 ? theme.colorScheme.primary : const Color(0xff2196f3); const Color defaultSelectionColor = Color(0x662196f3);
final Color defaultSelectionColor = material3 ? theme.colorScheme.primary.withOpacity(0.40) : const Color(0x662196f3); const Color defaultSelectionHandleColor = Color(0xff2196f3);
final Color defaultSelectionHandleColor = material3 ? theme.colorScheme.primary : const Color(0xff2196f3);
EditableText.debugDeterministicCursor = true; EditableText.debugDeterministicCursor = true;
addTearDown(() { addTearDown(() {
...@@ -91,6 +90,67 @@ void main() { ...@@ -91,6 +90,67 @@ void main() {
// Test the selection handle color. // Test the selection handle color.
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: theme,
home: Material(
child: Builder(
builder: (BuildContext context) {
return materialTextSelectionControls.buildHandle(
context,
TextSelectionHandleType.left,
10.0,
);
},
),
),
),
);
await tester.pumpAndSettle();
final RenderBox handle = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint));
expect(handle, paints..path(color: defaultSelectionHandleColor));
},
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/130469
leakTrackingTestConfig: const LeakTrackingTestConfig(
notDisposedAllowList: <String, int?>{
'ValueNotifier<MagnifierInfo>': 1,
'ValueNotifier<_OverlayEntryWidgetState?>': 2,
'ValueNotifier<bool>': 1,
},
// TODO(polina-c): investigate notGCed, if it does not disappear after fixing notDisposed.
allowAllNotGCed: true,
));
testWidgetsWithLeakTracking('Material3 - Empty textSelectionTheme will use defaults', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
final Color defaultCursorColor = theme.colorScheme.primary;
final Color defaultSelectionColor = theme.colorScheme.primary.withOpacity(0.40);
final Color defaultSelectionHandleColor = theme.colorScheme.primary;
EditableText.debugDeterministicCursor = true;
addTearDown(() {
EditableText.debugDeterministicCursor = false;
});
// Test TextField's cursor & selection color.
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: const Material(
child: TextField(autofocus: true),
),
),
);
await tester.pump();
await tester.pumpAndSettle();
final EditableTextState editableTextState = tester.firstState(find.byType(EditableText));
final RenderEditable renderEditable = editableTextState.renderEditable;
expect(renderEditable.cursorColor, defaultCursorColor);
expect(renderEditable.selectionColor, defaultSelectionColor);
// Test the selection handle color.
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Material( home: Material(
child: Builder( child: Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
......
...@@ -14,9 +14,8 @@ void main() { ...@@ -14,9 +14,8 @@ void main() {
const ShapeBorder defaultFABShapeM3 = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const ShapeBorder defaultFABShapeM3 = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const EdgeInsets defaultFABPadding = EdgeInsets.zero; const EdgeInsets defaultFABPadding = EdgeInsets.zero;
testWidgets('theme: ThemeData.light(), enabled: true', (WidgetTester tester) async { testWidgets('Material2 - theme: ThemeData.light(), enabled: true', (WidgetTester tester) async {
final ThemeData theme = ThemeData.light(); final ThemeData theme = ThemeData.light(useMaterial3: false);
final bool material3 = theme.useMaterial3;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: theme, theme: theme,
...@@ -31,21 +30,48 @@ void main() { ...@@ -31,21 +30,48 @@ void main() {
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton)); final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.enabled, true); expect(raw.enabled, true);
expect(raw.textStyle!.color, material3 ? theme.colorScheme.onPrimaryContainer : const Color(0xffffffff)); expect(raw.textStyle!.color, const Color(0xffffffff));
expect(raw.fillColor, material3 ? theme.colorScheme.primaryContainer : const Color(0xff2196f3)); expect(raw.fillColor, const Color(0xff2196f3));
expect(raw.elevation, 6.0); expect(raw.elevation, 6.0);
expect(raw.highlightElevation, material3 ? 6.0 : 12.0); expect(raw.highlightElevation, 12.0);
expect(raw.disabledElevation, 6.0); expect(raw.disabledElevation, 6.0);
expect(raw.constraints, defaultFABConstraints); expect(raw.constraints, defaultFABConstraints);
expect(raw.padding, defaultFABPadding); expect(raw.padding, defaultFABPadding);
expect(raw.shape, material3 ? defaultFABShapeM3 : defaultFABShape); expect(raw.shape, defaultFABShape);
expect(raw.animationDuration, defaultButtonDuration); expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded); expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
}); });
testWidgets('theme: ThemeData.light(), enabled: false', (WidgetTester tester) async { testWidgets('Material3 - theme: ThemeData.light(), enabled: true', (WidgetTester tester) async {
final ThemeData theme = ThemeData.light(); final ThemeData theme = ThemeData.light(useMaterial3: true);
final bool material3 = theme.useMaterial3; await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Center(
child: FloatingActionButton(
onPressed: () { }, // button.enabled == true
child: const Icon(Icons.add),
),
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.enabled, true);
expect(raw.textStyle!.color, theme.colorScheme.onPrimaryContainer);
expect(raw.fillColor, theme.colorScheme.primaryContainer);
expect(raw.elevation, 6.0);
expect(raw.highlightElevation, 6.0);
expect(raw.disabledElevation, 6.0);
expect(raw.constraints, defaultFABConstraints);
expect(raw.padding, defaultFABPadding);
expect(raw.shape, defaultFABShapeM3);
expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
testWidgets('Material2 - theme: ThemeData.light(), enabled: false', (WidgetTester tester) async {
final ThemeData theme = ThemeData.light(useMaterial3: false);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: theme, theme: theme,
...@@ -60,16 +86,46 @@ void main() { ...@@ -60,16 +86,46 @@ void main() {
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton)); final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.enabled, false); expect(raw.enabled, false);
expect(raw.textStyle!.color, material3 ? theme.colorScheme.onPrimaryContainer : const Color(0xffffffff)); expect(raw.textStyle!.color, const Color(0xffffffff));
expect(raw.fillColor, material3 ? theme.colorScheme.primaryContainer : const Color(0xff2196f3)); expect(raw.fillColor, const Color(0xff2196f3));
// highlightColor, disabled button can't be pressed
// splashColor, disabled button doesn't splash
expect(raw.elevation, 6.0);
expect(raw.highlightElevation, 12.0);
expect(raw.disabledElevation, 6.0);
expect(raw.constraints, defaultFABConstraints);
expect(raw.padding, defaultFABPadding);
expect(raw.shape, defaultFABShape);
expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
});
testWidgets('Material3 - theme: ThemeData.light(), enabled: false', (WidgetTester tester) async {
final ThemeData theme = ThemeData.light(useMaterial3: true);
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: const Center(
child: FloatingActionButton(
onPressed: null, // button.enabled == false
child: Icon(Icons.add),
),
),
),
);
final RawMaterialButton raw = tester.widget<RawMaterialButton>(find.byType(RawMaterialButton));
expect(raw.enabled, false);
expect(raw.textStyle!.color, theme.colorScheme.onPrimaryContainer);
expect(raw.fillColor, theme.colorScheme.primaryContainer);
// highlightColor, disabled button can't be pressed // highlightColor, disabled button can't be pressed
// splashColor, disabled button doesn't splash // splashColor, disabled button doesn't splash
expect(raw.elevation, 6.0); expect(raw.elevation, 6.0);
expect(raw.highlightElevation, material3 ? 6.0 : 12.0); expect(raw.highlightElevation, 6.0);
expect(raw.disabledElevation, 6.0); expect(raw.disabledElevation, 6.0);
expect(raw.constraints, defaultFABConstraints); expect(raw.constraints, defaultFABConstraints);
expect(raw.padding, defaultFABPadding); expect(raw.padding, defaultFABPadding);
expect(raw.shape, material3 ? defaultFABShapeM3 : defaultFABShape); expect(raw.shape, defaultFABShapeM3);
expect(raw.animationDuration, defaultButtonDuration); expect(raw.animationDuration, defaultButtonDuration);
expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded); expect(raw.materialTapTargetSize, MaterialTapTargetSize.padded);
}); });
......
...@@ -96,8 +96,7 @@ void main() { ...@@ -96,8 +96,7 @@ void main() {
expect(tester.widget<EditableText>(find.byType(EditableText)).cursorColor, themeCursorColor); expect(tester.widget<EditableText>(find.byType(EditableText)).cursorColor, themeCursorColor);
}); });
testWidgets('Fallback theme', (WidgetTester tester) async { testWidgets('Material2 - Fallback theme', (WidgetTester tester) async {
// For material 2
late BuildContext capturedContext; late BuildContext capturedContext;
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
...@@ -112,8 +111,9 @@ void main() { ...@@ -112,8 +111,9 @@ void main() {
); );
expect(Theme.of(capturedContext), equals(ThemeData.localize(ThemeData.fallback(useMaterial3: false), defaultGeometryTheme))); expect(Theme.of(capturedContext), equals(ThemeData.localize(ThemeData.fallback(useMaterial3: false), defaultGeometryTheme)));
});
// For material 3 testWidgets('Material3 - Fallback theme', (WidgetTester tester) async {
late BuildContext capturedContextM3; late BuildContext capturedContextM3;
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
...@@ -153,9 +153,12 @@ void main() { ...@@ -153,9 +153,12 @@ void main() {
); );
}); });
testWidgets('ThemeData with null typography uses proper defaults', (WidgetTester tester) async { testWidgets('Material2 - ThemeData with null typography uses proper defaults', (WidgetTester tester) async {
final ThemeData m2Theme = ThemeData(useMaterial3: false); final ThemeData m2Theme = ThemeData(useMaterial3: false);
expect(m2Theme.typography, Typography.material2014()); expect(m2Theme.typography, Typography.material2014());
});
testWidgets('Material3 - ThemeData with null typography uses proper defaults', (WidgetTester tester) async {
final ThemeData m3Theme = ThemeData(useMaterial3: true); final ThemeData m3Theme = ThemeData(useMaterial3: true);
expect(m3Theme.typography, Typography.material2021(colorScheme: m3Theme.colorScheme)); expect(m3Theme.typography, Typography.material2021(colorScheme: m3Theme.colorScheme));
}); });
...@@ -436,7 +439,7 @@ void main() { ...@@ -436,7 +439,7 @@ void main() {
expect(actualFontSize, kMagicFontSize); expect(actualFontSize, kMagicFontSize);
}); });
testWidgets('Default Theme provides all basic TextStyle properties - M2', (WidgetTester tester) async { testWidgets('Material2 - Default Theme provides all basic TextStyle properties', (WidgetTester tester) async {
late ThemeData theme; late ThemeData theme;
await tester.pumpWidget(Theme( await tester.pumpWidget(Theme(
data: ThemeData(useMaterial3: false), data: ThemeData(useMaterial3: false),
...@@ -494,7 +497,7 @@ void main() { ...@@ -494,7 +497,7 @@ void main() {
expect(theme.textTheme.displayLarge!.debugLabel, '(englishLike displayLarge 2014).merge(blackMountainView displayLarge)'); expect(theme.textTheme.displayLarge!.debugLabel, '(englishLike displayLarge 2014).merge(blackMountainView displayLarge)');
}); });
testWidgets('Default Theme provides all basic TextStyle properties - M3', (WidgetTester tester) async { testWidgets('Material3 - Default Theme provides all basic TextStyle properties', (WidgetTester tester) async {
late ThemeData theme; late ThemeData theme;
await tester.pumpWidget(Theme( await tester.pumpWidget(Theme(
data: ThemeData(useMaterial3: true), data: ThemeData(useMaterial3: true),
...@@ -579,9 +582,8 @@ void main() { ...@@ -579,9 +582,8 @@ void main() {
context = null; context = null;
}); });
testWidgets('Default light theme has defaults', (WidgetTester tester) async { testWidgets('Material2 - Default light theme has defaults', (WidgetTester tester) async {
final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData(useMaterial3: false)); final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData(useMaterial3: false));
final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData(useMaterial3: true));
expect(themeM2.brightness, Brightness.light); expect(themeM2.brightness, Brightness.light);
expect(themeM2.primaryColor, Colors.blue); expect(themeM2.primaryColor, Colors.blue);
...@@ -589,6 +591,10 @@ void main() { ...@@ -589,6 +591,10 @@ void main() {
expect(themeM2.primaryContrastingColor, Colors.white); expect(themeM2.primaryContrastingColor, Colors.white);
expect(themeM2.textTheme.textStyle.fontFamily, '.SF Pro Text'); expect(themeM2.textTheme.textStyle.fontFamily, '.SF Pro Text');
expect(themeM2.textTheme.textStyle.fontSize, 17.0); expect(themeM2.textTheme.textStyle.fontSize, 17.0);
});
testWidgets('Material3 - Default light theme has defaults', (WidgetTester tester) async {
final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData(useMaterial3: true));
expect(themeM3.brightness, Brightness.light); expect(themeM3.brightness, Brightness.light);
expect(themeM3.primaryColor, const Color(0xff6750a4)); expect(themeM3.primaryColor, const Color(0xff6750a4));
...@@ -598,9 +604,8 @@ void main() { ...@@ -598,9 +604,8 @@ void main() {
expect(themeM3.textTheme.textStyle.fontSize, 17.0); expect(themeM3.textTheme.textStyle.fontSize, 17.0);
}); });
testWidgets('Dark theme has defaults', (WidgetTester tester) async { testWidgets('Material2 - Dark theme has defaults', (WidgetTester tester) async {
final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData.dark(useMaterial3: false)); final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData.dark(useMaterial3: false));
final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData.dark(useMaterial3: true));
expect(themeM2.brightness, Brightness.dark); expect(themeM2.brightness, Brightness.dark);
expect(themeM2.primaryColor, Colors.blue); expect(themeM2.primaryColor, Colors.blue);
...@@ -608,6 +613,10 @@ void main() { ...@@ -608,6 +613,10 @@ void main() {
expect(themeM2.scaffoldBackgroundColor, Colors.grey[850]); expect(themeM2.scaffoldBackgroundColor, Colors.grey[850]);
expect(themeM2.textTheme.textStyle.fontFamily, '.SF Pro Text'); expect(themeM2.textTheme.textStyle.fontFamily, '.SF Pro Text');
expect(themeM2.textTheme.textStyle.fontSize, 17.0); expect(themeM2.textTheme.textStyle.fontSize, 17.0);
});
testWidgets('Material3 - Dark theme has defaults', (WidgetTester tester) async {
final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData.dark(useMaterial3: true));
expect(themeM3.brightness, Brightness.dark); expect(themeM3.brightness, Brightness.dark);
expect(themeM3.primaryColor, const Color(0xffd0bcff)); expect(themeM3.primaryColor, const Color(0xffd0bcff));
...@@ -638,7 +647,7 @@ void main() { ...@@ -638,7 +647,7 @@ void main() {
expect(CupertinoTheme.brightnessOf(context!), Brightness.light); expect(CupertinoTheme.brightnessOf(context!), Brightness.light);
}); });
testWidgets('Can override material theme', (WidgetTester tester) async { testWidgets('Material2 - Can override material theme', (WidgetTester tester) async {
final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData( final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData(
cupertinoOverrideTheme: const CupertinoThemeData( cupertinoOverrideTheme: const CupertinoThemeData(
scaffoldBackgroundColor: CupertinoColors.lightBackgroundGray, scaffoldBackgroundColor: CupertinoColors.lightBackgroundGray,
...@@ -654,7 +663,9 @@ void main() { ...@@ -654,7 +663,9 @@ void main() {
expect(themeM2.scaffoldBackgroundColor, CupertinoColors.lightBackgroundGray); expect(themeM2.scaffoldBackgroundColor, CupertinoColors.lightBackgroundGray);
expect(themeM2.textTheme.textStyle.fontFamily, '.SF Pro Text'); expect(themeM2.textTheme.textStyle.fontFamily, '.SF Pro Text');
expect(themeM2.textTheme.textStyle.fontSize, 17.0); expect(themeM2.textTheme.textStyle.fontSize, 17.0);
});
testWidgets('Material3 - Can override material theme', (WidgetTester tester) async {
final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData( final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData(
cupertinoOverrideTheme: const CupertinoThemeData( cupertinoOverrideTheme: const CupertinoThemeData(
scaffoldBackgroundColor: CupertinoColors.lightBackgroundGray, scaffoldBackgroundColor: CupertinoColors.lightBackgroundGray,
...@@ -672,7 +683,7 @@ void main() { ...@@ -672,7 +683,7 @@ void main() {
expect(themeM3.textTheme.textStyle.fontSize, 17.0); expect(themeM3.textTheme.textStyle.fontSize, 17.0);
}); });
testWidgets('Can override properties that are independent of material', (WidgetTester tester) async { testWidgets('Material2 - Can override properties that are independent of material', (WidgetTester tester) async {
final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData( final CupertinoThemeData themeM2 = await testTheme(tester, ThemeData(
cupertinoOverrideTheme: const CupertinoThemeData( cupertinoOverrideTheme: const CupertinoThemeData(
// The bar colors ignore all things material except brightness. // The bar colors ignore all things material except brightness.
...@@ -684,7 +695,9 @@ void main() { ...@@ -684,7 +695,9 @@ void main() {
expect(themeM2.primaryColor, Colors.blue); expect(themeM2.primaryColor, Colors.blue);
// MaterialBasedCupertinoThemeData should also function like a normal CupertinoThemeData. // MaterialBasedCupertinoThemeData should also function like a normal CupertinoThemeData.
expect(themeM2.barBackgroundColor, CupertinoColors.black); expect(themeM2.barBackgroundColor, CupertinoColors.black);
});
testWidgets('Material3 - Can override properties that are independent of material', (WidgetTester tester) async {
final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData( final CupertinoThemeData themeM3 = await testTheme(tester, ThemeData(
cupertinoOverrideTheme: const CupertinoThemeData( cupertinoOverrideTheme: const CupertinoThemeData(
// The bar colors ignore all things material except brightness. // The bar colors ignore all things material except brightness.
...@@ -698,7 +711,7 @@ void main() { ...@@ -698,7 +711,7 @@ void main() {
expect(themeM3.barBackgroundColor, CupertinoColors.black); expect(themeM3.barBackgroundColor, CupertinoColors.black);
}); });
testWidgets('Changing material theme triggers rebuilds - M2', (WidgetTester tester) async { testWidgets('Material2 - Changing material theme triggers rebuilds', (WidgetTester tester) async {
CupertinoThemeData themeM2 = await testTheme(tester, ThemeData( CupertinoThemeData themeM2 = await testTheme(tester, ThemeData(
useMaterial3: false, useMaterial3: false,
primarySwatch: Colors.red, primarySwatch: Colors.red,
...@@ -716,7 +729,7 @@ void main() { ...@@ -716,7 +729,7 @@ void main() {
expect(themeM2.primaryColor, Colors.orange); expect(themeM2.primaryColor, Colors.orange);
}); });
testWidgets('Changing material theme triggers rebuilds - M3', (WidgetTester tester) async { testWidgets('Material3 - Changing material theme triggers rebuilds', (WidgetTester tester) async {
CupertinoThemeData themeM3 = await testTheme(tester, ThemeData( CupertinoThemeData themeM3 = await testTheme(tester, ThemeData(
useMaterial3: true, useMaterial3: true,
colorScheme: const ColorScheme.light( colorScheme: const ColorScheme.light(
...@@ -745,8 +758,8 @@ void main() { ...@@ -745,8 +758,8 @@ void main() {
const Color cupertinoIconColor = Colors.black; const Color cupertinoIconColor = Colors.black;
await testTheme(tester, ThemeData( await testTheme(tester, ThemeData(
iconTheme: const IconThemeData(color: materialIconColor), iconTheme: const IconThemeData(color: materialIconColor),
cupertinoOverrideTheme: const CupertinoThemeData(primaryColor: cupertinoIconColor), cupertinoOverrideTheme: const CupertinoThemeData(primaryColor: cupertinoIconColor),
)); ));
expect(buildCount, 1); expect(buildCount, 1);
...@@ -807,7 +820,7 @@ void main() { ...@@ -807,7 +820,7 @@ void main() {
); );
testWidgets( testWidgets(
'Cupertino overrides do not block derivatives triggering rebuilds when derivatives are not overridden - M2', 'Material2 - Cupertino overrides do not block derivatives triggering rebuilds when derivatives are not overridden',
(WidgetTester tester) async { (WidgetTester tester) async {
CupertinoThemeData theme = await testTheme(tester, ThemeData( CupertinoThemeData theme = await testTheme(tester, ThemeData(
useMaterial3: false, useMaterial3: false,
...@@ -836,7 +849,7 @@ void main() { ...@@ -836,7 +849,7 @@ void main() {
); );
testWidgets( testWidgets(
'Cupertino overrides do not block derivatives triggering rebuilds when derivatives are not overridden - M3', 'Material3 - Cupertino overrides do not block derivatives triggering rebuilds when derivatives are not overridden',
(WidgetTester tester) async { (WidgetTester tester) async {
CupertinoThemeData theme = await testTheme(tester, ThemeData( CupertinoThemeData theme = await testTheme(tester, ThemeData(
useMaterial3: true, useMaterial3: true,
...@@ -869,7 +882,7 @@ void main() { ...@@ -869,7 +882,7 @@ void main() {
); );
testWidgets( testWidgets(
'copyWith only copies the overrides, not the material or cupertino derivatives - M2', 'Material2 - copyWith only copies the overrides, not the material or cupertino derivatives',
(WidgetTester tester) async { (WidgetTester tester) async {
final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData( final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData(
useMaterial3: false, useMaterial3: false,
...@@ -896,7 +909,7 @@ void main() { ...@@ -896,7 +909,7 @@ void main() {
); );
testWidgets( testWidgets(
'copyWith only copies the overrides, not the material or cupertino derivatives - M3', 'Material3 - copyWith only copies the overrides, not the material or cupertino derivatives',
(WidgetTester tester) async { (WidgetTester tester) async {
final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData( final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData(
useMaterial3: true, useMaterial3: true,
...@@ -923,7 +936,7 @@ void main() { ...@@ -923,7 +936,7 @@ void main() {
); );
testWidgets( testWidgets(
"Material themes with no cupertino overrides can also be copyWith'ed - M2", "Material2 - Material themes with no cupertino overrides can also be copyWith'ed",
(WidgetTester tester) async { (WidgetTester tester) async {
final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData( final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData(
useMaterial3: false, useMaterial3: false,
...@@ -946,7 +959,7 @@ void main() { ...@@ -946,7 +959,7 @@ void main() {
); );
testWidgets( testWidgets(
"Material themes with no cupertino overrides can also be copyWith'ed - M3", "Material3 - Material themes with no cupertino overrides can also be copyWith'ed",
(WidgetTester tester) async { (WidgetTester tester) async {
final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData( final CupertinoThemeData originalTheme = await testTheme(tester, ThemeData(
useMaterial3: true, useMaterial3: true,
......
...@@ -16,24 +16,216 @@ import '../widgets/semantics_tester.dart'; ...@@ -16,24 +16,216 @@ import '../widgets/semantics_tester.dart';
import 'feedback_tester.dart'; import 'feedback_tester.dart';
void main() { void main() {
for (final MaterialType materialType in MaterialType.values) { const String okString = 'OK';
final String selectTimeString; const String amString = 'AM';
final String enterTimeString; const String pmString = 'PM';
final String cancelString; Material getMaterialFromDialog(WidgetTester tester) {
const String okString = 'OK'; return tester.widget<Material>(find.descendant(of: find.byType(Dialog), matching: find.byType(Material)).first);
const String amString = 'AM'; }
const String pmString = 'PM';
switch (materialType) { testWidgets('Material2 - Dialog size - dial mode', (WidgetTester tester) async {
case MaterialType.material2: addTearDown(tester.view.reset);
selectTimeString = 'SELECT TIME';
enterTimeString = 'ENTER TIME'; const Size timePickerPortraitSize = Size(310, 468);
cancelString = 'CANCEL'; const Size timePickerLandscapeSize = Size(524, 342);
case MaterialType.material3: const Size timePickerLandscapeSizeM2 = Size(508, 300);
selectTimeString = 'Select time'; const EdgeInsets padding = EdgeInsets.fromLTRB(8, 18, 8, 8);
enterTimeString = 'Enter time'; double width;
cancelString = 'Cancel'; double height;
}
// portrait
tester.view.physicalSize = const Size(800, 800.5);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(tester, materialType: MaterialType.material2);
width = timePickerPortraitSize.width + padding.horizontal;
height = timePickerPortraitSize.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
// landscape
tester.view.physicalSize = const Size(800.5, 800);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
materialType: MaterialType.material2,
);
width = timePickerLandscapeSize.width + padding.horizontal;
height = timePickerLandscapeSizeM2.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('Material2 - Dialog size - input mode', (WidgetTester tester) async {
const TimePickerEntryMode entryMode = TimePickerEntryMode.input;
const Size timePickerInputSize = Size(312, 216);
const Size dayPeriodPortraitSize = Size(52, 80);
const EdgeInsets padding = EdgeInsets.fromLTRB(8, 18, 8, 8);
final double height = timePickerInputSize.height + padding.vertical;
double width;
await mediaQueryBoilerplate(
tester,
entryMode: entryMode,
materialType: MaterialType.material2,
);
width = timePickerInputSize.width + padding.horizontal;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
entryMode: entryMode,
materialType: MaterialType.material2,
);
width = timePickerInputSize.width - dayPeriodPortraitSize.width - 12 + padding.horizontal + 16;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('Material2 - respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: MaterialType.material2);
final List<String> labels00To22 = List<String>.generate(12, (int index) {
return (index * 2).toString().padLeft(2, '0');
});
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To22);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(selectedLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To22);
});
testWidgets('Material3 - Dialog size - dial mode', (WidgetTester tester) async {
addTearDown(tester.view.reset);
const Size timePickerPortraitSize = Size(310, 468);
const Size timePickerLandscapeSize = Size(524, 342);
const EdgeInsets padding = EdgeInsets.all(24.0);
double width;
double height;
// portrait
tester.view.physicalSize = const Size(800, 800.5);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(tester, materialType: MaterialType.material3);
width = timePickerPortraitSize.width + padding.horizontal;
height = timePickerPortraitSize.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
// landscape
tester.view.physicalSize = const Size(800.5, 800);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
materialType: MaterialType.material3,
);
width = timePickerLandscapeSize.width + padding.horizontal;
height = timePickerLandscapeSize.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('Material3 - Dialog size - input mode', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
const TimePickerEntryMode entryMode = TimePickerEntryMode.input;
const double textScaleFactor = 1.0;
const Size timePickerMinInputSize = Size(312, 216);
const Size dayPeriodPortraitSize = Size(52, 80);
const EdgeInsets padding = EdgeInsets.all(24.0);
final double height = timePickerMinInputSize.height * textScaleFactor + padding.vertical;
double width;
await mediaQueryBoilerplate(
tester,
entryMode: entryMode,
materialType: MaterialType.material3,
);
width = timePickerMinInputSize.width - (theme.useMaterial3 ? 32 : 0) + padding.horizontal;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
entryMode: entryMode,
materialType: MaterialType.material3,
);
width = timePickerMinInputSize.width - dayPeriodPortraitSize.width - 12 + padding.horizontal;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('Material3 - respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: MaterialType.material3);
final List<String> labels00To23 = List<String>.generate(24, (int index) {
return index == 0 ? '00' : index.toString();
});
final List<bool> inner0To23 = List<bool>.generate(24, (int index) => index >= 12);
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To23);
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<bool>((dynamic tp) => tp.inner as bool), inner0To23);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(selectedLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To23);
// ignore: avoid_dynamic_calls
expect(selectedLabels.map<bool>((dynamic tp) => tp.inner as bool), inner0To23);
});
for (final MaterialType materialType in MaterialType.values) {
group('Dial (${materialType.name})', () { group('Dial (${materialType.name})', () {
testWidgets('tap-select an hour', (WidgetTester tester) async { testWidgets('tap-select an hour', (WidgetTester tester) async {
TimeOfDay? result; TimeOfDay? result;
...@@ -280,21 +472,32 @@ void main() { ...@@ -280,21 +472,32 @@ void main() {
}); });
group('Dialog (${materialType.name})', () { group('Dialog (${materialType.name})', () {
Material getMaterialFromDialog(WidgetTester tester) { testWidgets('Material2 - Widgets have correct label capitalization', (WidgetTester tester) async {
return tester.widget<Material>(find.descendant(of: find.byType(Dialog), matching: find.byType(Material)).first); await startPicker(tester, (TimeOfDay? time) {}, materialType: MaterialType.material2);
} expect(find.text('SELECT TIME'), findsOneWidget);
expect(find.text('CANCEL'), findsOneWidget);
testWidgets('Widgets have correct label capitalization', (WidgetTester tester) async {
await startPicker(tester, (TimeOfDay? time) {}, materialType: materialType);
expect(find.text(selectTimeString), findsOneWidget);
expect(find.text(cancelString), findsOneWidget);
}); });
testWidgets('Widgets have correct label capitalization in input mode', (WidgetTester tester) async { testWidgets('Material3 - Widgets have correct label capitalization', (WidgetTester tester) async {
await startPicker(tester, (TimeOfDay? time) {}, materialType: MaterialType.material3);
expect(find.text('Select time'), findsOneWidget);
expect(find.text('Cancel'), findsOneWidget);
});
testWidgets('Material2 - Widgets have correct label capitalization in input mode', (WidgetTester tester) async {
await startPicker(tester, (TimeOfDay? time) {}, await startPicker(tester, (TimeOfDay? time) {},
entryMode: TimePickerEntryMode.input, materialType: materialType); entryMode: TimePickerEntryMode.input, materialType: MaterialType.material2
expect(find.text(enterTimeString), findsOneWidget); );
expect(find.text(cancelString), findsOneWidget); expect(find.text('ENTER TIME'), findsOneWidget);
expect(find.text('CANCEL'), findsOneWidget);
});
testWidgets('Material3 - Widgets have correct label capitalization in input mode', (WidgetTester tester) async {
await startPicker(tester, (TimeOfDay? time) {},
entryMode: TimePickerEntryMode.input, materialType: MaterialType.material3
);
expect(find.text('Enter time'), findsOneWidget);
expect(find.text('Cancel'), findsOneWidget);
}); });
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == false', (WidgetTester tester) async { testWidgets('respects MediaQueryData.alwaysUse24HourFormat == false', (WidgetTester tester) async {
...@@ -314,211 +517,6 @@ void main() { ...@@ -314,211 +517,6 @@ void main() {
expect(selectedLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels12To11); expect(selectedLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels12To11);
}); });
switch (materialType) {
case MaterialType.material2:
testWidgets('Dialog size - dial mode', (WidgetTester tester) async {
addTearDown(tester.view.reset);
const Size timePickerPortraitSize = Size(310, 468);
const Size timePickerLandscapeSize = Size(524, 342);
const Size timePickerLandscapeSizeM2 = Size(508, 300);
const EdgeInsets padding = EdgeInsets.fromLTRB(8, 18, 8, 8);
double width;
double height;
// portrait
tester.view.physicalSize = const Size(800, 800.5);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(tester, materialType: materialType);
width = timePickerPortraitSize.width + padding.horizontal;
height = timePickerPortraitSize.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
// landscape
tester.view.physicalSize = const Size(800.5, 800);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
materialType: materialType,
);
width = timePickerLandscapeSize.width + padding.horizontal;
height = timePickerLandscapeSizeM2.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('Dialog size - input mode', (WidgetTester tester) async {
const TimePickerEntryMode entryMode = TimePickerEntryMode.input;
const Size timePickerInputSize = Size(312, 216);
const Size dayPeriodPortraitSize = Size(52, 80);
const EdgeInsets padding = EdgeInsets.fromLTRB(8, 18, 8, 8);
final double height = timePickerInputSize.height + padding.vertical;
double width;
await mediaQueryBoilerplate(
tester,
entryMode: entryMode,
materialType: materialType,
);
width = timePickerInputSize.width + padding.horizontal;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
entryMode: entryMode,
materialType: materialType,
);
width = timePickerInputSize.width - dayPeriodPortraitSize.width - 12 + padding.horizontal + 16;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: materialType);
final List<String> labels00To22 = List<String>.generate(12, (int index) {
return (index * 2).toString().padLeft(2, '0');
});
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To22);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(selectedLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To22);
});
case MaterialType.material3:
testWidgets('Dialog size - dial mode', (WidgetTester tester) async {
addTearDown(tester.view.reset);
const Size timePickerPortraitSize = Size(310, 468);
const Size timePickerLandscapeSize = Size(524, 342);
const EdgeInsets padding = EdgeInsets.all(24.0);
double width;
double height;
// portrait
tester.view.physicalSize = const Size(800, 800.5);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(tester, materialType: materialType);
width = timePickerPortraitSize.width + padding.horizontal;
height = timePickerPortraitSize.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
// landscape
tester.view.physicalSize = const Size(800.5, 800);
tester.view.devicePixelRatio = 1;
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
materialType: materialType,
);
width = timePickerLandscapeSize.width + padding.horizontal;
height = timePickerLandscapeSize.height + padding.vertical;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('Dialog size - input mode', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
const TimePickerEntryMode entryMode = TimePickerEntryMode.input;
const double textScaleFactor = 1.0;
const Size timePickerMinInputSize = Size(312, 216);
const Size dayPeriodPortraitSize = Size(52, 80);
const EdgeInsets padding = EdgeInsets.all(24.0);
final double height = timePickerMinInputSize.height * textScaleFactor + padding.vertical;
double width;
await mediaQueryBoilerplate(
tester,
entryMode: entryMode,
materialType: materialType,
);
width = timePickerMinInputSize.width - (theme.useMaterial3 ? 32 : 0) + padding.horizontal;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
await tester.tap(find.text(okString)); // dismiss the dialog
await tester.pumpAndSettle();
await mediaQueryBoilerplate(
tester,
alwaysUse24HourFormat: true,
entryMode: entryMode,
materialType: materialType,
);
width = timePickerMinInputSize.width - dayPeriodPortraitSize.width - 12 + padding.horizontal;
expect(
tester.getSize(find.byWidget(getMaterialFromDialog(tester))),
Size(width, height),
);
});
testWidgets('respects MediaQueryData.alwaysUse24HourFormat == true', (WidgetTester tester) async {
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: materialType);
final List<String> labels00To23 = List<String>.generate(24, (int index) {
return index == 0 ? '00' : index.toString();
});
final List<bool> inner0To23 = List<bool>.generate(24, (int index) => index >= 12);
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To23);
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<bool>((dynamic tp) => tp.inner as bool), inner0To23);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(selectedLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To23);
// ignore: avoid_dynamic_calls
expect(selectedLabels.map<bool>((dynamic tp) => tp.inner as bool), inner0To23);
});
}
testWidgets('when change orientation, should reflect in render objects', (WidgetTester tester) async { testWidgets('when change orientation, should reflect in render objects', (WidgetTester tester) async {
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
...@@ -708,10 +706,12 @@ void main() { ...@@ -708,10 +706,12 @@ void main() {
expect(find.text(helperText), findsOneWidget); expect(find.text(helperText), findsOneWidget);
}); });
testWidgets('OK Cancel button and helpText layout', (WidgetTester tester) async { testWidgets('Material2 - OK Cancel button and helpText layout', (WidgetTester tester) async {
const String selectTimeString = 'SELECT TIME';
const String cancelString = 'CANCEL';
Widget buildFrame(TextDirection textDirection) { Widget buildFrame(TextDirection textDirection) {
return MaterialApp( return MaterialApp(
theme: ThemeData(useMaterial3: materialType == MaterialType.material3), theme: ThemeData(useMaterial3: false),
home: Material( home: Material(
child: Center( child: Center(
child: Builder( child: Builder(
...@@ -742,21 +742,13 @@ void main() { ...@@ -742,21 +742,13 @@ void main() {
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
switch (materialType) { expect(tester.getTopLeft(find.text(selectTimeString)), equals(const Offset(154, 155)));
case MaterialType.material2: expect(tester.getBottomRight(find.text(selectTimeString)), equals(
expect(tester.getTopLeft(find.text(selectTimeString)), equals(const Offset(154, 155))); ParagraphBuilder.shouldDisableRoundingHack ? const Offset(280.5, 165) : const Offset(281, 165),
expect(tester.getBottomRight(find.text(selectTimeString)), equals( ));
ParagraphBuilder.shouldDisableRoundingHack ? const Offset(280.5, 165) : const Offset(281, 165), expect(tester.getBottomRight(find.text(okString)).dx, 644);
)); expect(tester.getBottomLeft(find.text(okString)).dx, 616);
expect(tester.getBottomRight(find.text(okString)).dx, 644); expect(tester.getBottomRight(find.text(cancelString)).dx, 582);
expect(tester.getBottomLeft(find.text(okString)).dx, 616);
expect(tester.getBottomRight(find.text(cancelString)).dx, 582);
case MaterialType.material3:
expect(tester.getTopLeft(find.text(selectTimeString)), equals(const Offset(138, 129)));
expect(tester.getBottomRight(find.text(selectTimeString)), equals(const Offset(295.0, 149.0)));
expect(tester.getBottomLeft(find.text(okString)).dx, 615.5);
expect(tester.getBottomRight(find.text(cancelString)).dx, 578);
}
await tester.tap(find.text(okString)); await tester.tap(find.text(okString));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -765,23 +757,72 @@ void main() { ...@@ -765,23 +757,72 @@ void main() {
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
switch (materialType) { expect(tester.getTopLeft(find.text(selectTimeString)), equals(
case MaterialType.material2: ParagraphBuilder.shouldDisableRoundingHack ? const Offset(519.5, 155) : const Offset(519, 155),
expect(tester.getTopLeft(find.text(selectTimeString)), equals( ));
ParagraphBuilder.shouldDisableRoundingHack ? const Offset(519.5, 155) : const Offset(519, 155), expect(tester.getBottomRight(find.text(selectTimeString)), equals(const Offset(646, 165)));
)); expect(tester.getBottomLeft(find.text(okString)).dx, 156);
expect(tester.getBottomRight(find.text(selectTimeString)), equals(const Offset(646, 165))); expect(tester.getBottomRight(find.text(okString)).dx, 184);
expect(tester.getBottomLeft(find.text(okString)).dx, 156); expect(tester.getBottomLeft(find.text(cancelString)).dx, 218);
expect(tester.getBottomRight(find.text(okString)).dx, 184);
expect(tester.getBottomLeft(find.text(cancelString)).dx, 218); await tester.tap(find.text(okString));
case MaterialType.material3: await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text(selectTimeString)), equals(const Offset(505.0, 129.0))); });
expect(tester.getBottomRight(find.text(selectTimeString)), equals(const Offset(662, 149)));
expect(tester.getBottomLeft(find.text(okString)).dx, 155.5); testWidgets('Material3 - OK Cancel button and helpText layout', (WidgetTester tester) async {
expect(tester.getBottomRight(find.text(okString)).dx, 184.5); const String selectTimeString = 'Select time';
expect(tester.getBottomLeft(find.text(cancelString)).dx, 222); const String cancelString = 'Cancel';
Widget buildFrame(TextDirection textDirection) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Material(
child: Center(
child: Builder(
builder: (BuildContext context) {
return ElevatedButton(
child: const Text('X'),
onPressed: () {
showTimePicker(
context: context,
initialTime: const TimeOfDay(hour: 7, minute: 0),
builder: (BuildContext context, Widget? child) {
return Directionality(
textDirection: textDirection,
child: child!,
);
},
);
},
);
},
),
),
),
);
} }
await tester.pumpWidget(buildFrame(TextDirection.ltr));
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text(selectTimeString)), equals(const Offset(138, 129)));
expect(tester.getBottomRight(find.text(selectTimeString)), equals(const Offset(295.0, 149.0)));
expect(tester.getBottomLeft(find.text(okString)).dx, 615.5);
expect(tester.getBottomRight(find.text(cancelString)).dx, 578);
await tester.tap(find.text(okString));
await tester.pumpAndSettle();
await tester.pumpWidget(buildFrame(TextDirection.rtl));
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text(selectTimeString)), equals(const Offset(505.0, 129.0)));
expect(tester.getBottomRight(find.text(selectTimeString)), equals(const Offset(662, 149)));
expect(tester.getBottomLeft(find.text(okString)).dx, 155.5);
expect(tester.getBottomRight(find.text(okString)).dx, 184.5);
expect(tester.getBottomLeft(find.text(cancelString)).dx, 222);
await tester.tap(find.text(okString)); await tester.tap(find.text(okString));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
...@@ -996,9 +1037,34 @@ void main() { ...@@ -996,9 +1037,34 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('provides semantics information for header and footer', (WidgetTester tester) async { testWidgets('Material2 - provides semantics information for header and footer', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: materialType); await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: MaterialType.material2);
expect(semantics, isNot(includesNodeWith(label: ':')));
expect(
semantics.nodesWith(value: 'Select minutes 00'),
hasLength(1),
reason: '00 appears once in the header',
);
expect(
semantics.nodesWith(value: 'Select hours 07'),
hasLength(1),
reason: '07 appears once in the header',
);
expect(semantics, includesNodeWith(label: 'CANCEL'));
expect(semantics, includesNodeWith(label: okString));
// In 24-hour mode we don't have AM/PM control.
expect(semantics, isNot(includesNodeWith(label: amString)));
expect(semantics, isNot(includesNodeWith(label: pmString)));
semantics.dispose();
});
testWidgets('Material3 - provides semantics information for header and footer', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await mediaQueryBoilerplate(tester, alwaysUse24HourFormat: true, materialType: MaterialType.material3);
expect(semantics, isNot(includesNodeWith(label: ':'))); expect(semantics, isNot(includesNodeWith(label: ':')));
expect( expect(
...@@ -1011,7 +1077,7 @@ void main() { ...@@ -1011,7 +1077,7 @@ void main() {
hasLength(1), hasLength(1),
reason: '07 appears once in the header', reason: '07 appears once in the header',
); );
expect(semantics, includesNodeWith(label: cancelString)); expect(semantics, includesNodeWith(label: 'Cancel'));
expect(semantics, includesNodeWith(label: okString)); expect(semantics, includesNodeWith(label: okString));
// In 24-hour mode we don't have AM/PM control. // In 24-hour mode we don't have AM/PM control.
......
...@@ -98,89 +98,64 @@ void main() { ...@@ -98,89 +98,64 @@ void main() {
]); ]);
}); });
testWidgets('Passing no TimePickerThemeData uses defaults', (WidgetTester tester) async { testWidgets('Material2 - Passing no TimePickerThemeData uses defaults', (WidgetTester tester) async {
final ThemeData defaultTheme = ThemeData(); final ThemeData defaultTheme = ThemeData(useMaterial3: false);
final bool material3 = defaultTheme.useMaterial3;
await tester.pumpWidget(_TimePickerLauncher(themeData: defaultTheme)); await tester.pumpWidget(_TimePickerLauncher(themeData: defaultTheme));
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle(const Duration(seconds: 1));
final Material dialogMaterial = _dialogMaterial(tester); final Material dialogMaterial = _dialogMaterial(tester);
expect(dialogMaterial.color, defaultTheme.colorScheme.surface); expect(dialogMaterial.color, defaultTheme.colorScheme.surface);
expect(dialogMaterial.shape, material3 expect(
? const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0))) dialogMaterial.shape,
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))) const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
); );
final RenderBox dial = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint)); final RenderBox dial = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint));
expect( expect(
dial, dial,
material3 paints
? (paints ..circle(color: defaultTheme.colorScheme.onSurface.withOpacity(0.08)) // Dial background color.
..circle(color: defaultTheme.colorScheme.surfaceVariant.withOpacity(0.08)) // Dial background color. ..circle(color: Color(defaultTheme.colorScheme.primary.value))
..circle(color: Color(defaultTheme.colorScheme.primary.value)))
: (paints
..circle(color: defaultTheme.colorScheme.onSurface.withOpacity(0.08)) // Dial background color.
..circle(color: Color(defaultTheme.colorScheme.primary.value))), // Dial hand color.
); );
final RenderParagraph hourText = _textRenderParagraph(tester, '7'); final RenderParagraph hourText = _textRenderParagraph(tester, '7');
expect( expect(
hourText.text.style, hourText.text.style,
material3 Typography.material2014().englishLike.displayMedium!
? (Typography.material2021().englishLike.displayLarge! .merge(Typography.material2014().black.displayMedium)
.merge(Typography.material2021().black.displayLarge) .copyWith(color: defaultTheme.colorScheme.primary)
.copyWith(color: defaultTheme.colorScheme.onPrimaryContainer, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.displayMedium!
.merge(Typography.material2014().black.displayMedium)
.copyWith(color: defaultTheme.colorScheme.primary)),
); );
final RenderParagraph minuteText = _textRenderParagraph(tester, '15'); final RenderParagraph minuteText = _textRenderParagraph(tester, '15');
expect( expect(
minuteText.text.style, minuteText.text.style,
material3 Typography.material2014().englishLike.displayMedium!
? (Typography.material2021().englishLike.displayLarge! .merge(Typography.material2014().black.displayMedium)
.merge(Typography.material2021().black.displayLarge) .copyWith(color: defaultTheme.colorScheme.onSurface),
.copyWith(color: defaultTheme.colorScheme.onSurface, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.displayMedium!
.merge(Typography.material2014().black.displayMedium)
.copyWith(color: defaultTheme.colorScheme.onSurface)),
); );
final RenderParagraph amText = _textRenderParagraph(tester, 'AM'); final RenderParagraph amText = _textRenderParagraph(tester, 'AM');
expect( expect(
amText.text.style, amText.text.style,
material3 Typography.material2014().englishLike.titleMedium!
? (Typography.material2021().englishLike.titleMedium! .merge(Typography.material2014().black.titleMedium)
.merge(Typography.material2021().black.titleMedium) .copyWith(color: defaultTheme.colorScheme.primary),
.copyWith(color: defaultTheme.colorScheme.onTertiaryContainer, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.titleMedium!
.merge(Typography.material2014().black.titleMedium)
.copyWith(color: defaultTheme.colorScheme.primary)),
); );
final RenderParagraph pmText = _textRenderParagraph(tester, 'PM'); final RenderParagraph pmText = _textRenderParagraph(tester, 'PM');
expect( expect(
pmText.text.style, pmText.text.style,
material3 Typography.material2014().englishLike.titleMedium!
? (Typography.material2021().englishLike.titleMedium! .merge(Typography.material2014().black.titleMedium)
.merge(Typography.material2021().black.titleMedium) .copyWith(color: defaultTheme.colorScheme.onSurface.withOpacity(0.6)),
.copyWith(color: defaultTheme.colorScheme.onTertiaryContainer, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.titleMedium!
.merge(Typography.material2014().black.titleMedium)
.copyWith(color: defaultTheme.colorScheme.onSurface.withOpacity(0.6))),
); );
final RenderParagraph helperText = _textRenderParagraph(tester, material3 ? 'Select time' : 'SELECT TIME'); final RenderParagraph helperText = _textRenderParagraph(tester, 'SELECT TIME');
expect( expect(
helperText.text.style, helperText.text.style,
material3 Typography.material2014().englishLike.labelSmall!
? (Typography.material2021().englishLike.bodyMedium! .merge(Typography.material2014().black.labelSmall),
.merge(Typography.material2021().black.bodyMedium)
.copyWith(color: defaultTheme.colorScheme.onSurface, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.labelSmall!
.merge(Typography.material2014().black.labelSmall)),
); );
final CustomPaint dialPaint = tester.widget(findDialPaint); final CustomPaint dialPaint = tester.widget(findDialPaint);
...@@ -190,44 +165,36 @@ void main() { ...@@ -190,44 +165,36 @@ void main() {
expect( expect(
// ignore: avoid_dynamic_calls // ignore: avoid_dynamic_calls
primaryLabels.first.painter.text.style, primaryLabels.first.painter.text.style,
material3 Typography.material2014().englishLike.bodyLarge!
? (Typography.material2021().englishLike.bodyLarge! .merge(Typography.material2014().black.bodyLarge)
.merge(Typography.material2021().black.bodyLarge) .copyWith(color: defaultTheme.colorScheme.onSurface),
.copyWith(color: defaultTheme.colorScheme.onSurface, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.bodyLarge!
.merge(Typography.material2014().black.bodyLarge)
.copyWith(color: defaultTheme.colorScheme.onSurface)),
); );
// ignore: avoid_dynamic_calls // ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>; final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
expect( expect(
// ignore: avoid_dynamic_calls // ignore: avoid_dynamic_calls
selectedLabels.first.painter.text.style, selectedLabels.first.painter.text.style,
material3 Typography.material2014().englishLike.bodyLarge!
? (Typography.material2021().englishLike.bodyLarge! .merge(Typography.material2014().white.bodyLarge)
.merge(Typography.material2021().black.bodyLarge) .copyWith(color: defaultTheme.colorScheme.onPrimary),
.copyWith(color: defaultTheme.colorScheme.onPrimary, decorationColor: defaultTheme.colorScheme.onSurface))
: (Typography.material2014().englishLike.bodyLarge!
.merge(Typography.material2014().white.bodyLarge)
.copyWith(color: defaultTheme.colorScheme.onPrimary)),
); );
final Material hourMaterial = _textMaterial(tester, '7'); final Material hourMaterial = _textMaterial(tester, '7');
expect(hourMaterial.color, material3 ? defaultTheme.colorScheme.primaryContainer : defaultTheme.colorScheme.primary.withOpacity(0.12)); expect(hourMaterial.color, defaultTheme.colorScheme.primary.withOpacity(0.12));
expect(hourMaterial.shape, material3 expect(
? const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))) hourMaterial.shape,
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))) const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
); );
final Material minuteMaterial = _textMaterial(tester, '15'); final Material minuteMaterial = _textMaterial(tester, '15');
expect(minuteMaterial.color, material3 ? defaultTheme.colorScheme.surfaceVariant : defaultTheme.colorScheme.onSurface.withOpacity(0.12)); expect(minuteMaterial.color, defaultTheme.colorScheme.onSurface.withOpacity(0.12));
expect(minuteMaterial.shape, material3 expect(
? const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))) minuteMaterial.shape,
: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))) const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
); );
final Material amMaterial = _textMaterial(tester, 'AM'); final Material amMaterial = _textMaterial(tester, 'AM');
expect(amMaterial.color, material3 ? defaultTheme.colorScheme.tertiaryContainer : defaultTheme.colorScheme.primary.withOpacity(0.12)); expect(amMaterial.color, defaultTheme.colorScheme.primary.withOpacity(0.12));
final Material pmMaterial = _textMaterial(tester, 'PM'); final Material pmMaterial = _textMaterial(tester, 'PM');
expect(pmMaterial.color, Colors.transparent); expect(pmMaterial.color, Colors.transparent);
...@@ -239,61 +206,245 @@ void main() { ...@@ -239,61 +206,245 @@ void main() {
final Material dayPeriodMaterial = _dayPeriodMaterial(tester); final Material dayPeriodMaterial = _dayPeriodMaterial(tester);
expect( expect(
dayPeriodMaterial.shape, dayPeriodMaterial.shape,
material3 RoundedRectangleBorder(
? RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(4.0)),
borderRadius: const BorderRadius.all(Radius.circular(8.0)), side: BorderSide(color: expectedBorderColor),
side: BorderSide(color: defaultTheme.colorScheme.outline), ),
) : RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(4.0)),
side: BorderSide(color: expectedBorderColor),
),
); );
final Container dayPeriodDivider = _dayPeriodDivider(tester); final Container dayPeriodDivider = _dayPeriodDivider(tester);
expect( expect(
dayPeriodDivider.decoration, dayPeriodDivider.decoration,
material3 BoxDecoration(border: Border(left: BorderSide(color: expectedBorderColor))),
? BoxDecoration(border: Border(left: BorderSide(color: defaultTheme.colorScheme.outline)))
: BoxDecoration(border: Border(left: BorderSide(color: expectedBorderColor))),
); );
final IconButton entryModeIconButton = _entryModeIconButton(tester); final IconButton entryModeIconButton = _entryModeIconButton(tester);
expect( expect(
entryModeIconButton.color, entryModeIconButton.color,
material3 ? null : defaultTheme.colorScheme.onSurface.withOpacity(0.6), defaultTheme.colorScheme.onSurface.withOpacity(0.6),
);
});
testWidgets('Material3 - Passing no TimePickerThemeData uses defaults', (WidgetTester tester) async {
final ThemeData defaultTheme = ThemeData(useMaterial3: true);
await tester.pumpWidget(_TimePickerLauncher(themeData: defaultTheme));
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Material dialogMaterial = _dialogMaterial(tester);
expect(dialogMaterial.color, defaultTheme.colorScheme.surface);
expect(
dialogMaterial.shape,
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0))),
);
final RenderBox dial = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint));
expect(
dial,
paints
..circle(color: defaultTheme.colorScheme.surfaceVariant.withOpacity(0.08)) // Dial background color.
..circle(color: Color(defaultTheme.colorScheme.primary.value)), // Dial hand color.
);
final RenderParagraph hourText = _textRenderParagraph(tester, '7');
expect(
hourText.text.style,
Typography.material2021().englishLike.displayLarge!
.merge(Typography.material2021().black.displayLarge)
.copyWith(
color: defaultTheme.colorScheme.onPrimaryContainer,
decorationColor: defaultTheme.colorScheme.onSurface
),
);
final RenderParagraph minuteText = _textRenderParagraph(tester, '15');
expect(
minuteText.text.style,
Typography.material2021().englishLike.displayLarge!
.merge(Typography.material2021().black.displayLarge)
.copyWith(
color: defaultTheme.colorScheme.onSurface,
decorationColor: defaultTheme.colorScheme.onSurface
),
);
final RenderParagraph amText = _textRenderParagraph(tester, 'AM');
expect(
amText.text.style,
Typography.material2021().englishLike.titleMedium!
.merge(Typography.material2021().black.titleMedium)
.copyWith(
color: defaultTheme.colorScheme.onTertiaryContainer,
decorationColor: defaultTheme.colorScheme.onSurface
),
);
final RenderParagraph pmText = _textRenderParagraph(tester, 'PM');
expect(
pmText.text.style,
Typography.material2021().englishLike.titleMedium!
.merge(Typography.material2021().black.titleMedium)
.copyWith(
color: defaultTheme.colorScheme.onTertiaryContainer,
decorationColor: defaultTheme.colorScheme.onSurface
)
);
final RenderParagraph helperText = _textRenderParagraph(tester, 'Select time');
expect(
helperText.text.style,
Typography.material2021().englishLike.bodyMedium!
.merge(Typography.material2021().black.bodyMedium)
.copyWith(
color: defaultTheme.colorScheme.onSurface,
decorationColor: defaultTheme.colorScheme.onSurface
),
);
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
primaryLabels.first.painter.text.style,
Typography.material2021().englishLike.bodyLarge!
.merge(Typography.material2021().black.bodyLarge)
.copyWith(
color: defaultTheme.colorScheme.onSurface,
decorationColor: defaultTheme.colorScheme.onSurface
),
);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
selectedLabels.first.painter.text.style,
Typography.material2021().englishLike.bodyLarge!
.merge(Typography.material2021().black.bodyLarge)
.copyWith(
color: defaultTheme.colorScheme.onPrimary,
decorationColor: defaultTheme.colorScheme.onSurface,
),
);
final Material hourMaterial = _textMaterial(tester, '7');
expect(hourMaterial.color, defaultTheme.colorScheme.primaryContainer);
expect(
hourMaterial.shape,
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0)))
);
final Material minuteMaterial = _textMaterial(tester, '15');
expect(minuteMaterial.color, defaultTheme.colorScheme.surfaceVariant);
expect(
minuteMaterial.shape,
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
);
final Material amMaterial = _textMaterial(tester, 'AM');
expect(amMaterial.color, defaultTheme.colorScheme.tertiaryContainer);
final Material pmMaterial = _textMaterial(tester, 'PM');
expect(pmMaterial.color, Colors.transparent);
final Material dayPeriodMaterial = _dayPeriodMaterial(tester);
expect(
dayPeriodMaterial.shape,
RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
side: BorderSide(color: defaultTheme.colorScheme.outline),
),
);
final Container dayPeriodDivider = _dayPeriodDivider(tester);
expect(
dayPeriodDivider.decoration,
BoxDecoration(border: Border(left: BorderSide(color: defaultTheme.colorScheme.outline))),
); );
final IconButton entryModeIconButton = _entryModeIconButton(tester);
expect(entryModeIconButton.color, null);
}); });
testWidgets('Material2 - Passing no TimePickerThemeData uses defaults - input mode', (WidgetTester tester) async {
final ThemeData defaultTheme = ThemeData(useMaterial3: false);
await tester.pumpWidget(_TimePickerLauncher(themeData: defaultTheme, entryMode: TimePickerEntryMode.input));
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final InputDecoration hourDecoration = _textField(tester, '7').decoration!;
expect(hourDecoration.filled, true);
expect(
hourDecoration.fillColor,
MaterialStateColor.resolveWith((Set<MaterialState> states) =>
defaultTheme.colorScheme.onSurface.withOpacity(0.12))
);
expect(
hourDecoration.enabledBorder,
const OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent))
);
expect(
hourDecoration.errorBorder,
OutlineInputBorder(borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2))
);
expect(
hourDecoration.focusedBorder,
OutlineInputBorder(borderSide: BorderSide(color: defaultTheme.colorScheme.primary, width: 2))
);
expect(
hourDecoration.focusedErrorBorder,
OutlineInputBorder(borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2))
);
expect(
hourDecoration.hintStyle,
Typography.material2014().englishLike.displayMedium!
.merge(defaultTheme.textTheme.displayMedium!.copyWith(color: defaultTheme.colorScheme.onSurface.withOpacity(0.36)))
);
});
testWidgets('Passing no TimePickerThemeData uses defaults - input mode', (WidgetTester tester) async { testWidgets('Material3 - Passing no TimePickerThemeData uses defaults - input mode', (WidgetTester tester) async {
final ThemeData defaultTheme = ThemeData(); final ThemeData defaultTheme = ThemeData(useMaterial3: true);
final bool material3 = defaultTheme.useMaterial3;
await tester.pumpWidget(_TimePickerLauncher(themeData: defaultTheme, entryMode: TimePickerEntryMode.input)); await tester.pumpWidget(_TimePickerLauncher(themeData: defaultTheme, entryMode: TimePickerEntryMode.input));
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle(const Duration(seconds: 1));
final InputDecoration hourDecoration = _textField(tester, '7').decoration!; final InputDecoration hourDecoration = _textField(tester, '7').decoration!;
expect(hourDecoration.filled, true); expect(hourDecoration.filled, true);
expect(hourDecoration.fillColor, material3 expect(hourDecoration.fillColor, defaultTheme.colorScheme.surfaceVariant);
? defaultTheme.colorScheme.surfaceVariant expect(
: MaterialStateColor.resolveWith((Set<MaterialState> states) => defaultTheme.colorScheme.onSurface.withOpacity(0.12))); hourDecoration.enabledBorder,
expect(hourDecoration.enabledBorder, material3 ? const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(8.0)), borderSide: BorderSide(color: Colors.transparent)) : const OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent))); const OutlineInputBorder(
expect(hourDecoration.errorBorder, material3 ? OutlineInputBorder(borderRadius: const BorderRadius.all(Radius.circular(8.0)), borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2.0)) : OutlineInputBorder(borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2))); borderRadius: BorderRadius.all(Radius.circular(8.0)),
expect(hourDecoration.focusedBorder, material3 ? OutlineInputBorder(borderRadius: const BorderRadius.all(Radius.circular(8.0)), borderSide: BorderSide(color: defaultTheme.colorScheme.primary, width: 2.0)) : OutlineInputBorder(borderSide: BorderSide(color: defaultTheme.colorScheme.primary, width: 2))); borderSide: BorderSide(color: Colors.transparent)),
expect(hourDecoration.focusedErrorBorder, material3 ? OutlineInputBorder(borderRadius: const BorderRadius.all(Radius.circular(8.0)), borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2.0)) : OutlineInputBorder(borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2))); );
expect(
hourDecoration.errorBorder,
OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2.0)),
);
expect(
hourDecoration.focusedBorder,
OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
borderSide: BorderSide(color: defaultTheme.colorScheme.primary, width: 2.0)),
);
expect(
hourDecoration.focusedErrorBorder,
OutlineInputBorder(
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
borderSide: BorderSide(color: defaultTheme.colorScheme.error, width: 2.0)),
);
expect( expect(
hourDecoration.hintStyle, hourDecoration.hintStyle,
material3 TextStyle(color: defaultTheme.colorScheme.onSurface.withOpacity(0.36))
? TextStyle(color: defaultTheme.colorScheme.onSurface.withOpacity(0.36))
: (Typography.material2014().englishLike.displayMedium!
.merge(defaultTheme.textTheme.displayMedium!.copyWith(color: defaultTheme.colorScheme.onSurface.withOpacity(0.36)))),
); );
}); });
testWidgets('Time picker uses values from TimePickerThemeData', (WidgetTester tester) async { testWidgets('Material2 - Time picker uses values from TimePickerThemeData', (WidgetTester tester) async {
final TimePickerThemeData timePickerTheme = _timePickerTheme(); final TimePickerThemeData timePickerTheme = _timePickerTheme();
final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme); final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme, useMaterial3: false);
final bool material3 = theme.useMaterial3;
await tester.pumpWidget(_TimePickerLauncher(themeData: theme)); await tester.pumpWidget(_TimePickerLauncher(themeData: theme));
await tester.tap(find.text('X')); await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1)); await tester.pumpAndSettle(const Duration(seconds: 1));
...@@ -313,69 +464,45 @@ void main() { ...@@ -313,69 +464,45 @@ void main() {
final RenderParagraph hourText = _textRenderParagraph(tester, '7'); final RenderParagraph hourText = _textRenderParagraph(tester, '7');
expect( expect(
hourText.text.style, hourText.text.style,
material3 Typography.material2014().englishLike.bodyMedium!
? (Typography.material2021().englishLike.bodyMedium! .merge(Typography.material2014().black.bodyMedium)
.merge(Typography.material2021().black.bodyMedium) .merge(timePickerTheme.hourMinuteTextStyle)
.merge(timePickerTheme.hourMinuteTextStyle) .copyWith(color: _selectedColor),
.copyWith(color: _selectedColor, decorationColor: const Color(0xff1c1b1f)))
: (Typography.material2014().englishLike.bodyMedium!
.merge(Typography.material2014().black.bodyMedium)
.merge(timePickerTheme.hourMinuteTextStyle)
.copyWith(color: _selectedColor)),
); );
final RenderParagraph minuteText = _textRenderParagraph(tester, '15'); final RenderParagraph minuteText = _textRenderParagraph(tester, '15');
expect( expect(
minuteText.text.style, minuteText.text.style,
material3 Typography.material2014().englishLike.bodyMedium!
? (Typography.material2021().englishLike.bodyMedium! .merge(Typography.material2014().black.bodyMedium)
.merge(Typography.material2021().black.bodyMedium) .merge(timePickerTheme.hourMinuteTextStyle)
.merge(timePickerTheme.hourMinuteTextStyle) .copyWith(color: _unselectedColor),
.copyWith(color: _unselectedColor, decorationColor: const Color(0xff1c1b1f)))
: (Typography.material2014().englishLike.bodyMedium!
.merge(Typography.material2014().black.bodyMedium)
.merge(timePickerTheme.hourMinuteTextStyle)
.copyWith(color: _unselectedColor)),
); );
final RenderParagraph amText = _textRenderParagraph(tester, 'AM'); final RenderParagraph amText = _textRenderParagraph(tester, 'AM');
expect( expect(
amText.text.style, amText.text.style,
material3 Typography.material2014().englishLike.titleMedium!
? (Typography.material2021().englishLike.bodyMedium! .merge(Typography.material2014().black.titleMedium)
.merge(Typography.material2021().black.bodyMedium) .merge(timePickerTheme.dayPeriodTextStyle)
.merge(timePickerTheme.hourMinuteTextStyle) .copyWith(color: _selectedColor),
.copyWith(color: _selectedColor, decorationColor: const Color(0xff1c1b1f)))
: (Typography.material2014().englishLike.titleMedium!
.merge(Typography.material2014().black.titleMedium)
.merge(timePickerTheme.dayPeriodTextStyle)
.copyWith(color: _selectedColor)),
); );
final RenderParagraph pmText = _textRenderParagraph(tester, 'PM'); final RenderParagraph pmText = _textRenderParagraph(tester, 'PM');
expect( expect(
pmText.text.style, pmText.text.style,
material3 Typography.material2014().englishLike.titleMedium!
? (Typography.material2021().englishLike.bodyMedium! .merge(Typography.material2014().black.titleMedium)
.merge(Typography.material2021().black.bodyMedium) .merge(timePickerTheme.dayPeriodTextStyle)
.merge(timePickerTheme.hourMinuteTextStyle) .copyWith(color: _unselectedColor),
.copyWith(color: _unselectedColor, decorationColor: const Color(0xff1c1b1f)))
: (Typography.material2014().englishLike.titleMedium!
.merge(Typography.material2014().black.titleMedium)
.merge(timePickerTheme.dayPeriodTextStyle)
.copyWith(color: _unselectedColor)),
); );
final RenderParagraph helperText = _textRenderParagraph(tester, material3 ? 'Select time' : 'SELECT TIME'); final RenderParagraph helperText = _textRenderParagraph(tester, 'SELECT TIME');
expect( expect(
helperText.text.style, helperText.text.style,
material3 Typography.material2014().englishLike.bodyMedium!
? (Typography.material2021().englishLike.bodyMedium! .merge(Typography.material2014().black.bodyMedium)
.merge(Typography.material2021().black.bodyMedium) .merge(timePickerTheme.helpTextStyle),
.merge(timePickerTheme.helpTextStyle).copyWith(color: theme.colorScheme.onSurface, decorationColor: theme.colorScheme.onSurface))
: (Typography.material2014().englishLike.bodyMedium!
.merge(Typography.material2014().black.bodyMedium)
.merge(timePickerTheme.helpTextStyle)),
); );
final CustomPaint dialPaint = tester.widget(findDialPaint); final CustomPaint dialPaint = tester.widget(findDialPaint);
...@@ -385,26 +512,18 @@ void main() { ...@@ -385,26 +512,18 @@ void main() {
expect( expect(
// ignore: avoid_dynamic_calls // ignore: avoid_dynamic_calls
primaryLabels.first.painter.text.style, primaryLabels.first.painter.text.style,
material3 Typography.material2014().englishLike.bodyLarge!
? (Typography.material2021().englishLike.bodyLarge! .merge(Typography.material2014().black.bodyLarge)
.merge(Typography.material2021().black.bodyLarge) .copyWith(color: _unselectedColor),
.copyWith(color: _unselectedColor, decorationColor: theme.colorScheme.onSurface))
: (Typography.material2014().englishLike.bodyLarge!
.merge(Typography.material2014().black.bodyLarge)
.copyWith(color: _unselectedColor)),
); );
// ignore: avoid_dynamic_calls // ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>; final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
expect( expect(
// ignore: avoid_dynamic_calls // ignore: avoid_dynamic_calls
selectedLabels.first.painter.text.style, selectedLabels.first.painter.text.style,
material3 Typography.material2014().englishLike.bodyLarge!
? (Typography.material2021().englishLike.bodyLarge! .merge(Typography.material2014().white.bodyLarge)
.merge(Typography.material2021().black.bodyLarge) .copyWith(color: _selectedColor),
.copyWith(color: _selectedColor, decorationColor: theme.colorScheme.onSurface))
: (Typography.material2014().englishLike.bodyLarge!
.merge(Typography.material2014().white.bodyLarge)
.copyWith(color: _selectedColor)),
); );
final Material hourMaterial = _textMaterial(tester, '7'); final Material hourMaterial = _textMaterial(tester, '7');
...@@ -436,8 +555,125 @@ void main() { ...@@ -436,8 +555,125 @@ void main() {
final IconButton entryModeIconButton = _entryModeIconButton(tester); final IconButton entryModeIconButton = _entryModeIconButton(tester);
expect( expect(
entryModeIconButton.color, entryModeIconButton.color,
material3 ? null : timePickerTheme.entryModeIconColor, timePickerTheme.entryModeIconColor,
);
});
testWidgets('Material3 - Time picker uses values from TimePickerThemeData', (WidgetTester tester) async {
final TimePickerThemeData timePickerTheme = _timePickerTheme();
final ThemeData theme = ThemeData(timePickerTheme: timePickerTheme, useMaterial3: true);
await tester.pumpWidget(_TimePickerLauncher(themeData: theme));
await tester.tap(find.text('X'));
await tester.pumpAndSettle(const Duration(seconds: 1));
final Material dialogMaterial = _dialogMaterial(tester);
expect(dialogMaterial.color, timePickerTheme.backgroundColor);
expect(dialogMaterial.shape, timePickerTheme.shape);
final RenderBox dial = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint));
expect(
dial,
paints
..circle(color: Color(timePickerTheme.dialBackgroundColor!.value)) // Dial background color.
..circle(color: Color(timePickerTheme.dialHandColor!.value)), // Dial hand color.
);
final RenderParagraph hourText = _textRenderParagraph(tester, '7');
expect(
hourText.text.style,
Typography.material2021().englishLike.bodyMedium!
.merge(Typography.material2021().black.bodyMedium)
.merge(timePickerTheme.hourMinuteTextStyle)
.copyWith(color: _selectedColor, decorationColor: const Color(0xff1c1b1f)),
);
final RenderParagraph minuteText = _textRenderParagraph(tester, '15');
expect(
minuteText.text.style,
Typography.material2021().englishLike.bodyMedium!
.merge(Typography.material2021().black.bodyMedium)
.merge(timePickerTheme.hourMinuteTextStyle)
.copyWith(color: _unselectedColor, decorationColor: const Color(0xff1c1b1f)),
);
final RenderParagraph amText = _textRenderParagraph(tester, 'AM');
expect(
amText.text.style,
Typography.material2021().englishLike.bodyMedium!
.merge(Typography.material2021().black.bodyMedium)
.merge(timePickerTheme.hourMinuteTextStyle)
.copyWith(color: _selectedColor, decorationColor: const Color(0xff1c1b1f)),
);
final RenderParagraph pmText = _textRenderParagraph(tester, 'PM');
expect(
pmText.text.style,
Typography.material2021().englishLike.bodyMedium!
.merge(Typography.material2021().black.bodyMedium)
.merge(timePickerTheme.hourMinuteTextStyle)
.copyWith(color: _unselectedColor, decorationColor: const Color(0xff1c1b1f)),
);
final RenderParagraph helperText = _textRenderParagraph(tester, 'Select time');
expect(
helperText.text.style,
Typography.material2021().englishLike.bodyMedium!
.merge(Typography.material2021().black.bodyMedium)
.merge(timePickerTheme.helpTextStyle).copyWith(
color: theme.colorScheme.onSurface,
decorationColor: theme.colorScheme.onSurface
),
);
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
primaryLabels.first.painter.text.style,
Typography.material2021().englishLike.bodyLarge!
.merge(Typography.material2021().black.bodyLarge)
.copyWith(color: _unselectedColor, decorationColor: theme.colorScheme.onSurface),
);
// ignore: avoid_dynamic_calls
final List<dynamic> selectedLabels = dialPainter.selectedLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
selectedLabels.first.painter.text.style,
Typography.material2021().englishLike.bodyLarge!
.merge(Typography.material2021().black.bodyLarge)
.copyWith(color: _selectedColor, decorationColor: theme.colorScheme.onSurface),
);
final Material hourMaterial = _textMaterial(tester, '7');
expect(hourMaterial.color, _selectedColor);
expect(hourMaterial.shape, timePickerTheme.hourMinuteShape);
final Material minuteMaterial = _textMaterial(tester, '15');
expect(minuteMaterial.color, _unselectedColor);
expect(minuteMaterial.shape, timePickerTheme.hourMinuteShape);
final Material amMaterial = _textMaterial(tester, 'AM');
expect(amMaterial.color, _selectedColor);
final Material pmMaterial = _textMaterial(tester, 'PM');
expect(pmMaterial.color, _unselectedColor);
final Material dayPeriodMaterial = _dayPeriodMaterial(tester);
expect(
dayPeriodMaterial.shape,
timePickerTheme.dayPeriodShape!.copyWith(side: timePickerTheme.dayPeriodBorderSide),
); );
final Container dayPeriodDivider = _dayPeriodDivider(tester);
expect(
dayPeriodDivider.decoration,
BoxDecoration(border: Border(left: timePickerTheme.dayPeriodBorderSide!)),
);
final IconButton entryModeIconButton = _entryModeIconButton(tester);
expect(entryModeIconButton.color, null);
}); });
testWidgets('Time picker uses values from TimePickerThemeData with InputDecorationTheme - input mode', (WidgetTester tester) async { testWidgets('Time picker uses values from TimePickerThemeData with InputDecorationTheme - input mode', (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment