Test Material buttons against a11y contrast guidelines (#32050)
This commit is contained in:
parent
1349be95a3
commit
73957b94e7
@ -9,7 +9,7 @@ import 'package:flutter/rendering.dart';
|
||||
import '../rendering/mock_canvas.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('FlatButton implements debugFillDescription', (WidgetTester tester) async {
|
||||
testWidgets('FlatButton implements debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
FlatButton(
|
||||
onPressed: () { },
|
||||
@ -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 {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
37
packages/flutter/test/material/material_button_test.dart
Normal file
37
packages/flutter/test/material/material_button_test.dart
Normal file
@ -0,0 +1,37 @@
|
||||
// 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';
|
||||
import '../widgets/semantics_tester.dart';
|
||||
|
||||
void main() {
|
||||
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;
|
||||
}
|
||||
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('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 {
|
||||
int pressedCount = 0;
|
||||
|
||||
@ -136,7 +167,7 @@ void main() {
|
||||
outlineButton,
|
||||
paints
|
||||
..path(color: disabledBorderColor, strokeWidth: borderWidth));
|
||||
checkPhysicalLayer(
|
||||
_checkPhysicalLayer(
|
||||
tester.element(outlineButton),
|
||||
const Color(0),
|
||||
clipPath: clipPath,
|
||||
@ -158,7 +189,7 @@ void main() {
|
||||
paints
|
||||
..path(color: borderColor, strokeWidth: borderWidth));
|
||||
// initially, the interior of the button is transparent
|
||||
checkPhysicalLayer(
|
||||
_checkPhysicalLayer(
|
||||
tester.element(outlineButton),
|
||||
fillColor.withAlpha(0x00),
|
||||
clipPath: clipPath,
|
||||
@ -175,7 +206,7 @@ void main() {
|
||||
outlineButton,
|
||||
paints
|
||||
..path(color: highlightedBorderColor, strokeWidth: borderWidth));
|
||||
checkPhysicalLayer(
|
||||
_checkPhysicalLayer(
|
||||
tester.element(outlineButton),
|
||||
fillColor.withAlpha(0xFF),
|
||||
clipPath: clipPath,
|
||||
@ -189,7 +220,7 @@ void main() {
|
||||
outlineButton,
|
||||
paints
|
||||
..path(color: borderColor, strokeWidth: borderWidth));
|
||||
checkPhysicalLayer(
|
||||
_checkPhysicalLayer(
|
||||
tester.element(outlineButton),
|
||||
fillColor.withAlpha(0x00),
|
||||
clipPath: clipPath,
|
||||
@ -331,31 +362,6 @@ void main() {
|
||||
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 {
|
||||
Widget buildFrame(ThemeData theme) {
|
||||
return MaterialApp(
|
||||
@ -385,18 +391,18 @@ void main() {
|
||||
Color fillColor = Colors.grey[850];
|
||||
|
||||
// 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.
|
||||
TestGesture gesture = await tester.startGesture(center);
|
||||
await tester.pump(); // Start the button fill animation.
|
||||
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.
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00));
|
||||
_checkPhysicalLayer(buttonElement, fillColor.withAlpha(0x00));
|
||||
|
||||
await tester.pumpWidget(buildFrame(ThemeData.light()));
|
||||
await tester.pumpAndSettle(); // Finish the theme change animation.
|
||||
@ -412,11 +418,33 @@ void main() {
|
||||
gesture = await tester.startGesture(center);
|
||||
await tester.pump(); // Start the button fill animation.
|
||||
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.
|
||||
await gesture.up();
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
63
packages/flutter/test/material/raised_button_test.dart
Normal file
63
packages/flutter/test/material/raised_button_test.dart
Normal file
@ -0,0 +1,63 @@
|
||||
// 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,
|
||||
);
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user