Unverified Commit fe32675b authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Add M3 date picker tests and fix divider (#127197)

partial fix https://github.com/flutter/flutter/issues/126826 (date range picker is another PR)
fixes https://github.com/flutter/flutter/issues/126597

### Description

1. This PR adds a bunch of M3 date picker tests
2. Fixes divider taking more space than it should
3. Added dividerColor  theme value to allow users to customise divider color just for the date pickers from date picker theme 

<details> 
<summary>code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        datePickerTheme: DatePickerThemeData(
          headerBackgroundColor: Colors.amber,
        ),
        useMaterial3: true,
      ),
      home: Scaffold(
        body: Builder(builder: (BuildContext context) {
          return Center(
            child: ElevatedButton(
              onPressed: () async {
                showDatePicker(
                  context: context,
                  initialDate: DateTime(2016, DateTime.january, 15),
                  firstDate: DateTime(2001),
                  lastDate: DateTime(2031, DateTime.december, 31),
                );
              },
              child: const Text('Show Date Picker'),
            ),
          );
        }),
      ),
    );
  }
}
``` 
	
</details>

### Before
![Screenshot 2023-05-19 at 17 32 19](https://github.com/flutter/flutter/assets/48603081/4463de1a-fb94-4930-a6ab-8245331a8134)

### After
![Screenshot 2023-05-19 at 17 51 15](https://github.com/flutter/flutter/assets/48603081/296276f0-cf13-4a59-8542-a46da774153b)
parent d9045f02
......@@ -675,7 +675,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
if (useMaterial3) const Divider(),
if (useMaterial3) Divider(height: 0, color: datePickerTheme.dividerColor),
Expanded(child: picker),
actions,
],
......@@ -686,7 +686,7 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
if (useMaterial3) const VerticalDivider(),
if (useMaterial3) VerticalDivider(width: 0, color: datePickerTheme.dividerColor),
Flexible(
child: Column(
mainAxisSize: MainAxisSize.min,
......@@ -850,6 +850,7 @@ class _DatePickerHeader extends StatelessWidget {
padding: const EdgeInsetsDirectional.only(
start: 24,
end: 12,
bottom: 12,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
......
......@@ -67,6 +67,7 @@ class DatePickerThemeData with Diagnosticable {
this.rangePickerHeaderHelpStyle,
this.rangeSelectionBackgroundColor,
this.rangeSelectionOverlayColor,
this.dividerColor,
});
/// Overrides the default value of [Dialog.backgroundColor].
......@@ -282,6 +283,11 @@ class DatePickerThemeData with Diagnosticable {
/// [DateRangePickerDialog] is focused, hovered, or pressed.
final MaterialStateProperty<Color?>? rangeSelectionOverlayColor;
/// Overrides the default color used to paint the horizontal divider
/// below the header text when dialog is in in portrait orientation
/// and vertical divider when the dialog is in landscape orientation.
final Color? dividerColor;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
DatePickerThemeData copyWith({
......@@ -317,6 +323,7 @@ class DatePickerThemeData with Diagnosticable {
TextStyle? rangePickerHeaderHelpStyle,
Color? rangeSelectionBackgroundColor,
MaterialStateProperty<Color?>? rangeSelectionOverlayColor,
Color? dividerColor,
}) {
return DatePickerThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
......@@ -351,6 +358,7 @@ class DatePickerThemeData with Diagnosticable {
rangePickerHeaderHelpStyle: rangePickerHeaderHelpStyle ?? this.rangePickerHeaderHelpStyle,
rangeSelectionBackgroundColor: rangeSelectionBackgroundColor ?? this.rangeSelectionBackgroundColor,
rangeSelectionOverlayColor: rangeSelectionOverlayColor ?? this.rangeSelectionOverlayColor,
dividerColor: dividerColor ?? this.dividerColor,
);
}
......@@ -392,6 +400,7 @@ class DatePickerThemeData with Diagnosticable {
rangePickerHeaderHelpStyle: TextStyle.lerp(a?.rangePickerHeaderHelpStyle, b?.rangePickerHeaderHelpStyle, t),
rangeSelectionBackgroundColor: Color.lerp(a?.rangeSelectionBackgroundColor, b?.rangeSelectionBackgroundColor, t),
rangeSelectionOverlayColor: MaterialStateProperty.lerp<Color?>(a?.rangeSelectionOverlayColor, b?.rangeSelectionOverlayColor, t, Color.lerp),
dividerColor: Color.lerp(a?.dividerColor, b?.dividerColor, t),
);
}
......@@ -439,6 +448,7 @@ class DatePickerThemeData with Diagnosticable {
rangePickerHeaderHelpStyle,
rangeSelectionBackgroundColor,
rangeSelectionOverlayColor,
dividerColor,
]);
@override
......@@ -478,7 +488,8 @@ class DatePickerThemeData with Diagnosticable {
&& other.rangePickerHeaderHeadlineStyle == rangePickerHeaderHeadlineStyle
&& other.rangePickerHeaderHelpStyle == rangePickerHeaderHelpStyle
&& other.rangeSelectionBackgroundColor == rangeSelectionBackgroundColor
&& other.rangeSelectionOverlayColor == rangeSelectionOverlayColor;
&& other.rangeSelectionOverlayColor == rangeSelectionOverlayColor
&& other.dividerColor == dividerColor;
}
@override
......@@ -516,6 +527,7 @@ class DatePickerThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<TextStyle>('rangePickerHeaderHelpStyle', rangePickerHeaderHelpStyle, defaultValue: null));
properties.add(ColorProperty('rangeSelectionBackgroundColor', rangeSelectionBackgroundColor, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('rangeSelectionOverlayColor', rangeSelectionOverlayColor, defaultValue: null));
properties.add(ColorProperty('dividerColor', dividerColor, defaultValue: null));
}
}
......
......@@ -4,6 +4,7 @@
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -60,6 +61,9 @@ void main() {
currentMode = initialEntryMode;
});
const Size wideWindowSize = Size(1920.0, 1080.0);
const Size narrowWindowSize = Size(1070.0, 1770.0);
Future<void> prepareDatePicker(
WidgetTester tester,
Future<void> Function(Future<DateTime?> date) callback, {
......@@ -120,11 +124,62 @@ void main() {
}
group('showDatePicker Dialog', () {
testWidgets('Default dialog size', (WidgetTester tester) async {
Future<void> showPicker(WidgetTester tester, Size size) async {
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.reset);
await prepareDatePicker(tester, (Future<DateTime?> date) async {}, useMaterial3: true);
}
const Size calendarLandscapeDialogSize = Size(496.0, 346.0);
const Size calendarPortraitDialogSizeM3 = Size(328.0, 512.0);
// Test landscape layout.
await showPicker(tester, wideWindowSize);
Size dialogContainerSize = tester.getSize(find.byType(AnimatedContainer));
expect(dialogContainerSize, calendarLandscapeDialogSize);
// Close the dialog.
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();
// Test portrait layout.
await showPicker(tester, narrowWindowSize);
dialogContainerSize = tester.getSize(find.byType(AnimatedContainer));
expect(dialogContainerSize, calendarPortraitDialogSizeM3);
});
testWidgets('Default dialog properties', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
await prepareDatePicker(tester, (Future<DateTime?> date) async {
final Material dialogMaterial = tester.widget<Material>(
find.descendant(of: find.byType(Dialog),
matching: find.byType(Material),
).first);
expect(dialogMaterial.color, theme.colorScheme.surface);
expect(dialogMaterial.shadowColor, Colors.transparent);
expect(dialogMaterial.surfaceTintColor, theme.colorScheme.surfaceTint);
expect(dialogMaterial.elevation, 6.0);
expect(
dialogMaterial.shape,
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0))),
);
expect(dialogMaterial.clipBehavior, Clip.antiAlias);
final Dialog dialog = tester.widget<Dialog>(find.byType(Dialog));
expect(dialog.insetPadding, const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0));
}, useMaterial3: theme.useMaterial3);
});
testWidgets('Material3 uses sentence case labels', (WidgetTester tester) async {
await prepareDatePicker(tester, (Future<DateTime?> date) async {
expect(find.text('Select date'), findsOneWidget);
}, useMaterial3: true);
});
testWidgets('Cancel, confirm, and help text is used', (WidgetTester tester) async {
cancelText = 'nope';
confirmText = 'yep';
......@@ -348,7 +403,8 @@ void main() {
);
await tester.tap(find.text('X'));
await tester.pumpAndSettle();
final Material defaultDialogMaterial = tester.widget<Material>(find.descendant(of: find.byType(Dialog), matching: find.byType(Material)).first);
final Material defaultDialogMaterial = tester.widget<Material>(find.descendant(
of: find.byType(Dialog), matching: find.byType(Material)).first);
expect(defaultDialogMaterial.shape, datePickerDefaultDialogTheme.shape);
expect(defaultDialogMaterial.elevation, datePickerDefaultDialogTheme.elevation);
......@@ -578,6 +634,202 @@ void main() {
});
group('Calendar mode', () {
testWidgets('Default Calendar mode layout (Landscape)', (WidgetTester tester) async {
final Finder helpText = find.text('Select date');
final Finder headerText = find.text('Fri, Jan 15');
final Finder subHeaderText = find.text('January 2016');
final Finder cancelButtonText = find.text('Cancel');
final Finder okButtonText = find.text('OK');
const EdgeInsets insetPadding = EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0);
tester.view.physicalSize = wideWindowSize;
addTearDown(tester.view.reset);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Material(
child: DatePickerDialog(
initialDate: initialDate,
firstDate: firstDate,
lastDate: lastDate,
),
),
));
expect(helpText, findsOneWidget);
expect(headerText, findsOneWidget);
expect(subHeaderText, findsOneWidget);
expect(cancelButtonText, findsOneWidget);
expect(okButtonText, findsOneWidget);
// Test help text position.
final Offset dialogTopLeft = tester.getTopLeft(find.byType(AnimatedContainer));
final Offset helpTextTopLeft = tester.getTopLeft(helpText);
expect(helpTextTopLeft.dx, dialogTopLeft.dx + (insetPadding.horizontal / 2));
expect(helpTextTopLeft.dy, dialogTopLeft.dy + 16.0);
// Test header text position.
final Offset headerTextTopLeft = tester.getTopLeft(headerText);
final Offset helpTextBottomLeft = tester.getBottomLeft(helpText);
expect(headerTextTopLeft.dx, dialogTopLeft.dx + (insetPadding.horizontal / 2));
expect(headerTextTopLeft.dy, helpTextBottomLeft.dy + 16.0);
// Test switch button position.
final Finder switchButtonM3 = find.widgetWithIcon(IconButton, Icons.edit_outlined);
final Offset switchButtonTopLeft = tester.getTopLeft(switchButtonM3);
final Offset headerTextBottomLeft = tester.getBottomLeft(headerText);
expect(switchButtonTopLeft.dx, dialogTopLeft.dx + 4.0);
expect(switchButtonTopLeft.dy, headerTextBottomLeft.dy);
// Test vertical divider position.
final Finder divider = find.byType(VerticalDivider);
final Offset dividerTopLeft = tester.getTopLeft(divider);
final Offset headerTextTopRiught = tester.getTopRight(headerText);
expect(dividerTopLeft.dx, headerTextTopRiught.dx + 16.0);
expect(dividerTopLeft.dy, dialogTopLeft.dy);
// Test sub header text position.
final Offset subHeaderTextTopLeft = tester.getTopLeft(subHeaderText);
final Offset dividerTopRight = tester.getTopRight(divider);
expect(subHeaderTextTopLeft.dx, dividerTopRight.dx + 24.0);
// TODO(tahatesser): https://github.com/flutter/flutter/issues/99933
// A bug in the HTML renderer and/or Chrome 96+ causes a
// discrepancy in the paragraph height.
const bool hasIssue99933 = kIsWeb && !bool.fromEnvironment('FLUTTER_WEB_USE_SKIA');
expect(subHeaderTextTopLeft.dy, dialogTopLeft.dy + 16.0 - (hasIssue99933 ? 0.5 : 0.0));
// Test sub header icon position.
final Finder subHeaderIcon = find.byIcon(Icons.arrow_drop_down);
final Offset subHeaderIconTopLeft = tester.getTopLeft(subHeaderIcon);
final Offset subHeaderTextTopRight = tester.getTopRight(subHeaderText);
expect(subHeaderIconTopLeft.dx, subHeaderTextTopRight.dx);
expect(subHeaderIconTopLeft.dy, dialogTopLeft.dy + 14.0);
// Test calendar page view position.
final Finder calendarPageView = find.byType(PageView);
final Offset calendarPageViewTopLeft = tester.getTopLeft(calendarPageView);
final Offset subHeaderTextBottomLeft = tester.getBottomLeft(subHeaderText);
expect(calendarPageViewTopLeft.dx, dividerTopRight.dx);
expect(calendarPageViewTopLeft.dy, subHeaderTextBottomLeft.dy + 16.0 - (hasIssue99933 ? 0.5 : 0.0));
// Test month navigation icons position.
final Finder previousMonthButton = find.widgetWithIcon(IconButton, Icons.chevron_left);
final Finder nextMonthButton = find.widgetWithIcon(IconButton, Icons.chevron_right);
final Offset previousMonthButtonTopRight = tester.getTopRight(previousMonthButton);
final Offset nextMonthButtonTopRight = tester.getTopRight(nextMonthButton);
final Offset dialogTopRight = tester.getTopRight(find.byType(AnimatedContainer));
expect(nextMonthButtonTopRight.dx, dialogTopRight.dx - 4.0);
expect(nextMonthButtonTopRight.dy, dialogTopRight.dy + 2.0);
expect(previousMonthButtonTopRight.dx, nextMonthButtonTopRight.dx - 48.0);
// Test action buttons position.
final Offset dialogBottomRight = tester.getBottomRight(find.byType(AnimatedContainer));
final Offset okButtonTopRight = tester.getTopRight(find.widgetWithText(TextButton, 'OK'));
final Offset cancelButtonTopRight = tester.getTopRight(find.widgetWithText(TextButton, 'Cancel'));
final Offset calendarPageViewBottomRight = tester.getBottomRight(calendarPageView);
expect(okButtonTopRight.dx, dialogBottomRight.dx - 8);
expect(okButtonTopRight.dy, calendarPageViewBottomRight.dy + 2);
final Offset okButtonTopLeft = tester.getTopLeft(find.widgetWithText(TextButton, 'OK'));
expect(cancelButtonTopRight.dx, okButtonTopLeft.dx - 8);
});
testWidgets('Default Calendar mode layout (Portrait)', (WidgetTester tester) async {
final Finder helpText = find.text('Select date');
final Finder headerText = find.text('Fri, Jan 15');
final Finder subHeaderText = find.text('January 2016');
final Finder cancelButtonText = find.text('Cancel');
final Finder okButtonText = find.text('OK');
tester.view.physicalSize = narrowWindowSize;
addTearDown(tester.view.reset);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Material(
child: DatePickerDialog(
initialDate: initialDate,
firstDate: firstDate,
lastDate: lastDate,
),
),
));
expect(helpText, findsOneWidget);
expect(headerText, findsOneWidget);
expect(subHeaderText, findsOneWidget);
expect(cancelButtonText, findsOneWidget);
expect(okButtonText, findsOneWidget);
// Test help text position.
final Offset dialogTopLeft = tester.getTopLeft(find.byType(AnimatedContainer));
final Offset helpTextTopLeft = tester.getTopLeft(helpText);
expect(helpTextTopLeft.dx, dialogTopLeft.dx + 24.0);
expect(helpTextTopLeft.dy, dialogTopLeft.dy + 16.0);
// Test header text position
final Offset headerTextTextTopLeft = tester.getTopLeft(headerText);
final Offset helpTextBottomLeft = tester.getBottomLeft(helpText);
expect(headerTextTextTopLeft.dx, dialogTopLeft.dx + 24.0);
// TODO(tahatesser): https://github.com/flutter/flutter/issues/99933
// A bug in the HTML renderer and/or Chrome 96+ causes a
// discrepancy in the paragraph height.
const bool hasIssue99933 = kIsWeb && !bool.fromEnvironment('FLUTTER_WEB_USE_SKIA');
expect(headerTextTextTopLeft.dy, helpTextBottomLeft.dy + 28.0 - (hasIssue99933 ? 1.0 : 0.0));
// Test switch button position.
final Finder switchButtonM3 = find.widgetWithIcon(IconButton, Icons.edit_outlined);
final Offset switchButtonTopRight = tester.getTopRight(switchButtonM3);
final Offset dialogTopRight = tester.getTopRight(find.byType(AnimatedContainer));
expect(switchButtonTopRight.dx, dialogTopRight.dx - 12.0);
expect(switchButtonTopRight.dy, headerTextTextTopLeft.dy - 4.0);
// Test horizontal divider position.
final Finder divider = find.byType(Divider);
final Offset dividerTopLeft = tester.getTopLeft(divider);
final Offset headerTextBottomLeft = tester.getBottomLeft(headerText);
expect(dividerTopLeft.dx, dialogTopLeft.dx);
expect(dividerTopLeft.dy, headerTextBottomLeft.dy + 16.0);
// Test subHeaderText position.
final Offset subHeaderTextTopLeft = tester.getTopLeft(subHeaderText);
final Offset dividerBottomLeft = tester.getBottomLeft(divider);
expect(subHeaderTextTopLeft.dx, dialogTopLeft.dx + 24.0);
expect(subHeaderTextTopLeft.dy, dividerBottomLeft.dy + 16.0 - (hasIssue99933 ? 0.5 : 0.0));
// Test sub header icon position.
final Finder subHeaderIcon = find.byIcon(Icons.arrow_drop_down);
final Offset subHeaderIconTopLeft = tester.getTopLeft(subHeaderIcon);
final Offset subHeaderTextTopRight = tester.getTopRight(subHeaderText);
expect(subHeaderIconTopLeft.dx, subHeaderTextTopRight.dx);
expect(subHeaderIconTopLeft.dy, dividerBottomLeft.dy + 14.0);
// Test month navigation icons position.
final Finder previousMonthButton = find.widgetWithIcon(IconButton, Icons.chevron_left);
final Finder nextMonthButton = find.widgetWithIcon(IconButton, Icons.chevron_right);
final Offset previousMonthButtonTopRight = tester.getTopRight(previousMonthButton);
final Offset nextMonthButtonTopRight = tester.getTopRight(nextMonthButton);
expect(nextMonthButtonTopRight.dx, dialogTopRight.dx - 4.0);
expect(nextMonthButtonTopRight.dy, dividerBottomLeft.dy + 2.0);
expect(previousMonthButtonTopRight.dx, nextMonthButtonTopRight.dx - 48.0);
// Test calendar page view position.
final Finder calendarPageView = find.byType(PageView);
final Offset calendarPageViewTopLeft = tester.getTopLeft(calendarPageView);
final Offset subHeaderTextBottomLeft = tester.getBottomLeft(subHeaderText);
expect(calendarPageViewTopLeft.dx, dialogTopLeft.dx);
expect(calendarPageViewTopLeft.dy, subHeaderTextBottomLeft.dy + 16.0 - (hasIssue99933 ? 0.5 : 0.0));
// Test action buttons position.
final Offset dialogBottomRight = tester.getBottomRight(find.byType(AnimatedContainer));
final Offset okButtonTopRight = tester.getTopRight(find.widgetWithText(TextButton, 'OK'));
final Offset cancelButtonTopRight = tester.getTopRight(find.widgetWithText(TextButton, 'Cancel'));
final Offset calendarPageViewBottomRight = tester.getBottomRight(calendarPageView);
final Offset okButtonTopLeft = tester.getTopLeft(find.widgetWithText(TextButton, 'OK'));
expect(okButtonTopRight.dx, dialogBottomRight.dx - 8);
expect(okButtonTopRight.dy, calendarPageViewBottomRight.dy + 2);
expect(cancelButtonTopRight.dx, okButtonTopLeft.dx - 8);
});
testWidgets('Can select a day', (WidgetTester tester) async {
await prepareDatePicker(tester, (Future<DateTime?> date) async {
await tester.tap(find.text('12'));
......@@ -843,6 +1095,18 @@ void main() {
initialEntryMode = DatePickerEntryMode.input;
});
testWidgets('Default InputDecoration', (WidgetTester tester) async {
await prepareDatePicker(tester, (Future<DateTime?> date) async {
final InputDecoration decoration = tester.widget<TextField>(
find.byType(TextField)).decoration!;
expect(decoration.border, const OutlineInputBorder());
expect(decoration.filled, false);
expect(decoration.hintText, 'mm/dd/yyyy');
expect(decoration.labelText, 'Enter Date');
expect(decoration.errorText, null);
}, useMaterial3: true);
});
testWidgets('Initial entry mode is used', (WidgetTester tester) async {
await prepareDatePicker(tester, (Future<DateTime?> date) async {
expect(find.byType(TextField), findsOneWidget);
......@@ -1591,6 +1855,86 @@ void main() {
await tester.pumpAndSettle();
});
});
group('Material 2', () {
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
// is turned on by default, these tests can be removed.
group('showDatePicker Dialog', () {
testWidgets('Default dialog size', (WidgetTester tester) async {
Future<void> showPicker(WidgetTester tester, Size size) async {
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.reset);
await prepareDatePicker(tester, (Future<DateTime?> date) async {});
}
const Size wideWindowSize = Size(1920.0, 1080.0);
const Size narrowWindowSize = Size(1070.0, 1770.0);
const Size calendarLandscapeDialogSize = Size(496.0, 346.0);
const Size calendarPortraitDialogSizeM2 = Size(330.0, 518.0);
// Test landscape layout.
await showPicker(tester, wideWindowSize);
Size dialogContainerSize = tester.getSize(find.byType(AnimatedContainer));
expect(dialogContainerSize, calendarLandscapeDialogSize);
// Close the dialog.
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();
// Test portrait layout.
await showPicker(tester, narrowWindowSize);
dialogContainerSize = tester.getSize(find.byType(AnimatedContainer));
expect(dialogContainerSize, calendarPortraitDialogSizeM2);
});
testWidgets('Default dialog properties', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: false);
await prepareDatePicker(tester, (Future<DateTime?> date) async {
final Material dialogMaterial = tester.widget<Material>(
find.descendant(of: find.byType(Dialog),
matching: find.byType(Material),
).first);
expect(dialogMaterial.color, theme.colorScheme.surface);
expect(dialogMaterial.shadowColor, theme.shadowColor);
expect(dialogMaterial.elevation, 24.0);
expect(
dialogMaterial.shape,
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
);
expect(dialogMaterial.clipBehavior, Clip.antiAlias);
final Dialog dialog = tester.widget<Dialog>(find.byType(Dialog));
expect(dialog.insetPadding, const EdgeInsets.symmetric(horizontal: 16.0, vertical: 24.0));
}, useMaterial3: theme.useMaterial3);
});
});
group('Input mode', () {
setUp(() {
firstDate = DateTime(2015);
lastDate = DateTime(2017, DateTime.december, 31);
initialDate = DateTime(2016, DateTime.january, 15);
initialEntryMode = DatePickerEntryMode.input;
});
testWidgets('Default InputDecoration', (WidgetTester tester) async {
await prepareDatePicker(tester, (Future<DateTime?> date) async {
final InputDecoration decoration = tester.widget<TextField>(
find.byType(TextField)).decoration!;
expect(decoration.border, const UnderlineInputBorder());
expect(decoration.filled, false);
expect(decoration.hintText, 'mm/dd/yyyy');
expect(decoration.labelText, 'Enter Date');
expect(decoration.errorText, null);
});
});
});
});
}
class _RestorableDatePickerDialogTestWidget extends StatefulWidget {
......
......@@ -40,6 +40,7 @@ void main() {
rangePickerHeaderHelpStyle: TextStyle(fontSize: 15),
rangeSelectionBackgroundColor: Color(0xffffff2f),
rangeSelectionOverlayColor: MaterialStatePropertyAll<Color>(Color(0xffffff3f)),
dividerColor: Color(0xffffff3f),
);
Material findDialogMaterial(WidgetTester tester) {
......@@ -70,6 +71,9 @@ void main() {
return container.decoration as BoxDecoration?;
}
const Size wideWindowSize = Size(1920.0, 1080.0);
const Size narrowWindowSize = Size(1070.0, 1770.0);
test('DatePickerThemeData copyWith, ==, hashCode basics', () {
expect(const DatePickerThemeData(), const DatePickerThemeData().copyWith());
expect(const DatePickerThemeData().hashCode, const DatePickerThemeData().copyWith().hashCode);
......@@ -114,6 +118,7 @@ void main() {
expect(theme.rangePickerHeaderHelpStyle, null);
expect(theme.rangeSelectionBackgroundColor, null);
expect(theme.rangeSelectionOverlayColor, null);
expect(theme.dividerColor, null);
});
testWidgets('DatePickerTheme.defaults M3 defaults', (WidgetTester tester) async {
......@@ -187,9 +192,9 @@ void main() {
expect(m3.rangePickerHeaderForegroundColor, colorScheme.onSurfaceVariant);
expect(m3.rangePickerHeaderHeadlineStyle, textTheme.titleLarge);
expect(m3.rangePickerHeaderHelpStyle, textTheme.titleSmall);
expect(m3.dividerColor, null);
});
testWidgets('DatePickerTheme.defaults M2 defaults', (WidgetTester tester) async {
late final DatePickerThemeData m2; // M2 defaults
late final ThemeData theme;
......@@ -310,6 +315,7 @@ void main() {
'rangePickerHeaderHelpStyle: TextStyle(inherit: true, size: 15.0)',
'rangeSelectionBackgroundColor: Color(0xffffff2f)',
'rangeSelectionOverlayColor: MaterialStatePropertyAll(Color(0xffffff3f))',
'dividerColor: Color(0xffffff3f)',
]);
});
......@@ -392,7 +398,6 @@ void main() {
expect(year2023Decoration.border?.bottom.color, datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}));
});
testWidgets('DateRangePickerDialog uses ThemeData datePicker theme', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
......@@ -434,4 +439,44 @@ void main() {
expect(selectedDate.style?.color, datePickerTheme.rangePickerHeaderForegroundColor);
expect(selectedDate.style?.fontSize, datePickerTheme.rangePickerHeaderHeadlineStyle?.fontSize);
});
testWidgets('Dividers use DatePickerThemeData.dividerColor', (WidgetTester tester) async {
Future<void> showPicker(WidgetTester tester, Size size) async {
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.reset);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light(useMaterial3: true).copyWith(
datePickerTheme: datePickerTheme,
),
home: Directionality(
textDirection: TextDirection.ltr,
child: Material(
child: Center(
child: DatePickerDialog(
initialDate: DateTime(2023, DateTime.january, 25),
firstDate: DateTime(2022),
lastDate: DateTime(2024, DateTime.december, 31),
currentDate: DateTime(2023, DateTime.january, 24),
),
),
),
),
),
);
}
await showPicker(tester, wideWindowSize);
// Test vertical divider.
final VerticalDivider verticalDivider = tester.widget(find.byType(VerticalDivider));
expect(verticalDivider.color, datePickerTheme.dividerColor);
// Test portrait layout.
await showPicker(tester, narrowWindowSize);
// Test horizontal divider.
final Divider horizontalDivider = tester.widget(find.byType(Divider));
expect(horizontalDivider.color, datePickerTheme.dividerColor);
});
}
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