Commit 06ffa759 authored by Adam Barth's avatar Adam Barth

Convert some tests to fn3

parent b5893f9e
......@@ -153,6 +153,7 @@ class FocusState extends State<Focus> {
}
void initState(BuildContext context) {
super.initState(context);
if (config.autofocus)
FocusState._moveScopeTo(context, config);
_updateWidgetRemovalListener(_focusedWidget);
......
......@@ -631,9 +631,9 @@ abstract class BuildableElement<T extends Widget> extends Element<T> {
/// binding when scheduleBuild() has been called to mark this element dirty,
/// and by update() when the Widget has changed.
void rebuild() {
assert(_debugLifecycleState == _ElementLifecycle.mounted);
if (!_dirty)
return;
assert(_debugLifecycleState == _ElementLifecycle.mounted);
_dirty = false;
Widget built;
try {
......@@ -731,7 +731,12 @@ class StatefulComponentElement extends BuildableElement<StatefulComponent> {
_state._config = widget;
assert(_state._debugLifecycleState == _StateLifecycle.created);
_state.initState(this);
assert(_state._debugLifecycleState == _StateLifecycle.initialized);
assert(() {
if (_state._debugLifecycleState == _StateLifecycle.initialized)
return true;
print('${_state.runtimeType}.initState failed to call super.initState');
return false;
});
assert(() { _state._debugLifecycleState = _StateLifecycle.ready; return true; });
_builder = _state.build;
}
......
......@@ -6,7 +6,7 @@ import 'package:sky/src/fn3.dart';
import '../engine/mock_events.dart';
class RootComponent extends StatefulComponent {
RootComponentState createState() => new RootComponentState(this);
RootComponentState createState() => new RootComponentState();
}
class RootComponentState extends State<RootComponent> {
......@@ -24,13 +24,13 @@ class RootComponentState extends State<RootComponent> {
class WidgetTester {
void pumpFrame(Widget widget) {
void pumpFrame(Widget widget, [ double frameTimeMs = 0.0 ]) {
runApp(widget);
WidgetFlutterBinding.instance.beginFrame(0.0); // TODO(ianh): https://github.com/flutter/engine/issues/1084
WidgetFlutterBinding.instance.beginFrame(frameTimeMs); // TODO(ianh): https://github.com/flutter/engine/issues/1084
}
void pumpFrameWithoutChange() {
WidgetFlutterBinding.instance.beginFrame(0.0); // TODO(ianh): https://github.com/flutter/engine/issues/1084
void pumpFrameWithoutChange([ double frameTimeMs = 0.0 ]) {
WidgetFlutterBinding.instance.beginFrame(frameTimeMs); // TODO(ianh): https://github.com/flutter/engine/issues/1084
}
......@@ -64,6 +64,12 @@ class WidgetTester {
});
}
State findStateOfType(Type type) {
StatefulComponentElement element = findElement((Element element) {
return element is StatefulComponentElement && element.state.runtimeType == type;
});
return element?.state;
}
Point getCenter(Element element) {
return _getElementPoint(element, (Size size) => size.center(Point.origin));
......
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Align smoke test', () {
WidgetTester tester = new WidgetTester();
tester.pumpFrame(() {
return new Align(
tester.pumpFrame(
new Align(
child: new Container(),
horizontal: 0.75,
vertical: 0.75
);
});
)
);
tester.pumpFrame(() {
return new Align(
tester.pumpFrame(
new Align(
child: new Container(),
horizontal: 0.5,
vertical: 0.5
);
});
)
);
});
}
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
final Key blockKey = new Key('test');
......@@ -10,19 +10,19 @@ void main() {
test('Cannot scroll a non-overflowing block', () {
WidgetTester tester = new WidgetTester();
tester.pumpFrame(() {
return new Block([
tester.pumpFrame(
new Block([
new Container(
height: 200.0, // less than 600, the height of the test area
child: new Text('Hello')
)
],
key: blockKey);
});
key: blockKey)
);
tester.pumpFrameWithoutChange(); // for SizeObservers
Point middleOfContainer = tester.getCenter(tester.findText('Hello'));
Point target = tester.getCenter(tester.findWidget((widget) => widget.key == blockKey));
Point target = tester.getCenter(tester.findElementByKey(blockKey));
TestPointer pointer = new TestPointer();
tester.dispatchEvent(pointer.down(target), target);
tester.dispatchEvent(pointer.move(target + const Offset(0.0, -10.0)), target);
......@@ -37,19 +37,19 @@ void main() {
test('Can scroll an overflowing block', () {
WidgetTester tester = new WidgetTester();
tester.pumpFrame(() {
return new Block([
tester.pumpFrame(
new Block([
new Container(
height: 2000.0, // more than 600, the height of the test area
child: new Text('Hello')
)
],
key: blockKey);
});
key: blockKey)
);
tester.pumpFrameWithoutChange(); // for SizeObservers
Point middleOfContainer = tester.getCenter(tester.findText('Hello'));
Point target = tester.getCenter(tester.findWidget((widget) => widget.key == blockKey));
Point target = tester.getCenter(tester.findElementByKey(blockKey));
TestPointer pointer = new TestPointer();
tester.dispatchEvent(pointer.down(target), target);
tester.dispatchEvent(pointer.move(target + const Offset(0.0, -10.0)), target);
......
import 'package:sky/material.dart';
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Circles can have uniform borders', () {
WidgetTester tester = new WidgetTester();
tester.pumpFrame(() {
return new Container(
tester.pumpFrame(
new Container(
padding: new EdgeDims.all(50.0),
decoration: new BoxDecoration(
shape: Shape.circle,
border: new Border.all(width: 10.0, color: const Color(0x80FF00FF)),
backgroundColor: Colors.teal[600]
)
);
});
)
);
});
}
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Can be placed in an infinte box', () {
WidgetTester tester = new WidgetTester();
tester.pumpFrame(() {
return new Block([new Center()]);
});
tester.pumpFrame(new Block([new Center()]));
});
}
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Can select a day', () {
......@@ -9,26 +9,24 @@ void main() {
DateTime currentValue;
Widget builder() {
return new Block([
new DatePicker(
selectedDate: new DateTime.utc(2015, 6, 9, 7, 12),
firstDate: new DateTime.utc(2013),
lastDate: new DateTime.utc(2018),
onChanged: (DateTime dateTime) {
currentValue = dateTime;
}
)
]);
}
Widget widget = new Block([
new DatePicker(
selectedDate: new DateTime.utc(2015, 6, 9, 7, 12),
firstDate: new DateTime.utc(2013),
lastDate: new DateTime.utc(2018),
onChanged: (DateTime dateTime) {
currentValue = dateTime;
}
)
]);
tester.pumpFrame(builder);
tester.pumpFrame(widget);
expect(currentValue, isNull);
tester.tap(tester.findText('2015'));
tester.pumpFrame(builder);
tester.pumpFrame(widget);
tester.tap(tester.findText('2014'));
tester.pumpFrame(builder);
tester.pumpFrame(widget);
expect(currentValue, equals(new DateTime(2014, 6, 9)));
tester.tap(tester.findText('30'));
expect(currentValue, equals(new DateTime(2013, 1, 30)));
......
import 'package:sky/src/widgets/framework.dart';
import 'package:sky/src/widgets/basic.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
class Item {
GlobalKey key1 = new GlobalKey();
......@@ -12,15 +12,18 @@ List<Item> items = [new Item(), new Item()];
class StatefulLeaf extends StatefulComponent {
StatefulLeaf({ GlobalKey key }) : super(key: key);
void syncConstructorArguments(StatefulLeaf source) { }
StatefulLeafState createState() => new StatefulLeafState();
}
class StatefulLeafState extends State<StatefulLeaf> {
void test() { setState(() { }); }
Widget build() => new Text('leaf');
Widget build(BuildContext context) => new Text('leaf');
}
class KeyedWrapper extends Component {
class KeyedWrapper extends StatelessComponent {
KeyedWrapper(this.key1, this.key2);
Key key1, key2;
Widget build() {
Widget build(BuildContext context) {
return new Container(
key: key1,
child: new StatefulLeaf(
......@@ -40,13 +43,13 @@ Widget builder() {
void main() {
test('duplicate key smoke test', () {
WidgetTester tester = new WidgetTester();
tester.pumpFrame(builder);
StatefulLeaf leaf = tester.findWidget((widget) => widget is StatefulLeaf);
tester.pumpFrame(builder());
StatefulLeafState leaf = tester.findStateOfType(StatefulLeafState);
leaf.test();
tester.pumpFrameWithoutChange();
Item lastItem = items[1];
items.remove(lastItem);
items.insert(0, lastItem);
tester.pumpFrame(builder); // this marks the app dirty and rebuilds it
tester.pumpFrame(builder()); // this marks the app dirty and rebuilds it
});
}
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Can hit test flex children of stacks', () {
WidgetTester tester = new WidgetTester();
bool didReceiveTap = false;
tester.pumpFrame(() {
return new Container(
tester.pumpFrame(
new Container(
decoration: const BoxDecoration(
backgroundColor: const Color(0xFF00FF00)
),
......@@ -36,8 +36,8 @@ void main() {
])
)
])
);
});
)
);
tester.tap(tester.findText('X'));
expect(didReceiveTap, isTrue);
......
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import '../engine/mock_events.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Uncontested scrolls start immediately', () {
......@@ -13,22 +13,20 @@ void main() {
double updatedDragDelta;
bool didEndDrag = false;
Widget builder() {
return new GestureDetector(
onVerticalDragStart: () {
didStartDrag = true;
},
onVerticalDragUpdate: (double scrollDelta) {
updatedDragDelta = scrollDelta;
},
onVerticalDragEnd: (Offset velocity) {
didEndDrag = true;
},
child: new Container()
);
}
tester.pumpFrame(builder);
Widget widget = new GestureDetector(
onVerticalDragStart: () {
didStartDrag = true;
},
onVerticalDragUpdate: (double scrollDelta) {
updatedDragDelta = scrollDelta;
},
onVerticalDragEnd: (Offset velocity) {
didEndDrag = true;
},
child: new Container()
);
tester.pumpFrame(widget);
expect(didStartDrag, isFalse);
expect(updatedDragDelta, isNull);
expect(didEndDrag, isFalse);
......@@ -53,7 +51,7 @@ void main() {
expect(didEndDrag, isTrue);
didEndDrag = false;
tester.pumpFrame(() => new Container());
tester.pumpFrame(new Container());
});
test('Match two scroll gestures in succession', () {
......@@ -66,16 +64,14 @@ void main() {
Point downLocation = new Point(10.0, 10.0);
Point upLocation = new Point(10.0, 20.0);
Widget builder() {
return new GestureDetector(
onVerticalDragUpdate: (double delta) { dragDistance += delta; },
onVerticalDragEnd: (Offset velocity) { gestureCount += 1; },
onHorizontalDragUpdate: (_) { fail("gesture should not match"); },
onHorizontalDragEnd: (Offset velocity) { fail("gesture should not match"); },
child: new Container()
);
}
tester.pumpFrame(builder);
Widget widget = new GestureDetector(
onVerticalDragUpdate: (double delta) { dragDistance += delta; },
onVerticalDragEnd: (Offset velocity) { gestureCount += 1; },
onHorizontalDragUpdate: (_) { fail("gesture should not match"); },
onHorizontalDragEnd: (Offset velocity) { fail("gesture should not match"); },
child: new Container()
);
tester.pumpFrame(widget);
tester.dispatchEvent(pointer.down(downLocation), downLocation);
tester.dispatchEvent(pointer.move(upLocation), downLocation);
......@@ -87,5 +83,7 @@ void main() {
expect(gestureCount, 2);
expect(dragDistance, 20.0);
tester.pumpFrame(new Container());
});
}
import 'package:sky/widgets.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
class TestComponent extends StatefulComponent {
TestComponent(this.viewport);
HomogeneousViewport viewport;
void syncConstructorArguments(TestComponent source) {
viewport = source.viewport;
}
bool _flag = true;
void go(bool flag) {
setState(() {
_flag = flag;
});
}
Widget build() {
return _flag ? viewport : new Text('Not Today');
}
}
void main() {
test('HomogeneousViewport mount/dismount smoke test', () {
WidgetTester tester = new WidgetTester();
List<int> callbackTracker = <int>[];
// the root view is 800x600 in the test environment
// so if our widget is 100 pixels tall, it should fit exactly 6 times.
TestComponent testComponent;
Widget builder() {
testComponent = new TestComponent(new HomogeneousViewport(
builder: (int start, int count) {
List<Widget> result = <Widget>[];
for (int index = start; index < start + count; index += 1) {
callbackTracker.add(index);
result.add(new Container(
key: new ValueKey<int>(index),
height: 100.0,
child: new Text("$index")
));
}
return result;
},
startOffset: 0.0,
itemExtent: 100.0
));
return testComponent;
}
tester.pumpFrame(builder);
expect(callbackTracker, equals([0, 1, 2, 3, 4, 5]));
callbackTracker.clear();
testComponent.go(false);
tester.pumpFrameWithoutChange();
expect(callbackTracker, equals([]));
callbackTracker.clear();
testComponent.go(true);
tester.pumpFrameWithoutChange();
expect(callbackTracker, equals([0, 1, 2, 3, 4, 5]));
});
test('HomogeneousViewport vertical', () {
WidgetTester tester = new WidgetTester();
List<int> callbackTracker = <int>[];
// the root view is 800x600 in the test environment
// so if our widget is 200 pixels tall, it should fit exactly 3 times.
// but if we are offset by 300 pixels, there will be 4, numbered 1-4.
double offset = 300.0;
ListBuilder itemBuilder = (int start, int count) {
List<Widget> result = <Widget>[];
for (int index = start; index < start + count; index += 1) {
callbackTracker.add(index);
result.add(new Container(
key: new ValueKey<int>(index),
width: 500.0, // this should be ignored
height: 400.0, // should be overridden by itemExtent
child: new Text("$index")
));
}
return result;
};
TestComponent testComponent;
Widget builder() {
testComponent = new TestComponent(new HomogeneousViewport(
builder: itemBuilder,
startOffset: offset,
itemExtent: 200.0
));
return testComponent;
}
tester.pumpFrame(builder);
expect(callbackTracker, equals([1, 2, 3, 4]));
callbackTracker.clear();
offset = 400.0; // now only 3 should fit, numbered 2-4.
tester.pumpFrame(builder);
expect(callbackTracker, equals([2, 3, 4]));
callbackTracker.clear();
});
test('HomogeneousViewport horizontal', () {
WidgetTester tester = new WidgetTester();
List<int> callbackTracker = <int>[];
// the root view is 800x600 in the test environment
// so if our widget is 200 pixels wide, it should fit exactly 4 times.
// but if we are offset by 300 pixels, there will be 5, numbered 1-5.
double offset = 300.0;
ListBuilder itemBuilder = (int start, int count) {
List<Widget> result = <Widget>[];
for (int index = start; index < start + count; index += 1) {
callbackTracker.add(index);
result.add(new Container(
key: new ValueKey<int>(index),
width: 400.0, // this should be overridden by itemExtent
height: 500.0, // this should be ignored
child: new Text("$index")
));
}
return result;
};
TestComponent testComponent;
Widget builder() {
testComponent = new TestComponent(new HomogeneousViewport(
builder: itemBuilder,
startOffset: offset,
itemExtent: 200.0,
direction: ScrollDirection.horizontal
));
return testComponent;
}
tester.pumpFrame(builder);
expect(callbackTracker, equals([1, 2, 3, 4, 5]));
callbackTracker.clear();
offset = 400.0; // now only 4 should fit, numbered 2-5.
tester.pumpFrame(builder);
expect(callbackTracker, equals([2, 3, 4, 5]));
callbackTracker.clear();
});
}
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
void main() {
test('Events bubble up the tree', () {
......@@ -9,8 +9,8 @@ void main() {
List<String> log = new List<String>();
tester.pumpFrame(() {
return new Listener(
tester.pumpFrame(
new Listener(
onPointerDown: (_) {
log.add('top');
},
......@@ -28,8 +28,8 @@ void main() {
)
)
)
);
});
)
);
tester.tap(tester.findText('X'));
......
import 'package:sky/widgets.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
class TestComponent extends StatefulComponent {
TestComponent(this.viewport);
MixedViewport viewport;
void syncConstructorArguments(TestComponent source) {
viewport = source.viewport;
}
bool _flag = true;
void go(bool flag) {
setState(() {
_flag = flag;
});
}
Widget build() {
return _flag ? viewport : new Text('Not Today');
}
}
void main() {
test('MixedViewport mount/dismount smoke test', () {
WidgetTester tester = new WidgetTester();
MixedViewportLayoutState layoutState = new MixedViewportLayoutState();
List<int> callbackTracker = <int>[];
// the root view is 800x600 in the test environment
// so if our widget is 100 pixels tall, it should fit exactly 6 times.
TestComponent testComponent;
Widget builder() {
testComponent = new TestComponent(new MixedViewport(
builder: (int i) {
callbackTracker.add(i);
return new Container(
key: new ValueKey<int>(i),
height: 100.0,
child: new Text("$i")
);
},
startOffset: 0.0,
layoutState: layoutState
));
return testComponent;
}
tester.pumpFrame(builder);
expect(callbackTracker, equals([0, 1, 2, 3, 4, 5]));
callbackTracker.clear();
testComponent.go(false);
tester.pumpFrameWithoutChange();
expect(callbackTracker, equals([]));
callbackTracker.clear();
testComponent.go(true);
tester.pumpFrameWithoutChange();
expect(callbackTracker, equals([0, 1, 2, 3, 4, 5]));
});
test('MixedViewport vertical', () {
WidgetTester tester = new WidgetTester();
MixedViewportLayoutState layoutState = new MixedViewportLayoutState();
List<int> callbackTracker = <int>[];
// the root view is 800x600 in the test environment
// so if our widget is 200 pixels tall, it should fit exactly 3 times.
// but if we are offset by 300 pixels, there will be 4, numbered 1-4.
double offset = 300.0;
IndexedBuilder itemBuilder = (int i) {
callbackTracker.add(i);
return new Container(
key: new ValueKey<int>(i),
width: 500.0, // this should be ignored
height: 200.0,
child: new Text("$i")
);
};
TestComponent testComponent;
Widget builder() {
testComponent = new TestComponent(new MixedViewport(
builder: itemBuilder,
startOffset: offset,
layoutState: layoutState
));
return testComponent;
}
tester.pumpFrame(builder);
// 0 is built to find its width
expect(callbackTracker, equals([0, 1, 2, 3, 4]));
callbackTracker.clear();
offset = 400.0; // now only 3 should fit, numbered 2-4.
tester.pumpFrame(builder);
// 0 and 1 aren't built, we know their size and nothing else changed
expect(callbackTracker, equals([2, 3, 4]));
callbackTracker.clear();
});
test('MixedViewport horizontal', () {
WidgetTester tester = new WidgetTester();
MixedViewportLayoutState layoutState = new MixedViewportLayoutState();
List<int> callbackTracker = <int>[];
// the root view is 800x600 in the test environment
// so if our widget is 200 pixels wide, it should fit exactly 4 times.
// but if we are offset by 300 pixels, there will be 5, numbered 1-5.
double offset = 300.0;
IndexedBuilder itemBuilder = (int i) {
callbackTracker.add(i);
return new Container(
key: new ValueKey<int>(i),
height: 500.0, // this should be ignored
width: 200.0,
child: new Text("$i")
);
};
TestComponent testComponent;
Widget builder() {
testComponent = new TestComponent(new MixedViewport(
builder: itemBuilder,
startOffset: offset,
layoutState: layoutState,
direction: ScrollDirection.horizontal
));
return testComponent;
}
tester.pumpFrame(builder);
// 0 is built to find its width
expect(callbackTracker, equals([0, 1, 2, 3, 4, 5]));
callbackTracker.clear();
offset = 400.0; // now only 4 should fit, numbered 2-5.
tester.pumpFrame(builder);
// 0 and 1 aren't built, we know their size and nothing else changed
expect(callbackTracker, equals([2, 3, 4, 5]));
callbackTracker.clear();
});
}
import 'package:sky/animation.dart';
import 'package:sky/widgets.dart';
import 'package:sky/src/fn3.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
import '../fn3/widget_tester.dart';
class FirstComponent extends Component {
class FirstComponent extends StatelessComponent {
FirstComponent(this.navigator);
final Navigator navigator;
final NavigatorState navigator;
Widget build() {
Widget build(BuildContext context) {
return new GestureDetector(
onTap: () {
navigator.pushNamed('/second');
......@@ -27,15 +27,15 @@ class FirstComponent extends Component {
class SecondComponent extends StatefulComponent {
SecondComponent(this.navigator);
Navigator navigator;
final NavigatorState navigator;
void syncConstructorArguments(SecondComponent source) {
navigator = source.navigator;
}
SecondComponentState createState() => new SecondComponentState();
}
Widget build() {
class SecondComponentState extends State<SecondComponent> {
Widget build(BuildContext context) {
return new GestureDetector(
onTap: navigator.pop,
onTap: config.navigator.pop,
child: new Container(
decoration: new BoxDecoration(
backgroundColor: new Color(0xFFFF00FF)
......@@ -50,7 +50,7 @@ void main() {
test('Can navigator navigate to and from a stateful component', () {
WidgetTester tester = new WidgetTester();
final NavigationState routes = new NavigationState([
final NavigatorHistory routes = new NavigatorHistory([
new Route(
name: '/',
builder: (navigator, route) => new FirstComponent(navigator)
......@@ -61,9 +61,7 @@ void main() {
)
]);
tester.pumpFrame(() {
return new Navigator(routes);
});
tester.pumpFrame(new Navigator(routes));
expect(tester.findText('X'), isNotNull);
expect(tester.findText('Y'), isNull);
......
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