Skip to content

Commit ea8ae8c

Browse files
authored
Allow find.byTooltip to use a RegEx (#149348)
## Description This adds the ability for `find.byTooltip` to use a `RegEx` to match the tooltip. Also, adds some tests for `byTooltip`, since there weren't any. ## Tests - added tests
1 parent c77c0cf commit ea8ae8c

File tree

2 files changed

+109
-3
lines changed

2 files changed

+109
-3
lines changed

packages/flutter_test/lib/src/finders.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,20 @@ class CommonFinders {
365365
///
366366
/// ```dart
367367
/// expect(find.byTooltip('Back'), findsOneWidget);
368+
/// expect(find.byTooltip(RegExp('Back.*')), findsNWidgets(2));
368369
/// ```
369370
///
370371
/// If the `skipOffstage` argument is true (the default), then this skips
371372
/// nodes that are [Offstage] or that are from inactive [Route]s.
372-
Finder byTooltip(String message, { bool skipOffstage = true }) {
373+
Finder byTooltip(Pattern message, {bool skipOffstage = true}) {
373374
return byWidgetPredicate(
374-
(Widget widget) => widget is Tooltip && widget.message == message,
375+
(Widget widget) {
376+
return widget is Tooltip &&
377+
(message is RegExp
378+
? ((widget.message != null && message.hasMatch(widget.message!)) ||
379+
(widget.richMessage != null && message.hasMatch(widget.richMessage!.toPlainText())))
380+
: ((widget.message ?? widget.richMessage?.toPlainText()) == message));
381+
},
375382
skipOffstage: skipOffstage,
376383
);
377384
}

packages/flutter_test/test/finders_test.dart

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,98 @@ void main() {
301301
});
302302
});
303303

304+
group('byTooltip', () {
305+
testWidgets('finds widgets by tooltip', (WidgetTester tester) async {
306+
await tester.pumpWidget(_boilerplate(
307+
const Tooltip(
308+
message: 'Tooltip Message',
309+
child: Text('+'),
310+
),
311+
));
312+
expect(find.byTooltip('Tooltip Message'), findsOneWidget);
313+
});
314+
315+
testWidgets('finds widgets with tooltip by RegExp', (WidgetTester tester) async {
316+
await tester.pumpWidget(_boilerplate(
317+
const Tooltip(
318+
message: 'Tooltip Message',
319+
child: Text('+'),
320+
),
321+
));
322+
expect(find.byTooltip('Tooltip'), findsNothing);
323+
expect(find.byTooltip(RegExp(r'^Tooltip')), findsOneWidget);
324+
});
325+
326+
testWidgets('finds widgets by rich text tooltip', (WidgetTester tester) async {
327+
await tester.pumpWidget(_boilerplate(
328+
const Tooltip(
329+
richMessage: TextSpan(
330+
children: <InlineSpan>[
331+
TextSpan(text: 'Tooltip '),
332+
TextSpan(text: 'Message'),
333+
]),
334+
child: Text('+'),
335+
),
336+
));
337+
expect(find.byTooltip('Tooltip Message'), findsOneWidget);
338+
});
339+
340+
testWidgets('finds widgets with rich text tooltip by RegExp', (WidgetTester tester) async {
341+
await tester.pumpWidget(_boilerplate(
342+
const Tooltip(
343+
richMessage: TextSpan(
344+
children: <InlineSpan>[
345+
TextSpan(text: 'Tooltip '),
346+
TextSpan(text: 'Message'),
347+
]),
348+
child: Text('+'),
349+
),
350+
));
351+
expect(find.byTooltip('Tooltip M'), findsNothing);
352+
expect(find.byTooltip(RegExp(r'^Tooltip M')), findsOneWidget);
353+
});
354+
355+
testWidgets('finds empty string with tooltip', (WidgetTester tester) async {
356+
await tester.pumpWidget(_boilerplate(
357+
const Tooltip(
358+
message: '',
359+
child: Text('+'),
360+
),
361+
));
362+
expect(find.byTooltip(''), findsOneWidget);
363+
364+
await tester.pumpWidget(_boilerplate(
365+
const Tooltip(
366+
richMessage: TextSpan(
367+
children: <InlineSpan>[
368+
TextSpan(text: ''),
369+
]),
370+
child: Text('+'),
371+
),
372+
));
373+
expect(find.byTooltip(''), findsOneWidget);
374+
375+
await tester.pumpWidget(_boilerplate(
376+
const Tooltip(
377+
message: '',
378+
child: Text('+'),
379+
),
380+
));
381+
expect(find.byTooltip(RegExp(r'^$')), findsOneWidget);
382+
383+
await tester.pumpWidget(_boilerplate(
384+
const Tooltip(
385+
richMessage: TextSpan(
386+
children: <InlineSpan>[
387+
TextSpan(text: ''),
388+
]),
389+
child: Text('+'),
390+
),
391+
));
392+
expect(find.byTooltip(RegExp(r'^$')), findsOneWidget);
393+
});
394+
});
395+
304396
group('hitTestable', () {
305397
testWidgets('excludes non-hit-testable widgets',
306398
(WidgetTester tester) async {
@@ -1356,10 +1448,17 @@ void main() {
13561448
Widget _boilerplate(Widget child) {
13571449
return Directionality(
13581450
textDirection: TextDirection.ltr,
1359-
child: child,
1451+
child: Navigator(
1452+
onGenerateRoute: (RouteSettings settings) {
1453+
return MaterialPageRoute<void>(
1454+
builder: (BuildContext context) => child,
1455+
);
1456+
},
1457+
),
13601458
);
13611459
}
13621460

1461+
13631462
class SimpleCustomSemanticsWidget extends LeafRenderObjectWidget {
13641463
const SimpleCustomSemanticsWidget(this.label, {super.key});
13651464

0 commit comments

Comments
 (0)