Unverified Commit 5d555eb2 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Add M3 date range picker tests and fix header background theme color (#127662)

parent 9376a2ac
...@@ -13,7 +13,6 @@ import 'back_button.dart'; ...@@ -13,7 +13,6 @@ import 'back_button.dart';
import 'button_style.dart'; import 'button_style.dart';
import 'calendar_date_picker.dart'; import 'calendar_date_picker.dart';
import 'color_scheme.dart'; import 'color_scheme.dart';
import 'colors.dart';
import 'date.dart'; import 'date.dart';
import 'date_picker_theme.dart'; import 'date_picker_theme.dart';
import 'debug.dart'; import 'debug.dart';
...@@ -1588,6 +1587,7 @@ class _CalendarRangePickerDialog extends StatelessWidget { ...@@ -1588,6 +1587,7 @@ class _CalendarRangePickerDialog extends StatelessWidget {
final DatePickerThemeData themeData = DatePickerTheme.of(context); final DatePickerThemeData themeData = DatePickerTheme.of(context);
final DatePickerThemeData defaults = DatePickerTheme.defaults(context); final DatePickerThemeData defaults = DatePickerTheme.defaults(context);
final Color? dialogBackground = themeData.rangePickerBackgroundColor ?? defaults.rangePickerBackgroundColor; final Color? dialogBackground = themeData.rangePickerBackgroundColor ?? defaults.rangePickerBackgroundColor;
final Color? headerBackground = themeData.rangePickerHeaderBackgroundColor ?? defaults.rangePickerHeaderBackgroundColor;
final Color? headerForeground = themeData.rangePickerHeaderForegroundColor ?? defaults.rangePickerHeaderForegroundColor; final Color? headerForeground = themeData.rangePickerHeaderForegroundColor ?? defaults.rangePickerHeaderForegroundColor;
final Color? headerDisabledForeground = headerForeground?.withOpacity(0.38); final Color? headerDisabledForeground = headerForeground?.withOpacity(0.38);
final TextStyle? headlineStyle = themeData.rangePickerHeaderHeadlineStyle ?? defaults.rangePickerHeaderHeadlineStyle; final TextStyle? headlineStyle = themeData.rangePickerHeaderHeadlineStyle ?? defaults.rangePickerHeaderHeadlineStyle;
...@@ -1616,7 +1616,7 @@ class _CalendarRangePickerDialog extends StatelessWidget { ...@@ -1616,7 +1616,7 @@ class _CalendarRangePickerDialog extends StatelessWidget {
actionsIconTheme: iconTheme, actionsIconTheme: iconTheme,
elevation: useMaterial3 ? 0 : null, elevation: useMaterial3 ? 0 : null,
scrolledUnderElevation: useMaterial3 ? 0 : null, scrolledUnderElevation: useMaterial3 ? 0 : null,
backgroundColor: useMaterial3 ? Colors.transparent : null, backgroundColor: useMaterial3 ? headerBackground : null,
leading: CloseButton( leading: CloseButton(
onPressed: onCancel, onPressed: onCancel,
), ),
......
...@@ -431,6 +431,9 @@ void main() { ...@@ -431,6 +431,9 @@ void main() {
expect(material.surfaceTintColor, datePickerTheme.rangePickerSurfaceTintColor); expect(material.surfaceTintColor, datePickerTheme.rangePickerSurfaceTintColor);
expect(material.shape, datePickerTheme.rangePickerShape); expect(material.shape, datePickerTheme.rangePickerShape);
final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
expect(appBar.backgroundColor, datePickerTheme.rangePickerHeaderBackgroundColor);
final Text selectRange = tester.widget<Text>(find.text('Select range')); final Text selectRange = tester.widget<Text>(find.text('Select range'));
expect(selectRange.style?.color, datePickerTheme.rangePickerHeaderForegroundColor); expect(selectRange.style?.color, datePickerTheme.rangePickerHeaderForegroundColor);
expect(selectRange.style?.fontSize, datePickerTheme.rangePickerHeaderHelpStyle?.fontSize); expect(selectRange.style?.fontSize, datePickerTheme.rangePickerHeaderHelpStyle?.fontSize);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -108,6 +109,122 @@ void main() { ...@@ -108,6 +109,122 @@ void main() {
await callback(range); await callback(range);
} }
testWidgets('Default layout (calendar mode)', (WidgetTester tester) async {
await preparePicker(tester, (Future<DateTimeRange?> range) async {
final Finder helpText = find.text('Select range');
final Finder firstDateHeaderText = find.text('Jan 15');
final Finder lastDateHeaderText = find.text('Jan 25, 2016');
final Finder saveText = find.text('Save');
expect(helpText, findsOneWidget);
expect(firstDateHeaderText, findsOneWidget);
expect(lastDateHeaderText, findsOneWidget);
expect(saveText, findsOneWidget);
// Test the close button position.
final Offset closeButtonBottomRight = tester.getBottomRight(find.byType(CloseButton));
final Offset helpTextTopLeft = tester.getTopLeft(helpText);
expect(closeButtonBottomRight.dx, 56.0);
expect(closeButtonBottomRight.dy, helpTextTopLeft.dy);
// Test the save and entry buttons position.
final Offset saveButtonBottomLeft = tester.getBottomLeft(find.byType(TextButton));
final Offset entryButtonBottomLeft = tester.getBottomLeft(
find.widgetWithIcon(IconButton, Icons.edit_outlined),
);
expect(saveButtonBottomLeft.dx, 800 - 89.0);
expect(saveButtonBottomLeft.dy, helpTextTopLeft.dy);
expect(entryButtonBottomLeft.dx, saveButtonBottomLeft.dx - 48.0);
expect(entryButtonBottomLeft.dy, helpTextTopLeft.dy);
// Test help text position.
final Offset helpTextBottomLeft = tester.getBottomLeft(helpText);
expect(helpTextBottomLeft.dx, 72.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(helpTextBottomLeft.dy, closeButtonBottomRight.dy + 20.0 + (hasIssue99933 ? 1.0 : 0.0));
// Test the header position.
final Offset firstDateHeaderTopLeft = tester.getTopLeft(firstDateHeaderText);
final Offset lastDateHeaderTopLeft = tester.getTopLeft(lastDateHeaderText);
expect(firstDateHeaderTopLeft.dx, 72.0);
expect(firstDateHeaderTopLeft.dy, helpTextBottomLeft.dy + 8.0);
final Offset firstDateHeaderTopRight = tester.getTopRight(firstDateHeaderText);
expect(lastDateHeaderTopLeft.dx, firstDateHeaderTopRight.dx + 66.0);
expect(lastDateHeaderTopLeft.dy, helpTextBottomLeft.dy + 8.0);
// Test the day headers position.
final Offset dayHeadersGridTopLeft = tester.getTopLeft(find.byType(GridView).first);
final Offset firstDateHeaderBottomLeft = tester.getBottomLeft(firstDateHeaderText);
expect(dayHeadersGridTopLeft.dx, (800 - 384) / 2);
expect(dayHeadersGridTopLeft.dy, firstDateHeaderBottomLeft.dy + 16.0);
// Test the calendar custom scroll view position.
final Offset calendarScrollViewTopLeft = tester.getTopLeft(find.byType(CustomScrollView));
final Offset dayHeadersGridBottomLeft = tester.getBottomLeft(find.byType(GridView).first);
expect(calendarScrollViewTopLeft.dx, 0.0);
expect(calendarScrollViewTopLeft.dy, dayHeadersGridBottomLeft.dy);
}, useMaterial3: true);
});
testWidgets('Default Dialog properties (calendar mode)', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
await preparePicker(tester, (Future<DateTimeRange?> range) 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, Colors.transparent);
expect(dialogMaterial.elevation, 0.0);
expect(dialogMaterial.shape, const RoundedRectangleBorder());
expect(dialogMaterial.clipBehavior, Clip.antiAlias);
final Dialog dialog = tester.widget<Dialog>(find.byType(Dialog));
expect(dialog.insetPadding, EdgeInsets.zero);
}, useMaterial3: theme.useMaterial3);
});
testWidgets('Default Dialog properties (input mode)', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
await preparePicker(tester, (Future<DateTimeRange?> range) 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, Colors.transparent);
expect(dialogMaterial.elevation, 0.0);
expect(dialogMaterial.shape, const RoundedRectangleBorder());
expect(dialogMaterial.clipBehavior, Clip.antiAlias);
final Dialog dialog = tester.widget<Dialog>(find.byType(Dialog));
expect(dialog.insetPadding, EdgeInsets.zero);
}, useMaterial3: theme.useMaterial3);
});
testWidgets('Scaffold and AppBar defaults', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
await preparePicker(tester, (Future<DateTimeRange?> range) async {
final Scaffold scaffold = tester.widget<Scaffold>(find.byType(Scaffold));
expect(scaffold.backgroundColor, null);
final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
final IconThemeData iconTheme = IconThemeData(color: theme.colorScheme.onSurfaceVariant);
expect(appBar.iconTheme, iconTheme);
expect(appBar.actionsIconTheme, iconTheme);
expect(appBar.elevation, 0);
expect(appBar.scrolledUnderElevation, 0);
expect(appBar.backgroundColor, Colors.transparent);
}, useMaterial3: theme.useMaterial3);
});
group('Landscape input-only date picker headers use headlineSmall', () { group('Landscape input-only date picker headers use headlineSmall', () {
// Regression test for https://github.com/flutter/flutter/issues/122056 // Regression test for https://github.com/flutter/flutter/issues/122056
...@@ -668,6 +785,49 @@ void main() { ...@@ -668,6 +785,49 @@ void main() {
initialEntryMode = DatePickerEntryMode.input; initialEntryMode = DatePickerEntryMode.input;
}); });
testWidgets('Default Dialog properties (input mode)', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
await preparePicker(tester, (Future<DateTimeRange?> range) 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('Default InputDecoration', (WidgetTester tester) async {
await preparePicker(tester, (Future<DateTimeRange?> range) async {
final InputDecoration startDateDecoration = tester.widget<TextField>(
find.byType(TextField).first).decoration!;
expect(startDateDecoration.border, const OutlineInputBorder());
expect(startDateDecoration.filled, false);
expect(startDateDecoration.hintText, 'mm/dd/yyyy');
expect(startDateDecoration.labelText, 'Start Date');
expect(startDateDecoration.errorText, null);
final InputDecoration endDateDecoration = tester.widget<TextField>(
find.byType(TextField).last).decoration!;
expect(endDateDecoration.border, const OutlineInputBorder());
expect(endDateDecoration.filled, false);
expect(endDateDecoration.hintText, 'mm/dd/yyyy');
expect(endDateDecoration.labelText, 'End Date');
expect(endDateDecoration.errorText, null);
}, useMaterial3: true);
});
testWidgets('Initial entry mode is used', (WidgetTester tester) async { testWidgets('Initial entry mode is used', (WidgetTester tester) async {
await preparePicker(tester, (Future<DateTimeRange?> range) async { await preparePicker(tester, (Future<DateTimeRange?> range) async {
expect(find.byType(TextField), findsNWidgets(2)); expect(find.byType(TextField), findsNWidgets(2));
...@@ -1299,6 +1459,159 @@ void main() { ...@@ -1299,6 +1459,159 @@ void main() {
await tester.tap(find.text('CANCEL')); await tester.tap(find.text('CANCEL'));
await tester.pumpAndSettle(); 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.
testWidgets('Default layout (calendar mode)', (WidgetTester tester) async {
await preparePicker(tester, (Future<DateTimeRange?> range) async {
final Finder helpText = find.text('SELECT RANGE');
final Finder firstDateHeaderText = find.text('Jan 15');
final Finder lastDateHeaderText = find.text('Jan 25, 2016');
final Finder saveText = find.text('SAVE');
expect(helpText, findsOneWidget);
expect(firstDateHeaderText, findsOneWidget);
expect(lastDateHeaderText, findsOneWidget);
expect(saveText, findsOneWidget);
// Test the close button position.
final Offset closeButtonBottomRight = tester.getBottomRight(find.byType(CloseButton));
final Offset helpTextTopLeft = tester.getTopLeft(helpText);
expect(closeButtonBottomRight.dx, 56.0);
expect(closeButtonBottomRight.dy, helpTextTopLeft.dy - 6.0);
// Test the save and entry buttons position.
final Offset saveButtonBottomLeft = tester.getBottomLeft(find.byType(TextButton));
final Offset entryButtonBottomLeft = tester.getBottomLeft(
find.widgetWithIcon(IconButton, Icons.edit),
);
expect(saveButtonBottomLeft.dx, 800 - 80.0);
expect(saveButtonBottomLeft.dy, helpTextTopLeft.dy - 6.0);
expect(entryButtonBottomLeft.dx, saveButtonBottomLeft.dx - 48.0);
expect(entryButtonBottomLeft.dy, helpTextTopLeft.dy - 6.0);
// Test help text position.
final Offset helpTextBottomLeft = tester.getBottomLeft(helpText);
expect(helpTextBottomLeft.dx, 72.0);
expect(helpTextBottomLeft.dy, closeButtonBottomRight.dy + 16.0);
// Test the header position.
final Offset firstDateHeaderTopLeft = tester.getTopLeft(firstDateHeaderText);
final Offset lastDateHeaderTopLeft = tester.getTopLeft(lastDateHeaderText);
expect(firstDateHeaderTopLeft.dx, 72.0);
expect(firstDateHeaderTopLeft.dy, helpTextBottomLeft.dy + 8.0);
final Offset firstDateHeaderTopRight = tester.getTopRight(firstDateHeaderText);
expect(lastDateHeaderTopLeft.dx, firstDateHeaderTopRight.dx + 72.0);
expect(lastDateHeaderTopLeft.dy, helpTextBottomLeft.dy + 8.0);
// Test the day headers position.
final Offset dayHeadersGridTopLeft = tester.getTopLeft(find.byType(GridView).first);
final Offset firstDateHeaderBottomLeft = tester.getBottomLeft(firstDateHeaderText);
expect(dayHeadersGridTopLeft.dx, (800 - 384) / 2);
expect(dayHeadersGridTopLeft.dy, firstDateHeaderBottomLeft.dy + 16.0);
// Test the calendar custom scroll view position.
final Offset calendarScrollViewTopLeft = tester.getTopLeft(find.byType(CustomScrollView));
final Offset dayHeadersGridBottomLeft = tester.getBottomLeft(find.byType(GridView).first);
expect(calendarScrollViewTopLeft.dx, 0.0);
expect(calendarScrollViewTopLeft.dy, dayHeadersGridBottomLeft.dy);
});
});
testWidgets('Default Dialog properties (calendar mode)', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: false);
await preparePicker(tester, (Future<DateTimeRange?> range) 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, Colors.transparent);
expect(dialogMaterial.elevation, 0.0);
expect(dialogMaterial.shape, const RoundedRectangleBorder());
expect(dialogMaterial.clipBehavior, Clip.antiAlias);
final Dialog dialog = tester.widget<Dialog>(find.byType(Dialog));
expect(dialog.insetPadding, EdgeInsets.zero);
});
});
testWidgets('Scaffold and AppBar defaults', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: false);
await preparePicker(tester, (Future<DateTimeRange?> range) async {
final Scaffold scaffold = tester.widget<Scaffold>(find.byType(Scaffold));
expect(scaffold.backgroundColor, theme.colorScheme.surface);
final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
final IconThemeData iconTheme = IconThemeData(color: theme.colorScheme.onPrimary);
expect(appBar.iconTheme, iconTheme);
expect(appBar.actionsIconTheme, iconTheme);
expect(appBar.elevation, null);
expect(appBar.scrolledUnderElevation, null);
expect(appBar.backgroundColor, null);
});
});
group('Input mode', () {
setUp(() {
firstDate = DateTime(2015);
lastDate = DateTime(2017, DateTime.december, 31);
initialDateRange = DateTimeRange(
start: DateTime(2017, DateTime.january, 15),
end: DateTime(2017, DateTime.january, 17),
);
initialEntryMode = DatePickerEntryMode.input;
});
testWidgets('Default Dialog properties (input mode)', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: false);
await preparePicker(tester, (Future<DateTimeRange?> range) 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.surfaceTintColor, null);
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));
});
});
testWidgets('Default InputDecoration', (WidgetTester tester) async {
await preparePicker(tester, (Future<DateTimeRange?> range) async {
final InputDecoration startDateDecoration = tester.widget<TextField>(
find.byType(TextField).first).decoration!;
expect(startDateDecoration.border, const UnderlineInputBorder());
expect(startDateDecoration.filled, false);
expect(startDateDecoration.hintText, 'mm/dd/yyyy');
expect(startDateDecoration.labelText, 'Start Date');
expect(startDateDecoration.errorText, null);
final InputDecoration endDateDecoration = tester.widget<TextField>(
find.byType(TextField).last).decoration!;
expect(endDateDecoration.border, const UnderlineInputBorder());
expect(endDateDecoration.filled, false);
expect(endDateDecoration.hintText, 'mm/dd/yyyy');
expect(endDateDecoration.labelText, 'End Date');
expect(endDateDecoration.errorText, null);
});
});
});
});
} }
class _RestorableDateRangePickerDialogTestWidget extends StatefulWidget { class _RestorableDateRangePickerDialogTestWidget extends StatefulWidget {
......
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