1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/foundation.dart';
6import 'package:flutter/gestures.dart';
7import 'package:flutter/material.dart';
8import 'package:flutter/services.dart';
9import 'package:flutter_test/flutter_test.dart';
10
11void main() {
12 const DatePickerThemeData datePickerTheme = DatePickerThemeData(
13 backgroundColor: Color(0xfffffff0),
14 elevation: 6,
15 shadowColor: Color(0xfffffff1),
16 surfaceTintColor: Color(0xfffffff2),
17 shape: RoundedRectangleBorder(),
18 headerBackgroundColor: Color(0xfffffff3),
19 headerForegroundColor: Color(0xfffffff4),
20 headerHeadlineStyle: TextStyle(fontSize: 10),
21 headerHelpStyle: TextStyle(fontSize: 11),
22 weekdayStyle: TextStyle(fontSize: 12),
23 dayStyle: TextStyle(fontSize: 13),
24 dayForegroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff5)),
25 dayBackgroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff6)),
26 dayOverlayColor: MaterialStatePropertyAll<Color>(Color(0xfffffff7)),
27 dayShape: MaterialStatePropertyAll<OutlinedBorder>(RoundedRectangleBorder()),
28 todayForegroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff8)),
29 todayBackgroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffff9)),
30 todayBorder: BorderSide(width: 3),
31 yearStyle: TextStyle(fontSize: 13),
32 yearForegroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffffa)),
33 yearBackgroundColor: MaterialStatePropertyAll<Color>(Color(0xfffffffb)),
34 yearOverlayColor: MaterialStatePropertyAll<Color>(Color(0xfffffffc)),
35 yearShape: MaterialStatePropertyAll<OutlinedBorder>(RoundedRectangleBorder()),
36 rangePickerBackgroundColor: Color(0xfffffffd),
37 rangePickerElevation: 7,
38 rangePickerShadowColor: Color(0xfffffffe),
39 rangePickerSurfaceTintColor: Color(0xffffffff),
40 rangePickerShape: RoundedRectangleBorder(),
41 rangePickerHeaderBackgroundColor: Color(0xffffff0f),
42 rangePickerHeaderForegroundColor: Color(0xffffff1f),
43 rangePickerHeaderHeadlineStyle: TextStyle(fontSize: 14),
44 rangePickerHeaderHelpStyle: TextStyle(fontSize: 15),
45 rangeSelectionBackgroundColor: Color(0xffffff2f),
46 rangeSelectionOverlayColor: MaterialStatePropertyAll<Color>(Color(0xffffff3f)),
47 dividerColor: Color(0xffffff4f),
48 inputDecorationTheme: InputDecorationTheme(
49 fillColor: Color(0xffffff5f),
50 border: UnderlineInputBorder(),
51 ),
52 cancelButtonStyle: ButtonStyle(
53 foregroundColor: MaterialStatePropertyAll<Color>(Color(0xffffff6f)),
54 ),
55 confirmButtonStyle: ButtonStyle(
56 foregroundColor: MaterialStatePropertyAll<Color>(Color(0xffffff7f)),
57 ),
58 locale: Locale('en'),
59 );
60
61 Material findDialogMaterial(WidgetTester tester) {
62 return tester.widget<Material>(
63 find.descendant(of: find.byType(Dialog), matching: find.byType(Material)).first,
64 );
65 }
66
67 Material findHeaderMaterial(WidgetTester tester, String text) {
68 return tester.widget<Material>(
69 find.ancestor(of: find.text(text), matching: find.byType(Material)).first,
70 );
71 }
72
73 ShapeDecoration? findTextDecoration(WidgetTester tester, String date) {
74 final Container container = tester.widget<Container>(
75 find.ancestor(of: find.text(date), matching: find.byType(Container)).first,
76 );
77 return container.decoration as ShapeDecoration?;
78 }
79
80 ShapeDecoration? findDayDecoration(WidgetTester tester, String day) {
81 return tester
82 .widget<Ink>(find.ancestor(of: find.text(day), matching: find.byType(Ink)))
83 .decoration
84 as ShapeDecoration?;
85 }
86
87 ButtonStyle actionButtonStyle(WidgetTester tester, String text) {
88 return tester.widget<TextButton>(find.widgetWithText(TextButton, text)).style!;
89 }
90
91 const Size wideWindowSize = Size(1920.0, 1080.0);
92 const Size narrowWindowSize = Size(1070.0, 1770.0);
93
94 test('DatePickerThemeData copyWith, ==, hashCode basics', () {
95 expect(const DatePickerThemeData(), const DatePickerThemeData().copyWith());
96 expect(const DatePickerThemeData().hashCode, const DatePickerThemeData().copyWith().hashCode);
97 });
98
99 test('DatePickerThemeData lerp special cases', () {
100 const DatePickerThemeData data = DatePickerThemeData();
101 expect(identical(DatePickerThemeData.lerp(data, data, 0.5), data), true);
102 });
103
104 test('DatePickerThemeData defaults', () {
105 const DatePickerThemeData theme = DatePickerThemeData();
106 expect(theme.backgroundColor, null);
107 expect(theme.elevation, null);
108 expect(theme.shadowColor, null);
109 expect(theme.surfaceTintColor, null);
110 expect(theme.shape, null);
111 expect(theme.headerBackgroundColor, null);
112 expect(theme.headerForegroundColor, null);
113 expect(theme.headerHeadlineStyle, null);
114 expect(theme.headerHelpStyle, null);
115 expect(theme.weekdayStyle, null);
116 expect(theme.dayStyle, null);
117 expect(theme.dayForegroundColor, null);
118 expect(theme.dayBackgroundColor, null);
119 expect(theme.dayOverlayColor, null);
120 expect(theme.dayShape, null);
121 expect(theme.todayForegroundColor, null);
122 expect(theme.todayBackgroundColor, null);
123 expect(theme.todayBorder, null);
124 expect(theme.yearStyle, null);
125 expect(theme.yearForegroundColor, null);
126 expect(theme.yearBackgroundColor, null);
127 expect(theme.yearOverlayColor, null);
128 expect(theme.rangePickerBackgroundColor, null);
129 expect(theme.rangePickerElevation, null);
130 expect(theme.rangePickerShadowColor, null);
131 expect(theme.rangePickerSurfaceTintColor, null);
132 expect(theme.rangePickerShape, null);
133 expect(theme.rangePickerHeaderBackgroundColor, null);
134 expect(theme.rangePickerHeaderForegroundColor, null);
135 expect(theme.rangePickerHeaderHeadlineStyle, null);
136 expect(theme.rangePickerHeaderHelpStyle, null);
137 expect(theme.rangeSelectionBackgroundColor, null);
138 expect(theme.rangeSelectionOverlayColor, null);
139 expect(theme.dividerColor, null);
140 expect(theme.inputDecorationTheme, null);
141 expect(theme.cancelButtonStyle, null);
142 expect(theme.confirmButtonStyle, null);
143 expect(theme.locale, null);
144 });
145
146 testWidgets('DatePickerTheme.defaults M3 defaults', (WidgetTester tester) async {
147 late final DatePickerThemeData m3; // M3 Defaults
148 late final ThemeData theme;
149 late final ColorScheme colorScheme;
150 late final TextTheme textTheme;
151
152 await tester.pumpWidget(
153 MaterialApp(
154 home: Builder(
155 builder: (BuildContext context) {
156 m3 = DatePickerTheme.defaults(context);
157 theme = Theme.of(context);
158 colorScheme = theme.colorScheme;
159 textTheme = theme.textTheme;
160 return Container();
161 },
162 ),
163 ),
164 );
165
166 expect(m3.backgroundColor, colorScheme.surfaceContainerHigh);
167 expect(m3.elevation, 6);
168 expect(m3.shadowColor, const Color(0x00000000)); // Colors.transparent
169 expect(m3.surfaceTintColor, Colors.transparent);
170 expect(m3.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(28)));
171 expect(m3.headerBackgroundColor, const Color(0x00000000)); // Colors.transparent
172 expect(m3.headerForegroundColor, colorScheme.onSurfaceVariant);
173 expect(m3.headerHeadlineStyle, textTheme.headlineLarge);
174 expect(m3.headerHelpStyle, textTheme.labelLarge);
175 expect(m3.weekdayStyle, textTheme.bodyLarge?.apply(color: colorScheme.onSurface));
176 expect(m3.dayStyle, textTheme.bodyLarge);
177 expect(m3.dayForegroundColor?.resolve(<MaterialState>{}), colorScheme.onSurface);
178 expect(
179 m3.dayForegroundColor?.resolve(<MaterialState>{MaterialState.selected}),
180 colorScheme.onPrimary,
181 );
182 expect(
183 m3.dayForegroundColor?.resolve(<MaterialState>{MaterialState.disabled}),
184 colorScheme.onSurface.withOpacity(0.38),
185 );
186 expect(m3.dayBackgroundColor?.resolve(<MaterialState>{}), null);
187 expect(
188 m3.dayBackgroundColor?.resolve(<MaterialState>{MaterialState.selected}),
189 colorScheme.primary,
190 );
191 expect(m3.dayOverlayColor?.resolve(<MaterialState>{}), null);
192 expect(
193 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.hovered}),
194 colorScheme.onPrimary.withOpacity(0.08),
195 );
196 expect(
197 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.focused}),
198 colorScheme.onPrimary.withOpacity(0.1),
199 );
200 expect(
201 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.hovered}),
202 colorScheme.onSurfaceVariant.withOpacity(0.08),
203 );
204 expect(
205 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.focused}),
206 colorScheme.onSurfaceVariant.withOpacity(0.1),
207 );
208 expect(
209 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.pressed}),
210 colorScheme.onSurfaceVariant.withOpacity(0.1),
211 );
212 expect(
213 m3.dayOverlayColor?.resolve(<MaterialState>{
214 MaterialState.selected,
215 MaterialState.hovered,
216 MaterialState.focused,
217 }),
218 colorScheme.onPrimary.withOpacity(0.08),
219 );
220 expect(
221 m3.dayOverlayColor?.resolve(<MaterialState>{
222 MaterialState.selected,
223 MaterialState.hovered,
224 MaterialState.pressed,
225 }),
226 colorScheme.onPrimary.withOpacity(0.1),
227 );
228 expect(
229 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.hovered, MaterialState.focused}),
230 colorScheme.onSurfaceVariant.withOpacity(0.08),
231 );
232 expect(
233 m3.dayOverlayColor?.resolve(<MaterialState>{MaterialState.hovered, MaterialState.pressed}),
234 colorScheme.onSurfaceVariant.withOpacity(0.1),
235 );
236 expect(m3.dayShape?.resolve(<MaterialState>{}), const CircleBorder());
237 expect(m3.todayForegroundColor?.resolve(<MaterialState>{}), colorScheme.primary);
238 expect(
239 m3.todayForegroundColor?.resolve(<MaterialState>{MaterialState.disabled}),
240 colorScheme.primary.withOpacity(0.38),
241 );
242 expect(m3.todayBorder, BorderSide(color: colorScheme.primary));
243 expect(m3.yearStyle, textTheme.bodyLarge);
244 expect(m3.yearForegroundColor?.resolve(<MaterialState>{}), colorScheme.onSurfaceVariant);
245 expect(
246 m3.yearForegroundColor?.resolve(<MaterialState>{MaterialState.selected}),
247 colorScheme.onPrimary,
248 );
249 expect(
250 m3.yearForegroundColor?.resolve(<MaterialState>{MaterialState.disabled}),
251 colorScheme.onSurfaceVariant.withOpacity(0.38),
252 );
253 expect(m3.yearBackgroundColor?.resolve(<MaterialState>{}), null);
254 expect(
255 m3.yearBackgroundColor?.resolve(<MaterialState>{MaterialState.selected}),
256 colorScheme.primary,
257 );
258 expect(m3.yearOverlayColor?.resolve(<MaterialState>{}), null);
259 expect(
260 m3.yearOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.hovered}),
261 colorScheme.onPrimary.withOpacity(0.08),
262 );
263 expect(
264 m3.yearOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.focused}),
265 colorScheme.onPrimary.withOpacity(0.1),
266 );
267 expect(
268 m3.yearOverlayColor?.resolve(<MaterialState>{MaterialState.hovered}),
269 colorScheme.onSurfaceVariant.withOpacity(0.08),
270 );
271 expect(
272 m3.yearOverlayColor?.resolve(<MaterialState>{MaterialState.focused}),
273 colorScheme.onSurfaceVariant.withOpacity(0.1),
274 );
275 expect(
276 m3.yearOverlayColor?.resolve(<MaterialState>{MaterialState.pressed}),
277 colorScheme.onSurfaceVariant.withOpacity(0.1),
278 );
279 expect(m3.rangePickerElevation, 0);
280 expect(m3.rangePickerShape, const RoundedRectangleBorder());
281 expect(m3.rangePickerShadowColor, Colors.transparent);
282 expect(m3.rangePickerSurfaceTintColor, Colors.transparent);
283 expect(m3.rangeSelectionOverlayColor?.resolve(<MaterialState>{}), null);
284 expect(m3.rangePickerHeaderBackgroundColor, Colors.transparent);
285 expect(m3.rangePickerHeaderForegroundColor, colorScheme.onSurfaceVariant);
286 expect(m3.rangePickerHeaderHeadlineStyle, textTheme.titleLarge);
287 expect(m3.rangePickerHeaderHelpStyle, textTheme.titleSmall);
288 expect(m3.dividerColor, null);
289 expect(m3.inputDecorationTheme, null);
290 expect(
291 m3.cancelButtonStyle.toString(),
292 equalsIgnoringHashCodes(TextButton.styleFrom().toString()),
293 );
294 expect(
295 m3.confirmButtonStyle.toString(),
296 equalsIgnoringHashCodes(TextButton.styleFrom().toString()),
297 );
298 expect(m3.locale, null);
299 });
300
301 testWidgets('DatePickerTheme.defaults M2 defaults', (WidgetTester tester) async {
302 late final DatePickerThemeData m2; // M2 defaults
303 late final ThemeData theme;
304 late final ColorScheme colorScheme;
305 late final TextTheme textTheme;
306
307 await tester.pumpWidget(
308 MaterialApp(
309 theme: ThemeData(useMaterial3: false),
310 home: Builder(
311 builder: (BuildContext context) {
312 m2 = DatePickerTheme.defaults(context);
313 theme = Theme.of(context);
314 colorScheme = theme.colorScheme;
315 textTheme = theme.textTheme;
316 return Container();
317 },
318 ),
319 ),
320 );
321
322 expect(m2.elevation, 24);
323 expect(
324 m2.shape,
325 const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
326 );
327 expect(m2.headerBackgroundColor, colorScheme.primary);
328 expect(m2.headerForegroundColor, colorScheme.onPrimary);
329 expect(m2.headerHeadlineStyle, textTheme.headlineSmall);
330 expect(m2.headerHelpStyle, textTheme.labelSmall);
331 expect(
332 m2.weekdayStyle,
333 textTheme.bodySmall?.apply(color: colorScheme.onSurface.withOpacity(0.60)),
334 );
335 expect(m2.dayStyle, textTheme.bodySmall);
336 expect(m2.dayForegroundColor?.resolve(<MaterialState>{}), colorScheme.onSurface);
337 expect(
338 m2.dayForegroundColor?.resolve(<MaterialState>{MaterialState.selected}),
339 colorScheme.onPrimary,
340 );
341 expect(
342 m2.dayForegroundColor?.resolve(<MaterialState>{MaterialState.disabled}),
343 colorScheme.onSurface.withOpacity(0.38),
344 );
345 expect(m2.dayBackgroundColor?.resolve(<MaterialState>{}), null);
346 expect(
347 m2.dayBackgroundColor?.resolve(<MaterialState>{MaterialState.selected}),
348 colorScheme.primary,
349 );
350 expect(m2.dayOverlayColor?.resolve(<MaterialState>{}), null);
351 expect(
352 m2.dayOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.hovered}),
353 colorScheme.onPrimary.withOpacity(0.08),
354 );
355 expect(
356 m2.dayOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.focused}),
357 colorScheme.onPrimary.withOpacity(0.12),
358 );
359 expect(
360 m2.dayOverlayColor?.resolve(<MaterialState>{MaterialState.selected, MaterialState.pressed}),
361 colorScheme.onPrimary.withOpacity(0.38),
362 );
363 expect(
364 m2.dayOverlayColor?.resolve(<MaterialState>{
365 MaterialState.selected,
366 MaterialState.hovered,
367 MaterialState.focused,
368 }),
369 colorScheme.onPrimary.withOpacity(0.08),
370 );
371 expect(
372 m2.dayOverlayColor?.resolve(<MaterialState>{
373 MaterialState.selected,
374 MaterialState.hovered,
375 MaterialState.pressed,
376 }),
377 colorScheme.onPrimary.withOpacity(0.38),
378 );
379 expect(
380 m2.dayOverlayColor?.resolve(<MaterialState>{MaterialState.hovered}),
381 colorScheme.onSurfaceVariant.withOpacity(0.08),
382 );
383 expect(
384 m2.dayOverlayColor?.resolve(<MaterialState>{MaterialState.focused}),
385 colorScheme.onSurfaceVariant.withOpacity(0.12),
386 );
387 expect(
388 m2.dayOverlayColor?.resolve(<MaterialState>{MaterialState.pressed}),
389 colorScheme.onSurfaceVariant.withOpacity(0.12),
390 );
391 expect(m2.dayShape?.resolve(<MaterialState>{}), const CircleBorder());
392 expect(m2.todayForegroundColor?.resolve(<MaterialState>{}), colorScheme.primary);
393 expect(
394 m2.todayForegroundColor?.resolve(<MaterialState>{MaterialState.disabled}),
395 colorScheme.onSurface.withOpacity(0.38),
396 );
397 expect(m2.todayBorder, BorderSide(color: colorScheme.primary));
398 expect(m2.yearStyle, textTheme.bodyLarge);
399 expect(m2.rangePickerBackgroundColor, colorScheme.surface);
400 expect(m2.rangePickerElevation, 0);
401 expect(m2.rangePickerShape, const RoundedRectangleBorder());
402 expect(m2.rangePickerShadowColor, Colors.transparent);
403 expect(m2.rangePickerSurfaceTintColor, Colors.transparent);
404 expect(m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{}), null);
405 expect(
406 m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{
407 MaterialState.selected,
408 MaterialState.hovered,
409 }),
410 colorScheme.onPrimary.withOpacity(0.08),
411 );
412 expect(
413 m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{
414 MaterialState.selected,
415 MaterialState.focused,
416 }),
417 colorScheme.onPrimary.withOpacity(0.12),
418 );
419 expect(
420 m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{
421 MaterialState.selected,
422 MaterialState.pressed,
423 }),
424 colorScheme.onPrimary.withOpacity(0.38),
425 );
426 expect(
427 m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{MaterialState.hovered}),
428 colorScheme.onSurfaceVariant.withOpacity(0.08),
429 );
430 expect(
431 m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{MaterialState.focused}),
432 colorScheme.onSurfaceVariant.withOpacity(0.12),
433 );
434 expect(
435 m2.rangeSelectionOverlayColor?.resolve(<MaterialState>{MaterialState.pressed}),
436 colorScheme.onSurfaceVariant.withOpacity(0.12),
437 );
438 expect(m2.rangePickerHeaderBackgroundColor, colorScheme.primary);
439 expect(m2.rangePickerHeaderForegroundColor, colorScheme.onPrimary);
440 expect(m2.rangePickerHeaderHeadlineStyle, textTheme.headlineSmall);
441 expect(m2.rangePickerHeaderHelpStyle, textTheme.labelSmall);
442 expect(m2.dividerColor, null);
443 expect(m2.inputDecorationTheme, null);
444 expect(
445 m2.cancelButtonStyle.toString(),
446 equalsIgnoringHashCodes(TextButton.styleFrom().toString()),
447 );
448 expect(
449 m2.confirmButtonStyle.toString(),
450 equalsIgnoringHashCodes(TextButton.styleFrom().toString()),
451 );
452 expect(m2.locale, null);
453 expect(m2.yearShape?.resolve(<MaterialState>{}), const StadiumBorder());
454 });
455
456 testWidgets('Default DatePickerThemeData debugFillProperties', (WidgetTester tester) async {
457 final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
458 const DatePickerThemeData().debugFillProperties(builder);
459
460 final List<String> description =
461 builder.properties
462 .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
463 .map((DiagnosticsNode node) => node.toString())
464 .toList();
465
466 expect(description, <String>[]);
467 });
468
469 testWidgets('DatePickerThemeData implements debugFillProperties', (WidgetTester tester) async {
470 final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
471
472 datePickerTheme.debugFillProperties(builder);
473
474 final List<String> description =
475 builder.properties
476 .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
477 .map((DiagnosticsNode node) => node.toString())
478 .toList();
479
480 expect(
481 description,
482 equalsIgnoringHashCodes(<String>[
483 'backgroundColor: ${const Color(0xfffffff0)}',
484 'elevation: 6.0',
485 'shadowColor: ${const Color(0xfffffff1)}',
486 'surfaceTintColor: ${const Color(0xfffffff2)}',
487 'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)',
488 'headerBackgroundColor: ${const Color(0xfffffff3)}',
489 'headerForegroundColor: ${const Color(0xfffffff4)}',
490 'headerHeadlineStyle: TextStyle(inherit: true, size: 10.0)',
491 'headerHelpStyle: TextStyle(inherit: true, size: 11.0)',
492 'weekDayStyle: TextStyle(inherit: true, size: 12.0)',
493 'dayStyle: TextStyle(inherit: true, size: 13.0)',
494 'dayForegroundColor: WidgetStatePropertyAll(${const Color(0xfffffff5)})',
495 'dayBackgroundColor: WidgetStatePropertyAll(${const Color(0xfffffff6)})',
496 'dayOverlayColor: WidgetStatePropertyAll(${const Color(0xfffffff7)})',
497 'dayShape: WidgetStatePropertyAll(RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero))',
498 'todayForegroundColor: WidgetStatePropertyAll(${const Color(0xfffffff8)})',
499 'todayBackgroundColor: WidgetStatePropertyAll(${const Color(0xfffffff9)})',
500 'todayBorder: BorderSide(width: 3.0)',
501 'yearStyle: TextStyle(inherit: true, size: 13.0)',
502 'yearForegroundColor: WidgetStatePropertyAll(${const Color(0xfffffffa)})',
503 'yearBackgroundColor: WidgetStatePropertyAll(${const Color(0xfffffffb)})',
504 'yearOverlayColor: WidgetStatePropertyAll(${const Color(0xfffffffc)})',
505 'yearShape: WidgetStatePropertyAll(RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero))',
506 'rangePickerBackgroundColor: ${const Color(0xfffffffd)}',
507 'rangePickerElevation: 7.0',
508 'rangePickerShadowColor: ${const Color(0xfffffffe)}',
509 'rangePickerSurfaceTintColor: ${const Color(0xffffffff)}',
510 'rangePickerShape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)',
511 'rangePickerHeaderBackgroundColor: ${const Color(0xffffff0f)}',
512 'rangePickerHeaderForegroundColor: ${const Color(0xffffff1f)}',
513 'rangePickerHeaderHeadlineStyle: TextStyle(inherit: true, size: 14.0)',
514 'rangePickerHeaderHelpStyle: TextStyle(inherit: true, size: 15.0)',
515 'rangeSelectionBackgroundColor: ${const Color(0xffffff2f)}',
516 'rangeSelectionOverlayColor: WidgetStatePropertyAll(${const Color(0xffffff3f)})',
517 'dividerColor: ${const Color(0xffffff4f)}',
518 'inputDecorationTheme: InputDecorationTheme#00000(fillColor: ${const Color(0xffffff5f)}, border: UnderlineInputBorder())',
519 'cancelButtonStyle: ButtonStyle#00000(foregroundColor: WidgetStatePropertyAll(${const Color(0xffffff6f)}))',
520 'confirmButtonStyle: ButtonStyle#00000(foregroundColor: WidgetStatePropertyAll(${const Color(0xffffff7f)}))',
521 'locale: en',
522 ]),
523 );
524 });
525
526 testWidgets('DatePickerDialog uses ThemeData datePicker theme (calendar mode)', (
527 WidgetTester tester,
528 ) async {
529 await tester.pumpWidget(
530 MaterialApp(
531 theme: ThemeData(datePickerTheme: datePickerTheme),
532 home: Directionality(
533 textDirection: TextDirection.ltr,
534 child: Material(
535 child: Center(
536 child: DatePickerDialog(
537 initialDate: DateTime(2023, DateTime.january, 25),
538 firstDate: DateTime(2022),
539 lastDate: DateTime(2024, DateTime.december, 31),
540 currentDate: DateTime(2023, DateTime.january, 24),
541 ),
542 ),
543 ),
544 ),
545 ),
546 );
547
548 final Material material = findDialogMaterial(tester);
549 expect(material.color, datePickerTheme.backgroundColor);
550 expect(material.elevation, datePickerTheme.elevation);
551 expect(material.shadowColor, datePickerTheme.shadowColor);
552 expect(material.surfaceTintColor, datePickerTheme.surfaceTintColor);
553 expect(material.shape, datePickerTheme.shape);
554
555 final Text selectDate = tester.widget<Text>(find.text('Select date'));
556 final Material headerMaterial = findHeaderMaterial(tester, 'Select date');
557 expect(selectDate.style?.color, datePickerTheme.headerForegroundColor);
558 expect(selectDate.style?.fontSize, datePickerTheme.headerHelpStyle?.fontSize);
559 expect(headerMaterial.color, datePickerTheme.headerBackgroundColor);
560
561 final Text weekday = tester.widget<Text>(find.text('W'));
562 expect(weekday.style?.color, datePickerTheme.weekdayStyle?.color);
563 expect(weekday.style?.fontSize, datePickerTheme.weekdayStyle?.fontSize);
564
565 final Text selectedDate = tester.widget<Text>(find.text('Wed, Jan 25'));
566 expect(selectedDate.style?.color, datePickerTheme.headerForegroundColor);
567 expect(selectedDate.style?.fontSize, datePickerTheme.headerHeadlineStyle?.fontSize);
568
569 final Text day31 = tester.widget<Text>(find.text('31'));
570 final ShapeDecoration day31Decoration = findDayDecoration(tester, '31')!;
571 expect(day31.style?.color, datePickerTheme.dayForegroundColor?.resolve(<MaterialState>{}));
572 expect(day31.style?.fontSize, datePickerTheme.dayStyle?.fontSize);
573 expect(day31Decoration.color, datePickerTheme.dayBackgroundColor?.resolve(<MaterialState>{}));
574 expect(day31Decoration.shape, datePickerTheme.dayShape?.resolve(<MaterialState>{}));
575
576 final Text day24 = tester.widget<Text>(find.text('24')); // DatePickerDialog.currentDate
577 final ShapeDecoration day24Decoration = findDayDecoration(tester, '24')!;
578 final OutlinedBorder day24Shape = day24Decoration.shape as OutlinedBorder;
579 expect(day24.style?.fontSize, datePickerTheme.dayStyle?.fontSize);
580 expect(day24.style?.color, datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}));
581 expect(day24Decoration.color, datePickerTheme.todayBackgroundColor?.resolve(<MaterialState>{}));
582 expect(
583 day24Decoration.shape,
584 datePickerTheme.dayShape
585 ?.resolve(<MaterialState>{})!
586 .copyWith(
587 side: datePickerTheme.todayBorder?.copyWith(
588 color: datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}),
589 ),
590 ),
591 );
592 expect(day24Shape.side.width, datePickerTheme.todayBorder?.width);
593
594 // Test the day overlay color.
595 final RenderObject inkFeatures = tester.allRenderObjects.firstWhere(
596 (RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures',
597 );
598 final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
599 await gesture.addPointer();
600 await gesture.moveTo(tester.getCenter(find.text('25')));
601 await tester.pumpAndSettle();
602 expect(
603 inkFeatures,
604 paints..circle(color: datePickerTheme.dayOverlayColor?.resolve(<MaterialState>{})),
605 );
606
607 // Show the year selector.
608
609 await tester.tap(find.text('January 2023'));
610 await tester.pumpAndSettle();
611
612 final Text year2022 = tester.widget<Text>(find.text('2022'));
613 final ShapeDecoration year2022Decoration = findTextDecoration(tester, '2022')!;
614 expect(year2022.style?.fontSize, datePickerTheme.yearStyle?.fontSize);
615 expect(year2022.style?.color, datePickerTheme.yearForegroundColor?.resolve(<MaterialState>{}));
616 expect(
617 year2022Decoration.color,
618 datePickerTheme.yearBackgroundColor?.resolve(<MaterialState>{}),
619 );
620 expect(year2022Decoration.shape, datePickerTheme.yearShape?.resolve(<MaterialState>{}));
621
622 final Text year2023 = tester.widget<Text>(find.text('2023')); // DatePickerDialog.currentDate
623 final ShapeDecoration year2023Decoration = findTextDecoration(tester, '2023')!;
624 expect(year2023.style?.fontSize, datePickerTheme.yearStyle?.fontSize);
625 expect(year2023.style?.color, datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}));
626 expect(
627 year2023Decoration.color,
628 datePickerTheme.todayBackgroundColor?.resolve(<MaterialState>{}),
629 );
630 final RoundedRectangleBorder roundedRectangleBorder =
631 year2023Decoration.shape as RoundedRectangleBorder;
632 expect(roundedRectangleBorder.side.width, datePickerTheme.todayBorder?.width);
633 expect(
634 roundedRectangleBorder.side.color,
635 datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}),
636 );
637
638 // Test the year overlay color.
639 await gesture.moveTo(tester.getCenter(find.text('2024')));
640 await tester.pumpAndSettle();
641 expect(
642 inkFeatures,
643 paints..rect(color: datePickerTheme.yearOverlayColor?.resolve(<MaterialState>{})),
644 );
645
646 final ButtonStyle cancelButtonStyle = actionButtonStyle(tester, 'Cancel');
647 expect(
648 cancelButtonStyle.toString(),
649 equalsIgnoringHashCodes(datePickerTheme.cancelButtonStyle.toString()),
650 );
651
652 final ButtonStyle confirmButtonStyle = actionButtonStyle(tester, 'OK');
653 expect(
654 confirmButtonStyle.toString(),
655 equalsIgnoringHashCodes(datePickerTheme.confirmButtonStyle.toString()),
656 );
657 });
658
659 testWidgets('DatePickerDialog uses ThemeData datePicker theme (input mode)', (
660 WidgetTester tester,
661 ) async {
662 await tester.pumpWidget(
663 MaterialApp(
664 theme: ThemeData(datePickerTheme: datePickerTheme),
665 home: Directionality(
666 textDirection: TextDirection.ltr,
667 child: Material(
668 child: Center(
669 child: DatePickerDialog(
670 initialEntryMode: DatePickerEntryMode.input,
671 initialDate: DateTime(2023, DateTime.january, 25),
672 firstDate: DateTime(2022),
673 lastDate: DateTime(2024, DateTime.december, 31),
674 currentDate: DateTime(2023, DateTime.january, 24),
675 ),
676 ),
677 ),
678 ),
679 ),
680 );
681
682 final Material material = findDialogMaterial(tester);
683 expect(material.color, datePickerTheme.backgroundColor);
684 expect(material.elevation, datePickerTheme.elevation);
685 expect(material.shadowColor, datePickerTheme.shadowColor);
686 expect(material.surfaceTintColor, datePickerTheme.surfaceTintColor);
687 expect(material.shape, datePickerTheme.shape);
688
689 final Text selectDate = tester.widget<Text>(find.text('Select date'));
690 final Material headerMaterial = findHeaderMaterial(tester, 'Select date');
691 expect(selectDate.style?.color, datePickerTheme.headerForegroundColor);
692 expect(selectDate.style?.fontSize, datePickerTheme.headerHelpStyle?.fontSize);
693 expect(headerMaterial.color, datePickerTheme.headerBackgroundColor);
694
695 final InputDecoration inputDecoration =
696 tester.widget<TextField>(find.byType(TextField)).decoration!;
697 expect(inputDecoration.fillColor, datePickerTheme.inputDecorationTheme?.fillColor);
698
699 final ButtonStyle cancelButtonStyle = actionButtonStyle(tester, 'Cancel');
700 expect(
701 cancelButtonStyle.toString(),
702 equalsIgnoringHashCodes(datePickerTheme.cancelButtonStyle.toString()),
703 );
704
705 final ButtonStyle confirmButtonStyle = actionButtonStyle(tester, 'OK');
706 expect(
707 confirmButtonStyle.toString(),
708 equalsIgnoringHashCodes(datePickerTheme.confirmButtonStyle.toString()),
709 );
710 });
711
712 testWidgets('DateRangePickerDialog uses ThemeData datePicker theme', (WidgetTester tester) async {
713 await tester.pumpWidget(
714 MaterialApp(
715 theme: ThemeData(datePickerTheme: datePickerTheme),
716 home: Directionality(
717 textDirection: TextDirection.ltr,
718 child: Material(
719 child: Center(
720 child: DateRangePickerDialog(
721 firstDate: DateTime(2023),
722 lastDate: DateTime(2023, DateTime.january, 31),
723 initialDateRange: DateTimeRange(
724 start: DateTime(2023, DateTime.january, 17),
725 end: DateTime(2023, DateTime.january, 20),
726 ),
727 currentDate: DateTime(2023, DateTime.january, 23),
728 ),
729 ),
730 ),
731 ),
732 ),
733 );
734
735 final Material material = findDialogMaterial(tester);
736 expect(material.color, datePickerTheme.backgroundColor);
737 expect(
738 tester.widget<Scaffold>(find.byType(Scaffold)).backgroundColor,
739 datePickerTheme.rangePickerBackgroundColor,
740 );
741 expect(material.elevation, datePickerTheme.rangePickerElevation);
742 expect(material.shadowColor, datePickerTheme.rangePickerShadowColor);
743 expect(material.surfaceTintColor, datePickerTheme.rangePickerSurfaceTintColor);
744 expect(material.shape, datePickerTheme.rangePickerShape);
745
746 final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
747 expect(appBar.backgroundColor, datePickerTheme.rangePickerHeaderBackgroundColor);
748
749 final Text selectRange = tester.widget<Text>(find.text('Select range'));
750 expect(selectRange.style?.color, datePickerTheme.rangePickerHeaderForegroundColor);
751 expect(selectRange.style?.fontSize, datePickerTheme.rangePickerHeaderHelpStyle?.fontSize);
752
753 final Text selectedDate = tester.widget<Text>(find.text('Jan 17'));
754 expect(selectedDate.style?.color, datePickerTheme.rangePickerHeaderForegroundColor);
755 expect(selectedDate.style?.fontSize, datePickerTheme.rangePickerHeaderHeadlineStyle?.fontSize);
756
757 // Test the day overlay color.
758 final RenderObject inkFeatures = tester.allRenderObjects.firstWhere(
759 (RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures',
760 );
761 final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
762 await gesture.addPointer();
763 await gesture.moveTo(tester.getCenter(find.text('16')));
764 await tester.pumpAndSettle();
765 expect(
766 inkFeatures,
767 paints..circle(color: datePickerTheme.dayOverlayColor?.resolve(<MaterialState>{})),
768 );
769
770 // Test the range selection overlay color.
771 await gesture.moveTo(tester.getCenter(find.text('18')));
772 await tester.pumpAndSettle();
773 expect(
774 inkFeatures,
775 paints..circle(color: datePickerTheme.rangeSelectionOverlayColor?.resolve(<MaterialState>{})),
776 );
777 });
778
779 testWidgets('Material2 - DateRangePickerDialog uses ThemeData datePicker theme', (
780 WidgetTester tester,
781 ) async {
782 await tester.pumpWidget(
783 MaterialApp(
784 theme: ThemeData(datePickerTheme: datePickerTheme, useMaterial3: false),
785 home: Directionality(
786 textDirection: TextDirection.ltr,
787 child: Material(
788 child: Center(
789 child: DateRangePickerDialog(
790 firstDate: DateTime(2023),
791 lastDate: DateTime(2023, DateTime.january, 31),
792 initialDateRange: DateTimeRange(
793 start: DateTime(2023, DateTime.january, 17),
794 end: DateTime(2023, DateTime.january, 20),
795 ),
796 currentDate: DateTime(2023, DateTime.january, 23),
797 ),
798 ),
799 ),
800 ),
801 ),
802 );
803
804 final Material material = findDialogMaterial(tester);
805 expect(material.color, datePickerTheme.backgroundColor);
806 expect(
807 tester.widget<Scaffold>(find.byType(Scaffold)).backgroundColor,
808 datePickerTheme.rangePickerBackgroundColor,
809 );
810 expect(material.elevation, datePickerTheme.rangePickerElevation);
811 expect(material.shadowColor, datePickerTheme.rangePickerShadowColor);
812 expect(material.surfaceTintColor, datePickerTheme.rangePickerSurfaceTintColor);
813 expect(material.shape, datePickerTheme.rangePickerShape);
814
815 final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
816 expect(appBar.backgroundColor, datePickerTheme.rangePickerHeaderBackgroundColor);
817
818 final Text selectRange = tester.widget<Text>(find.text('SELECT RANGE'));
819 expect(selectRange.style?.color, datePickerTheme.rangePickerHeaderForegroundColor);
820 expect(selectRange.style?.fontSize, datePickerTheme.rangePickerHeaderHelpStyle?.fontSize);
821
822 final Text selectedDate = tester.widget<Text>(find.text('Jan 17'));
823 expect(selectedDate.style?.color, datePickerTheme.rangePickerHeaderForegroundColor);
824 expect(selectedDate.style?.fontSize, datePickerTheme.rangePickerHeaderHeadlineStyle?.fontSize);
825
826 // Test the day overlay color.
827 final RenderObject inkFeatures = tester.allRenderObjects.firstWhere(
828 (RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures',
829 );
830 final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
831 await gesture.addPointer();
832 await gesture.moveTo(tester.getCenter(find.text('16')));
833 await tester.pumpAndSettle();
834 expect(
835 inkFeatures,
836 paints..circle(color: datePickerTheme.dayOverlayColor?.resolve(<MaterialState>{})),
837 );
838
839 // Test the range selection overlay color.
840 await gesture.moveTo(tester.getCenter(find.text('18')));
841 await tester.pumpAndSettle();
842 expect(
843 inkFeatures,
844 paints..circle(color: datePickerTheme.rangeSelectionOverlayColor?.resolve(<MaterialState>{})),
845 );
846 });
847
848 testWidgets('Dividers use DatePickerThemeData.dividerColor', (WidgetTester tester) async {
849 Future<void> showPicker(WidgetTester tester, Size size) async {
850 tester.view.physicalSize = size;
851 tester.view.devicePixelRatio = 1.0;
852 addTearDown(tester.view.reset);
853 await tester.pumpWidget(
854 MaterialApp(
855 theme: ThemeData(datePickerTheme: datePickerTheme),
856 home: Directionality(
857 textDirection: TextDirection.ltr,
858 child: Material(
859 child: Center(
860 child: DatePickerDialog(
861 initialDate: DateTime(2023, DateTime.january, 25),
862 firstDate: DateTime(2022),
863 lastDate: DateTime(2024, DateTime.december, 31),
864 currentDate: DateTime(2023, DateTime.january, 24),
865 ),
866 ),
867 ),
868 ),
869 ),
870 );
871 }
872
873 await showPicker(tester, wideWindowSize);
874
875 // Test vertical divider.
876 final VerticalDivider verticalDivider = tester.widget(find.byType(VerticalDivider));
877 expect(verticalDivider.color, datePickerTheme.dividerColor);
878
879 // Test portrait layout.
880 await showPicker(tester, narrowWindowSize);
881
882 // Test horizontal divider.
883 final Divider horizontalDivider = tester.widget(find.byType(Divider));
884 expect(horizontalDivider.color, datePickerTheme.dividerColor);
885 });
886
887 testWidgets('DatePicker uses ThemeData.inputDecorationTheme properties '
888 'which are null in DatePickerThemeData.inputDecorationTheme', (WidgetTester tester) async {
889 Widget buildWidget({
890 InputDecorationTheme? inputDecorationTheme,
891 DatePickerThemeData? datePickerTheme,
892 }) {
893 return MaterialApp(
894 theme: ThemeData(
895 inputDecorationTheme: inputDecorationTheme,
896 datePickerTheme: datePickerTheme,
897 ),
898 home: Directionality(
899 textDirection: TextDirection.ltr,
900 child: Material(
901 child: Center(
902 child: DatePickerDialog(
903 initialEntryMode: DatePickerEntryMode.input,
904 initialDate: DateTime(2023, DateTime.january, 25),
905 firstDate: DateTime(2022),
906 lastDate: DateTime(2024, DateTime.december, 31),
907 currentDate: DateTime(2023, DateTime.january, 24),
908 ),
909 ),
910 ),
911 ),
912 );
913 }
914
915 // Test DatePicker with DatePickerThemeData.inputDecorationTheme.
916 await tester.pumpWidget(
917 buildWidget(
918 inputDecorationTheme: const InputDecorationTheme(filled: true),
919 datePickerTheme: datePickerTheme,
920 ),
921 );
922 InputDecoration inputDecoration = tester.widget<TextField>(find.byType(TextField)).decoration!;
923 expect(inputDecoration.fillColor, datePickerTheme.inputDecorationTheme!.fillColor);
924 expect(inputDecoration.border, datePickerTheme.inputDecorationTheme!.border);
925
926 // Test DatePicker with ThemeData.inputDecorationTheme.
927 await tester.pumpWidget(
928 buildWidget(
929 inputDecorationTheme: const InputDecorationTheme(
930 filled: true,
931 fillColor: Color(0xFF00FF00),
932 border: OutlineInputBorder(),
933 ),
934 ),
935 );
936 await tester.pumpAndSettle();
937
938 inputDecoration = tester.widget<TextField>(find.byType(TextField)).decoration!;
939 expect(inputDecoration.fillColor, const Color(0xFF00FF00));
940 expect(inputDecoration.border, const OutlineInputBorder());
941 });
942
943 testWidgets('DatePickerDialog resolves DatePickerTheme.dayOverlayColor states', (
944 WidgetTester tester,
945 ) async {
946 final MaterialStateProperty<Color> dayOverlayColor = MaterialStateProperty.resolveWith<Color>((
947 Set<MaterialState> states,
948 ) {
949 if (states.contains(MaterialState.hovered)) {
950 return const Color(0xff00ff00);
951 }
952 if (states.contains(MaterialState.focused)) {
953 return const Color(0xffff00ff);
954 }
955 if (states.contains(MaterialState.pressed)) {
956 return const Color(0xffffff00);
957 }
958 return Colors.transparent;
959 });
960
961 await tester.pumpWidget(
962 MaterialApp(
963 theme: ThemeData(datePickerTheme: DatePickerThemeData(dayOverlayColor: dayOverlayColor)),
964 home: Directionality(
965 textDirection: TextDirection.ltr,
966 child: Material(
967 child: Center(
968 child: Focus(
969 child: DatePickerDialog(
970 initialDate: DateTime(2023, DateTime.january, 25),
971 firstDate: DateTime(2022),
972 lastDate: DateTime(2024, DateTime.december, 31),
973 currentDate: DateTime(2023, DateTime.january, 24),
974 ),
975 ),
976 ),
977 ),
978 ),
979 ),
980 );
981
982 MaterialInkController findDayGridMaterial(WidgetTester tester) {
983 // All days are painted on the same Material widget.
984 // Use an arbitrary day to find this Material.
985 return Material.of(tester.element(find.text('17')));
986 }
987
988 // Test the hover overlay color.
989 final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
990 await gesture.addPointer();
991 await gesture.moveTo(tester.getCenter(find.text('20')));
992 await tester.pumpAndSettle();
993
994 expect(
995 findDayGridMaterial(tester),
996 paints
997 ..circle() // Today decoration.
998 ..circle() // Selected day decoration.
999 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.hovered})),
1000 );
1001
1002 // Test the pressed overlay color.
1003 await gesture.down(tester.getCenter(find.text('20')));
1004 await tester.pumpAndSettle();
1005 if (kIsWeb) {
1006 // An extra circle is painted on the web for the hovered state.
1007 expect(
1008 findDayGridMaterial(tester),
1009 paints
1010 ..circle() // Today decoration.
1011 ..circle() // Selected day decoration.
1012 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.hovered}))
1013 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.hovered}))
1014 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.pressed})),
1015 );
1016 } else {
1017 expect(
1018 findDayGridMaterial(tester),
1019 paints
1020 ..circle() // Today decoration.
1021 ..circle() // Selected day decoration.
1022 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.hovered}))
1023 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.pressed})),
1024 );
1025 }
1026
1027 await gesture.removePointer();
1028 await tester.pumpAndSettle();
1029
1030 // Focus day selection.
1031 for (int i = 0; i < 5; i++) {
1032 await tester.sendKeyEvent(LogicalKeyboardKey.tab);
1033 await tester.pumpAndSettle();
1034 }
1035
1036 // Test the focused overlay color.
1037 expect(
1038 findDayGridMaterial(tester),
1039 paints
1040 ..circle() // Today decoration.
1041 ..circle() // Selected day decoration.
1042 ..circle(color: dayOverlayColor.resolve(<MaterialState>{MaterialState.focused})),
1043 );
1044 });
1045
1046 testWidgets('DatePickerDialog resolves DatePickerTheme.yearOverlayColor states', (
1047 WidgetTester tester,
1048 ) async {
1049 final MaterialStateProperty<Color> yearOverlayColor = MaterialStateProperty.resolveWith<Color>((
1050 Set<MaterialState> states,
1051 ) {
1052 if (states.contains(MaterialState.hovered)) {
1053 return const Color(0xff00ff00);
1054 }
1055 if (states.contains(MaterialState.focused)) {
1056 return const Color(0xffff00ff);
1057 }
1058 if (states.contains(MaterialState.pressed)) {
1059 return const Color(0xffffff00);
1060 }
1061 return Colors.transparent;
1062 });
1063
1064 await tester.pumpWidget(
1065 MaterialApp(
1066 theme: ThemeData(datePickerTheme: DatePickerThemeData(yearOverlayColor: yearOverlayColor)),
1067 home: Directionality(
1068 textDirection: TextDirection.ltr,
1069 child: Material(
1070 child: Center(
1071 child: Focus(
1072 child: DatePickerDialog(
1073 initialDate: DateTime(2023, DateTime.january, 25),
1074 firstDate: DateTime(2022),
1075 lastDate: DateTime(2024, DateTime.december, 31),
1076 currentDate: DateTime(2023, DateTime.january, 24),
1077 initialCalendarMode: DatePickerMode.year,
1078 ),
1079 ),
1080 ),
1081 ),
1082 ),
1083 ),
1084 );
1085
1086 // Test the hover overlay color.
1087 final RenderObject inkFeatures = tester.allRenderObjects.firstWhere(
1088 (RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures',
1089 );
1090 final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
1091 await gesture.addPointer();
1092 await gesture.moveTo(tester.getCenter(find.text('2022')));
1093 await tester.pumpAndSettle();
1094 expect(
1095 inkFeatures,
1096 paints..rect(color: yearOverlayColor.resolve(<MaterialState>{MaterialState.hovered})),
1097 );
1098
1099 // Test the pressed overlay color.
1100 await gesture.down(tester.getCenter(find.text('2022')));
1101 await tester.pumpAndSettle();
1102 expect(
1103 inkFeatures,
1104 paints
1105 ..rect(color: yearOverlayColor.resolve(<MaterialState>{MaterialState.hovered}))
1106 ..rect(color: yearOverlayColor.resolve(<MaterialState>{MaterialState.pressed})),
1107 );
1108
1109 await gesture.removePointer();
1110 await tester.pumpAndSettle();
1111
1112 // Focus year selection.
1113 for (int i = 0; i < 3; i++) {
1114 await tester.sendKeyEvent(LogicalKeyboardKey.tab);
1115 await tester.pumpAndSettle();
1116 }
1117
1118 // Test the focused overlay color.
1119 expect(
1120 inkFeatures,
1121 paints..rect(color: yearOverlayColor.resolve(<MaterialState>{MaterialState.focused})),
1122 );
1123 });
1124
1125 testWidgets('DateRangePickerDialog resolves DatePickerTheme.rangeSelectionOverlayColor states', (
1126 WidgetTester tester,
1127 ) async {
1128 final MaterialStateProperty<Color> rangeSelectionOverlayColor =
1129 MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
1130 if (states.contains(MaterialState.hovered)) {
1131 return const Color(0xff00ff00);
1132 }
1133 if (states.contains(MaterialState.pressed)) {
1134 return const Color(0xffffff00);
1135 }
1136 return Colors.transparent;
1137 });
1138
1139 await tester.pumpWidget(
1140 MaterialApp(
1141 theme: ThemeData(
1142 datePickerTheme: DatePickerThemeData(
1143 rangeSelectionOverlayColor: rangeSelectionOverlayColor,
1144 ),
1145 ),
1146 home: Directionality(
1147 textDirection: TextDirection.ltr,
1148 child: Material(
1149 child: Center(
1150 child: DateRangePickerDialog(
1151 firstDate: DateTime(2023),
1152 lastDate: DateTime(2023, DateTime.january, 31),
1153 initialDateRange: DateTimeRange(
1154 start: DateTime(2023, DateTime.january, 17),
1155 end: DateTime(2023, DateTime.january, 20),
1156 ),
1157 currentDate: DateTime(2023, DateTime.january, 23),
1158 ),
1159 ),
1160 ),
1161 ),
1162 ),
1163 );
1164
1165 // Test the hover overlay color.
1166 final RenderObject inkFeatures = tester.allRenderObjects.firstWhere(
1167 (RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures',
1168 );
1169 final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
1170 await gesture.addPointer();
1171 await gesture.moveTo(tester.getCenter(find.text('18')));
1172 await tester.pumpAndSettle();
1173 expect(
1174 inkFeatures,
1175 paints
1176 ..circle(color: rangeSelectionOverlayColor.resolve(<MaterialState>{MaterialState.hovered})),
1177 );
1178
1179 // Test the pressed overlay color.
1180 await gesture.down(tester.getCenter(find.text('18')));
1181 await tester.pumpAndSettle();
1182 if (kIsWeb) {
1183 // An extra circle is painted on the web for the hovered state.
1184 expect(
1185 inkFeatures,
1186 paints
1187 ..circle(
1188 color: rangeSelectionOverlayColor.resolve(<MaterialState>{MaterialState.hovered}),
1189 )
1190 ..circle(
1191 color: rangeSelectionOverlayColor.resolve(<MaterialState>{MaterialState.hovered}),
1192 )
1193 ..circle(
1194 color: rangeSelectionOverlayColor.resolve(<MaterialState>{MaterialState.pressed}),
1195 ),
1196 );
1197 } else {
1198 expect(
1199 inkFeatures,
1200 paints
1201 ..circle(
1202 color: rangeSelectionOverlayColor.resolve(<MaterialState>{MaterialState.hovered}),
1203 )
1204 ..circle(
1205 color: rangeSelectionOverlayColor.resolve(<MaterialState>{MaterialState.pressed}),
1206 ),
1207 );
1208 }
1209 });
1210
1211 testWidgets('YearPicker maintains default year shape at textScaleFactor 1, 1.5, 2', (
1212 WidgetTester tester,
1213 ) async {
1214 double textScaleFactor = 1.0;
1215 Widget buildFrame() {
1216 return MaterialApp(
1217 home: Builder(
1218 builder: (BuildContext context) {
1219 return MediaQuery.withClampedTextScaling(
1220 minScaleFactor: textScaleFactor,
1221 maxScaleFactor: textScaleFactor,
1222 child: Scaffold(
1223 body: YearPicker(
1224 currentDate: DateTime(2025),
1225 firstDate: DateTime(2021),
1226 lastDate: DateTime(2030),
1227 selectedDate: DateTime(2025),
1228 onChanged: (DateTime value) {},
1229 ),
1230 ),
1231 );
1232 },
1233 ),
1234 );
1235 }
1236
1237 await tester.pumpWidget(buildFrame());
1238
1239 // Find container whose child is text 2025.
1240 final Finder yearContainer =
1241 find.ancestor(of: find.text('2025'), matching: find.byType(Container)).first;
1242
1243 expect(
1244 tester.renderObject(yearContainer),
1245 paints..rrect(
1246 rrect: RRect.fromLTRBR(0.5, 0.5, 71.5, 35.5, const Radius.circular(17.5)),
1247 color: const Color(0xFF6750A4),
1248 ),
1249 );
1250
1251 textScaleFactor = 1.5;
1252 await tester.pumpWidget(buildFrame());
1253
1254 expect(
1255 tester.renderObject(yearContainer),
1256 paints..rrect(
1257 rrect: RRect.fromLTRBR(0.5, 0.5, 107.5, 51.5, const Radius.circular(25.5)),
1258 color: const Color(0xFF6750A4),
1259 ),
1260 );
1261
1262 textScaleFactor = 2;
1263 await tester.pumpWidget(buildFrame());
1264
1265 expect(
1266 tester.renderObject(yearContainer),
1267 paints..rrect(
1268 rrect: RRect.fromLTRBR(0.5, 0.5, 143.5, 51.5, const Radius.circular(25.5)),
1269 color: const Color(0xFF6750A4),
1270 ),
1271 );
1272 });
1273
1274 testWidgets('YearPicker applies shape from DatePickerThemeData.yearShape correctly', (
1275 WidgetTester tester,
1276 ) async {
1277 const OutlinedBorder yearShpae = CircleBorder();
1278 await tester.pumpWidget(
1279 MaterialApp(
1280 theme: ThemeData(
1281 datePickerTheme: datePickerTheme.copyWith(
1282 yearShape: MaterialStateProperty.all<OutlinedBorder>(yearShpae),
1283 ),
1284 ),
1285 home: Directionality(
1286 textDirection: TextDirection.ltr,
1287 child: Material(
1288 child: Center(
1289 child: YearPicker(
1290 currentDate: DateTime(2025),
1291 firstDate: DateTime(2021),
1292 lastDate: DateTime(2030),
1293 selectedDate: DateTime(2025),
1294 onChanged: (DateTime value) {},
1295 ),
1296 ),
1297 ),
1298 ),
1299 ),
1300 );
1301
1302 final ShapeDecoration year2022Decoration = findTextDecoration(tester, '2022')!;
1303 final OutlinedBorder year2022roundedRectangleBorder = year2022Decoration.shape as CircleBorder;
1304 expect(year2022roundedRectangleBorder.side.width, 0.0);
1305 expect(year2022roundedRectangleBorder.side.color, yearShpae.side.color);
1306
1307 final ShapeDecoration year2025Decoration = findTextDecoration(tester, '2025')!;
1308 final OutlinedBorder year2022RoundedRectangleBorder = year2025Decoration.shape as CircleBorder;
1309 expect(year2022RoundedRectangleBorder.side.width, datePickerTheme.todayBorder?.width);
1310 expect(
1311 year2022RoundedRectangleBorder.side.color,
1312 datePickerTheme.todayForegroundColor?.resolve(<MaterialState>{}),
1313 );
1314 });
1315}
1316

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com