Open
Description
The problem
Let's say that I have the following Widget:
IconButton(
iconSize: 20,
icon: FaIcon(FontAwesomeIcons.eye),
onPressed: () {/* change PasswordTextField visibility */},
);
If I want to test that this Widget is visible, I'd normally use
// password_text_field_test.dart
testWidgets(
'tapping on password visibility button toggles it',
(tester) async {
final eyeFinder = find.widgetWithIcon(IconButton, FontAwesomeIcons.eye);
expect(eyeFinder, findsOneWidget);
});
But the above will fail:
tapping on password visibility button toggles it
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _AncestorFinder:<zero widgets with type "IconButton" which is an ancestor of icon
"IconData(U+0F06E)">
Which: means none were found but one was expected
The reason is that FaIcon
is not an Icon
(i.e FaIcon extends StatelessWidget
), so find.widgetWithIcon
can't find it.
The solution 1/2
To make find.widgetWithIcon
work with FaIcon
, we have to create a custom implementation of Flutter's WidgetIconFinder
:
class WidgetFaIconFinder extends MatchFinder {
WidgetFaIconFinder(this.icon, {bool skipOffstage = true})
: super(skipOffstage: skipOffstage);
final IconData icon;
@override
String get description => 'Font Awesome icon "$icon"';
@override
bool matches(Element candidate) {
final widget = candidate.widget;
return widget is FaIcon && widget.icon == icon;
}
}
Then, to make it shorter for use in tests, we can create our own CustomFinders
class, basing on Flutter's CommonFinders
:
// finders.dart
const customFind = CustomFinders._();
class CustomFinders {
const CustomFinders._();
/// Like [CommonFinders.byIcon], but for FontAwesomeIcons.
Finder byFaIcon(IconData icon, {bool skipOffstage = true}) =>
WidgetFaIconFinder(icon, skipOffstage: skipOffstage);
/// Like [CommonFinders.widgetWithIcon], but for FontAwesomeIcons.
Finder widgetWithFaIcon(
Type widgetType,
IconData icon, {
bool skipOffstage = true,
}) {
return find.ancestor(
of: customFind.byFaIcon(icon),
matching: find.byType(widgetType),
);
}
}
The solution 2/2
Then, we can use our custom finders just like we'd use the default ones
// password_text_field_test.dart
testWidgets(
'tapping on password visibility button toggles it',
(tester) async {
final eyeFinder = customFind.widgetWithFaIcon(IconButton, FontAwesomeIcons.eye);
expect(eyeFinder, findsOneWidget);
});
Further steps
I see 2 ways:
- add custom finders to this package, so users don't have to write their own
- include information about how to test
FaIcon
(maybe link to this issue?)
Metadata
Metadata
Assignees
Labels
No labels