From 995fcdc92bbb1a48f81aff3e30ce2df0f37d096e Mon Sep 17 00:00:00 2001 From: Yegor Date: Mon, 17 Oct 2016 17:16:22 -0700 Subject: [PATCH] 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. --- .../flutter_driver/lib/src/extension.dart | 2 +- packages/flutter_test/lib/src/finders.dart | 42 +++++++++++++------ .../flutter_test/test/widget_tester_test.dart | 33 +++++++++++++++ 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/packages/flutter_driver/lib/src/extension.dart b/packages/flutter_driver/lib/src/extension.dart index a035da87256..3827e8c387d 100644 --- a/packages/flutter_driver/lib/src/extension.dart +++ b/packages/flutter_driver/lib/src/extension.dart @@ -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) { diff --git a/packages/flutter_test/lib/src/finders.dart b/packages/flutter_test/lib/src/finders.dart index 02534089937..1e27f5c8ce6 100644 --- a/packages/flutter_test/lib/src/finders.dart +++ b/packages/flutter_test/lib/src/finders.dart @@ -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) { diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart index bfb081ab8ec..ab5bdc23140 100644 --- a/packages/flutter_test/test/widget_tester_test.dart +++ b/packages/flutter_test/test/widget_tester_test.dart @@ -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: ?: false, description: customDescription), findsOneWidget); + } catch(e) { + failure = e; + } + + expect(failure, isNotNull); + expect(failure.message, contains('Actual: ?: