diff --git a/packages/flutter/lib/src/widgets/table.dart b/packages/flutter/lib/src/widgets/table.dart index e178b16c1f6..f9ef88f6d9c 100644 --- a/packages/flutter/lib/src/widgets/table.dart +++ b/packages/flutter/lib/src/widgets/table.dart @@ -269,7 +269,15 @@ class _TableElement extends RenderObjectElement { @override void removeChildRenderObject(RenderObject child) { - assert(_debugWillReattachChildren); + assert(() { + if (_debugWillReattachChildren) + return true; + for (Element forgottenChild in _forgottenChildren) { + if (forgottenChild.renderObject == child) + return true; + } + return false; + }); TableCellParentData childParentData = child.parentData; renderObject.setChild(childParentData.x, childParentData.y, null); } diff --git a/packages/flutter/lib/src/widgets/text_selection.dart b/packages/flutter/lib/src/widgets/text_selection.dart index b7ade8e0f67..f1e1307d9d5 100644 --- a/packages/flutter/lib/src/widgets/text_selection.dart +++ b/packages/flutter/lib/src/widgets/text_selection.dart @@ -401,13 +401,13 @@ class _TextSelectionHandleOverlayState extends State<_TextSelectionHandleOverlay if (config.selection.isCollapsed) return TextSelectionHandleType.collapsed; + assert(endpoint.direction != null); switch (endpoint.direction) { case TextDirection.ltr: return ltrType; case TextDirection.rtl: return rtlType; } - assert(endpoint.direction != null); return null; } } diff --git a/packages/flutter/lib/src/widgets/ticker_provider.dart b/packages/flutter/lib/src/widgets/ticker_provider.dart index ed923c30ace..46b75aafbc3 100644 --- a/packages/flutter/lib/src/widgets/ticker_provider.dart +++ b/packages/flutter/lib/src/widgets/ticker_provider.dart @@ -130,11 +130,9 @@ abstract class SingleTickerProviderStateMixin implements State, TickerP if (_ticker != null) { if (_ticker.isActive && _ticker.muted) description.add('ticker active but muted'); - else - if (_ticker.isActive) + else if (_ticker.isActive) description.add('ticker active'); - else - if (_ticker.muted) + else if (_ticker.muted) description.add('ticker inactive and muted'); else description.add('ticker inactive'); diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart index f0e831dad4d..17137bb34f6 100644 --- a/packages/flutter/test/material/switch_test.dart +++ b/packages/flutter/test/material/switch_test.dart @@ -6,42 +6,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; -class TestBoxPainter extends BoxPainter { - TestBoxPainter(VoidCallback onChanged): super(onChanged); - - @override - void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { } -} - -class TestDecoration extends Decoration { - int listeners = 0; - - @override - Decoration lerpFrom(Decoration a, double t) { - if (t == 0.0) - return a; - if (t == 1.0) - return this; - return new TestDecoration(); - } - - @override - Decoration lerpTo(Decoration b, double t) { - if (t == 1.0) - return b; - if (t == 0.0) - return this; - return new TestDecoration(); - } - - @override - BoxPainter createBoxPainter([VoidCallback onChanged]) { - if (onChanged != null) - listeners += 1; - return new TestBoxPainter(onChanged); - } -} - void main() { testWidgets('Switch can toggle on tap', (WidgetTester tester) async { Key switchKey = new UniqueKey(); @@ -71,4 +35,47 @@ void main() { await tester.tap(find.byKey(switchKey)); expect(value, isTrue); }); + + testWidgets('Switch can drag', (WidgetTester tester) async { + bool value = false; + + await tester.pumpWidget( + new StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return new Material( + child: new Center( + child: new Switch( + value: value, + onChanged: (bool newValue) { + setState(() { + value = newValue; + }); + } + ) + ) + ); + } + ) + ); + + expect(value, isFalse); + + await tester.scroll(find.byType(Switch), const Offset(-30.0, 0.0)); + + expect(value, isFalse); + + await tester.scroll(find.byType(Switch), const Offset(30.0, 0.0)); + + expect(value, isTrue); + + await tester.pump(); + await tester.scroll(find.byType(Switch), const Offset(30.0, 0.0)); + + expect(value, isTrue); + + await tester.pump(); + await tester.scroll(find.byType(Switch), const Offset(-30.0, 0.0)); + + expect(value, isFalse); + }); } diff --git a/packages/flutter/test/widgets/table_test.dart b/packages/flutter/test/widgets/table_test.dart index 48e6362b361..f327966ede3 100644 --- a/packages/flutter/test/widgets/table_test.dart +++ b/packages/flutter/test/widgets/table_test.dart @@ -6,6 +6,18 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; +class TestStatefulWidget extends StatefulWidget { + TestStatefulWidget({ Key key }) : super(key: key); + + @override + TestStatefulWidgetState createState() => new TestStatefulWidgetState(); +} + +class TestStatefulWidgetState extends State { + @override + Widget build(BuildContext context) => new Container(); +} + void main() { testWidgets('Table widget - control test', (WidgetTester tester) async { await tester.pumpWidget( @@ -331,5 +343,159 @@ void main() { expect(contexts.length, equals(2)); expect(contexts[0], equals(contexts[1])); }); + + testWidgets('Table widget - keyed rows', (WidgetTester tester) async { + await tester.pumpWidget( + new Table( + children: [ + new TableRow( + key: const ValueKey(1), + children: [ + new TestStatefulWidget(key: const ValueKey(11)), + new TestStatefulWidget(key: const ValueKey(12)), + ], + ), + new TableRow( + key: const ValueKey(2), + children: [ + new TestStatefulWidget(key: const ValueKey(21)), + new TestStatefulWidget(key: const ValueKey(22)), + ], + ), + ] + ) + ); + + TestStatefulWidgetState state11 = tester.state(find.byKey(const ValueKey(11))); + TestStatefulWidgetState state12 = tester.state(find.byKey(const ValueKey(12))); + TestStatefulWidgetState state21 = tester.state(find.byKey(const ValueKey(21))); + TestStatefulWidgetState state22 = tester.state(find.byKey(const ValueKey(22))); + + expect(state11.mounted, isTrue); + expect(state12.mounted, isTrue); + expect(state21.mounted, isTrue); + expect(state22.mounted, isTrue); + + await tester.pumpWidget( + new Table( + children: [ + new TableRow( + key: const ValueKey(2), + children: [ + new TestStatefulWidget(key: const ValueKey(21)), + new TestStatefulWidget(key: const ValueKey(22)), + ], + ), + ] + ) + ); + + expect(state11.mounted, isFalse); + expect(state12.mounted, isFalse); + expect(state21.mounted, isTrue); + expect(state22.mounted, isTrue); + }); + + testWidgets('Table widget - global key reparenting', (WidgetTester tester) async { + GlobalKey key = new GlobalKey(); + Key tableKey = new UniqueKey(); + + await tester.pumpWidget( + new Column( + children: [ + new Expanded( + key: tableKey, + child: new Table( + children: [ + new TableRow( + children: [ + new Container(key: const ValueKey(1)), + new TestStatefulWidget(key: key), + new Container(key: const ValueKey(2)), + ], + ), + ], + ), + ), + ], + ), + ); + + RenderTable table = tester.renderObject(find.byType(Table)); + expect(table.row(0).length, 3); + + await tester.pumpWidget( + new Column( + children: [ + new Expanded(child: new TestStatefulWidget(key: key)), + new Expanded( + key: tableKey, + child: new Table( + children: [ + new TableRow( + children: [ + new Container(key: const ValueKey(1)), + new Container(key: const ValueKey(2)), + ], + ), + ], + ), + ), + ], + ), + ); + + expect(tester.renderObject(find.byType(Table)), equals(table)); + expect(table.row(0).length, 2); + + await tester.pumpWidget( + new Column( + children: [ + new Expanded( + key: tableKey, + child: new Table( + children: [ + new TableRow( + children: [ + new Container(key: const ValueKey(1)), + new TestStatefulWidget(key: key), + new Container(key: const ValueKey(2)), + ], + ), + ], + ), + ), + ], + ), + ); + + expect(tester.renderObject(find.byType(Table)), equals(table)); + expect(table.row(0).length, 3); + + await tester.pumpWidget( + new Column( + children: [ + new Expanded( + key: tableKey, + child: new Table( + children: [ + new TableRow( + children: [ + new Container(key: const ValueKey(1)), + new Container(key: const ValueKey(2)), + ], + ), + ], + ), + ), + new Expanded(child: new TestStatefulWidget(key: key)), + ], + ), + ); + + expect(tester.renderObject(find.byType(Table)), equals(table)); + expect(table.row(0).length, 2); + }); + // TODO(ianh): Test handling of TableCell object } diff --git a/packages/flutter/test/widgets/ticker_provider_test.dart b/packages/flutter/test/widgets/ticker_provider_test.dart index da55d7ee8c0..34ba3dad411 100644 --- a/packages/flutter/test/widgets/ticker_provider_test.dart +++ b/packages/flutter/test/widgets/ticker_provider_test.dart @@ -7,10 +7,13 @@ import 'package:flutter/material.dart'; void main() { testWidgets('TickerMode', (WidgetTester tester) async { - await tester.pumpWidget(new TickerMode( + Widget widget = new TickerMode( enabled: false, child: new LinearProgressIndicator() - )); + ); + expect(widget.toString, isNot(throwsException)); + + await tester.pumpWidget(widget); expect(tester.binding.transientCallbackCount, 0); @@ -52,7 +55,10 @@ void main() { }); testWidgets('SingleTickerProviderStateMixin can handle not being used', (WidgetTester tester) async { - await tester.pumpWidget(new BoringTickerTest()); + Widget widget = new BoringTickerTest(); + expect(widget.toString, isNot(throwsException)); + + await tester.pumpWidget(widget); await tester.pumpWidget(new Container()); // the test is that this doesn't crash, like it used to... }); @@ -66,4 +72,4 @@ class BoringTickerTest extends StatefulWidget { class _BoringTickerTestState extends State with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) => new Container(); -} \ No newline at end of file +} diff --git a/packages/flutter/test/widgets/title_test.dart b/packages/flutter/test/widgets/title_test.dart new file mode 100644 index 00000000000..adf5d751295 --- /dev/null +++ b/packages/flutter/test/widgets/title_test.dart @@ -0,0 +1,16 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/widgets.dart'; + +void main() { + testWidgets('toString control test', (WidgetTester tester) async { + Widget widget = new Title( + color: const Color(0xFF00FF00), + title: 'Awesome app', + ); + expect(widget.toString, isNot(throwsException)); + }); +} diff --git a/packages/flutter/test/widgets/transitions_test.dart b/packages/flutter/test/widgets/transitions_test.dart new file mode 100644 index 00000000000..2aed5ef0a84 --- /dev/null +++ b/packages/flutter/test/widgets/transitions_test.dart @@ -0,0 +1,16 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/widgets.dart'; + +void main() { + testWidgets('toString control test', (WidgetTester tester) async { + Widget widget = new FadeTransition( + opacity: kAlwaysCompleteAnimation, + child: new Text('Ready'), + ); + expect(widget.toString, isNot(throwsException)); + }); +} diff --git a/packages/flutter/test/widgets/unique_widget_test.dart b/packages/flutter/test/widgets/unique_widget_test.dart new file mode 100644 index 00000000000..bb846a1b138 --- /dev/null +++ b/packages/flutter/test/widgets/unique_widget_test.dart @@ -0,0 +1,34 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/widgets.dart'; + +class TestUniqueWidget extends UniqueWidget { + TestUniqueWidget({ GlobalKey key }) : super(key: key); + + @override + TestUniqueWidgetState createState() => new TestUniqueWidgetState(); +} + +class TestUniqueWidgetState extends State { + @override + Widget build(BuildContext context) => new Container(); +} + +void main() { + testWidgets('Unique widget control test', (WidgetTester tester) async { + TestUniqueWidget widget = new TestUniqueWidget(key: new GlobalKey()); + + await tester.pumpWidget(widget); + + TestUniqueWidgetState state = widget.currentState; + + expect(state, isNotNull); + + await tester.pumpWidget(new Container(child: widget)); + + expect(widget.currentState, equals(state)); + }); +}