| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/gestures.dart'; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/rendering.dart'; |
| import 'package:flutter/widgets.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| import '../rendering/mock_canvas.dart'; |
| import '../widgets/semantics_tester.dart'; |
| |
| void main() { |
| setUp(() { |
| debugResetSemanticsIdCounter(); |
| }); |
| |
| testWidgets('MaterialButton defaults', (WidgetTester tester) async { |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(MaterialButton), |
| matching: find.byType(Material), |
| ); |
| |
| // Enabled MaterialButton |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| Material material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, null); |
| expect(material.elevation, 2.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.transparency); |
| |
| final Offset center = tester.getCenter(find.byType(MaterialButton)); |
| await tester.startGesture(center); |
| await tester.pumpAndSettle(); |
| |
| // Only elevation changes when enabled and pressed. |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, null); |
| expect(material.elevation, 8.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.transparency); |
| |
| // Disabled MaterialButton |
| await tester.pumpWidget( |
| const Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| onPressed: null, |
| child: Text('button'), |
| ), |
| ), |
| ); |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, null); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0x61000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.transparency); |
| }); |
| |
| testWidgets('FlatButton defaults', (WidgetTester tester) async { |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(FlatButton), |
| matching: find.byType(Material), |
| ); |
| |
| // Enabled FlatButton |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: FlatButton( |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| Material material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, null); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.transparency); |
| |
| final Offset center = tester.getCenter(find.byType(FlatButton)); |
| await tester.startGesture(center); |
| await tester.pumpAndSettle(); |
| |
| material = tester.widget<Material>(rawButtonMaterial); |
| // No change vs enabled and not pressed. |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, null); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.transparency); |
| |
| // Disabled FlatButton |
| await tester.pumpWidget( |
| const Directionality( |
| textDirection: TextDirection.ltr, |
| child: FlatButton( |
| onPressed: null, |
| child: Text('button'), |
| ), |
| ), |
| ); |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, null); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0x61000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.transparency); |
| }); |
| |
| testWidgets('RaisedButton defaults', (WidgetTester tester) async { |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(RaisedButton), |
| matching: find.byType(Material), |
| ); |
| |
| // Enabled RaisedButton |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: RaisedButton( |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| Material material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, const Color(0xffe0e0e0)); |
| expect(material.elevation, 2.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.button); |
| |
| final Offset center = tester.getCenter(find.byType(RaisedButton)); |
| await tester.startGesture(center); |
| await tester.pumpAndSettle(); |
| |
| // Only elevation changes when enabled and pressed. |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, const Color(0xffe0e0e0)); |
| expect(material.elevation, 8.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.button); |
| |
| // Disabled RaisedButton |
| await tester.pumpWidget( |
| const Directionality( |
| textDirection: TextDirection.ltr, |
| child: RaisedButton( |
| onPressed: null, |
| child: Text('button'), |
| ), |
| ), |
| ); |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 200)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, const Color(0x61000000)); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.shape, RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0))); |
| expect(material.textStyle.color, const Color(0x61000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.button); |
| }); |
| |
| testWidgets('OutlineButton defaults', (WidgetTester tester) async { |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(OutlineButton), |
| matching: find.byType(Material), |
| ); |
| |
| // Enabled OutlineButton |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: OutlineButton( |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| Material material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 75)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, const Color(0x00000000)); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.button); |
| |
| final Offset center = tester.getCenter(find.byType(OutlineButton)); |
| await tester.startGesture(center); |
| await tester.pumpAndSettle(); |
| |
| // No change vs enabled and not pressed. |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 75)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, const Color(0x00000000)); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.textStyle.color, const Color(0xdd000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.button); |
| |
| // Disabled OutlineButton |
| await tester.pumpWidget( |
| const Directionality( |
| textDirection: TextDirection.ltr, |
| child: OutlineButton( |
| onPressed: null, |
| child: Text('button'), |
| ), |
| ), |
| ); |
| material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.animationDuration, const Duration(milliseconds: 75)); |
| expect(material.borderOnForeground, true); |
| expect(material.borderRadius, null); |
| expect(material.clipBehavior, Clip.none); |
| expect(material.color, const Color(0x00000000)); |
| expect(material.elevation, 0.0); |
| expect(material.shadowColor, const Color(0xff000000)); |
| expect(material.textStyle.color, const Color(0x61000000)); |
| expect(material.textStyle.fontFamily, 'Roboto'); |
| expect(material.textStyle.fontSize, 14); |
| expect(material.textStyle.fontWeight, FontWeight.w500); |
| expect(material.type, MaterialType.button); |
| }); |
| |
| testWidgets('Do buttons work with hover', (WidgetTester tester) async { |
| const Color hoverColor = Color(0xff001122); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| hoverColor: hoverColor, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| |
| final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); |
| await gesture.addPointer(); |
| await gesture.moveTo(tester.getCenter(find.byType(MaterialButton))); |
| await tester.pumpAndSettle(); |
| |
| RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: hoverColor)); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: FlatButton( |
| hoverColor: hoverColor, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| |
| await tester.pumpAndSettle(); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: hoverColor)); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: OutlineButton( |
| hoverColor: hoverColor, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| |
| await tester.pumpAndSettle(); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: hoverColor)); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: RaisedButton( |
| hoverColor: hoverColor, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| |
| await tester.pumpAndSettle(); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: hoverColor)); |
| |
| gesture.removePointer(); |
| }); |
| |
| testWidgets('Do buttons work with focus', (WidgetTester tester) async { |
| const Color focusColor = Color(0xff001122); |
| |
| FocusNode focusNode = FocusNode(debugLabel: 'MaterialButton Node'); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| focusColor: focusColor, |
| focusNode: focusNode, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| |
| WidgetsBinding.instance.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; |
| focusNode.requestFocus(); |
| await tester.pumpAndSettle(); |
| |
| RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)); |
| |
| focusNode = FocusNode(debugLabel: 'FlatButton Node'); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: FlatButton( |
| focusColor: focusColor, |
| focusNode: focusNode, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| focusNode.requestFocus(); |
| await tester.pumpAndSettle(); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)); |
| |
| focusNode = FocusNode(debugLabel: 'RaisedButton Node'); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: RaisedButton( |
| focusColor: focusColor, |
| focusNode: focusNode, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| focusNode.requestFocus(); |
| await tester.pumpAndSettle(); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)); |
| |
| focusNode = FocusNode(debugLabel: 'OutlineButton Node'); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: OutlineButton( |
| focusColor: focusColor, |
| focusNode: focusNode, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| focusNode.requestFocus(); |
| await tester.pumpAndSettle(); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)); |
| }); |
| |
| testWidgets('Button elevation and colors have proper precedence', (WidgetTester tester) async { |
| const double elevation = 10.0; |
| const double focusElevation = 11.0; |
| const double hoverElevation = 12.0; |
| const double highlightElevation = 13.0; |
| const Color focusColor = Color(0xff001122); |
| const Color hoverColor = Color(0xff112233); |
| const Color highlightColor = Color(0xff223344); |
| |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(MaterialButton), |
| matching: find.byType(Material), |
| ); |
| |
| final FocusNode focusNode = FocusNode(debugLabel: 'MaterialButton Node'); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| focusColor: focusColor, |
| hoverColor: hoverColor, |
| highlightColor: highlightColor, |
| elevation: elevation, |
| focusElevation: focusElevation, |
| hoverElevation: hoverElevation, |
| highlightElevation: highlightElevation, |
| focusNode: focusNode, |
| onPressed: () { }, |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| await tester.pumpAndSettle(); |
| WidgetsBinding.instance.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; |
| |
| // Base elevation |
| Material material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.elevation, equals(elevation)); |
| |
| // Focus elevation overrides base |
| focusNode.requestFocus(); |
| await tester.pumpAndSettle(); |
| material = tester.widget<Material>(rawButtonMaterial); |
| RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)); |
| expect(focusNode.hasPrimaryFocus, isTrue); |
| expect(material.elevation, equals(focusElevation)); |
| |
| // Hover elevation overrides focus |
| TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); |
| await gesture.addPointer(); |
| addTearDown(() => gesture?.removePointer()); |
| await gesture.moveTo(tester.getCenter(find.byType(MaterialButton))); |
| await tester.pumpAndSettle(); |
| material = tester.widget<Material>(rawButtonMaterial); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)..rect(color: hoverColor)); |
| expect(material.elevation, equals(hoverElevation)); |
| await gesture.removePointer(); |
| gesture = null; |
| |
| // Highlight elevation overrides hover |
| final TestGesture gesture2 = await tester.startGesture(tester.getCenter(find.byType(MaterialButton))); |
| addTearDown(gesture2.removePointer); |
| await tester.pumpAndSettle(); |
| material = tester.widget<Material>(rawButtonMaterial); |
| inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures'); |
| expect(inkFeatures, paints..rect(color: focusColor)..rect(color: highlightColor)); |
| expect(material.elevation, equals(highlightElevation)); |
| await gesture2.up(); |
| }); |
| |
| testWidgets('Does FlatButton contribute semantics', (WidgetTester tester) async { |
| final SemanticsTester semantics = SemanticsTester(tester); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: FlatButton( |
| onPressed: () { }, |
| child: const Text('ABC'), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(semantics, hasSemantics( |
| TestSemantics.root( |
| children: <TestSemantics>[ |
| TestSemantics.rootChild( |
| actions: <SemanticsAction>[ |
| SemanticsAction.tap, |
| ], |
| label: 'ABC', |
| rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), |
| transform: Matrix4.translationValues(356.0, 276.0, 0.0), |
| flags: <SemanticsFlag>[ |
| SemanticsFlag.isButton, |
| SemanticsFlag.hasEnabledState, |
| SemanticsFlag.isEnabled, |
| ], |
| ), |
| ], |
| ), |
| ignoreId: true, |
| )); |
| |
| semantics.dispose(); |
| }); |
| |
| testWidgets('Does RaisedButton contribute semantics', (WidgetTester tester) async { |
| final SemanticsTester semantics = SemanticsTester(tester); |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: RaisedButton( |
| onPressed: () { }, |
| child: const Text('ABC'), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(semantics, hasSemantics( |
| TestSemantics.root( |
| children: <TestSemantics>[ |
| TestSemantics.rootChild( |
| actions: <SemanticsAction>[ |
| SemanticsAction.tap, |
| ], |
| label: 'ABC', |
| rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), |
| transform: Matrix4.translationValues(356.0, 276.0, 0.0), |
| flags: <SemanticsFlag>[ |
| SemanticsFlag.isButton, |
| SemanticsFlag.hasEnabledState, |
| SemanticsFlag.isEnabled, |
| ], |
| ), |
| ] |
| ), |
| ignoreId: true, |
| )); |
| |
| semantics.dispose(); |
| }); |
| |
| testWidgets('Does FlatButton scale with font scale changes', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: MediaQuery( |
| data: const MediaQueryData(textScaleFactor: 1.0), |
| child: Center( |
| child: FlatButton( |
| onPressed: () { }, |
| child: const Text('ABC'), |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byType(FlatButton)), equals(const Size(88.0, 48.0))); |
| expect(tester.getSize(find.byType(Text)), equals(const Size(42.0, 14.0))); |
| |
| // textScaleFactor expands text, but not button. |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: MediaQuery( |
| data: const MediaQueryData(textScaleFactor: 1.3), |
| child: Center( |
| child: FlatButton( |
| onPressed: () { }, |
| child: const Text('ABC'), |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byType(FlatButton)), equals(const Size(88.0, 48.0))); |
| // Scaled text rendering is different on Linux and Mac by one pixel. |
| // TODO(gspencergoog): Figure out why this is, and fix it. https://github.com/flutter/flutter/issues/12357 |
| expect(tester.getSize(find.byType(Text)).width, isIn(<double>[54.0, 55.0])); |
| expect(tester.getSize(find.byType(Text)).height, isIn(<double>[18.0, 19.0])); |
| |
| // Set text scale large enough to expand text and button. |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: MediaQuery( |
| data: const MediaQueryData(textScaleFactor: 3.0), |
| child: Center( |
| child: FlatButton( |
| onPressed: () { }, |
| child: const Text('ABC'), |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| // Scaled text rendering is different on Linux and Mac by one pixel. |
| // TODO(gspencergoog): Figure out why this is, and fix it. https://github.com/flutter/flutter/issues/12357 |
| expect(tester.getSize(find.byType(FlatButton)).width, isIn(<double>[158.0, 159.0])); |
| expect(tester.getSize(find.byType(FlatButton)).height, equals(48.0)); |
| expect(tester.getSize(find.byType(Text)).width, isIn(<double>[126.0, 127.0])); |
| expect(tester.getSize(find.byType(Text)).height, equals(42.0)); |
| }, skip: isBrowser); |
| |
| // This test is very similar to the '...explicit splashColor and highlightColor' test |
| // in icon_button_test.dart. If you change this one, you may want to also change that one. |
| testWidgets('MaterialButton with explicit splashColor and highlightColor', (WidgetTester tester) async { |
| const Color directSplashColor = Color(0xFF000011); |
| const Color directHighlightColor = Color(0xFF000011); |
| |
| Widget buttonWidget = Material( |
| child: Center( |
| child: MaterialButton( |
| splashColor: directSplashColor, |
| highlightColor: directHighlightColor, |
| onPressed: () { /* to make sure the button is enabled */ }, |
| clipBehavior: Clip.antiAlias, |
| ), |
| ), |
| ); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Theme( |
| data: ThemeData( |
| materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, |
| ), |
| child: buttonWidget, |
| ), |
| ), |
| ); |
| |
| final Offset center = tester.getCenter(find.byType(MaterialButton)); |
| final TestGesture gesture = await tester.startGesture(center); |
| await tester.pump(); // start gesture |
| await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way |
| |
| const Rect expectedClipRect = Rect.fromLTRB(356.0, 282.0, 444.0, 318.0); |
| final Path expectedClipPath = Path() |
| ..addRRect(RRect.fromRectAndRadius( |
| expectedClipRect, |
| const Radius.circular(2.0), |
| )); |
| expect( |
| Material.of(tester.element(find.byType(MaterialButton))), |
| paints |
| ..clipPath(pathMatcher: coversSameAreaAs( |
| expectedClipPath, |
| areaToCompare: expectedClipRect.inflate(10.0), |
| )) |
| ..circle(color: directSplashColor) |
| ..rect(color: directHighlightColor), |
| ); |
| |
| const Color themeSplashColor1 = Color(0xFF001100); |
| const Color themeHighlightColor1 = Color(0xFF001100); |
| |
| buttonWidget = Material( |
| child: Center( |
| child: MaterialButton( |
| onPressed: () { /* to make sure the button is enabled */ }, |
| clipBehavior: Clip.antiAlias, |
| ), |
| ), |
| ); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Theme( |
| data: ThemeData( |
| highlightColor: themeHighlightColor1, |
| splashColor: themeSplashColor1, |
| materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, |
| ), |
| child: buttonWidget, |
| ), |
| ), |
| ); |
| |
| expect( |
| Material.of(tester.element(find.byType(MaterialButton))), |
| paints |
| ..clipPath(pathMatcher: coversSameAreaAs( |
| expectedClipPath, |
| areaToCompare: expectedClipRect.inflate(10.0), |
| )) |
| ..circle(color: themeSplashColor1) |
| ..rect(color: themeHighlightColor1), |
| ); |
| |
| const Color themeSplashColor2 = Color(0xFF002200); |
| const Color themeHighlightColor2 = Color(0xFF002200); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Theme( |
| data: ThemeData( |
| highlightColor: themeHighlightColor2, |
| splashColor: themeSplashColor2, |
| materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, |
| ), |
| child: buttonWidget, // same widget, so does not get updated because of us |
| ), |
| ), |
| ); |
| |
| expect( |
| Material.of(tester.element(find.byType(MaterialButton))), |
| paints |
| ..circle(color: themeSplashColor2) |
| ..rect(color: themeHighlightColor2), |
| ); |
| |
| await gesture.up(); |
| }); |
| |
| testWidgets('MaterialButton has no clip by default', (WidgetTester tester) async { |
| final GlobalKey buttonKey = GlobalKey(); |
| final Widget buttonWidget = Material( |
| child: Center( |
| child: MaterialButton( |
| key: buttonKey, |
| onPressed: () { /* to make sure the button is enabled */ }, |
| ), |
| ), |
| ); |
| |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Theme( |
| data: ThemeData( |
| materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, |
| ), |
| child: buttonWidget, |
| ), |
| ), |
| ); |
| |
| expect( |
| tester.renderObject(find.byKey(buttonKey)), |
| paintsExactlyCountTimes(#clipPath, 0), |
| ); |
| }); |
| |
| testWidgets('Disabled MaterialButton has correct default text color', (WidgetTester tester) async { |
| const String testText = 'Disabled'; |
| const Widget buttonWidget = Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: MaterialButton( |
| onPressed: null, |
| child: Text(testText), // button is disabled |
| ), |
| ), |
| ), |
| ); |
| |
| await tester.pumpWidget(buttonWidget); |
| |
| final RichText text = tester.widget<RichText>(find.byType(RichText)); |
| expect(text.text.style.color, Colors.black38); |
| }); |
| |
| testWidgets('Disabled MaterialButton has same semantic size as enabled and exposes disabled semantics', (WidgetTester tester) async { |
| final SemanticsTester semantics = SemanticsTester(tester); |
| |
| const Rect expectedButtonSize = Rect.fromLTRB(0.0, 0.0, 116.0, 48.0); |
| // Button is in center of screen |
| final Matrix4 expectedButtonTransform = Matrix4.identity() |
| ..translate( |
| TestSemantics.fullScreen.width / 2 - expectedButtonSize.width /2, |
| TestSemantics.fullScreen.height / 2 - expectedButtonSize.height /2, |
| ); |
| |
| // enabled button |
| await tester.pumpWidget(Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: MaterialButton( |
| child: const Text('Button'), |
| onPressed: () { /* to make sure the button is enabled */ }, |
| ), |
| ), |
| ), |
| )); |
| |
| expect(semantics, hasSemantics( |
| TestSemantics.root( |
| children: <TestSemantics>[ |
| TestSemantics.rootChild( |
| id: 1, |
| rect: expectedButtonSize, |
| transform: expectedButtonTransform, |
| label: 'Button', |
| actions: <SemanticsAction>[ |
| SemanticsAction.tap, |
| ], |
| flags: <SemanticsFlag>[ |
| SemanticsFlag.isButton, |
| SemanticsFlag.hasEnabledState, |
| SemanticsFlag.isEnabled, |
| ], |
| ), |
| ], |
| ), |
| )); |
| |
| // disabled button |
| await tester.pumpWidget(const Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: MaterialButton( |
| child: Text('Button'), |
| onPressed: null, // button is disabled |
| ), |
| ), |
| ), |
| )); |
| |
| expect(semantics, hasSemantics( |
| TestSemantics.root( |
| children: <TestSemantics>[ |
| TestSemantics.rootChild( |
| id: 1, |
| rect: expectedButtonSize, |
| transform: expectedButtonTransform, |
| label: 'Button', |
| flags: <SemanticsFlag>[ |
| SemanticsFlag.isButton, |
| SemanticsFlag.hasEnabledState, |
| ], |
| ), |
| ], |
| ), |
| )); |
| |
| |
| semantics.dispose(); |
| }, skip: isBrowser); |
| |
| testWidgets('MaterialButton minWidth and height parameters', (WidgetTester tester) async { |
| Widget buildFrame({ double minWidth, double height, EdgeInsets padding = EdgeInsets.zero, Widget child }) { |
| return Directionality( |
| textDirection: TextDirection.ltr, |
| child: Center( |
| child: MaterialButton( |
| padding: padding, |
| minWidth: minWidth, |
| height: height, |
| onPressed: null, |
| materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, |
| child: child, |
| ), |
| ), |
| ); |
| } |
| |
| await tester.pumpWidget(buildFrame(minWidth: 8.0, height: 24.0)); |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(8.0, 24.0)); |
| |
| await tester.pumpWidget(buildFrame(minWidth: 8.0)); |
| // Default minHeight constraint is 36, see RawMaterialButton. |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(8.0, 36.0)); |
| |
| await tester.pumpWidget(buildFrame(height: 8.0)); |
| // Default minWidth constraint is 88, see RawMaterialButton. |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(88.0, 8.0)); |
| |
| await tester.pumpWidget(buildFrame()); |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(88.0, 36.0)); |
| |
| await tester.pumpWidget(buildFrame(padding: const EdgeInsets.all(4.0))); |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(88.0, 36.0)); |
| |
| // Size is defined by the padding. |
| await tester.pumpWidget( |
| buildFrame( |
| minWidth: 0.0, |
| height: 0.0, |
| padding: const EdgeInsets.all(4.0), |
| ), |
| ); |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(8.0, 8.0)); |
| |
| // Size is defined by the padded child. |
| await tester.pumpWidget( |
| buildFrame( |
| minWidth: 0.0, |
| height: 0.0, |
| padding: const EdgeInsets.all(4.0), |
| child: const SizedBox(width: 8.0, height: 8.0), |
| ), |
| ); |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(16.0, 16.0)); |
| |
| // Size is defined by the minWidth, height constraints. |
| await tester.pumpWidget( |
| buildFrame( |
| minWidth: 18.0, |
| height: 18.0, |
| padding: const EdgeInsets.all(4.0), |
| child: const SizedBox(width: 8.0, height: 8.0), |
| ), |
| ); |
| expect(tester.getSize(find.byType(MaterialButton)), const Size(18.0, 18.0)); |
| }); |
| |
| testWidgets('MaterialButton size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async { |
| final Key key1 = UniqueKey(); |
| await tester.pumpWidget( |
| Theme( |
| data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded), |
| child: Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: MaterialButton( |
| key: key1, |
| child: const SizedBox(width: 50.0, height: 8.0), |
| onPressed: () { }, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byKey(key1)), const Size(88.0, 48.0)); |
| |
| final Key key2 = UniqueKey(); |
| await tester.pumpWidget( |
| Theme( |
| data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap), |
| child: Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: MaterialButton( |
| key: key2, |
| child: const SizedBox(width: 50.0, height: 8.0), |
| onPressed: () { }, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byKey(key2)), const Size(88.0, 36.0)); |
| }); |
| |
| testWidgets('FlatButton size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async { |
| final Key key1 = UniqueKey(); |
| await tester.pumpWidget( |
| Theme( |
| data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded), |
| child: Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: FlatButton( |
| key: key1, |
| child: const SizedBox(width: 50.0, height: 8.0), |
| onPressed: () { }, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byKey(key1)), const Size(88.0, 48.0)); |
| |
| final Key key2 = UniqueKey(); |
| await tester.pumpWidget( |
| Theme( |
| data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap), |
| child: Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: FlatButton( |
| key: key2, |
| child: const SizedBox(width: 50.0, height: 8.0), |
| onPressed: () { }, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byKey(key2)), const Size(88.0, 36.0)); |
| }); |
| |
| testWidgets('RaisedButton size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async { |
| final Key key1 = UniqueKey(); |
| await tester.pumpWidget( |
| Theme( |
| data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded), |
| child: Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: RaisedButton( |
| key: key1, |
| child: const SizedBox(width: 50.0, height: 8.0), |
| onPressed: () { }, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byKey(key1)), const Size(88.0, 48.0)); |
| |
| final Key key2 = UniqueKey(); |
| await tester.pumpWidget( |
| Theme( |
| data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap), |
| child: Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: Center( |
| child: RaisedButton( |
| key: key2, |
| child: const SizedBox(width: 50.0, height: 8.0), |
| onPressed: () { }, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| |
| expect(tester.getSize(find.byKey(key2)), const Size(88.0, 36.0)); |
| }); |
| |
| testWidgets('RaisedButton has no clip by default', (WidgetTester tester) async { |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: Material( |
| child: RaisedButton( |
| onPressed: () { /* to make sure the button is enabled */ }, |
| ), |
| ), |
| ), |
| ); |
| |
| expect( |
| tester.renderObject(find.byType(RaisedButton)), |
| paintsExactlyCountTimes(#clipPath, 0), |
| ); |
| }); |
| |
| testWidgets('MaterialButton shape overrides ButtonTheme shape', (WidgetTester tester) async { |
| // Regression test for https://github.com/flutter/flutter/issues/29146 |
| await tester.pumpWidget( |
| Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| onPressed: () { }, |
| shape: const StadiumBorder(), |
| child: const Text('button'), |
| ), |
| ), |
| ); |
| |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(MaterialButton), |
| matching: find.byType(Material), |
| ); |
| expect(tester.widget<Material>(rawButtonMaterial).shape, const StadiumBorder()); |
| }); |
| |
| testWidgets('MaterialButton disabled default is correct.', (WidgetTester tester) async { |
| // Regression test for https://github.com/flutter/flutter/issues/30012. |
| |
| final Finder rawButtonMaterial = find.descendant( |
| of: find.byType(MaterialButton), |
| matching: find.byType(Material), |
| ); |
| |
| await tester.pumpWidget( |
| const Directionality( |
| textDirection: TextDirection.ltr, |
| child: MaterialButton( |
| disabledColor: Color(0xff00ff00), |
| onPressed: null, |
| child: Text('button'), |
| ), |
| ), |
| ); |
| |
| final Material material = tester.widget<Material>(rawButtonMaterial); |
| expect(material.color, const Color(0xff00ff00)); |
| }); |
| } |