add description to by-predicate finders (#6362)

Add an option to provide a custom description to predicate
finders. Without a custom description we default to printing the
predicate function's signature, which is not all that useful.

Use this new option in the driver extension to print the text of the
sought after tooltip.
This commit is contained in:
Yegor 2016-10-17 17:16:22 -07:00 committed by GitHub
parent 08ba8dc495
commit 995fcdc92b
3 changed files with 64 additions and 13 deletions

View File

@ -163,7 +163,7 @@ class FlutterDriverExtension {
if (widget is Tooltip)
return widget.message == arguments.text;
return false;
});
}, description: 'widget with text tooltip "${arguments.text}"');
}
Finder _createByValueKeyFinder(ByValueKey arguments) {

View File

@ -110,18 +110,24 @@ class CommonFinders {
/// nodes that are [Offstage] or that are from inactive [Route]s.
Finder byConfig(Widget config, { bool skipOffstage: true }) => new _ConfigFinder(config, skipOffstage: skipOffstage);
/// Finds widgets using a widget predicate.
/// Finds widgets using a widget [predicate].
///
/// Example:
///
/// expect(tester, hasWidget(find.byWidgetPredicate(
/// (Widget widget) => widget is Tooltip && widget.message == 'Back'
/// (Widget widget) => widget is Tooltip && widget.message == 'Back',
/// description: 'widget with tooltip "Back"',
/// )));
///
/// If [description] is provided, then this uses it as the description of the
/// [Finder] and appears, for example, in the error message when the finder
/// fails to locate the desired widget. Otherwise, the description prints the
/// signature of the predicate function.
///
/// If the `skipOffstage` argument is true (the default), then this skips
/// nodes that are [Offstage] or that are from inactive [Route]s.
Finder byWidgetPredicate(WidgetPredicate predicate, { bool skipOffstage: true }) {
return new _WidgetPredicateFinder(predicate, skipOffstage: skipOffstage);
Finder byWidgetPredicate(WidgetPredicate predicate, { String description, bool skipOffstage: true }) {
return new _WidgetPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
}
/// Finds Tooltip widgets with the given message.
@ -139,7 +145,7 @@ class CommonFinders {
);
}
/// Finds widgets using an element predicate.
/// Finds widgets using an element [predicate].
///
/// Example:
///
@ -147,13 +153,19 @@ class CommonFinders {
/// // finds elements of type SingleChildRenderObjectElement, including
/// // those that are actually subclasses of that type.
/// // (contrast with byElementType, which only returns exact matches)
/// (Element element) => element is SingleChildRenderObjectElement
/// (Element element) => element is SingleChildRenderObjectElement,
/// description: '$SingleChildRenderObjectElement element',
/// )));
///
/// If [description] is provided, then this uses it as the description of the
/// [Finder] and appears, for example, in the error message when the finder
/// fails to locate the desired widget. Otherwise, the description prints the
/// signature of the predicate function.
///
/// If the `skipOffstage` argument is true (the default), then this skips
/// nodes that are [Offstage] or that are from inactive [Route]s.
Finder byElementPredicate(ElementPredicate predicate, { bool skipOffstage: true }) {
return new _ElementPredicateFinder(predicate, skipOffstage: skipOffstage);
Finder byElementPredicate(ElementPredicate predicate, { String description, bool skipOffstage: true }) {
return new _ElementPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
}
}
@ -397,12 +409,15 @@ class _ConfigFinder extends MatchFinder {
}
class _WidgetPredicateFinder extends MatchFinder {
_WidgetPredicateFinder(this.predicate, { bool skipOffstage: true }) : super(skipOffstage: skipOffstage);
_WidgetPredicateFinder(this.predicate, { String description, bool skipOffstage: true })
: _description = description,
super(skipOffstage: skipOffstage);
final WidgetPredicate predicate;
final String _description;
@override
String get description => 'widget matching predicate ($predicate)';
String get description => _description ?? 'widget matching predicate ($predicate)';
@override
bool matches(Element candidate) {
@ -411,12 +426,15 @@ class _WidgetPredicateFinder extends MatchFinder {
}
class _ElementPredicateFinder extends MatchFinder {
_ElementPredicateFinder(this.predicate, { bool skipOffstage: true }) : super(skipOffstage: skipOffstage);
_ElementPredicateFinder(this.predicate, { String description, bool skipOffstage: true })
: _description = description,
super(skipOffstage: skipOffstage);
final ElementPredicate predicate;
final String _description;
@override
String get description => 'element matching predicate ($predicate)';
String get description => _description ?? 'element matching predicate ($predicate)';
@override
bool matches(Element candidate) {

View File

@ -104,4 +104,37 @@ void main() {
});
});
group('find.byElementPredicate', () {
testWidgets('fails with a custom description in the message', (WidgetTester tester) async {
await tester.pumpWidget(new Text('foo'));
String customDescription = 'custom description';
TestFailure failure;
try {
expect(find.byElementPredicate((_) => false, description: customDescription), findsOneWidget);
} catch(e) {
failure = e;
}
expect(failure, isNotNull);
expect(failure.message, contains('Actual: ?:<zero widgets with $customDescription'));
});
});
group('find.byWidgetPredicate', () {
testWidgets('fails with a custom description in the message', (WidgetTester tester) async {
await tester.pumpWidget(new Text('foo'));
String customDescription = 'custom description';
TestFailure failure;
try {
expect(find.byWidgetPredicate((_) => false, description: customDescription), findsOneWidget);
} catch(e) {
failure = e;
}
expect(failure, isNotNull);
expect(failure.message, contains('Actual: ?:<zero widgets with $customDescription'));
});
});
}