mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Added find.ancestor to CommonFinders (#13691)
This commit is contained in:
parent
95aeb05ced
commit
83134cd39f
@ -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,6 +198,66 @@ void main() {
|
||||
contains('Actual: ?:<zero widgets with text "bar" that has ancestor(s) with type Column with text "foo"')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('find.ancestor', () {
|
||||
testWidgets('finds one ancestor', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Row(
|
||||
textDirection: TextDirection.ltr,
|
||||
children: <Widget>[
|
||||
new Column(children: fooBarTexts),
|
||||
],
|
||||
));
|
||||
|
||||
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(
|
||||
@ -207,9 +267,9 @@ void main() {
|
||||
],
|
||||
));
|
||||
|
||||
expect(find.descendant(
|
||||
of: find.widgetWithText(Row, 'foo'),
|
||||
matching: find.byType(Row),
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user