blob: 918939d82c9d9f39a69f7aecf7c0fd2a5f0b30a7 [file] [log] [blame]
// Copyright 2014 The Flutter 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/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('default search field has a border radius', (WidgetTester tester) async {
await tester.pumpWidget(const CupertinoApp(home: Center(child: CupertinoSearchTextField())));
final decoration =
tester
.widget<DecoratedBox>(
find.descendant(
of: find.byType(CupertinoSearchTextField),
matching: find.byType(DecoratedBox),
),
)
.decoration
as BoxDecoration;
expect(decoration.borderRadius, const BorderRadius.all(Radius.circular(9)));
});
testWidgets('decoration overrides default background color', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
decoration: BoxDecoration(color: Color.fromARGB(1, 1, 1, 1)),
),
),
),
);
final decoration =
tester
.widget<DecoratedBox>(
find.descendant(
of: find.byType(CupertinoSearchTextField),
matching: find.byType(DecoratedBox),
),
)
.decoration
as BoxDecoration;
expect(decoration.color, const Color.fromARGB(1, 1, 1, 1));
});
testWidgets('decoration overrides default border radius', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
decoration: BoxDecoration(borderRadius: BorderRadius.zero),
),
),
),
);
final decoration =
tester
.widget<DecoratedBox>(
find.descendant(
of: find.byType(CupertinoSearchTextField),
matching: find.byType(DecoratedBox),
),
)
.decoration
as BoxDecoration;
expect(decoration.borderRadius, BorderRadius.zero);
});
testWidgets('text entries are padded by default', (WidgetTester tester) async {
final controller = TextEditingController(text: 'initial');
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(controller: controller)),
),
);
expect(
tester.getTopLeft(find.text('initial')) -
tester.getTopLeft(find.byType(CupertinoSearchTextField)),
const Offset(31.5, 9.5),
);
});
testWidgets('can change keyboard type', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(keyboardType: TextInputType.number)),
),
);
await tester.tap(find.byType(CupertinoSearchTextField));
await tester.showKeyboard(find.byType(CupertinoSearchTextField));
expect(
(tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'],
equals('TextInputType.number'),
);
});
testWidgets('can control text content via controller', (WidgetTester tester) async {
final controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(controller: controller)),
),
);
controller.text = 'controller text';
await tester.pump();
expect(find.text('controller text'), findsOneWidget);
controller.text = '';
await tester.pump();
expect(find.text('controller text'), findsNothing);
});
testWidgets('placeholder color', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
theme: CupertinoThemeData(brightness: Brightness.dark),
home: Center(child: CupertinoSearchTextField()),
),
);
Text placeholder = tester.widget(find.text('Search'));
expect(placeholder.style!.color!.value, CupertinoColors.secondaryLabel.darkColor.value);
await tester.pumpAndSettle();
await tester.pumpWidget(
const CupertinoApp(
theme: CupertinoThemeData(brightness: Brightness.light),
home: Center(child: CupertinoSearchTextField()),
),
);
placeholder = tester.widget(find.text('Search'));
expect(placeholder.style!.color!.value, CupertinoColors.secondaryLabel.color.value);
});
testWidgets("placeholderStyle modifies placeholder's style and doesn't affect text's style", (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
placeholder: 'placeholder',
style: TextStyle(color: Color(0x00FFFFFF), fontWeight: FontWeight.w300),
placeholderStyle: TextStyle(color: Color(0xAAFFFFFF), fontWeight: FontWeight.w600),
),
),
),
);
final Text placeholder = tester.widget(find.text('placeholder'));
expect(placeholder.style!.color, const Color(0xAAFFFFFF));
expect(placeholder.style!.fontWeight, FontWeight.w600);
await tester.enterText(find.byType(CupertinoSearchTextField), 'input');
await tester.pump();
final EditableText inputText = tester.widget(find.text('input'));
expect(inputText.style.color, const Color(0x00FFFFFF));
expect(inputText.style.fontWeight, FontWeight.w300);
});
testWidgets('prefix widget is in front of the text', (WidgetTester tester) async {
final controller = TextEditingController(text: 'input');
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(controller: controller)),
),
);
expect(
tester.getTopRight(find.byIcon(CupertinoIcons.search)).dx + 5.5,
tester.getTopLeft(find.byType(EditableText)).dx,
);
expect(
tester.getTopLeft(find.byType(EditableText)).dx,
tester.getTopLeft(find.byType(CupertinoSearchTextField)).dx +
tester.getSize(find.byIcon(CupertinoIcons.search)).width +
11.5,
);
});
testWidgets('suffix widget is after the text', (WidgetTester tester) async {
final controller = TextEditingController(text: 'Hi');
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(controller: controller)),
),
);
expect(
tester.getTopRight(find.byType(EditableText)).dx + 5.5,
tester.getTopLeft(find.byIcon(CupertinoIcons.xmark_circle_fill)).dx,
);
expect(
tester.getTopRight(find.byType(EditableText)).dx,
tester.getTopRight(find.byType(CupertinoSearchTextField)).dx -
tester.getSize(find.byIcon(CupertinoIcons.xmark_circle_fill)).width -
10.5,
);
});
testWidgets('prefix widget visibility', (WidgetTester tester) async {
const prefixIcon = Key('prefix');
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
prefixIcon: SizedBox(key: prefixIcon, width: 50, height: 50),
),
),
),
);
expect(find.byIcon(CupertinoIcons.search), findsNothing);
expect(find.byKey(prefixIcon), findsOneWidget);
await tester.enterText(find.byType(CupertinoSearchTextField), 'text input');
await tester.pump();
expect(find.text('text input'), findsOneWidget);
expect(find.byIcon(CupertinoIcons.search), findsNothing);
expect(find.byKey(prefixIcon), findsOneWidget);
});
testWidgets('suffix widget respects visibility mode', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(suffixMode: OverlayVisibilityMode.notEditing)),
),
);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsOneWidget);
await tester.enterText(find.byType(CupertinoSearchTextField), 'text input');
await tester.pump();
expect(find.text('text input'), findsOneWidget);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsNothing);
});
testWidgets('Default prefix and suffix insets are aligned', (WidgetTester tester) async {
await tester.pumpWidget(const CupertinoApp(home: Center(child: CupertinoSearchTextField())));
expect(find.byIcon(CupertinoIcons.search), findsOneWidget);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsNothing);
await tester.enterText(find.byType(CupertinoSearchTextField), 'text input');
await tester.pump();
expect(find.text('text input'), findsOneWidget);
expect(find.byIcon(CupertinoIcons.search), findsOneWidget);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsOneWidget);
expect(tester.getTopLeft(find.byIcon(CupertinoIcons.search)), const Offset(6.0, 290.0));
expect(
tester.getTopLeft(find.byIcon(CupertinoIcons.xmark_circle_fill)),
const Offset(775.0, 290.0),
);
expect(tester.getBottomRight(find.byIcon(CupertinoIcons.search)), const Offset(26.0, 310.0));
expect(
tester.getBottomRight(find.byIcon(CupertinoIcons.xmark_circle_fill)),
const Offset(795.0, 310.0),
);
});
testWidgets('clear button shows with right visibility mode', (WidgetTester tester) async {
var controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
controller: controller,
placeholder: 'placeholder does not affect clear button',
),
),
),
);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsNothing);
await tester.enterText(find.byType(CupertinoSearchTextField), 'text input');
await tester.pump();
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsOneWidget);
expect(find.text('text input'), findsOneWidget);
controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
controller: controller,
placeholder: 'placeholder does not affect clear button',
suffixMode: OverlayVisibilityMode.notEditing,
),
),
),
);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsOneWidget);
controller.text = 'input';
await tester.pump();
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsNothing);
});
testWidgets('clear button removes text', (WidgetTester tester) async {
final controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(controller: controller)),
),
);
controller.text = 'text entry';
await tester.pump();
await tester.tap(find.byIcon(CupertinoIcons.xmark_circle_fill));
await tester.pump();
expect(controller.text, '');
expect(find.text('Search'), findsOneWidget);
expect(find.text('text entry'), findsNothing);
expect(find.byIcon(CupertinoIcons.xmark_circle_fill), findsNothing);
});
testWidgets('tapping clear button also calls onChanged when text not empty', (
WidgetTester tester,
) async {
var value = 'text entry';
final controller = TextEditingController();
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
controller: controller,
placeholder: 'placeholder',
onChanged: (String newValue) => value = newValue,
),
),
),
);
controller.text = value;
await tester.pump();
await tester.tap(find.byIcon(CupertinoIcons.xmark_circle_fill));
await tester.pump();
expect(controller.text, isEmpty);
expect(find.text('text entry'), findsNothing);
expect(value, isEmpty);
});
testWidgets('RTL puts attachments to the right places', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Directionality(
textDirection: TextDirection.rtl,
child: Center(child: CupertinoSearchTextField(suffixMode: OverlayVisibilityMode.always)),
),
),
);
expect(tester.getTopLeft(find.byIcon(CupertinoIcons.search)).dx, 800.0 - 26.0);
expect(tester.getTopRight(find.byIcon(CupertinoIcons.xmark_circle_fill)).dx, 25.0);
});
testWidgets('Can modify prefix and suffix insets', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
suffixMode: OverlayVisibilityMode.always,
prefixInsets: EdgeInsets.zero,
suffixInsets: EdgeInsets.zero,
),
),
),
);
expect(tester.getTopLeft(find.byIcon(CupertinoIcons.search)).dx, 0.0);
expect(tester.getTopRight(find.byIcon(CupertinoIcons.xmark_circle_fill)).dx, 800.0);
});
testWidgets('custom suffix onTap overrides default clearing behavior', (
WidgetTester tester,
) async {
final controller = TextEditingController(text: 'Text');
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoSearchTextField(controller: controller, onSuffixTap: () {}),
),
),
);
await tester.pump();
await tester.tap(find.byIcon(CupertinoIcons.xmark_circle_fill));
await tester.pump();
expect(controller.text, isNotEmpty);
expect(find.text('Text'), findsOneWidget);
});
testWidgets('onTap is properly forwarded to the inner text field', (WidgetTester tester) async {
var onTapCallCount = 0;
// onTap can be null.
await tester.pumpWidget(const CupertinoApp(home: Center(child: CupertinoSearchTextField())));
// onTap callback is called if not null.
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoSearchTextField(
onTap: () {
onTapCallCount++;
},
),
),
),
);
expect(onTapCallCount, 0);
await tester.tap(find.byType(CupertinoTextField));
expect(onTapCallCount, 1);
});
testWidgets('autocorrect is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(home: Center(child: CupertinoSearchTextField(autocorrect: false))),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.autocorrect, false);
});
testWidgets('enabled is properly forwarded to the inner text field', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(home: Center(child: CupertinoSearchTextField(enabled: false))),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.enabled, false);
});
testWidgets('textInputAction is set to TextInputAction.search by default', (
WidgetTester tester,
) async {
await tester.pumpWidget(const CupertinoApp(home: Center(child: CupertinoSearchTextField())));
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.textInputAction, TextInputAction.search);
});
testWidgets('autofocus:true gives focus to the widget', (WidgetTester tester) async {
final focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(focusNode: focusNode, autofocus: true)),
),
);
expect(focusNode.hasFocus, isTrue);
});
testWidgets('smartQuotesType is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(smartQuotesType: SmartQuotesType.disabled)),
),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.smartQuotesType, SmartQuotesType.disabled);
});
testWidgets('smartDashesType is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(smartDashesType: SmartDashesType.disabled)),
),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.smartDashesType, SmartDashesType.disabled);
});
testWidgets('enableIMEPersonalizedLearning is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(enableIMEPersonalizedLearning: false)),
),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.enableIMEPersonalizedLearning, false);
});
testWidgets('cursorWidth is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(home: Center(child: CupertinoSearchTextField(cursorWidth: 1))),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.cursorWidth, 1);
});
testWidgets('cursorHeight is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(home: Center(child: CupertinoSearchTextField(cursorHeight: 10))),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.cursorHeight, 10);
});
testWidgets('cursorRadius is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(cursorRadius: Radius.circular(1.0))),
),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.cursorRadius, const Radius.circular(1.0));
});
testWidgets('cursorOpacityAnimates is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(cursorOpacityAnimates: false)),
),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.cursorOpacityAnimates, false);
});
testWidgets('cursorColor is properly forwarded to the inner text field', (
WidgetTester tester,
) async {
await tester.pumpWidget(
const CupertinoApp(
home: Center(child: CupertinoSearchTextField(cursorColor: Color.fromARGB(255, 255, 0, 0))),
),
);
final CupertinoTextField textField = tester.widget(find.byType(CupertinoTextField));
expect(textField.cursorColor, const Color.fromARGB(255, 255, 0, 0));
});
testWidgets('Icons and placeholder fade while resizing on scroll', (WidgetTester tester) async {
await tester.pumpWidget(
const CupertinoApp(
home: CupertinoPageScaffold(
child: CustomScrollView(
slivers: <Widget>[
SliverResizingHeader(
child: CupertinoSearchTextField(suffixMode: OverlayVisibilityMode.always),
),
SliverFillRemaining(),
],
),
),
),
);
final Finder searchTextFieldFinder = find.byType(CupertinoSearchTextField);
expect(searchTextFieldFinder, findsOneWidget);
final Finder prefixIconFinder = find.descendant(
of: searchTextFieldFinder,
matching: find.byIcon(CupertinoIcons.search),
);
final Finder suffixIconFinder = find.descendant(
of: searchTextFieldFinder,
matching: find.byIcon(CupertinoIcons.xmark_circle_fill),
);
final Finder placeholderFinder = find.descendant(
of: searchTextFieldFinder,
matching: find.text('Search'),
);
expect(prefixIconFinder, findsOneWidget);
expect(suffixIconFinder, findsOneWidget);
expect(placeholderFinder, findsOneWidget);
// Initially, the icons are fully opaque.
expect(
tester
.widget<Opacity>(find.ancestor(of: prefixIconFinder, matching: find.byType(Opacity)))
.opacity,
equals(1.0),
);
expect(
tester
.widget<Opacity>(find.ancestor(of: suffixIconFinder, matching: find.byType(Opacity)))
.opacity,
equals(1.0),
);
// The default placeholder color is semi-transparent.
expect(tester.widget<Text>(placeholderFinder).style?.color?.a, equals(0.6));
final double searchTextFieldHeight = tester.getSize(searchTextFieldFinder).height;
final TestGesture scrollGesture1 = await tester.startGesture(
tester.getCenter(find.byType(CustomScrollView)),
);
await scrollGesture1.moveBy(Offset(0, -searchTextFieldHeight / 5));
await scrollGesture1.up();
await tester.pumpAndSettle();
// The icons and placeholder text start to fade.
expect(
tester
.widget<Opacity>(find.ancestor(of: prefixIconFinder, matching: find.byType(Opacity)))
.opacity,
greaterThan(0.0),
);
expect(
tester
.widget<Opacity>(find.ancestor(of: prefixIconFinder, matching: find.byType(Opacity)))
.opacity,
lessThan(1.0),
);
expect(
tester
.widget<Opacity>(find.ancestor(of: suffixIconFinder, matching: find.byType(Opacity)))
.opacity,
greaterThan(0.0),
);
expect(
tester
.widget<Opacity>(find.ancestor(of: suffixIconFinder, matching: find.byType(Opacity)))
.opacity,
lessThan(1.0),
);
expect(tester.widget<Text>(placeholderFinder).style?.color?.a, greaterThan(0.0));
expect(tester.widget<Text>(placeholderFinder).style?.color?.a, lessThan(1.0));
final TestGesture scrollGesture2 = await tester.startGesture(
tester.getCenter(find.byType(CustomScrollView)),
);
await scrollGesture2.moveBy(Offset(0, -4 * searchTextFieldHeight / 5));
await scrollGesture2.up();
await tester.pumpAndSettle();
// The icons and placeholder text have faded completely.
expect(
tester
.widget<Opacity>(find.ancestor(of: prefixIconFinder, matching: find.byType(Opacity)))
.opacity,
equals(0.0),
);
expect(
tester
.widget<Opacity>(find.ancestor(of: suffixIconFinder, matching: find.byType(Opacity)))
.opacity,
equals(0.0),
);
expect(tester.widget<Text>(placeholderFinder).style?.color?.a, equals(0.0));
});
testWidgets('Top padding animates while resizing on scroll', (WidgetTester tester) async {
const TextDirection direction = TextDirection.ltr;
await tester.pumpWidget(
const Directionality(
textDirection: direction,
child: CupertinoApp(
home: CupertinoPageScaffold(
child: CustomScrollView(
slivers: <Widget>[
SliverResizingHeader(child: CupertinoSearchTextField()),
SliverFillRemaining(),
],
),
),
),
),
);
final Finder searchTextFieldFinder = find.byType(CupertinoSearchTextField);
expect(searchTextFieldFinder, findsOneWidget);
final double initialPadding = tester
.widget<CupertinoTextField>(
find.descendant(of: searchTextFieldFinder, matching: find.byType(CupertinoTextField)),
)
.padding
.resolve(direction)
.top;
expect(initialPadding, equals(8.0));
final double searchTextFieldHeight = tester.getSize(searchTextFieldFinder).height;
final TestGesture scrollGesture = await tester.startGesture(
tester.getCenter(find.byType(CustomScrollView)),
);
await scrollGesture.moveBy(Offset(0, -searchTextFieldHeight / 5));
await scrollGesture.up();
await tester.pumpAndSettle();
expect(
tester
.widget<CupertinoTextField>(
find.descendant(of: searchTextFieldFinder, matching: find.byType(CupertinoTextField)),
)
.padding
.resolve(direction)
.top,
lessThan(initialPadding),
);
});
testWidgets('Fades and animates insets on scroll if search field starts out collapsed', (
WidgetTester tester,
) async {
const TextDirection direction = TextDirection.ltr;
const double scrollOffset = 200;
await tester.pumpWidget(
const Directionality(
textDirection: direction,
child: CupertinoApp(
home: CupertinoPageScaffold(
child: CustomScrollView(
slivers: <Widget>[
CupertinoSliverNavigationBar.search(
largeTitle: Text('Large title'),
searchField: CupertinoSearchTextField(),
),
SliverToBoxAdapter(child: SizedBox(height: 1000)),
],
),
),
),
),
);
final Finder searchTextFieldFinder = find.byType(CupertinoSearchTextField);
expect(searchTextFieldFinder, findsOneWidget);
final double searchTextFieldHeight = tester.getSize(searchTextFieldFinder).height;
await tester.tap(find.widgetWithText(CupertinoSearchTextField, 'Search'), warnIfMissed: false);
final TestGesture scrollGesture1 = await tester.startGesture(
tester.getCenter(find.byType(CustomScrollView)),
);
await scrollGesture1.moveBy(const Offset(0, -scrollOffset));
await scrollGesture1.up();
await tester.pumpAndSettle();
expect(find.text('Cancel'), findsOneWidget);
await tester.tap(find.text('Cancel'));
await tester.pumpAndSettle();
final TestGesture scrollGesture2 = await tester.startGesture(
tester.getCenter(find.byType(CustomScrollView)),
);
await scrollGesture2.moveBy(Offset(0, scrollOffset - searchTextFieldHeight / 2));
await scrollGesture2.up();
await tester.pump();
final Finder prefixIconFinder = find.descendant(
of: searchTextFieldFinder,
matching: find.byIcon(CupertinoIcons.search),
);
// The prefix icon has faded.
expect(prefixIconFinder, findsOneWidget);
expect(
tester
.widget<Opacity>(find.ancestor(of: prefixIconFinder, matching: find.byType(Opacity)))
.opacity,
lessThan(1.0),
);
});
testWidgets('Focused search field hides prefix in higher accessibility text scale modes', (
WidgetTester tester,
) async {
var scaleFactor = 3.0;
const iconSize = 10.0;
final focusNode = FocusNode();
addTearDown(focusNode.dispose);
late StateSetter setState;
await tester.pumpWidget(
CupertinoApp(
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setter) {
setState = setter;
return MediaQuery.withClampedTextScaling(
minScaleFactor: scaleFactor,
maxScaleFactor: scaleFactor,
child: CupertinoPageScaffold(
child: Center(
child: CupertinoSearchTextField(
placeholder: 'Search',
focusNode: focusNode,
prefixIcon: const Icon(CupertinoIcons.add),
suffixIcon: const Icon(CupertinoIcons.xmark),
suffixMode: OverlayVisibilityMode.always,
itemSize: iconSize,
),
),
),
);
},
),
),
);
final Iterable<RichText> barItems = tester.widgetList<RichText>(
find.descendant(of: find.byType(CupertinoSearchTextField), matching: find.byType(RichText)),
);
expect(barItems.length, greaterThan(0));
for (final icon in <IconData>[CupertinoIcons.add, CupertinoIcons.xmark]) {
expect(tester.getSize(find.byIcon(icon)), Size.square(scaleFactor * iconSize));
}
focusNode.requestFocus();
await tester.pumpAndSettle();
// The prefix icon shrinks at higher accessibility text scale modes.
expect(tester.getSize(find.byIcon(CupertinoIcons.add)), Size.zero);
expect(tester.getSize(find.byIcon(CupertinoIcons.xmark)), Size.square(scaleFactor * iconSize));
setState(() {
scaleFactor = 2.9;
});
await tester.pumpAndSettle();
// Below the threshold, the prefix icon is displayed.
for (final icon in <IconData>[CupertinoIcons.add, CupertinoIcons.xmark]) {
expect(tester.getSize(find.byIcon(icon)), Size.square(scaleFactor * iconSize));
}
});
testWidgets('CupertinoSearchTextField does not crash at zero area', (WidgetTester tester) async {
tester.view.physicalSize = Size.zero;
final controller = TextEditingController(text: 'X');
addTearDown(tester.view.reset);
addTearDown(controller.dispose);
await tester.pumpWidget(
CupertinoApp(
home: Center(child: CupertinoSearchTextField(controller: controller)),
),
);
expect(tester.getSize(find.byType(CupertinoSearchTextField)), Size.zero);
controller.selection = const TextSelection.collapsed(offset: 0);
await tester.pump();
});
}