Unverified Commit 83134cd3 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Added find.ancestor to CommonFinders (#13691)

parent 95aeb05c
......@@ -198,6 +198,29 @@ class CommonFinders {
Finder descendant({ Finder of, Finder matching, bool matchRoot: false, bool skipOffstage: true }) {
return new _DescendantFinder(of, matching, matchRoot: matchRoot, skipOffstage: skipOffstage);
}
/// Finds widgets that are ancestors of the [of] parameter and that match
/// the [matching] parameter.
///
/// Example:
///
/// // Test if a Text widget that contains 'faded' is the
/// // descendant of an Opacity widget with opacity 0.5:
/// expect(
/// tester.widget<Opacity>(
/// find.ancestor(
/// of: find.text('faded'),
/// matching: find.byType('Opacity'),
/// )
/// ).opacity,
/// 0.5
/// );
///
/// If the [matchRoot] argument is true then the widget(s) specified by [of]
/// will be matched along with the ancestors.
Finder ancestor({ Finder of, Finder matching, bool matchRoot: false}) {
return new _AncestorFinder(of, matching, matchRoot: matchRoot);
}
}
/// Searches a widget tree and returns nodes that match a particular
......@@ -583,3 +606,39 @@ class _DescendantFinder extends Finder {
return candidates;
}
}
class _AncestorFinder extends Finder {
_AncestorFinder(this.descendant, this.ancestor, { this.matchRoot: false }) : super(skipOffstage: false);
final Finder ancestor;
final Finder descendant;
final bool matchRoot;
@override
String get description {
if (matchRoot)
return 'ancestor ${ancestor.description} beginning with ${descendant.description}';
return '${ancestor.description} which is an ancestor of ${descendant.description}';
}
@override
Iterable<Element> apply(Iterable<Element> candidates) {
return candidates.where((Element element) => ancestor.evaluate().contains(element));
}
@override
Iterable<Element> get allCandidates {
final List<Element> candidates = <Element>[];
for (Element root in descendant.evaluate()) {
final List<Element> ancestors = <Element>[];
if (matchRoot)
ancestors.add(root);
root.visitAncestorElements((Element element) {
ancestors.add(element);
return true;
});
candidates.addAll(ancestors);
}
return candidates;
}
}
......@@ -198,8 +198,10 @@ void main() {
contains('Actual: ?:<zero widgets with text "bar" that has ancestor(s) with type Column with text "foo"')
);
});
});
testWidgets('Root not matched by default', (WidgetTester tester) async {
group('find.ancestor', () {
testWidgets('finds one ancestor', (WidgetTester tester) async {
await tester.pumpWidget(new Row(
textDirection: TextDirection.ltr,
children: <Widget>[
......@@ -207,9 +209,67 @@ void main() {
],
));
expect(find.descendant(
of: find.widgetWithText(Row, 'foo'),
expect(find.ancestor(
of: find.text('bar'),
matching: find.widgetWithText(Row, 'foo'),
), findsOneWidget);
});
testWidgets('finds two matching ancestors, one descendant', (WidgetTester tester) async {
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Row(
children: <Widget>[
new Row(children: fooBarTexts),
],
),
),
);
expect(find.ancestor(
of: find.text('bar'),
matching: find.byType(Row),
), findsNWidgets(2));
});
testWidgets('fails with a descriptive message', (WidgetTester tester) async {
await tester.pumpWidget(new Row(
textDirection: TextDirection.ltr,
children: <Widget>[
new Column(children: <Text>[const Text('foo', textDirection: TextDirection.ltr)]),
const Text('bar', textDirection: TextDirection.ltr),
],
));
TestFailure failure;
try {
expect(find.ancestor(
of: find.text('bar'),
matching: find.widgetWithText(Column, 'foo'),
), findsOneWidget);
} catch (e) {
failure = e;
}
expect(failure, isNotNull);
expect(
failure.message,
contains('Actual: ?:<zero widgets with type Column with text "foo" which is an ancestor of text "bar"'),
);
});
testWidgets('Root not matched by default', (WidgetTester tester) async {
await tester.pumpWidget(new Row(
textDirection: TextDirection.ltr,
children: <Widget>[
new Column(children: fooBarTexts),
],
));
expect(find.ancestor(
of: find.byType(Column),
matching: find.widgetWithText(Column, 'foo'),
), findsNothing);
});
......@@ -222,12 +282,11 @@ void main() {
));
expect(find.descendant(
of: find.widgetWithText(Row, 'foo'),
matching: find.byType(Row),
of: find.byType(Column),
matching: find.widgetWithText(Column, 'foo'),
matchRoot: true,
), findsOneWidget);
});
});
testWidgets('hasRunningAnimations control test', (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment