Unverified Commit 73957b94 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Test Material buttons against a11y contrast guidelines (#32050)

parent 1349be95
...@@ -9,7 +9,7 @@ import 'package:flutter/rendering.dart'; ...@@ -9,7 +9,7 @@ import 'package:flutter/rendering.dart';
import '../rendering/mock_canvas.dart'; import '../rendering/mock_canvas.dart';
void main() { void main() {
testWidgets('FlatButton implements debugFillDescription', (WidgetTester tester) async { testWidgets('FlatButton implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
FlatButton( FlatButton(
onPressed: () { }, onPressed: () { },
...@@ -32,6 +32,33 @@ void main() { ...@@ -32,6 +32,33 @@ void main() {
]); ]);
}); });
testWidgets('Default FlatButton meets a11y contrast guidelines', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: FlatButton(
child: const Text('FlatButton'),
onPressed: () { },
),
),
),
),
);
// Default, not disabled.
await expectLater(tester, meetsGuideline(textContrastGuideline));
// Highlighted (pressed).
final Offset center = tester.getCenter(find.byType(FlatButton));
await tester.startGesture(center);
await tester.pump(); // Start the splash and highlight animations.
await tester.pump(const Duration(milliseconds: 800)); // Wait for splash and highlight to be well under way.
await expectLater(tester, meetsGuideline(textContrastGuideline));
},
semanticsEnabled: true,
);
testWidgets('FlatButton has no clip by default', (WidgetTester tester) async { testWidgets('FlatButton has no clip by default', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
......
// Copyright 2019 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/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
void main() {
testWidgets('Default MaterialButton meets a11y contrast guidelines', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: MaterialButton(
child: const Text('MaterialButton'),
onPressed: () { },
),
),
),
),
);
// Default, not disabled.
await expectLater(tester, meetsGuideline(textContrastGuideline));
// Highlighted (pressed).
final Offset center = tester.getCenter(find.byType(MaterialButton));
await tester.startGesture(center);
await tester.pump(); // Start the splash and highlight animations.
await tester.pump(const Duration(milliseconds: 800)); // Wait for splash and highlight to be well under way.
await expectLater(tester, meetsGuideline(textContrastGuideline));
},
semanticsEnabled: true,
);
}
...@@ -10,27 +10,58 @@ import '../rendering/mock_canvas.dart'; ...@@ -10,27 +10,58 @@ import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart'; import '../widgets/semantics_tester.dart';
void main() { void main() {
PhysicalModelLayer findPhysicalLayer(Element element) { testWidgets('OutlineButton implements debugFillProperties', (WidgetTester tester) async {
expect(element, isNotNull); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
RenderObject object = element.renderObject; OutlineButton(
while (object != null && object is! RenderRepaintBoundary && object is! RenderView) { onPressed: () { },
object = object.parent; textColor: const Color(0xFF00FF00),
} disabledTextColor: const Color(0xFFFF0000),
expect(object.debugLayer, isNotNull); color: const Color(0xFF000000),
expect(object.debugLayer.firstChild, isInstanceOf<PhysicalModelLayer>()); highlightColor: const Color(0xFF1565C0),
final PhysicalModelLayer layer = object.debugLayer.firstChild; splashColor: const Color(0xFF9E9E9E),
return layer.firstChild is PhysicalModelLayer ? layer.firstChild : layer; child: const Text('Hello'),
} ).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString()).toList();
expect(description, <String>[
'textColor: Color(0xff00ff00)',
'disabledTextColor: Color(0xffff0000)',
'color: Color(0xff000000)',
'highlightColor: Color(0xff1565c0)',
'splashColor: Color(0xff9e9e9e)',
]);
});
testWidgets('Default OutlineButton meets a11y contrast guidelines', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: OutlineButton(
child: const Text('OutlineButton'),
onPressed: () { },
),
),
),
),
);
// Default, not disabled.
await expectLater(tester, meetsGuideline(textContrastGuideline));
// Highlighted (pressed).
final Offset center = tester.getCenter(find.byType(OutlineButton));
await tester.startGesture(center);
await tester.pump(); // Start the splash and highlight animations.
await tester.pump(const Duration(milliseconds: 800)); // Wait for splash and highlight to be well under way.
await expectLater(tester, meetsGuideline(textContrastGuideline));
},
semanticsEnabled: true,
);
void checkPhysicalLayer(Element element, Color expectedColor, {Path clipPath, Rect clipRect}) {
final PhysicalModelLayer expectedLayer = findPhysicalLayer(element);
expect(expectedLayer.elevation, 0.0);
expect(expectedLayer.color, expectedColor);
if (clipPath != null) {
expect(clipRect, isNotNull);
expect(expectedLayer.clipPath, coversSameAreaAs(clipPath, areaToCompare: clipRect.inflate(10.0)));
}
}
testWidgets('Outline button responds to tap when enabled', (WidgetTester tester) async { testWidgets('Outline button responds to tap when enabled', (WidgetTester tester) async {
int pressedCount = 0; int pressedCount = 0;
...@@ -136,7 +167,7 @@ void main() { ...@@ -136,7 +167,7 @@ void main() {
outlineButton, outlineButton,
paints paints
..path(color: disabledBorderColor, strokeWidth: borderWidth)); ..path(color: disabledBorderColor, strokeWidth: borderWidth));
checkPhysicalLayer( _checkPhysicalLayer(
tester.element(outlineButton), tester.element(outlineButton),
const Color(0), const Color(0),
clipPath: clipPath, clipPath: clipPath,
...@@ -158,7 +189,7 @@ void main() { ...@@ -158,7 +189,7 @@ void main() {
paints paints
..path(color: borderColor, strokeWidth: borderWidth)); ..path(color: borderColor, strokeWidth: borderWidth));
// initially, the interior of the button is transparent // initially, the interior of the button is transparent
checkPhysicalLayer( _checkPhysicalLayer(
tester.element(outlineButton), tester.element(outlineButton),
fillColor.withAlpha(0x00), fillColor.withAlpha(0x00),
clipPath: clipPath, clipPath: clipPath,
...@@ -175,7 +206,7 @@ void main() { ...@@ -175,7 +206,7 @@ void main() {
outlineButton, outlineButton,
paints paints
..path(color: highlightedBorderColor, strokeWidth: borderWidth)); ..path(color: highlightedBorderColor, strokeWidth: borderWidth));
checkPhysicalLayer( _checkPhysicalLayer(
tester.element(outlineButton), tester.element(outlineButton),
fillColor.withAlpha(0xFF), fillColor.withAlpha(0xFF),
clipPath: clipPath, clipPath: clipPath,
...@@ -189,7 +220,7 @@ void main() { ...@@ -189,7 +220,7 @@ void main() {
outlineButton, outlineButton,
paints paints
..path(color: borderColor, strokeWidth: borderWidth)); ..path(color: borderColor, strokeWidth: borderWidth));
checkPhysicalLayer( _checkPhysicalLayer(
tester.element(outlineButton), tester.element(outlineButton),
fillColor.withAlpha(0x00), fillColor.withAlpha(0x00),
clipPath: clipPath, clipPath: clipPath,
...@@ -331,31 +362,6 @@ void main() { ...@@ -331,31 +362,6 @@ void main() {
expect(tester.getSize(find.byType(Text)).height, equals(42.0)); expect(tester.getSize(find.byType(Text)).height, equals(42.0));
}); });
testWidgets('OutlineButton implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
OutlineButton(
onPressed: () { },
textColor: const Color(0xFF00FF00),
disabledTextColor: const Color(0xFFFF0000),
color: const Color(0xFF000000),
highlightColor: const Color(0xFF1565C0),
splashColor: const Color(0xFF9E9E9E),
child: const Text('Hello'),
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString()).toList();
expect(description, <String>[
'textColor: Color(0xff00ff00)',
'disabledTextColor: Color(0xffff0000)',
'color: Color(0xff000000)',
'highlightColor: Color(0xff1565c0)',
'splashColor: Color(0xff9e9e9e)',
]);
});
testWidgets('OutlineButton pressed fillColor default', (WidgetTester tester) async { testWidgets('OutlineButton pressed fillColor default', (WidgetTester tester) async {
Widget buildFrame(ThemeData theme) { Widget buildFrame(ThemeData theme) {
return MaterialApp( return MaterialApp(
...@@ -385,18 +391,18 @@ void main() { ...@@ -385,18 +391,18 @@ void main() {
Color fillColor = Colors.grey[850]; Color fillColor = Colors.grey[850];
// Initially the interior of the button is transparent. // Initially the interior of the button is transparent.
checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00)); _checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00));
// Tap-press gesture on the button triggers the fill animation. // Tap-press gesture on the button triggers the fill animation.
TestGesture gesture = await tester.startGesture(center); TestGesture gesture = await tester.startGesture(center);
await tester.pump(); // Start the button fill animation. await tester.pump(); // Start the button fill animation.
await tester.pump(const Duration(milliseconds: 200)); // Animation is complete. await tester.pump(const Duration(milliseconds: 200)); // Animation is complete.
checkPhysicalLayer(buttonElement, fillColor.withAlpha(0xFF)); _checkPhysicalLayer(buttonElement, fillColor.withAlpha(0xFF));
// Tap gesture completes, button returns to its initial configuration. // Tap gesture completes, button returns to its initial configuration.
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00)); _checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00));
await tester.pumpWidget(buildFrame(ThemeData.light())); await tester.pumpWidget(buildFrame(ThemeData.light()));
await tester.pumpAndSettle(); // Finish the theme change animation. await tester.pumpAndSettle(); // Finish the theme change animation.
...@@ -412,11 +418,33 @@ void main() { ...@@ -412,11 +418,33 @@ void main() {
gesture = await tester.startGesture(center); gesture = await tester.startGesture(center);
await tester.pump(); // Start the button fill animation. await tester.pump(); // Start the button fill animation.
await tester.pump(const Duration(milliseconds: 200)); // Animation is complete. await tester.pump(const Duration(milliseconds: 200)); // Animation is complete.
checkPhysicalLayer(buttonElement, fillColor.withAlpha(0xFF)); _checkPhysicalLayer(buttonElement, fillColor.withAlpha(0xFF));
// Tap gesture completes, button returns to its initial configuration. // Tap gesture completes, button returns to its initial configuration.
await gesture.up(); await gesture.up();
await tester.pumpAndSettle(); await tester.pumpAndSettle();
checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00)); _checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00));
}); });
} }
PhysicalModelLayer _findPhysicalLayer(Element element) {
expect(element, isNotNull);
RenderObject object = element.renderObject;
while (object != null && object is! RenderRepaintBoundary && object is! RenderView) {
object = object.parent;
}
expect(object.debugLayer, isNotNull);
expect(object.debugLayer.firstChild, isInstanceOf<PhysicalModelLayer>());
final PhysicalModelLayer layer = object.debugLayer.firstChild;
return layer.firstChild is PhysicalModelLayer ? layer.firstChild : layer;
}
void _checkPhysicalLayer(Element element, Color expectedColor, { Path clipPath, Rect clipRect }) {
final PhysicalModelLayer expectedLayer = _findPhysicalLayer(element);
expect(expectedLayer.elevation, 0.0);
expect(expectedLayer.color, expectedColor);
if (clipPath != null) {
expect(clipRect, isNotNull);
expect(expectedLayer.clipPath, coversSameAreaAs(clipPath, areaToCompare: clipRect.inflate(10.0)));
}
}
// Copyright 2019 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/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
void main() {
testWidgets('RaisedButton implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
RaisedButton(
onPressed: () { },
textColor: const Color(0xFF00FF00),
disabledTextColor: const Color(0xFFFF0000),
color: const Color(0xFF000000),
highlightColor: const Color(0xFF1565C0),
splashColor: const Color(0xFF9E9E9E),
child: const Text('Hello'),
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString()).toList();
expect(description, <String>[
'textColor: Color(0xff00ff00)',
'disabledTextColor: Color(0xffff0000)',
'color: Color(0xff000000)',
'highlightColor: Color(0xff1565c0)',
'splashColor: Color(0xff9e9e9e)',
]);
});
testWidgets('Default RaisedButton meets a11y contrast guidelines', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: RaisedButton(
child: const Text('RaisedButton'),
onPressed: () { },
),
),
),
),
);
// Default, not disabled.
await expectLater(tester, meetsGuideline(textContrastGuideline));
// Highlighted (pressed).
final Offset center = tester.getCenter(find.byType(RaisedButton));
await tester.startGesture(center);
await tester.pump(); // Start the splash and highlight animations.
await tester.pump(const Duration(milliseconds: 800)); // Wait for splash and highlight to be well under way.
await expectLater(tester, meetsGuideline(textContrastGuideline));
},
semanticsEnabled: true,
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment