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 | |
5 | import 'package:flutter/foundation.dart'; |
6 | import 'package:flutter/gestures.dart'; |
7 | import 'package:flutter/material.dart'; |
8 | import 'package:flutter/services.dart'; |
9 | import 'package:flutter_test/flutter_test.dart'; |
10 | |
11 | void 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 | |