Skip to content

Commit da127f1

Browse files
authored
Updated material button theme tests for Material3 (#128543)
1 parent befd86d commit da127f1

File tree

6 files changed

+451
-24
lines changed

6 files changed

+451
-24
lines changed

packages/flutter/lib/src/material/outlined_button.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ class OutlinedButton extends ButtonStyleButton {
281281
/// * hovered - Theme.colorScheme.primary(0.08)
282282
/// * focused or pressed - Theme.colorScheme.primary(0.12)
283283
/// * others - null
284-
/// * `shadowColor` - null
284+
/// * `shadowColor` - Colors.transparent,
285285
/// * `surfaceTintColor` - null
286286
/// * `elevation` - 0
287287
/// * `padding`

packages/flutter/lib/src/material/text_button.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ class TextButton extends ButtonStyleButton {
315315
/// * hovered - Theme.colorScheme.primary(0.08)
316316
/// * focused or pressed - Theme.colorScheme.primary(0.12)
317317
/// * others - null
318-
/// * `shadowColor` - null
318+
/// * `shadowColor` - Colors.transparent,
319319
/// * `surfaceTintColor` - null
320320
/// * `elevation` - 0
321321
/// * `padding`

packages/flutter/test/material/elevated_button_theme_test.dart

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,48 @@ void main() {
1212
expect(identical(ElevatedButtonThemeData.lerp(data, data, 0.5), data), true);
1313
});
1414

15-
testWidgets('Passing no ElevatedButtonTheme returns defaults', (WidgetTester tester) async {
15+
testWidgets('Material3: Passing no ElevatedButtonTheme returns defaults', (WidgetTester tester) async {
1616
const ColorScheme colorScheme = ColorScheme.light();
1717
await tester.pumpWidget(
1818
MaterialApp(
19-
theme: ThemeData.from(colorScheme: colorScheme),
19+
theme: ThemeData.from(colorScheme: colorScheme, useMaterial3: true),
20+
home: Scaffold(
21+
body: Center(
22+
child: ElevatedButton(
23+
onPressed: () { },
24+
child: const Text('button'),
25+
),
26+
),
27+
),
28+
),
29+
);
30+
31+
final Finder buttonMaterial = find.descendant(
32+
of: find.byType(ElevatedButton),
33+
matching: find.byType(Material),
34+
);
35+
36+
final Material material = tester.widget<Material>(buttonMaterial);
37+
expect(material.animationDuration, const Duration(milliseconds: 200));
38+
expect(material.borderRadius, null);
39+
expect(material.color, colorScheme.surface);
40+
expect(material.elevation, 1);
41+
expect(material.shadowColor, colorScheme.shadow);
42+
expect(material.shape, const StadiumBorder());
43+
expect(material.textStyle!.color, colorScheme.primary);
44+
expect(material.textStyle!.fontFamily, 'Roboto');
45+
expect(material.textStyle!.fontSize, 14);
46+
expect(material.textStyle!.fontWeight, FontWeight.w500);
47+
48+
final Align align = tester.firstWidget<Align>(find.ancestor(of: find.text('button'), matching: find.byType(Align)));
49+
expect(align.alignment, Alignment.center);
50+
});
51+
52+
testWidgets('Material2: Passing no ElevatedButtonTheme returns defaults', (WidgetTester tester) async {
53+
const ColorScheme colorScheme = ColorScheme.light();
54+
await tester.pumpWidget(
55+
MaterialApp(
56+
theme: ThemeData.from(colorScheme: colorScheme, useMaterial3: false),
2057
home: Scaffold(
2158
body: Center(
2259
child: ElevatedButton(
@@ -98,7 +135,7 @@ void main() {
98135
},
99136
);
100137
return MaterialApp(
101-
theme: ThemeData.from(colorScheme: const ColorScheme.light()).copyWith(
138+
theme: ThemeData.from(useMaterial3: false, colorScheme: const ColorScheme.light()).copyWith(
102139
elevatedButtonTheme: ElevatedButtonThemeData(style: overallStyle),
103140
),
104141
home: Scaffold(
@@ -191,14 +228,85 @@ void main() {
191228
});
192229
});
193230

194-
testWidgets('Theme shadowColor', (WidgetTester tester) async {
231+
testWidgets('Material 3: Theme shadowColor', (WidgetTester tester) async {
232+
const ColorScheme colorScheme = ColorScheme.light();
233+
const Color shadowColor = Color(0xff000001);
234+
const Color overriddenColor = Color(0xff000002);
235+
236+
Widget buildFrame({ Color? overallShadowColor, Color? themeShadowColor, Color? shadowColor }) {
237+
return MaterialApp(
238+
theme: ThemeData.from(
239+
useMaterial3: true,
240+
colorScheme: colorScheme.copyWith(shadow: overallShadowColor),
241+
),
242+
home: Scaffold(
243+
body: Center(
244+
child: ElevatedButtonTheme(
245+
data: ElevatedButtonThemeData(
246+
style: ElevatedButton.styleFrom(
247+
shadowColor: themeShadowColor,
248+
),
249+
),
250+
child: Builder(
251+
builder: (BuildContext context) {
252+
return ElevatedButton(
253+
style: ElevatedButton.styleFrom(
254+
shadowColor: shadowColor,
255+
),
256+
onPressed: () { },
257+
child: const Text('button'),
258+
);
259+
},
260+
),
261+
),
262+
),
263+
),
264+
);
265+
}
266+
267+
final Finder buttonMaterialFinder = find.descendant(
268+
of: find.byType(ElevatedButton),
269+
matching: find.byType(Material),
270+
);
271+
272+
await tester.pumpWidget(buildFrame());
273+
Material material = tester.widget<Material>(buttonMaterialFinder);
274+
expect(material.shadowColor, Colors.black); //default
275+
276+
await tester.pumpWidget(buildFrame(overallShadowColor: shadowColor));
277+
await tester.pumpAndSettle(); // theme animation
278+
material = tester.widget<Material>(buttonMaterialFinder);
279+
expect(material.shadowColor, shadowColor);
280+
281+
await tester.pumpWidget(buildFrame(themeShadowColor: shadowColor));
282+
await tester.pumpAndSettle(); // theme animation
283+
material = tester.widget<Material>(buttonMaterialFinder);
284+
expect(material.shadowColor, shadowColor);
285+
286+
await tester.pumpWidget(buildFrame(shadowColor: shadowColor));
287+
await tester.pumpAndSettle(); // theme animation
288+
material = tester.widget<Material>(buttonMaterialFinder);
289+
expect(material.shadowColor, shadowColor);
290+
291+
await tester.pumpWidget(buildFrame(overallShadowColor: overriddenColor, themeShadowColor: shadowColor));
292+
await tester.pumpAndSettle(); // theme animation
293+
material = tester.widget<Material>(buttonMaterialFinder);
294+
expect(material.shadowColor, shadowColor);
295+
296+
await tester.pumpWidget(buildFrame(themeShadowColor: overriddenColor, shadowColor: shadowColor));
297+
await tester.pumpAndSettle(); // theme animation
298+
material = tester.widget<Material>(buttonMaterialFinder);
299+
expect(material.shadowColor, shadowColor);
300+
});
301+
302+
testWidgets('Material 2: Theme shadowColor', (WidgetTester tester) async {
195303
const ColorScheme colorScheme = ColorScheme.light();
196304
const Color shadowColor = Color(0xff000001);
197305
const Color overriddenColor = Color(0xff000002);
198306

199307
Widget buildFrame({ Color? overallShadowColor, Color? themeShadowColor, Color? shadowColor }) {
200308
return MaterialApp(
201-
theme: ThemeData.from(colorScheme: colorScheme).copyWith(
309+
theme: ThemeData.from(useMaterial3: false, colorScheme: colorScheme).copyWith(
202310
shadowColor: overallShadowColor,
203311
),
204312
home: Scaffold(

packages/flutter/test/material/floating_action_button_theme_test.dart

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ void main() {
1919
expect(identical(FloatingActionButtonThemeData.lerp(data, data, 0.5), data), true);
2020
});
2121

22-
testWidgets('Default values are used when no FloatingActionButton or FloatingActionButtonThemeData properties are specified', (WidgetTester tester) async {
22+
testWidgets('Material3: Default values are used when no FloatingActionButton or FloatingActionButtonThemeData properties are specified', (WidgetTester tester) async {
23+
const ColorScheme colorScheme = ColorScheme.light();
2324
await tester.pumpWidget(MaterialApp(
25+
theme: ThemeData.from(useMaterial3: true, colorScheme: colorScheme),
2426
home: Scaffold(
2527
floatingActionButton: FloatingActionButton(
2628
onPressed: () { },
@@ -29,10 +31,33 @@ void main() {
2931
),
3032
));
3133

32-
// The color scheme values are guaranteed to be non null since the default
33-
// [ThemeData] creates it with [ColorScheme.fromSwatch].
34-
expect(_getRawMaterialButton(tester).fillColor, ThemeData().colorScheme.secondary);
35-
expect(_getRichText(tester).text.style!.color, ThemeData().colorScheme.onSecondary);
34+
expect(_getRawMaterialButton(tester).fillColor, colorScheme.primaryContainer);
35+
expect(_getRichText(tester).text.style!.color, colorScheme.onPrimaryContainer);
36+
37+
// These defaults come directly from the [FloatingActionButton].
38+
expect(_getRawMaterialButton(tester).elevation, 6);
39+
expect(_getRawMaterialButton(tester).highlightElevation, 6);
40+
expect(_getRawMaterialButton(tester).shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))));
41+
expect(_getRawMaterialButton(tester).splashColor, colorScheme.onPrimaryContainer.withOpacity(0.12));
42+
expect(_getRawMaterialButton(tester).constraints, const BoxConstraints.tightFor(width: 56.0, height: 56.0));
43+
expect(_getIconSize(tester).width, 24.0);
44+
expect(_getIconSize(tester).height, 24.0);
45+
});
46+
47+
testWidgets('Material2: Default values are used when no FloatingActionButton or FloatingActionButtonThemeData properties are specified', (WidgetTester tester) async {
48+
const ColorScheme colorScheme = ColorScheme.light();
49+
await tester.pumpWidget(MaterialApp(
50+
theme: ThemeData.from(useMaterial3: false, colorScheme: colorScheme),
51+
home: Scaffold(
52+
floatingActionButton: FloatingActionButton(
53+
onPressed: () { },
54+
child: const Icon(Icons.add),
55+
),
56+
),
57+
));
58+
59+
expect(_getRawMaterialButton(tester).fillColor, colorScheme.secondary);
60+
expect(_getRichText(tester).text.style!.color, colorScheme.onSecondary);
3661

3762
// These defaults come directly from the [FloatingActionButton].
3863
expect(_getRawMaterialButton(tester).elevation, 6);
@@ -191,7 +216,8 @@ void main() {
191216
expect(_getIconSize(tester).height, iconSize);
192217
});
193218

194-
testWidgets('FloatingActionButton.extended uses custom properties when specified in the theme', (WidgetTester tester) async {
219+
testWidgets('Material3: FloatingActionButton.extended uses custom properties when specified in the theme', (WidgetTester tester) async {
220+
const ColorScheme colorScheme = ColorScheme.light();
195221
const Key iconKey = Key('icon');
196222
const Key labelKey = Key('label');
197223
const BoxConstraints constraints = BoxConstraints.tightFor(height: 100.0);
@@ -200,7 +226,43 @@ void main() {
200226
const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
201227

202228
await tester.pumpWidget(MaterialApp(
203-
theme: ThemeData().copyWith(
229+
theme: ThemeData(
230+
useMaterial3: true,
231+
colorScheme: colorScheme,
232+
).copyWith(
233+
floatingActionButtonTheme: const FloatingActionButtonThemeData(
234+
extendedSizeConstraints: constraints,
235+
extendedIconLabelSpacing: iconLabelSpacing,
236+
extendedPadding: padding,
237+
extendedTextStyle: textStyle,
238+
),
239+
),
240+
home: Scaffold(
241+
floatingActionButton: FloatingActionButton.extended(
242+
onPressed: () { },
243+
label: const Text('Extended', key: labelKey),
244+
icon: const Icon(Icons.add, key: iconKey),
245+
),
246+
),
247+
));
248+
249+
expect(_getRawMaterialButton(tester).constraints, constraints);
250+
expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing);
251+
expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start);
252+
expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
253+
expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: colorScheme.onPrimaryContainer));
254+
});
255+
256+
testWidgets('Material2: FloatingActionButton.extended uses custom properties when specified in the theme', (WidgetTester tester) async {
257+
const Key iconKey = Key('icon');
258+
const Key labelKey = Key('label');
259+
const BoxConstraints constraints = BoxConstraints.tightFor(height: 100.0);
260+
const double iconLabelSpacing = 33.0;
261+
const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
262+
const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
263+
264+
await tester.pumpWidget(MaterialApp(
265+
theme: ThemeData(useMaterial3: false).copyWith(
204266
floatingActionButtonTheme: const FloatingActionButtonThemeData(
205267
extendedSizeConstraints: constraints,
206268
extendedIconLabelSpacing: iconLabelSpacing,
@@ -225,15 +287,52 @@ void main() {
225287
expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: const Color(0xffffffff)));
226288
});
227289

228-
testWidgets('FloatingActionButton.extended custom properties takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async {
290+
testWidgets('Material3: FloatingActionButton.extended custom properties takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async {
291+
const ColorScheme colorScheme = ColorScheme.light();
229292
const Key iconKey = Key('icon');
230293
const Key labelKey = Key('label');
231294
const double iconLabelSpacing = 33.0;
232295
const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
233296
const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
234297

235298
await tester.pumpWidget(MaterialApp(
236-
theme: ThemeData().copyWith(
299+
theme: ThemeData(
300+
useMaterial3: true,
301+
colorScheme: colorScheme,
302+
).copyWith(
303+
floatingActionButtonTheme: const FloatingActionButtonThemeData(
304+
extendedIconLabelSpacing: 25.0,
305+
extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
306+
extendedTextStyle: TextStyle(letterSpacing: 3.0),
307+
),
308+
),
309+
home: Scaffold(
310+
floatingActionButton: FloatingActionButton.extended(
311+
onPressed: () { },
312+
label: const Text('Extended', key: labelKey),
313+
icon: const Icon(Icons.add, key: iconKey),
314+
extendedIconLabelSpacing: iconLabelSpacing,
315+
extendedPadding: padding,
316+
extendedTextStyle: textStyle,
317+
),
318+
),
319+
));
320+
321+
expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing);
322+
expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start);
323+
expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
324+
expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: colorScheme.onPrimaryContainer));
325+
});
326+
327+
testWidgets('Material2: FloatingActionButton.extended custom properties takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async {
328+
const Key iconKey = Key('icon');
329+
const Key labelKey = Key('label');
330+
const double iconLabelSpacing = 33.0;
331+
const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
332+
const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
333+
334+
await tester.pumpWidget(MaterialApp(
335+
theme: ThemeData(useMaterial3: false).copyWith(
237336
floatingActionButtonTheme: const FloatingActionButtonThemeData(
238337
extendedIconLabelSpacing: 25.0,
239338
extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),

0 commit comments

Comments
 (0)