Commit 43190374 authored by Adam Barth's avatar Adam Barth

Merge pull request #1424 from abarth/consolidate_tests

Consolidate widget tests
parents b05d42c3 45251598
......@@ -10,7 +10,6 @@ library animation;
export 'src/animation/animated_simulation.dart';
export 'src/animation/animated_value.dart';
export 'src/animation/animation_performance.dart';
export 'src/animation/clamped_simulation.dart';
export 'src/animation/curves.dart';
export 'src/animation/forces.dart';
export 'src/animation/scheduler.dart';
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
void main() {
test('Events bubble up the tree', () {
WidgetTester tester = new WidgetTester();
List<String> log = new List<String>();
tester.pumpFrame(
new Listener(
onPointerDown: (_) {
log.add('top');
},
child: new Listener(
onPointerDown: (_) {
log.add('middle');
},
child: new DecoratedBox(
decoration: const BoxDecoration(),
child: new Listener(
onPointerDown: (_) {
log.add('bottom');
},
child: new Text('X')
)
)
)
)
);
tester.tap(tester.findText('X'));
expect(log, equals([
'bottom',
'middle',
'top',
]));
});
}
import 'dart:sky' as sky;
import 'package:sky/animation.dart';
import 'package:sky/rendering.dart';
import 'package:sky/src/fn3.dart';
import '../engine/mock_events.dart';
class RootComponent extends StatefulComponent {
RootComponentState createState() => new RootComponentState();
}
class RootComponentState extends State<RootComponent> {
Widget _child = new DecoratedBox(decoration: new BoxDecoration());
Widget get child => _child;
void set child(Widget value) {
if (value != _child) {
setState(() {
_child = value;
});
}
}
Widget build(BuildContext context) => child;
}
class WidgetTester {
// See thttps://github.com/flutter/engine/issues/1084 regarding frameTimeMs vs FakeAsync
void pumpFrame(Widget widget, [ double frameTimeMs = 0.0 ]) {
runApp(widget);
scheduler.beginFrame(frameTimeMs);
}
void pumpFrameWithoutChange([ double frameTimeMs = 0.0 ]) {
scheduler.beginFrame(frameTimeMs);
}
void reset() {
runApp(new Container());
scheduler.beginFrame(0.0);
}
List<Layer> _layers(Layer layer) {
List<Layer> result = [layer];
if (layer is ContainerLayer) {
ContainerLayer root = layer;
Layer child = root.firstChild;
while(child != null) {
result.addAll(_layers(child));
child = child.nextSibling;
}
}
return result;
}
List<Layer> get layers => _layers(FlutterBinding.instance.renderView.layer);
void walkElements(ElementVisitor visitor) {
void walk(Element element) {
visitor(element);
element.visitChildren(walk);
}
WidgetFlutterBinding.instance.renderViewElement.visitChildren(walk);
}
Element findElement(bool predicate(Element element)) {
try {
walkElements((Element element) {
if (predicate(element))
throw element;
});
} on Element catch (e) {
return e;
}
return null;
}
Element findElementByKey(Key key) {
return findElement((Element element) => element.widget.key == key);
}
Element findText(String text) {
return findElement((Element element) {
return element.widget is Text && element.widget.data == text;
});
}
State findStateOfType(Type type) {
StatefulComponentElement element = findElement((Element element) {
return element is StatefulComponentElement && element.state.runtimeType == type;
});
return element?.state;
}
State findStateByConfig(Widget config) {
StatefulComponentElement element = findElement((Element element) {
return element is StatefulComponentElement && element.state.config == config;
});
return element?.state;
}
Point getCenter(Element element) {
return _getElementPoint(element, (Size size) => size.center(Point.origin));
}
Point getTopLeft(Element element) {
return _getElementPoint(element, (_) => Point.origin);
}
Point getTopRight(Element element) {
return _getElementPoint(element, (Size size) => size.topRight(Point.origin));
}
Point getBottomLeft(Element element) {
return _getElementPoint(element, (Size size) => size.bottomLeft(Point.origin));
}
Point getBottomRight(Element element) {
return _getElementPoint(element, (Size size) => size.bottomRight(Point.origin));
}
Point _getElementPoint(Element element, Function sizeToPoint) {
assert(element != null);
RenderBox box = element.renderObject as RenderBox;
assert(box != null);
return box.localToGlobal(sizeToPoint(box.size));
}
void tap(Element element, { int pointer: 1 }) {
tapAt(getCenter(element), pointer: pointer);
}
void tapAt(Point location, { int pointer: 1 }) {
HitTestResult result = _hitTest(location);
TestPointer p = new TestPointer(pointer);
_dispatchEvent(p.down(location), result);
_dispatchEvent(p.up(), result);
}
void scroll(Element element, Offset offset, { int pointer: 1 }) {
Point startLocation = getCenter(element);
Point endLocation = startLocation + offset;
TestPointer p = new TestPointer(pointer);
// Events for the entire press-drag-release gesture are dispatched
// to the widgets "hit" by the pointer down event.
HitTestResult result = _hitTest(startLocation);
_dispatchEvent(p.down(startLocation), result);
_dispatchEvent(p.move(endLocation), result);
_dispatchEvent(p.up(), result);
}
void dispatchEvent(sky.Event event, Point location) {
_dispatchEvent(event, _hitTest(location));
}
HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location);
void _dispatchEvent(sky.Event event, HitTestResult result) {
WidgetFlutterBinding.instance.dispatchEvent(event, result);
}
}
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Align smoke test', () {
......
......@@ -2,7 +2,7 @@ import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
final Key blockKey = new Key('test');
......
......@@ -2,7 +2,7 @@ import 'package:sky/material.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Circles can have uniform borders', () {
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import '../fn3/test_widgets.dart';
import 'widget_tester.dart';
import 'test_widgets.dart';
class ProbeWidget extends StatefulComponent {
ProbeWidgetState createState() => new ProbeWidgetState();
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Can be placed in an infinte box', () {
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Can select a day', () {
......
......@@ -3,7 +3,7 @@ import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
const double itemExtent = 100.0;
ScrollDirection scrollDirection = ScrollDirection.vertical;
......
......@@ -2,7 +2,7 @@ import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Drag and drop - control test', () {
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
class Item {
GlobalKey key1 = new GlobalKey();
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Can hit test flex children of stacks', () {
......
......@@ -2,7 +2,7 @@ import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Uncontested scrolls start immediately', () {
......
......@@ -5,7 +5,7 @@ import 'package:sky/services.dart';
import 'package:sky/widgets_next.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
import '../services/mock_services.dart';
class MockKeyboard implements KeyboardService {
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Events bubble up the tree', () {
......
......@@ -2,7 +2,7 @@ import 'package:sky/animation.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
class FirstComponent extends StatelessComponent {
FirstComponent(this.navigator);
......
......@@ -2,7 +2,7 @@ import 'package:quiver/testing/async.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
const Size pageSize = const Size(800.0, 600.0);
const List<int> pages = const <int>[0, 1, 2, 3, 4, 5];
......
......@@ -3,7 +3,7 @@ import 'package:sky/rendering.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('LinearProgressIndicator changes when its value changes', () {
......
......@@ -2,7 +2,7 @@ import 'package:sky/rendering.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
const List<int> items = const <int>[0, 1, 2, 3, 4, 5];
List<int> tapped = <int>[];
......
......@@ -2,7 +2,7 @@ import 'package:sky/rendering.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
const List<int> items = const <int>[0, 1, 2, 3, 4, 5];
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
const List<int> items = const <int>[0, 1, 2, 3, 4, 5];
......
......@@ -5,7 +5,7 @@
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
ChangerState changer;
......
......@@ -2,7 +2,7 @@ import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
class Inside extends StatefulComponent {
InsideState createState() => new InsideState();
......
......@@ -8,7 +8,7 @@ import 'package:quiver/testing/async.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
const double itemExtent = 200.0;
ScrollDirection scrollDirection = ScrollDirection.vertical;
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Can change position data', () {
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
class InnerComponent extends StatefulComponent {
InnerComponent({ Key key }) : super(key: key);
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
class TestWidget extends StatefulComponent {
TestWidget({ this.child, this.persistentState, this.syncedState });
......
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../fn3/widget_tester.dart';
import 'widget_tester.dart';
void main() {
test('Transform origin', () {
......
......@@ -2,36 +2,44 @@ import 'dart:sky' as sky;
import 'package:sky/animation.dart';
import 'package:sky/rendering.dart';
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import '../engine/mock_events.dart';
typedef Widget WidgetBuilder();
class TestApp extends App {
class RootComponent extends StatefulComponent {
RootComponentState createState() => new RootComponentState();
}
WidgetBuilder _builder;
void set builder (WidgetBuilder value) {
class RootComponentState extends State<RootComponent> {
Widget _child = new DecoratedBox(decoration: new BoxDecoration());
Widget get child => _child;
void set child(Widget value) {
if (value != _child) {
setState(() {
_builder = value;
_child = value;
});
}
Widget build() {
if (_builder != null)
return _builder();
return new Container();
}
Widget build(BuildContext context) => child;
}
class WidgetTester {
WidgetTester() {
_app = new TestApp();
runApp(_app);
scheduler.beginFrame(0.0); // to initialise the app
// See thttps://github.com/flutter/engine/issues/1084 regarding frameTimeMs vs FakeAsync
void pumpFrame(Widget widget, [ double frameTimeMs = 0.0 ]) {
runApp(widget);
scheduler.beginFrame(frameTimeMs);
}
void pumpFrameWithoutChange([ double frameTimeMs = 0.0 ]) {
scheduler.beginFrame(frameTimeMs);
}
TestApp _app;
void reset() {
runApp(new Container());
scheduler.beginFrame(0.0);
}
List<Layer> _layers(Layer layer) {
List<Layer> result = [layer];
......@@ -47,70 +55,81 @@ class WidgetTester {
}
List<Layer> get layers => _layers(FlutterBinding.instance.renderView.layer);
void walkWidgets(WidgetTreeWalker walker) {
void walk(Widget widget) {
walker(widget);
widget.walkChildren(walk);
}
_app.walkChildren(walk);
void walkElements(ElementVisitor visitor) {
void walk(Element element) {
visitor(element);
element.visitChildren(walk);
}
WidgetFlutterBinding.instance.renderViewElement.visitChildren(walk);
}
Widget findWidget(bool predicate(Widget widget)) {
Element findElement(bool predicate(Element element)) {
try {
walkWidgets((Widget widget) {
if (predicate(widget))
throw widget;
walkElements((Element element) {
if (predicate(element))
throw element;
});
} catch (e) {
if (e is Widget)
} on Element catch (e) {
return e;
rethrow;
}
return null;
}
Text findText(String text) {
return findWidget((Widget widget) {
return widget is Text && widget.data == text;
Element findElementByKey(Key key) {
return findElement((Element element) => element.widget.key == key);
}
Element findText(String text) {
return findElement((Element element) {
return element.widget is Text && element.widget.data == text;
});
}
Point _getWidgetPoint(Widget widget, Function sizeToPoint) {
assert(widget != null);
RenderBox box = widget.renderObject as RenderBox;
assert(box != null);
return box.localToGlobal(sizeToPoint(box.size));
State findStateOfType(Type type) {
StatefulComponentElement element = findElement((Element element) {
return element is StatefulComponentElement && element.state.runtimeType == type;
});
return element?.state;
}
Point getCenter(Widget widget) {
return _getWidgetPoint(widget, (Size size) => size.center(Point.origin));
State findStateByConfig(Widget config) {
StatefulComponentElement element = findElement((Element element) {
return element is StatefulComponentElement && element.state.config == config;
});
return element?.state;
}
Point getTopLeft(Widget widget) {
return _getWidgetPoint(widget, (_) => Point.origin);
Point getCenter(Element element) {
return _getElementPoint(element, (Size size) => size.center(Point.origin));
}
Point getTopRight(Widget widget) {
return _getWidgetPoint(widget, (Size size) => size.topRight(Point.origin));
Point getTopLeft(Element element) {
return _getElementPoint(element, (_) => Point.origin);
}
Point getBottomLeft(Widget widget) {
return _getWidgetPoint(widget, (Size size) => size.bottomLeft(Point.origin));
Point getTopRight(Element element) {
return _getElementPoint(element, (Size size) => size.topRight(Point.origin));
}
Point getBottomRight(Widget widget) {
return _getWidgetPoint(widget, (Size size) => size.bottomRight(Point.origin));
Point getBottomLeft(Element element) {
return _getElementPoint(element, (Size size) => size.bottomLeft(Point.origin));
}
HitTestResult _hitTest(Point location) => FlutterBinding.instance.hitTest(location);
Point getBottomRight(Element element) {
return _getElementPoint(element, (Size size) => size.bottomRight(Point.origin));
}
void _dispatchEvent(sky.Event event, HitTestResult result) {
FlutterBinding.instance.dispatchEvent(event, result);
Point _getElementPoint(Element element, Function sizeToPoint) {
assert(element != null);
RenderBox box = element.renderObject as RenderBox;
assert(box != null);
return box.localToGlobal(sizeToPoint(box.size));
}
void tap(Widget widget, { int pointer: 1 }) {
tapAt(getCenter(widget), pointer: pointer);
void tap(Element element, { int pointer: 1 }) {
tapAt(getCenter(element), pointer: pointer);
}
void tapAt(Point location, { int pointer: 1 }) {
......@@ -120,8 +139,8 @@ class WidgetTester {
_dispatchEvent(p.up(), result);
}
void scroll(Widget widget, Offset offset, { int pointer: 1 }) {
Point startLocation = getCenter(widget);
void scroll(Element element, Offset offset, { int pointer: 1 }) {
Point startLocation = getCenter(element);
Point endLocation = startLocation + offset;
TestPointer p = new TestPointer(pointer);
// Events for the entire press-drag-release gesture are dispatched
......@@ -136,13 +155,10 @@ class WidgetTester {
_dispatchEvent(event, _hitTest(location));
}
void pumpFrame(WidgetBuilder builder, [double frameTimeMs = 0.0]) {
_app.builder = builder;
scheduler.beginFrame(frameTimeMs);
}
HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location);
void pumpFrameWithoutChange([double frameTimeMs = 0.0]) {
scheduler.beginFrame(frameTimeMs);
void _dispatchEvent(sky.Event event, HitTestResult result) {
WidgetFlutterBinding.instance.dispatchEvent(event, result);
}
}
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