Commit c167efca authored by Ian Hickson's avatar Ian Hickson

Minor widget_tester refactoring and docs (#3472)

This reorders some classes so that this file makes more sense, and adds
a bunch of docs. It also makes the following changes:

* Move allElements from Instrumentation to TestWidgets. (Instrumentation
  is going away.)

* Remove findElements.

* Rename byElement to byElementPredicate

* Rename byPredicate to byWidgetPredicate

* Implement _WidgetPredicateFinder so that byWidgetPredicate has good
  messages

* Fix one use of byElementPredicate to use byWidgetPredicate.
parent 31d199b0
......@@ -15,8 +15,7 @@ void main() {
tester.pump(); // see https://github.com/flutter/flutter/issues/1865
tester.pump(); // triggers a frame
Finder navigationMenu = find.byElement((Element element) {
Widget widget = element.widget;
Finder navigationMenu = find.byWidgetPredicate((Widget widget) {
if (widget is Tooltip)
return widget.message == 'Open navigation menu';
return false;
......
......@@ -14,14 +14,14 @@ import '../lib/gallery/item.dart' as material_gallery;
const List<String> demoCategories = const <String>['Demos', 'Components', 'Style'];
Finder findGalleryItemByRouteName(WidgetTester tester, String routeName) {
return find.byPredicate((Widget widget) {
return find.byWidgetPredicate((Widget widget) {
return widget is material_gallery.GalleryItem
&& widget.routeName == routeName;
});
}
Finder byTooltip(WidgetTester tester, String message) {
return find.byPredicate((Widget widget) {
return find.byWidgetPredicate((Widget widget) {
return widget is Tooltip && widget.message == message;
});
}
......
......@@ -10,8 +10,9 @@ import 'package:test/test.dart';
import 'test_widgets.dart';
void checkTree(WidgetTester tester, List<BoxDecoration> expectedDecorations) {
MultiChildRenderObjectElement element =
tester.elementOf(find.byElement((Element element) => element is MultiChildRenderObjectElement));
MultiChildRenderObjectElement element = tester.elementOf(find.byElementPredicate(
(Element element) => element is MultiChildRenderObjectElement
));
expect(element, isNotNull);
expect(element.renderObject is RenderStack, isTrue);
RenderStack renderObject = element.renderObject;
......
......@@ -19,8 +19,9 @@ class TestParentData {
}
void checkTree(WidgetTester tester, List<TestParentData> expectedParentData) {
MultiChildRenderObjectElement element =
tester.elementOf(find.byElement((Element element) => element is MultiChildRenderObjectElement));
MultiChildRenderObjectElement element = tester.elementOf(
find.byElementPredicate((Element element) => element is MultiChildRenderObjectElement)
);
expect(element, isNotNull);
expect(element.renderObject is RenderStack, isTrue);
RenderStack renderObject = element.renderObject;
......
......@@ -14,8 +14,9 @@ void main() {
testWidgets((WidgetTester tester) {
void checkTree(BoxDecoration expectedDecoration) {
SingleChildRenderObjectElement element =
tester.elementOf(find.byElement((Element element) => element is SingleChildRenderObjectElement));
SingleChildRenderObjectElement element = tester.elementOf(
find.byElementPredicate((Element element) => element is SingleChildRenderObjectElement)
);
expect(element, isNotNull);
expect(element.renderObject is RenderDecoratedBox, isTrue);
RenderDecoratedBox renderObject = element.renderObject;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:collection';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
......@@ -63,20 +61,6 @@ class Instrumentation {
return null;
}
/// Returns all elements ordered in a depth-first traversal fashion.
///
/// The returned iterable is lazy. It does not walk the entire element tree
/// immediately, but rather a chunk at a time as the iteration progresses
/// using [Iterator.moveNext].
Iterable<Element> get allElements {
return new _DepthFirstChildIterable(binding.renderViewElement);
}
/// Returns all elements that satisfy [predicate].
Iterable<Element> findElements(bool predicate(Element element)) {
return allElements.where(predicate);
}
/// Returns the first element that corresponds to a widget with the
/// given [Key], or null if there is no such element.
Element findElementByKey(Key key) {
......@@ -248,42 +232,3 @@ class Instrumentation {
return result;
}
}
class _DepthFirstChildIterable extends IterableBase<Element> {
_DepthFirstChildIterable(this.rootElement);
Element rootElement;
@override
Iterator<Element> get iterator => new _DepthFirstChildIterator(rootElement);
}
class _DepthFirstChildIterator implements Iterator<Element> {
_DepthFirstChildIterator(Element rootElement)
: _stack = _reverseChildrenOf(rootElement).toList();
Element _current;
final List<Element> _stack;
@override
Element get current => _current;
@override
bool moveNext() {
if (_stack.isEmpty)
return false;
_current = _stack.removeLast();
// Stack children in reverse order to traverse first branch first
_stack.addAll(_reverseChildrenOf(_current));
return true;
}
static Iterable<Element> _reverseChildrenOf(Element element) {
List<Element> children = <Element>[];
element.visitChildren(children.add);
return children.reversed;
}
}
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