Unverified Commit 0f4ea504 authored by xster's avatar xster Committed by GitHub

Correctly chain finders to ancestor/descendant finders (#20601)

parent 28bc8180
......@@ -86,7 +86,7 @@ double getHintOpacity(WidgetTester tester) {
find.ancestor(
of: find.text('hint'),
matching: find.byType(FadeTransition),
).last
).first
);
return opacityWidget.opacity.value;
}
......
......@@ -375,38 +375,55 @@ abstract class Finder {
}
}
class _FirstFinder extends Finder {
_FirstFinder(this.parent);
/// Applies additional filtering against a [parent] [Finder].
abstract class ChainedFinder extends Finder {
/// Create a Finder chained against the candidates of another [Finder].
ChainedFinder(this.parent) : assert(parent != null);
/// Another [Finder] that will run first.
final Finder parent;
/// Return another [Iterable] when given an [Iterable] of candidates from a
/// parent [Finder].
///
/// This is the method to implement when subclassing [ChainedFinder].
Iterable<Element> filter(Iterable<Element> parentCandidates);
@override
Iterable<Element> apply(Iterable<Element> candidates) {
return filter(parent.apply(candidates));
}
@override
Iterable<Element> get allCandidates => parent.allCandidates;
}
class _FirstFinder extends ChainedFinder {
_FirstFinder(Finder parent) : super(parent);
@override
String get description => '${parent.description} (ignoring all but first)';
@override
Iterable<Element> apply(Iterable<Element> candidates) sync* {
yield parent.apply(candidates).first;
Iterable<Element> filter(Iterable<Element> parentCandidates) sync* {
yield parentCandidates.first;
}
}
class _LastFinder extends Finder {
_LastFinder(this.parent);
final Finder parent;
class _LastFinder extends ChainedFinder {
_LastFinder(Finder parent) : super(parent);
@override
String get description => '${parent.description} (ignoring all but last)';
@override
Iterable<Element> apply(Iterable<Element> candidates) sync* {
yield parent.apply(candidates).last;
Iterable<Element> filter(Iterable<Element> parentCandidates) sync* {
yield parentCandidates.last;
}
}
class _IndexFinder extends Finder {
_IndexFinder(this.parent, this.index);
final Finder parent;
class _IndexFinder extends ChainedFinder {
_IndexFinder(Finder parent, this.index) : super(parent);
final int index;
......@@ -414,23 +431,22 @@ class _IndexFinder extends Finder {
String get description => '${parent.description} (ignoring all but index $index)';
@override
Iterable<Element> apply(Iterable<Element> candidates) sync* {
yield parent.apply(candidates).elementAt(index);
Iterable<Element> filter(Iterable<Element> parentCandidates) sync* {
yield parentCandidates.elementAt(index);
}
}
class _HitTestableFinder extends Finder {
_HitTestableFinder(this.parent, this.alignment);
class _HitTestableFinder extends ChainedFinder {
_HitTestableFinder(Finder parent, this.alignment) : super(parent);
final Finder parent;
final Alignment alignment;
@override
String get description => '${parent.description} (considering only hit-testable ones)';
@override
Iterable<Element> apply(Iterable<Element> candidates) sync* {
for (final Element candidate in parent.apply(candidates)) {
Iterable<Element> filter(Iterable<Element> parentCandidates) sync* {
for (final Element candidate in parentCandidates) {
final RenderBox box = candidate.renderObject;
assert(box != null);
final Offset absoluteOffset = box.localToGlobal(alignment.alongSize(box.size));
......
......@@ -56,6 +56,34 @@ void main() {
expect(tester.widget(hitTestable).key, const ValueKey<int>(0));
});
});
testWidgets('ChainedFinders chain properly', (WidgetTester tester) async {
final GlobalKey key1 = new GlobalKey();
await tester.pumpWidget(
_boilerplate(new Column(
children: <Widget>[
new Container(
key: key1,
child: const Text('1'),
),
new Container(
child: const Text('2'),
)
],
)),
);
// Get the text back. By correctly chaining the descendant finder's
// candidates, it should find 1 instead of 2. If the _LastFinder wasn't
// correctly chained after the descendant's candidates, the last element
// with a Text widget would have been 2.
final Text text = find.descendant(
of: find.byKey(key1),
matching: find.byType(Text),
).last.evaluate().single.widget;
expect(text.data, '1');
});
}
Widget _boilerplate(Widget child) {
......
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