Unverified Commit 34b454f4 authored by Bruno Leroux's avatar Bruno Leroux Committed by GitHub

InputDecorator M3 tests migration - Step5 - Helper/Counter/Error (#144932)

## Description

This PR migrates `InputDecorator` helper/counter/error related tests to M3 and adds some missing tests.

It is the fifth step for the M3 test migration for `InputDecorator`.
Step 1: https://github.com/flutter/flutter/pull/142981
Step 2: https://github.com/flutter/flutter/pull/143369
Step 3: https://github.com/flutter/flutter/pull/143520
Step 4: https://github.com/flutter/flutter/pull/144169

## Related Issue

Related to https://github.com/flutter/flutter/issues/139076
fixes https://github.com/flutter/flutter/issues/138213
parent c83237f3
......@@ -18,6 +18,9 @@ import 'package:flutter_test/flutter_test.dart';
const String hintText = 'hint';
const String inputText = 'text';
const String labelText = 'label';
const String errorText = 'error';
const String helperText = 'helper';
const String counterText = 'counter';
const Key customLabelKey = Key('label');
const Widget customLabel = Text.rich(
......@@ -32,6 +35,9 @@ const Widget customLabel = Text.rich(
),
);
const String twoLines = 'line1\nline2';
const String threeLines = 'line1\nline2\nline3';
Widget buildInputDecorator({
InputDecoration decoration = const InputDecoration(),
ThemeData? theme,
......@@ -165,6 +171,48 @@ double getHintOpacity(WidgetTester tester) {
return getOpacity(tester, hintText);
}
Finder findHelper() {
return find.text(helperText);
}
Rect getHelperRect(WidgetTester tester) {
return tester.getRect(findHelper());
}
TextStyle getHelperStyle(WidgetTester tester) {
return tester.widget<RichText>(
find.descendant(of: findHelper(), matching: find.byType(RichText)),
).text.style!;
}
Finder findError() {
return find.text(errorText);
}
Rect getErrorRect(WidgetTester tester) {
return tester.getRect(findError());
}
TextStyle getErrorStyle(WidgetTester tester) {
return tester.widget<RichText>(
find.descendant(of: findError(), matching: find.byType(RichText)),
).text.style!;
}
Finder findCounter() {
return find.text(counterText);
}
Rect getCounterRect(WidgetTester tester) {
return tester.getRect(findCounter());
}
TextStyle getCounterStyle(WidgetTester tester) {
return tester.widget<RichText>(
find.descendant(of: findCounter(), matching: find.byType(RichText)),
).text.style!;
}
Finder findDecorator() {
return find.byType(InputDecorator);
}
......@@ -237,7 +285,7 @@ void main() {
// See https://github.com/flutter/flutter/issues/139076
// Work in progress.
group('Material3 - InputDecoration.labelText layout', () {
group('Material3 - InputDecoration labelText layout', () {
testWidgets('The label appears above input', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
......@@ -369,7 +417,7 @@ void main() {
});
});
group('Material3 - InputDecoration.label layout', () {
group('Material3 - InputDecoration label layout', () {
testWidgets('The label appears above input', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
......@@ -605,9 +653,191 @@ void main() {
final ThemeData theme = Theme.of(tester.element(find.byType(InputDecorator)));
expect(getBorderColor(tester), theme.colorScheme.onSurface.withOpacity(0.38));
});
testWidgets('InputDecorator with no input border', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isEmpty: true,
decoration: const InputDecoration(
border: InputBorder.none,
),
),
);
expect(getBorderWeight(tester), 0.0);
});
testWidgets('OutlineInputBorder radius carries over when lerping', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/23982
const Key key = Key('textField');
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: TextField(
key: key,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2.0),
borderRadius: BorderRadius.zero,
),
),
),
),
),
),
);
// TextField has the given border
expect(getBorderRadius(tester), BorderRadius.zero);
// Focusing does not change the border
await tester.tap(find.byKey(key));
await tester.pump();
expect(getBorderRadius(tester), BorderRadius.zero);
await tester.pump(const Duration(milliseconds: 100));
expect(getBorderRadius(tester), BorderRadius.zero);
await tester.pumpAndSettle();
expect(getBorderRadius(tester), BorderRadius.zero);
});
testWidgets('OutlineInputBorder async lerp', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/28724
final Completer<void> completer = Completer<void>();
bool waitIsOver = false;
await tester.pumpWidget(
MaterialApp(
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return GestureDetector(
onTap: () async {
setState(() { waitIsOver = true; });
await completer.future;
setState(() { waitIsOver = false; });
},
child: InputDecorator(
decoration: InputDecoration(
labelText: 'Test',
enabledBorder: !waitIsOver ? null : const OutlineInputBorder(borderSide: BorderSide(color: Colors.blue)),
),
),
);
},
),
),
);
await tester.tap(find.byType(StatefulBuilder));
await tester.pumpAndSettle();
completer.complete();
await tester.pumpAndSettle();
});
test('InputBorder equality', () {
// OutlineInputBorder's equality is defined by the borderRadius, borderSide, & gapPadding.
const OutlineInputBorder outlineInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
);
expect(outlineInputBorder, const OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.all(Radius.circular(9.0)),
gapPadding: 32.0,
));
expect(outlineInputBorder, isNot(const OutlineInputBorder()));
expect(outlineInputBorder, isNot(const OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(9.0)),
gapPadding: 32.0,
)));
expect(outlineInputBorder, isNot(const OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
gapPadding: 32.0,
)));
expect(outlineInputBorder, isNot(const OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.all(Radius.circular(9.0)),
gapPadding: 33.0,
)));
// UnderlineInputBorder's equality is defined by the borderSide and borderRadius.
const UnderlineInputBorder underlineInputBorder = UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
);
expect(underlineInputBorder, const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
));
expect(underlineInputBorder, isNot(const UnderlineInputBorder()));
expect(underlineInputBorder, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
)));
expect(underlineInputBorder, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.0), topRight: Radius.circular(6.0)),
)));
});
test('InputBorder hashCodes', () {
// OutlineInputBorder's hashCode is defined by the borderRadius, borderSide, & gapPadding.
const OutlineInputBorder outlineInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
);
expect(outlineInputBorder.hashCode, const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
).hashCode);
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder().hashCode));
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.red),
gapPadding: 32.0,
).hashCode));
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
).hashCode));
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 33.0,
).hashCode));
// UnderlineInputBorder's hashCode is defined by the borderSide and borderRadius.
const UnderlineInputBorder underlineInputBorder = UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
);
expect(underlineInputBorder.hashCode, const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
).hashCode);
expect(underlineInputBorder.hashCode, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
).hashCode));
expect(underlineInputBorder.hashCode, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.0), topRight: Radius.circular(6.0)),
).hashCode));
});
});
group('Material3 - InputDecoration.hintText', () {
group('Material3 - InputDecoration hintText', () {
group('without label', () {
// Overall height for this InputDecorator is 48dp on mobile:
// 12 - Top padding
......@@ -1175,98 +1405,769 @@ void main() {
);
}
// `alignLabelWithHint: false` centers the label vertically in the TextField.
await tester.pumpWidget(buildFrame(false));
await tester.pumpAndSettle();
expect(getLabelCenter(tester).dy, getDecoratorCenter(tester).dy);
// `alignLabelWithHint: false` centers the label vertically in the TextField.
await tester.pumpWidget(buildFrame(false));
await tester.pumpAndSettle();
expect(getLabelCenter(tester).dy, getDecoratorCenter(tester).dy);
// Entering text happens in the center as well.
await tester.enterText(find.byType(InputDecorator), inputText);
expect(getInputCenter(tester).dy, getDecoratorCenter(tester).dy);
controller.clear();
focusNode.unfocus();
// `alignLabelWithHint: true` aligns keeps the label in the center because
// that's where the hint is.
await tester.pumpWidget(buildFrame(true));
await tester.pumpAndSettle();
// On M3, hint centering is slightly wrong.
// TODO(bleroux): remove closeTo usage when this is fixed.
expect(getHintCenter(tester).dy, closeTo(getDecoratorCenter(tester).dy, 2.0));
expect(getLabelCenter(tester).dy, getHintCenter(tester).dy);
// Entering text still happens in the center.
await tester.enterText(find.byType(InputDecorator), inputText);
expect(getInputCenter(tester).dy, getDecoratorCenter(tester).dy);
controller.clear();
focusNode.unfocus();
});
});
group('Horizontal alignment', () {
testWidgets('Label for outlined decoration aligns horizontally with prefixIcon by default', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/113537.
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.ac_unit),
labelText: labelText,
border: OutlineInputBorder(),
),
isFocused: true,
),
);
// 12 is the left padding.
// TODO(bleroux): consider changing this padding because from M3 soec this should be 16.
expect(getLabelRect(tester).left, 12.0);
// TODO(bleroux): consider changing the input text position because, based on M3 spec,
// the expected horizontal position is 52 (12 padding, 24 icon, 16 gap between icon and input).
// See https://m3.material.io/components/text-fields/specs#1ad2798c-ab41-4f0c-9a97-295ab9b37f33
// (Note that the diagrams on the spec for outlined text field are wrong but the table for
// outlined text fields and the diagrams for filled text field point to these values).
// The 48.0 value come from icon min interactive width and height.
expect(getInputRect(tester).left, 48.0);
});
testWidgets('Label for outlined decoration aligns horizontally with input when alignLabelWithHint is true', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/113537.
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.ac_unit),
labelText: labelText,
border: OutlineInputBorder(),
alignLabelWithHint: true,
),
isFocused: true,
),
);
expect(getLabelRect(tester).left, getInputRect(tester).left);
});
testWidgets('Label for filled decoration is horizontally aligned with text by default', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/113537.
// See https://github.com/flutter/flutter/pull/115540.
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.ac_unit),
labelText: labelText,
filled: true,
),
isFocused: true,
),
);
// Label and input are horizontally aligned despite `alignLabelWithHint` being false (default value).
// The reason is that `alignLabelWithHint` was initially intended for vertical alignement only.
// See https://github.com/flutter/flutter/pull/24993 which introduced `alignLabelWithHint` parameter.
// See https://github.com/flutter/flutter/pull/115409 which used `alignLabelWithHint` for
// horizontal alignment in outlined text field.
expect(getLabelRect(tester).left, getInputRect(tester).left);
});
});
});
});
});
group('Material3 - InputDecoration helper/counter/error', () {
// Overall height for InputDecorator (filled or outlined) is 80dp on mobile:
// 8 - top padding
// 12 - floating label (font size = 16 * 0.75, line height is forced to 1.0)
// 4 - gap between label and input
// 24 - input text (font size = 16, line height = 1.5)
// 8 - bottom padding
// 8 - gap above supporting text
// 16 - helper/counter (font size = 12, line height is 1.5)
const double topPadding = 8.0;
const double floatingLabelHeight = 12.0;
const double labelInputGap = 4.0;
const double inputHeight = 24.0;
const double bottomPadding = 8.0;
// TODO(bleroux): make the InputDecorator implementation compliant with M3 spec by changing
// the helperGap to 4.0 instead of 8.0.
// See https://github.com/flutter/flutter/issues/144984.
const double helperGap = 8.0;
const double helperHeight = 16.0;
const double containerHeight = topPadding + floatingLabelHeight + labelInputGap + inputHeight + bottomPadding; // 56.0
const double fullHeight = containerHeight + helperGap + helperHeight; // 80.0 (should be 76.0 based on M3 spec)
const double errorHeight = helperHeight;
// TODO(bleroux): consider changing this padding because, from the M3 specification, it should be 16.
const double helperStartPadding = 12.0;
const double counterEndPadding = 12.0;
// Actual size varies a little on web platforms with HTML renderer.
// TODO(bleroux): remove closeTo usage when https://github.com/flutter/flutter/issues/99933 is fixed.
final Matcher closeToFullHeight = closeTo(fullHeight, 0.1);
final Matcher closeToHelperHeight = closeTo(helperHeight, 0.1);
final Matcher closeToErrorHeight = closeTo(errorHeight, 0.1);
group('for filled text field', () {
group('when field is enabled', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is disabled', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
enabled: false,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
filled: true,
enabled: false,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurface.withOpacity(0.38);
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is hovered', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isHovering: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isHovering: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is focused', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is in error', () {
testWidgets('Error and counter are visible, helper is not visible', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
errorText: errorText,
),
),
);
expect(findError(), findsOneWidget);
expect(findCounter(), findsOneWidget);
expect(findHelper(), findsNothing);
});
testWidgets('Error and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
errorText: errorText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getErrorRect(tester).top, containerHeight + helperGap);
expect(getErrorRect(tester).height, closeToErrorHeight);
expect(getErrorRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToErrorHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Error and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
filled: true,
labelText: labelText,
helperText: helperText,
counterText: counterText,
errorText: errorText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.error;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getErrorStyle(tester), expectedStyle);
final Color expectedCounterColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedCounterStyle = theme.textTheme.bodySmall!.copyWith(color: expectedCounterColor);
expect(getCounterStyle(tester), expectedCounterStyle);
});
});
});
group('for outlined text field', () {
group('when field is enabled', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is disabled', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
border: OutlineInputBorder(),
enabled: false,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
border: OutlineInputBorder(),
enabled: false,
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurface.withOpacity(0.38);
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is hovered', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isHovering: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isHovering: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is focused', () {
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getHelperRect(tester).top, containerHeight + helperGap);
expect(getHelperRect(tester).height, closeToHelperHeight);
expect(getHelperRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToHelperHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Helper and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getHelperStyle(tester), expectedStyle);
expect(getCounterStyle(tester), expectedStyle);
});
});
group('when field is in error', () {
testWidgets('Error and counter are visible, helper is not visible', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
errorText: errorText,
),
),
);
expect(findHelper(), findsNothing);
expect(findError(), findsOneWidget);
expect(findCounter(), findsOneWidget);
});
testWidgets('Error and counter are correctly positioned', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
errorText: errorText,
),
),
);
expect(getDecoratorRect(tester).height, closeToFullHeight);
expect(getBorderBottom(tester), containerHeight);
expect(getErrorRect(tester).top, containerHeight + helperGap);
expect(getErrorRect(tester).height, closeToErrorHeight);
expect(getErrorRect(tester).left, helperStartPadding);
expect(getCounterRect(tester).top, containerHeight + helperGap);
expect(getCounterRect(tester).height, closeToErrorHeight);
expect(getCounterRect(tester).right, 800 - counterEndPadding);
});
testWidgets('Error and counter are correctly styled', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
isFocused: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: labelText,
helperText: helperText,
counterText: counterText,
errorText: errorText,
),
),
);
final ThemeData theme = Theme.of(tester.element(findDecorator()));
final Color expectedColor = theme.colorScheme.error;
final TextStyle expectedStyle = theme.textTheme.bodySmall!.copyWith(color: expectedColor);
expect(getErrorStyle(tester), expectedStyle);
final Color expectedCounterColor = theme.colorScheme.onSurfaceVariant;
final TextStyle expectedCounterStyle = theme.textTheme.bodySmall!.copyWith(color: expectedCounterColor);
expect(getCounterStyle(tester), expectedCounterStyle);
});
});
});
group('Multiline error/helper', () {
testWidgets('Error height grows to accommodate error text', (WidgetTester tester) async {
const int maxLines = 3;
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
errorText: threeLines,
errorMaxLines: maxLines,
filled: true,
),
),
);
final Rect errorRect = tester.getRect(find.text(threeLines));
expect(errorRect.height, closeTo(errorHeight * maxLines, 0.25));
expect(getDecoratorRect(tester).height, closeTo(containerHeight + helperGap + errorHeight * maxLines, 0.25));
});
testWidgets('Error height is correct when errorMaxLines is restricted', (WidgetTester tester) async {
const int maxLines = 2;
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
errorText: threeLines,
errorMaxLines: maxLines,
filled: true,
),
),
);
final Rect errorRect = tester.getRect(find.text(threeLines));
expect(errorRect.height, closeTo(errorHeight * maxLines, 0.25));
expect(getDecoratorRect(tester).height, closeTo(containerHeight + helperGap + errorHeight * maxLines, 0.25));
});
testWidgets('Error height is correct when errorMaxLines is bigger than the number of lines in errorText', (WidgetTester tester) async {
const int numberOfLines = 2;
const int maxLines = 3;
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
errorText: twoLines,
errorMaxLines: maxLines,
filled: true,
),
),
);
final Rect errorRect = tester.getRect(find.text(twoLines));
expect(errorRect.height, closeTo(errorHeight * numberOfLines, 0.25));
expect(getDecoratorRect(tester).height, closeTo(containerHeight + helperGap + errorHeight * numberOfLines, 0.25));
});
// Entering text happens in the center as well.
await tester.enterText(find.byType(InputDecorator), inputText);
expect(getInputCenter(tester).dy, getDecoratorCenter(tester).dy);
controller.clear();
focusNode.unfocus();
testWidgets('Helper height grows to accommodate helper text', (WidgetTester tester) async {
const int maxLines = 3;
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
helperText: threeLines,
helperMaxLines: maxLines,
filled: true,
),
),
);
// `alignLabelWithHint: true` aligns keeps the label in the center because
// that's where the hint is.
await tester.pumpWidget(buildFrame(true));
await tester.pumpAndSettle();
final Rect helperRect = tester.getRect(find.text(threeLines));
expect(helperRect.height, closeTo(helperHeight * maxLines, 0.25));
expect(getDecoratorRect(tester).height, closeTo(containerHeight + helperGap + helperHeight * maxLines, 0.25));
});
// On M3, hint centering is slightly wrong.
// TODO(bleroux): remove closeTo usage when this is fixed.
expect(getHintCenter(tester).dy, closeTo(getDecoratorCenter(tester).dy, 2.0));
expect(getLabelCenter(tester).dy, getHintCenter(tester).dy);
testWidgets('Helper height is correct when maxLines is restricted', (WidgetTester tester) async {
const int maxLines = 2;
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
helperText: threeLines,
helperMaxLines: maxLines,
filled: true,
),
),
);
// Entering text still happens in the center.
await tester.enterText(find.byType(InputDecorator), inputText);
expect(getInputCenter(tester).dy, getDecoratorCenter(tester).dy);
controller.clear();
focusNode.unfocus();
});
});
final Rect helperRect = tester.getRect(find.text(threeLines));
expect(helperRect.height, closeTo(helperHeight * maxLines, 0.25));
expect(getDecoratorRect(tester).height, closeTo(containerHeight + helperGap + helperHeight * maxLines, 0.25));
});
group('Horizontal alignment', () {
testWidgets('Label for outlined decoration aligns horizontally with prefixIcon by default', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/113537.
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.ac_unit),
labelText: labelText,
border: OutlineInputBorder(),
),
isFocused: true,
),
);
testWidgets('Helper height is correct when helperMaxLines is bigger than the number of lines in helperText', (WidgetTester tester) async {
const int numberOfLines = 2;
const int maxLines = 3;
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
helperText: twoLines,
helperMaxLines: maxLines,
filled: true,
),
),
);
// 12.0 is the left padding from M3 spec for outlined text field with icon.
expect(getLabelRect(tester).left, 12.0);
// TODO(bleroux): consider changing the input text position because, based on M3 spec,
// the expected horizontal position is 52 (12 padding, 24 icon, 16 gap between icon and input).
// See https://m3.material.io/components/text-fields/specs#1ad2798c-ab41-4f0c-9a97-295ab9b37f33
// (Note that the diagrams on the spec for outlined text field are wrong but the table for
// outlined text fields and the diagrams for filled text field point to these values).
expect(getInputRect(tester).left, 48.0);
});
final Rect helperRect = tester.getRect(find.text(twoLines));
expect(helperRect.height, closeTo(helperHeight * numberOfLines, 0.25));
expect(getDecoratorRect(tester).height, closeTo(containerHeight + helperGap + helperHeight * numberOfLines, 0.25));
});
});
testWidgets('Label for outlined decoration aligns horizontally with input when alignLabelWithHint is true', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/113537.
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.ac_unit),
labelText: labelText,
border: OutlineInputBorder(),
alignLabelWithHint: true,
),
isFocused: true,
),
);
group('Error widget', () {
testWidgets('InputDecorator shows error widget', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
error: Text('error', style: TextStyle(fontSize: 20.0)),
),
),
);
expect(getLabelRect(tester).left, getInputRect(tester).left);
});
expect(find.text('error'), findsOneWidget);
});
testWidgets('Label for filled decoration is horizontally aligned with text by default', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/113537.
// See https://github.com/flutter/flutter/pull/115540.
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.ac_unit),
labelText: labelText,
filled: true,
),
isFocused: true,
testWidgets('InputDecorator throws when error text and error widget are provided', (WidgetTester tester) async {
expect(
() {
buildInputDecorator(
decoration: InputDecoration(
errorText: 'errorText',
error: const Text('error', style: TextStyle(fontSize: 20.0)),
),
);
// Label and input are horizontally aligned despite `alignLabelWithHint` being false (default value).
// The reason is that `alignLabelWithHint` was initially intended for vertical alignement only.
// See https://github.com/flutter/flutter/pull/24993 which introduced `alignLabelWithHint` parameter.
// See https://github.com/flutter/flutter/pull/115409 which used `alignLabelWithHint` for
// horizontal alignment in outlined text field.
expect(getLabelRect(tester).left, getInputRect(tester).left);
});
});
},
throwsAssertionError,
);
});
});
});
......@@ -1309,6 +2210,26 @@ void main() {
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
}, variant: TargetPlatformVariant.desktop());
testWidgets('Material3 - Default height is 56dp on mobile', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
decoration: const InputDecoration(
labelText: 'label',
),
),
);
// Overall height for this InputDecorator is 56dp on mobile:
// 8 - top padding
// 12 - floating label (font size = 16 * 0.75, line height is forced to 1.0)
// 4 - gap between label and input
// 24 - input text (font size = 16, line height = 1.5)
// 8 - bottom padding
// TODO(bleroux): fix input decorator to not rely on a 4 pixels gap between the label and the input,
// this gap is not compliant with the M3 spec (M3 spec uses line height for this purpose).
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
}, variant: TargetPlatformVariant.mobile());
// This is a regression test for https://github.com/flutter/flutter/issues/139916.
testWidgets('Prefix ignores pointer when hidden', (WidgetTester tester) async {
bool tapped = false;
......@@ -1987,141 +2908,6 @@ void main() {
expect(debugString, contains('focusedBorder: OutlineInputBorder()'));
});
testWidgets('OutlineInputBorder radius carries over when lerping', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/23982
const Key key = Key('textField');
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: TextField(
key: key,
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2.0),
borderRadius: BorderRadius.zero,
),
),
),
),
),
),
);
// TextField has the given border
expect(getBorderRadius(tester), BorderRadius.zero);
// Focusing does not change the border
await tester.tap(find.byKey(key));
await tester.pump();
expect(getBorderRadius(tester), BorderRadius.zero);
await tester.pump(const Duration(milliseconds: 100));
expect(getBorderRadius(tester), BorderRadius.zero);
await tester.pumpAndSettle();
expect(getBorderRadius(tester), BorderRadius.zero);
});
test('InputBorder equality', () {
// OutlineInputBorder's equality is defined by the borderRadius, borderSide, & gapPadding.
const OutlineInputBorder outlineInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
);
expect(outlineInputBorder, const OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.all(Radius.circular(9.0)),
gapPadding: 32.0,
));
expect(outlineInputBorder, isNot(const OutlineInputBorder()));
expect(outlineInputBorder, isNot(const OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(9.0)),
gapPadding: 32.0,
)));
expect(outlineInputBorder, isNot(const OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
gapPadding: 32.0,
)));
expect(outlineInputBorder, isNot(const OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.all(Radius.circular(9.0)),
gapPadding: 33.0,
)));
// UnderlineInputBorder's equality is defined by the borderSide and borderRadius.
const UnderlineInputBorder underlineInputBorder = UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
);
expect(underlineInputBorder, const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
));
expect(underlineInputBorder, isNot(const UnderlineInputBorder()));
expect(underlineInputBorder, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
)));
expect(underlineInputBorder, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.0), topRight: Radius.circular(6.0)),
)));
});
test('InputBorder hashCodes', () {
// OutlineInputBorder's hashCode is defined by the borderRadius, borderSide, & gapPadding.
const OutlineInputBorder outlineInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
);
expect(outlineInputBorder.hashCode, const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
).hashCode);
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder().hashCode));
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.red),
gapPadding: 32.0,
).hashCode));
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 32.0,
).hashCode));
expect(outlineInputBorder.hashCode, isNot(const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
borderSide: BorderSide(color: Colors.blue),
gapPadding: 33.0,
).hashCode));
// UnderlineInputBorder's hashCode is defined by the borderSide and borderRadius.
const UnderlineInputBorder underlineInputBorder = UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
);
expect(underlineInputBorder.hashCode, const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
).hashCode);
expect(underlineInputBorder.hashCode, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
).hashCode));
expect(underlineInputBorder.hashCode, isNot(const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.0), topRight: Radius.circular(6.0)),
).hashCode));
});
testWidgets('InputDecorationTheme implements debugFillDescription', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const InputDecorationTheme(
......@@ -2173,41 +2959,6 @@ void main() {
]);
});
testWidgets('OutlineInputBorder async lerp', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/28724
final Completer<void> completer = Completer<void>();
bool waitIsOver = false;
await tester.pumpWidget(
MaterialApp(
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return GestureDetector(
onTap: () async {
setState(() { waitIsOver = true; });
await completer.future;
setState(() { waitIsOver = false; });
},
child: InputDecorator(
decoration: InputDecoration(
labelText: 'Test',
enabledBorder: !waitIsOver ? null : const OutlineInputBorder(borderSide: BorderSide(color: Colors.blue)),
),
),
);
},
),
),
);
await tester.tap(find.byType(StatefulBuilder));
await tester.pumpAndSettle();
completer.complete();
await tester.pumpAndSettle();
});
testWidgets("InputDecorator label width isn't affected by prefix or suffix", (WidgetTester tester) async {
const String labelText = 'My Label';
const String prefixText = 'The five boxing wizards jump quickly.';
......@@ -2749,6 +3500,130 @@ void main() {
expect(copy2.fillColor, isNot(const Color(0xDEADCAFE)));
});
test('InputDecorationTheme copyWith, ==, hashCode basics', () {
expect(const InputDecorationTheme(), const InputDecorationTheme().copyWith());
expect(const InputDecorationTheme().hashCode, const InputDecorationTheme().copyWith().hashCode);
});
test('InputDecorationTheme copyWith correctly copies and replaces values', () {
const InputDecorationTheme original = InputDecorationTheme(
focusColor: Colors.orange,
fillColor: Colors.green,
);
final InputDecorationTheme copy = original.copyWith(
focusColor: Colors.yellow,
fillColor: Colors.blue,
);
expect(original.focusColor, Colors.orange);
expect(original.fillColor, Colors.green);
expect(copy.focusColor, Colors.yellow);
expect(copy.fillColor, Colors.blue);
});
test('InputDecorationTheme merge', () {
const InputDecorationTheme overrideTheme = InputDecorationTheme(
labelStyle: TextStyle(color: Color(0x000000f0)),
floatingLabelStyle: TextStyle(color: Color(0x000000f1)),
helperStyle: TextStyle(color: Color(0x000000f2)),
helperMaxLines: 1,
hintStyle: TextStyle(color: Color(0x000000f3)),
errorStyle: TextStyle(color: Color(0x000000f4)),
errorMaxLines: 1,
floatingLabelBehavior: FloatingLabelBehavior.never,
floatingLabelAlignment: FloatingLabelAlignment.center,
isDense: true,
contentPadding: EdgeInsets.all(1.0),
isCollapsed: true,
iconColor: Color(0x000000f5),
prefixStyle: TextStyle(color: Color(0x000000f6)),
prefixIconColor: Color(0x000000f7),
suffixStyle: TextStyle(color: Color(0x000000f8)),
suffixIconColor: Color(0x000000f9),
counterStyle: TextStyle(color: Color(0x00000f10)),
filled: true,
fillColor: Color(0x00000f11),
activeIndicatorBorder: BorderSide(
color: Color(0x00000f12),
),
outlineBorder: BorderSide(
color: Color(0x00000f13),
),
focusColor: Color(0x00000f14),
hoverColor: Color(0x00000f15),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(2.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f16),
),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f17),
),
),
disabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f18),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f19),
),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f20),
),
),
alignLabelWithHint: true,
constraints: BoxConstraints(
minHeight: 1.0,
minWidth: 1.0,
),
);
final InputDecorationTheme inputDecorationTheme = ThemeData().inputDecorationTheme;
final InputDecorationTheme merged = inputDecorationTheme.merge(overrideTheme);
expect(merged.labelStyle, overrideTheme.labelStyle);
expect(merged.floatingLabelStyle, overrideTheme.floatingLabelStyle);
expect(merged.helperStyle, overrideTheme.helperStyle);
expect(merged.helperMaxLines, overrideTheme.helperMaxLines);
expect(merged.hintStyle, overrideTheme.hintStyle);
expect(merged.errorStyle, overrideTheme.errorStyle);
expect(merged.errorMaxLines, overrideTheme.errorMaxLines);
expect(merged.floatingLabelBehavior, isNot(overrideTheme.floatingLabelBehavior));
expect(merged.floatingLabelAlignment, isNot(overrideTheme.floatingLabelAlignment));
expect(merged.isDense, isNot(overrideTheme.isDense));
expect(merged.contentPadding, overrideTheme.contentPadding);
expect(merged.isCollapsed, isNot(overrideTheme.isCollapsed));
expect(merged.iconColor, overrideTheme.iconColor);
expect(merged.prefixStyle, overrideTheme.prefixStyle);
expect(merged.prefixIconColor, overrideTheme.prefixIconColor);
expect(merged.suffixStyle, overrideTheme.suffixStyle);
expect(merged.suffixIconColor, overrideTheme.suffixIconColor);
expect(merged.counterStyle, overrideTheme.counterStyle);
expect(merged.filled, isNot(overrideTheme.filled));
expect(merged.fillColor, overrideTheme.fillColor);
expect(merged.activeIndicatorBorder, overrideTheme.activeIndicatorBorder);
expect(merged.outlineBorder, overrideTheme.outlineBorder);
expect(merged.focusColor, overrideTheme.focusColor);
expect(merged.hoverColor, overrideTheme.hoverColor);
expect(merged.errorBorder, overrideTheme.errorBorder);
expect(merged.focusedBorder, overrideTheme.focusedBorder);
expect(merged.focusedErrorBorder, overrideTheme.focusedErrorBorder);
expect(merged.disabledBorder, overrideTheme.disabledBorder);
expect(merged.enabledBorder, overrideTheme.enabledBorder);
expect(merged.border, overrideTheme.border);
expect(merged.alignLabelWithHint, isNot(overrideTheme.alignLabelWithHint));
expect(merged.constraints, overrideTheme.constraints);
});
group('Material2', () {
// These tests are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests
......@@ -6584,129 +7459,6 @@ void main() {
expect(getOpacity(tester, 'label'), 0.0);
});
test('InputDecorationTheme copyWith, ==, hashCode basics', () {
expect(const InputDecorationTheme(), const InputDecorationTheme().copyWith());
expect(const InputDecorationTheme().hashCode, const InputDecorationTheme().copyWith().hashCode);
});
test('InputDecorationTheme copyWith correctly copies and replaces values', () {
const InputDecorationTheme original = InputDecorationTheme(
focusColor: Colors.orange,
fillColor: Colors.green,
);
final InputDecorationTheme copy = original.copyWith(
focusColor: Colors.yellow,
fillColor: Colors.blue,
);
expect(original.focusColor, Colors.orange);
expect(original.fillColor, Colors.green);
expect(copy.focusColor, Colors.yellow);
expect(copy.fillColor, Colors.blue);
});
test('InputDecorationTheme merge', () {
const InputDecorationTheme overrideTheme = InputDecorationTheme(
labelStyle: TextStyle(color: Color(0x000000f0)),
floatingLabelStyle: TextStyle(color: Color(0x000000f1)),
helperStyle: TextStyle(color: Color(0x000000f2)),
helperMaxLines: 1,
hintStyle: TextStyle(color: Color(0x000000f3)),
errorStyle: TextStyle(color: Color(0x000000f4)),
errorMaxLines: 1,
floatingLabelBehavior: FloatingLabelBehavior.never,
floatingLabelAlignment: FloatingLabelAlignment.center,
isDense: true,
contentPadding: EdgeInsets.all(1.0),
isCollapsed: true,
iconColor: Color(0x000000f5),
prefixStyle: TextStyle(color: Color(0x000000f6)),
prefixIconColor: Color(0x000000f7),
suffixStyle: TextStyle(color: Color(0x000000f8)),
suffixIconColor: Color(0x000000f9),
counterStyle: TextStyle(color: Color(0x00000f10)),
filled: true,
fillColor: Color(0x00000f11),
activeIndicatorBorder: BorderSide(
color: Color(0x00000f12),
),
outlineBorder: BorderSide(
color: Color(0x00000f13),
),
focusColor: Color(0x00000f14),
hoverColor: Color(0x00000f15),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(2.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f16),
),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f17),
),
),
disabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f18),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f19),
),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000f20),
),
),
alignLabelWithHint: true,
constraints: BoxConstraints(
minHeight: 1.0,
minWidth: 1.0,
),
);
final InputDecorationTheme inputDecorationTheme = ThemeData().inputDecorationTheme;
final InputDecorationTheme merged = inputDecorationTheme.merge(overrideTheme);
expect(merged.labelStyle, overrideTheme.labelStyle);
expect(merged.floatingLabelStyle, overrideTheme.floatingLabelStyle);
expect(merged.helperStyle, overrideTheme.helperStyle);
expect(merged.helperMaxLines, overrideTheme.helperMaxLines);
expect(merged.hintStyle, overrideTheme.hintStyle);
expect(merged.errorStyle, overrideTheme.errorStyle);
expect(merged.errorMaxLines, overrideTheme.errorMaxLines);
expect(merged.floatingLabelBehavior, isNot(overrideTheme.floatingLabelBehavior));
expect(merged.floatingLabelAlignment, isNot(overrideTheme.floatingLabelAlignment));
expect(merged.isDense, isNot(overrideTheme.isDense));
expect(merged.contentPadding, overrideTheme.contentPadding);
expect(merged.isCollapsed, isNot(overrideTheme.isCollapsed));
expect(merged.iconColor, overrideTheme.iconColor);
expect(merged.prefixStyle, overrideTheme.prefixStyle);
expect(merged.prefixIconColor, overrideTheme.prefixIconColor);
expect(merged.suffixStyle, overrideTheme.suffixStyle);
expect(merged.suffixIconColor, overrideTheme.suffixIconColor);
expect(merged.counterStyle, overrideTheme.counterStyle);
expect(merged.filled, isNot(overrideTheme.filled));
expect(merged.fillColor, overrideTheme.fillColor);
expect(merged.activeIndicatorBorder, overrideTheme.activeIndicatorBorder);
expect(merged.outlineBorder, overrideTheme.outlineBorder);
expect(merged.focusColor, overrideTheme.focusColor);
expect(merged.hoverColor, overrideTheme.hoverColor);
expect(merged.errorBorder, overrideTheme.errorBorder);
expect(merged.focusedBorder, overrideTheme.focusedBorder);
expect(merged.focusedErrorBorder, overrideTheme.focusedErrorBorder);
expect(merged.disabledBorder, overrideTheme.disabledBorder);
expect(merged.enabledBorder, overrideTheme.enabledBorder);
expect(merged.border, overrideTheme.border);
expect(merged.alignLabelWithHint, isNot(overrideTheme.alignLabelWithHint));
expect(merged.constraints, overrideTheme.constraints);
});
testWidgets('InputDecorationTheme outline border', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecoratorM2(
......
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