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/material.dart'; |
7 | import 'package:flutter_test/flutter_test.dart'; |
8 | |
9 | void main() { |
10 | test('DropdownMenuThemeData copyWith, ==, hashCode basics' , () { |
11 | expect(const DropdownMenuThemeData(), const DropdownMenuThemeData().copyWith()); |
12 | expect(const DropdownMenuThemeData().hashCode, const DropdownMenuThemeData().copyWith().hashCode); |
13 | |
14 | const DropdownMenuThemeData custom = DropdownMenuThemeData( |
15 | menuStyle: MenuStyle(backgroundColor: MaterialStatePropertyAll<Color>(Colors.green)), |
16 | inputDecorationTheme: InputDecorationTheme(filled: true), |
17 | textStyle: TextStyle(fontSize: 25.0), |
18 | ); |
19 | final DropdownMenuThemeData copy = const DropdownMenuThemeData().copyWith( |
20 | menuStyle: custom.menuStyle, |
21 | inputDecorationTheme: custom.inputDecorationTheme, |
22 | textStyle: custom.textStyle, |
23 | ); |
24 | expect(copy, custom); |
25 | }); |
26 | |
27 | test('DropdownMenuThemeData lerp special cases' , () { |
28 | expect(DropdownMenuThemeData.lerp(null, null, 0), const DropdownMenuThemeData()); |
29 | const DropdownMenuThemeData data = DropdownMenuThemeData(); |
30 | expect(identical(DropdownMenuThemeData.lerp(data, data, 0.5), data), true); |
31 | }); |
32 | |
33 | testWidgets('Default DropdownMenuThemeData debugFillProperties' , (WidgetTester tester) async { |
34 | final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); |
35 | const DropdownMenuThemeData().debugFillProperties(builder); |
36 | |
37 | final List<String> description = builder.properties |
38 | .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) |
39 | .map((DiagnosticsNode node) => node.toString()) |
40 | .toList(); |
41 | |
42 | expect(description, <String>[]); |
43 | }); |
44 | |
45 | testWidgets('With no other configuration, defaults are used' , (WidgetTester tester) async { |
46 | final ThemeData themeData = ThemeData(); |
47 | await tester.pumpWidget( |
48 | MaterialApp( |
49 | theme: themeData, |
50 | home: const Scaffold( |
51 | body: Center( |
52 | child: DropdownMenu<int>( |
53 | dropdownMenuEntries: <DropdownMenuEntry<int>>[ |
54 | DropdownMenuEntry<int>(value: 0, label: 'Item 0' ), |
55 | DropdownMenuEntry<int>(value: 1, label: 'Item 1' ), |
56 | DropdownMenuEntry<int>(value: 2, label: 'Item 2' ), |
57 | ], |
58 | ), |
59 | ), |
60 | ), |
61 | ) |
62 | ); |
63 | |
64 | final EditableText editableText = tester.widget(find.byType(EditableText)); |
65 | expect(editableText.style.color, themeData.textTheme.labelLarge!.color); |
66 | expect(editableText.style.background, themeData.textTheme.labelLarge!.background); |
67 | expect(editableText.style.shadows, themeData.textTheme.labelLarge!.shadows); |
68 | expect(editableText.style.decoration, themeData.textTheme.labelLarge!.decoration); |
69 | expect(editableText.style.locale, themeData.textTheme.labelLarge!.locale); |
70 | expect(editableText.style.wordSpacing, themeData.textTheme.labelLarge!.wordSpacing); |
71 | |
72 | final TextField textField = tester.widget(find.byType(TextField)); |
73 | expect(textField.decoration?.border, const OutlineInputBorder()); |
74 | |
75 | await tester.tap(find.widgetWithIcon(IconButton, Icons.arrow_drop_down).first); |
76 | await tester.pump(); |
77 | expect(find.byType(MenuAnchor), findsOneWidget); |
78 | |
79 | final Finder menuMaterial = find.ancestor( |
80 | of: find.widgetWithText(TextButton, 'Item 0' ), |
81 | matching: find.byType(Material), |
82 | ).at(1); |
83 | Material material = tester.widget<Material>(menuMaterial); |
84 | expect(material.color, themeData.colorScheme.surfaceContainer); |
85 | expect(material.shadowColor, themeData.colorScheme.shadow); |
86 | expect(material.surfaceTintColor, Colors.transparent); |
87 | expect(material.elevation, 3.0); |
88 | expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0)))); |
89 | |
90 | final Finder buttonMaterial = find.descendant( |
91 | of: find.widgetWithText(TextButton, 'Item 0' ), |
92 | matching: find.byType(Material), |
93 | ).last; |
94 | |
95 | material = tester.widget<Material>(buttonMaterial); |
96 | expect(material.color, Colors.transparent); |
97 | expect(material.elevation, 0.0); |
98 | expect(material.shape, const RoundedRectangleBorder()); |
99 | expect(material.textStyle?.color, themeData.colorScheme.onSurface); |
100 | }); |
101 | |
102 | testWidgets('ThemeData.dropdownMenuTheme overrides defaults' , (WidgetTester tester) async { |
103 | final ThemeData theme = ThemeData( |
104 | dropdownMenuTheme: DropdownMenuThemeData( |
105 | textStyle: TextStyle( |
106 | color: Colors.orange, |
107 | backgroundColor: Colors.indigo, |
108 | fontSize: 30.0, |
109 | shadows: kElevationToShadow[1], |
110 | decoration: TextDecoration.underline, |
111 | wordSpacing: 2.0, |
112 | ), |
113 | menuStyle: const MenuStyle( |
114 | backgroundColor: MaterialStatePropertyAll<Color>(Colors.grey), |
115 | shadowColor: MaterialStatePropertyAll<Color>(Colors.brown), |
116 | surfaceTintColor: MaterialStatePropertyAll<Color>(Colors.amberAccent), |
117 | elevation: MaterialStatePropertyAll<double>(10.0), |
118 | shape: MaterialStatePropertyAll<OutlinedBorder>( |
119 | RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))), |
120 | ), |
121 | ), |
122 | inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.lightGreen), |
123 | ) |
124 | ); |
125 | |
126 | await tester.pumpWidget( |
127 | MaterialApp( |
128 | theme: theme, |
129 | home: const Scaffold( |
130 | body: Center( |
131 | child: DropdownMenu<int>( |
132 | dropdownMenuEntries: <DropdownMenuEntry<int>>[ |
133 | DropdownMenuEntry<int>(value: 0, label: 'Item 0' ), |
134 | DropdownMenuEntry<int>(value: 1, label: 'Item 1' ), |
135 | DropdownMenuEntry<int>(value: 2, label: 'Item 2' ), |
136 | ], |
137 | ), |
138 | ), |
139 | ) |
140 | ) |
141 | ); |
142 | |
143 | final EditableText editableText = tester.widget(find.byType(EditableText)); |
144 | expect(editableText.style.color, Colors.orange); |
145 | expect(editableText.style.backgroundColor, Colors.indigo); |
146 | expect(editableText.style.shadows, kElevationToShadow[1]); |
147 | expect(editableText.style.decoration, TextDecoration.underline); |
148 | expect(editableText.style.wordSpacing, 2.0); |
149 | |
150 | final TextField textField = tester.widget(find.byType(TextField)); |
151 | expect(textField.decoration?.filled, isTrue); |
152 | expect(textField.decoration?.fillColor, Colors.lightGreen); |
153 | |
154 | await tester.tap(find.widgetWithIcon(IconButton, Icons.arrow_drop_down).first); |
155 | await tester.pump(); |
156 | expect(find.byType(MenuAnchor), findsOneWidget); |
157 | |
158 | final Finder menuMaterial = find.ancestor( |
159 | of: find.widgetWithText(TextButton, 'Item 0' ), |
160 | matching: find.byType(Material), |
161 | ).at(1); |
162 | Material material = tester.widget<Material>(menuMaterial); |
163 | expect(material.color, Colors.grey); |
164 | expect(material.shadowColor, Colors.brown); |
165 | expect(material.surfaceTintColor, Colors.amberAccent); |
166 | expect(material.elevation, 10.0); |
167 | expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)))); |
168 | |
169 | final Finder buttonMaterial = find.descendant( |
170 | of: find.widgetWithText(TextButton, 'Item 0' ), |
171 | matching: find.byType(Material), |
172 | ).last; |
173 | |
174 | material = tester.widget<Material>(buttonMaterial); |
175 | expect(material.color, Colors.transparent); |
176 | expect(material.elevation, 0.0); |
177 | expect(material.shape, const RoundedRectangleBorder()); |
178 | expect(material.textStyle?.color, theme.colorScheme.onSurface); |
179 | }); |
180 | |
181 | testWidgets('DropdownMenuTheme overrides ThemeData and defaults' , (WidgetTester tester) async { |
182 | final DropdownMenuThemeData global = DropdownMenuThemeData( |
183 | textStyle: TextStyle( |
184 | color: Colors.orange, |
185 | backgroundColor: Colors.indigo, |
186 | fontSize: 30.0, |
187 | shadows: kElevationToShadow[1], |
188 | decoration: TextDecoration.underline, |
189 | wordSpacing: 2.0, |
190 | ), |
191 | menuStyle: const MenuStyle( |
192 | backgroundColor: MaterialStatePropertyAll<Color>(Colors.grey), |
193 | shadowColor: MaterialStatePropertyAll<Color>(Colors.brown), |
194 | surfaceTintColor: MaterialStatePropertyAll<Color>(Colors.amberAccent), |
195 | elevation: MaterialStatePropertyAll<double>(10.0), |
196 | shape: MaterialStatePropertyAll<OutlinedBorder>( |
197 | RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))), |
198 | ), |
199 | ), |
200 | inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.lightGreen), |
201 | ); |
202 | |
203 | final DropdownMenuThemeData dropdownMenuTheme = DropdownMenuThemeData( |
204 | textStyle: TextStyle( |
205 | color: Colors.red, |
206 | backgroundColor: Colors.orange, |
207 | fontSize: 27.0, |
208 | shadows: kElevationToShadow[2], |
209 | decoration: TextDecoration.lineThrough, |
210 | wordSpacing: 5.0, |
211 | ), |
212 | menuStyle: const MenuStyle( |
213 | backgroundColor: MaterialStatePropertyAll<Color>(Colors.yellow), |
214 | shadowColor: MaterialStatePropertyAll<Color>(Colors.green), |
215 | surfaceTintColor: MaterialStatePropertyAll<Color>(Colors.teal), |
216 | elevation: MaterialStatePropertyAll<double>(15.0), |
217 | shape: MaterialStatePropertyAll<OutlinedBorder>( |
218 | RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))), |
219 | ), |
220 | ), |
221 | inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.blue), |
222 | ); |
223 | |
224 | final ThemeData theme = ThemeData(dropdownMenuTheme: global); |
225 | await tester.pumpWidget( |
226 | MaterialApp( |
227 | theme: theme, |
228 | home: DropdownMenuTheme( |
229 | data: dropdownMenuTheme, |
230 | child: const Scaffold( |
231 | body: Center( |
232 | child: DropdownMenu<int>( |
233 | dropdownMenuEntries: <DropdownMenuEntry<int>>[ |
234 | DropdownMenuEntry<int>(value: 0, label: 'Item 0' ), |
235 | DropdownMenuEntry<int>(value: 1, label: 'Item 1' ), |
236 | DropdownMenuEntry<int>(value: 2, label: 'Item 2' ), |
237 | ], |
238 | ), |
239 | ), |
240 | ), |
241 | ) |
242 | ) |
243 | ); |
244 | |
245 | final EditableText editableText = tester.widget(find.byType(EditableText)); |
246 | expect(editableText.style.color, Colors.red); |
247 | expect(editableText.style.backgroundColor, Colors.orange); |
248 | expect(editableText.style.fontSize, 27.0); |
249 | expect(editableText.style.shadows, kElevationToShadow[2]); |
250 | expect(editableText.style.decoration, TextDecoration.lineThrough); |
251 | expect(editableText.style.wordSpacing, 5.0); |
252 | |
253 | final TextField textField = tester.widget(find.byType(TextField)); |
254 | expect(textField.decoration?.filled, isTrue); |
255 | expect(textField.decoration?.fillColor, Colors.blue); |
256 | |
257 | await tester.tap(find.widgetWithIcon(IconButton, Icons.arrow_drop_down).first); |
258 | await tester.pump(); |
259 | expect(find.byType(MenuAnchor), findsOneWidget); |
260 | |
261 | final Finder menuMaterial = find.ancestor( |
262 | of: find.widgetWithText(TextButton, 'Item 0' ), |
263 | matching: find.byType(Material), |
264 | ).at(1); |
265 | Material material = tester.widget<Material>(menuMaterial); |
266 | expect(material.color, Colors.yellow); |
267 | expect(material.shadowColor, Colors.green); |
268 | expect(material.surfaceTintColor, Colors.teal); |
269 | expect(material.elevation, 15.0); |
270 | expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0)))); |
271 | |
272 | final Finder buttonMaterial = find.descendant( |
273 | of: find.widgetWithText(TextButton, 'Item 0' ), |
274 | matching: find.byType(Material), |
275 | ).last; |
276 | |
277 | material = tester.widget<Material>(buttonMaterial); |
278 | expect(material.color, Colors.transparent); |
279 | expect(material.elevation, 0.0); |
280 | expect(material.shape, const RoundedRectangleBorder()); |
281 | expect(material.textStyle?.color, theme.colorScheme.onSurface); |
282 | }); |
283 | |
284 | testWidgets('Widget parameters overrides DropdownMenuTheme, ThemeData and defaults' , (WidgetTester tester) async { |
285 | final DropdownMenuThemeData global = DropdownMenuThemeData( |
286 | textStyle: TextStyle( |
287 | color: Colors.orange, |
288 | backgroundColor: Colors.indigo, |
289 | fontSize: 30.0, |
290 | shadows: kElevationToShadow[1], |
291 | decoration: TextDecoration.underline, |
292 | wordSpacing: 2.0, |
293 | ), |
294 | menuStyle: const MenuStyle( |
295 | backgroundColor: MaterialStatePropertyAll<Color>(Colors.grey), |
296 | shadowColor: MaterialStatePropertyAll<Color>(Colors.brown), |
297 | surfaceTintColor: MaterialStatePropertyAll<Color>(Colors.amberAccent), |
298 | elevation: MaterialStatePropertyAll<double>(10.0), |
299 | shape: MaterialStatePropertyAll<OutlinedBorder>( |
300 | RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))), |
301 | ), |
302 | ), |
303 | inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.lightGreen), |
304 | ); |
305 | |
306 | final DropdownMenuThemeData dropdownMenuTheme = DropdownMenuThemeData( |
307 | textStyle: TextStyle( |
308 | color: Colors.red, |
309 | backgroundColor: Colors.orange, |
310 | fontSize: 27.0, |
311 | shadows: kElevationToShadow[2], |
312 | decoration: TextDecoration.lineThrough, |
313 | wordSpacing: 5.0, |
314 | ), |
315 | menuStyle: const MenuStyle( |
316 | backgroundColor: MaterialStatePropertyAll<Color>(Colors.yellow), |
317 | shadowColor: MaterialStatePropertyAll<Color>(Colors.green), |
318 | surfaceTintColor: MaterialStatePropertyAll<Color>(Colors.teal), |
319 | elevation: MaterialStatePropertyAll<double>(15.0), |
320 | shape: MaterialStatePropertyAll<OutlinedBorder>( |
321 | RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))), |
322 | ), |
323 | ), |
324 | inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.blue), |
325 | ); |
326 | |
327 | final ThemeData theme = ThemeData(dropdownMenuTheme: global); |
328 | await tester.pumpWidget( |
329 | MaterialApp( |
330 | theme: theme, |
331 | home: DropdownMenuTheme( |
332 | data: dropdownMenuTheme, |
333 | child: Scaffold( |
334 | body: Center( |
335 | child: DropdownMenu<int>( |
336 | textStyle: TextStyle( |
337 | color: Colors.pink, |
338 | backgroundColor: Colors.cyan, |
339 | fontSize: 32.0, |
340 | shadows: kElevationToShadow[3], |
341 | decoration: TextDecoration.overline, |
342 | wordSpacing: 3.0, |
343 | ), |
344 | menuStyle: const MenuStyle( |
345 | backgroundColor: MaterialStatePropertyAll<Color>(Colors.limeAccent), |
346 | shadowColor: MaterialStatePropertyAll<Color>(Colors.deepOrangeAccent), |
347 | surfaceTintColor: MaterialStatePropertyAll<Color>(Colors.lightBlue), |
348 | elevation: MaterialStatePropertyAll<double>(21.0), |
349 | shape: MaterialStatePropertyAll<OutlinedBorder>( |
350 | RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15.0))), |
351 | ), |
352 | ), |
353 | inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.deepPurple), |
354 | dropdownMenuEntries: const <DropdownMenuEntry<int>>[ |
355 | DropdownMenuEntry<int>(value: 0, label: 'Item 0' ), |
356 | DropdownMenuEntry<int>(value: 1, label: 'Item 1' ), |
357 | DropdownMenuEntry<int>(value: 2, label: 'Item 2' ), |
358 | ], |
359 | ), |
360 | ), |
361 | ), |
362 | ) |
363 | ) |
364 | ); |
365 | |
366 | final EditableText editableText = tester.widget(find.byType(EditableText)); |
367 | expect(editableText.style.color, Colors.pink); |
368 | expect(editableText.style.backgroundColor, Colors.cyan); |
369 | expect(editableText.style.fontSize, 32.0); |
370 | expect(editableText.style.shadows, kElevationToShadow[3]); |
371 | expect(editableText.style.decoration, TextDecoration.overline); |
372 | expect(editableText.style.wordSpacing, 3.0); |
373 | |
374 | final TextField textField = tester.widget(find.byType(TextField)); |
375 | expect(textField.decoration?.filled, isTrue); |
376 | expect(textField.decoration?.fillColor, Colors.deepPurple); |
377 | |
378 | await tester.tap(find.widgetWithIcon(IconButton, Icons.arrow_drop_down).first); |
379 | await tester.pump(); |
380 | expect(find.byType(MenuAnchor), findsOneWidget); |
381 | |
382 | final Finder menuMaterial = find.ancestor( |
383 | of: find.widgetWithText(TextButton, 'Item 0' ), |
384 | matching: find.byType(Material), |
385 | ).at(1); |
386 | Material material = tester.widget<Material>(menuMaterial); |
387 | expect(material.color, Colors.limeAccent); |
388 | expect(material.shadowColor, Colors.deepOrangeAccent); |
389 | expect(material.surfaceTintColor, Colors.lightBlue); |
390 | expect(material.elevation, 21.0); |
391 | expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15.0)))); |
392 | |
393 | final Finder buttonMaterial = find.descendant( |
394 | of: find.widgetWithText(TextButton, 'Item 0' ), |
395 | matching: find.byType(Material), |
396 | ).last; |
397 | |
398 | material = tester.widget<Material>(buttonMaterial); |
399 | expect(material.color, Colors.transparent); |
400 | expect(material.elevation, 0.0); |
401 | expect(material.shape, const RoundedRectangleBorder()); |
402 | expect(material.textStyle?.color, theme.colorScheme.onSurface); |
403 | }); |
404 | } |
405 | |