Skip to content

Commit 9aa3c62

Browse files
committed
test: Add find.text analogue with includePlaceholders option
The bulk of this code is copied verbatim from the implementation of `find.text`, in `package:flutter_test/src/finders.dart`. The new logic is just the includePlaceholders flag, and passing it down to where InlineSpan.toPlainText gets called. The latter already has a corresponding flag, which does the rest.
1 parent 032110b commit 9aa3c62

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

test/widgets/finders.dart

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
4+
/// Like `find.text` from flutter_test upstream, but with
5+
/// the `includePlaceholders` option.
6+
///
7+
/// When `includePlaceholders` is true, any [PlaceholderSpan] (for example,
8+
/// any [WidgetSpan]) in the tree will be represented as
9+
/// an "object replacement character", U+FFFC.
10+
/// When `includePlaceholders` is false, such spans will be omitted.
11+
///
12+
/// TODO(upstream): get `find.text` to accept includePlaceholders
13+
Finder findText(String text, {
14+
bool findRichText = false,
15+
bool includePlaceholders = true,
16+
bool skipOffstage = true,
17+
}) {
18+
return _TextWidgetFinder(text,
19+
findRichText: findRichText,
20+
includePlaceholders: includePlaceholders,
21+
skipOffstage: skipOffstage);
22+
}
23+
24+
// (Compare the implementation in `package:flutter_test/src/finders.dart`.)
25+
abstract class _MatchTextFinder extends MatchFinder {
26+
_MatchTextFinder({this.findRichText = false, this.includePlaceholders = true,
27+
super.skipOffstage});
28+
29+
/// Whether standalone [RichText] widgets should be found or not.
30+
///
31+
/// Defaults to `false`.
32+
///
33+
/// If disabled, only [Text] widgets will be matched. [RichText] widgets
34+
/// *without* a [Text] ancestor will be ignored.
35+
/// If enabled, only [RichText] widgets will be matched. This *implicitly*
36+
/// matches [Text] widgets as well since they always insert a [RichText]
37+
/// child.
38+
///
39+
/// In either case, [EditableText] widgets will also be matched.
40+
final bool findRichText;
41+
42+
final bool includePlaceholders;
43+
44+
bool matchesText(String textToMatch);
45+
46+
@override
47+
bool matches(Element candidate) {
48+
final Widget widget = candidate.widget;
49+
if (widget is EditableText) {
50+
return _matchesEditableText(widget);
51+
}
52+
53+
if (!findRichText) {
54+
return _matchesNonRichText(widget);
55+
}
56+
// It would be sufficient to always use _matchesRichText if we wanted to
57+
// match both standalone RichText widgets as well as Text widgets. However,
58+
// the find.text() finder used to always ignore standalone RichText widgets,
59+
// which is why we need the _matchesNonRichText method in order to not be
60+
// backwards-compatible and not break existing tests.
61+
return _matchesRichText(widget);
62+
}
63+
64+
bool _matchesRichText(Widget widget) {
65+
if (widget is RichText) {
66+
return matchesText(widget.text.toPlainText(
67+
includePlaceholders: includePlaceholders));
68+
}
69+
return false;
70+
}
71+
72+
bool _matchesNonRichText(Widget widget) {
73+
if (widget is Text) {
74+
if (widget.data != null) {
75+
return matchesText(widget.data!);
76+
}
77+
assert(widget.textSpan != null);
78+
return matchesText(widget.textSpan!.toPlainText(
79+
includePlaceholders: includePlaceholders));
80+
}
81+
return false;
82+
}
83+
84+
bool _matchesEditableText(EditableText widget) {
85+
return matchesText(widget.controller.text);
86+
}
87+
}
88+
89+
class _TextWidgetFinder extends _MatchTextFinder {
90+
_TextWidgetFinder(this.text, {super.findRichText, super.includePlaceholders,
91+
super.skipOffstage});
92+
93+
final String text;
94+
95+
@override
96+
String get description => 'text "$text"';
97+
98+
@override
99+
bool matchesText(String textToMatch) {
100+
return textToMatch == text;
101+
}
102+
}

0 commit comments

Comments
 (0)