flutter/packages/flutter/test/widget/inherited_test.dart
Ian Hickson 3252701753 Make it possible to run tests live on a device (#3936)
This makes it possible to substitute 'flutter run' for 'flutter test'
and actually watch a test run on a device.

For any test that depends on flutter_test:

1. Remove any import of 'package:test/test.dart'.

2. Replace `testWidgets('...', (WidgetTester tester) {`
      with `testWidgets('...', (WidgetTester tester) async {`

3. Add an "await" in front of calls to any of the following:
    * tap()
    * tapAt()
    * fling()
    * flingFrom()
    * scroll()
    * scrollAt()
    * pump()
    * pumpWidget()

4. Replace any calls to `tester.flushMicrotasks()` with calls to
   `await tester.idle()`.

There's a guarding API that you can use, if you have particularly
complicated tests, to get better error messages. Search for
TestAsyncUtils.
2016-05-16 12:53:13 -07:00

441 lines
12 KiB
Dart

// Copyright 2015 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/material.dart';
import 'test_widgets.dart';
class TestInherited extends InheritedWidget {
TestInherited({ Key key, Widget child, this.shouldNotify: true })
: super(key: key, child: child);
final bool shouldNotify;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return shouldNotify;
}
}
class ValueInherited extends InheritedWidget {
ValueInherited({ Key key, Widget child, this.value })
: super(key: key, child: child);
final int value;
@override
bool updateShouldNotify(ValueInherited oldWidget) => value != oldWidget.value;
}
void main() {
testWidgets('Inherited notifies dependents', (WidgetTester tester) async {
List<TestInherited> log = <TestInherited>[];
Builder builder = new Builder(
builder: (BuildContext context) {
log.add(context.inheritFromWidgetOfExactType(TestInherited));
return new Container();
}
);
TestInherited first = new TestInherited(child: builder);
await tester.pumpWidget(first);
expect(log, equals(<TestInherited>[first]));
TestInherited second = new TestInherited(child: builder, shouldNotify: false);
await tester.pumpWidget(second);
expect(log, equals(<TestInherited>[first]));
TestInherited third = new TestInherited(child: builder, shouldNotify: true);
await tester.pumpWidget(third);
expect(log, equals(<TestInherited>[first, third]));
});
testWidgets('Update inherited when reparenting state', (WidgetTester tester) async {
GlobalKey globalKey = new GlobalKey();
List<TestInherited> log = <TestInherited>[];
TestInherited build() {
return new TestInherited(
key: new UniqueKey(),
child: new Container(
key: globalKey,
child: new Builder(
builder: (BuildContext context) {
log.add(context.inheritFromWidgetOfExactType(TestInherited));
return new Container();
}
)
)
);
}
TestInherited first = build();
await tester.pumpWidget(first);
expect(log, equals(<TestInherited>[first]));
TestInherited second = build();
await tester.pumpWidget(second);
expect(log, equals(<TestInherited>[first, second]));
});
testWidgets('Update inherited when removing node', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
new Container(
child: new ValueInherited(
value: 1,
child: new Container(
child: new FlipWidget(
left: new Container(
child: new ValueInherited(
value: 2,
child: new Container(
child: new ValueInherited(
value: 3,
child: new Container(
child: new Builder(
builder: (BuildContext context) {
ValueInherited v = context.inheritFromWidgetOfExactType(ValueInherited);
log.add('a: ${v.value}');
return new Text('');
}
)
)
)
)
)
),
right: new Container(
child: new ValueInherited(
value: 2,
child: new Container(
child: new Container(
child: new Builder(
builder: (BuildContext context) {
ValueInherited v = context.inheritFromWidgetOfExactType(ValueInherited);
log.add('b: ${v.value}');
return new Text('');
}
)
)
)
)
)
)
)
)
)
);
expect(log, equals(<String>['a: 3']));
log.clear();
await tester.pump();
expect(log, equals(<String>[]));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<String>['b: 2']));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<String>['a: 3']));
log.clear();
});
testWidgets('Update inherited when removing node and child has global key', (WidgetTester tester) async {
final List<String> log = <String>[];
Key key = new GlobalKey();
await tester.pumpWidget(
new Container(
child: new ValueInherited(
value: 1,
child: new Container(
child: new FlipWidget(
left: new Container(
child: new ValueInherited(
value: 2,
child: new Container(
child: new ValueInherited(
value: 3,
child: new Container(
key: key,
child: new Builder(
builder: (BuildContext context) {
ValueInherited v = context.inheritFromWidgetOfExactType(ValueInherited);
log.add('a: ${v.value}');
return new Text('');
}
)
)
)
)
)
),
right: new Container(
child: new ValueInherited(
value: 2,
child: new Container(
child: new Container(
key: key,
child: new Builder(
builder: (BuildContext context) {
ValueInherited v = context.inheritFromWidgetOfExactType(ValueInherited);
log.add('b: ${v.value}');
return new Text('');
}
)
)
)
)
)
)
)
)
)
);
expect(log, equals(<String>['a: 3']));
log.clear();
await tester.pump();
expect(log, equals(<String>[]));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<String>['b: 2']));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<String>['a: 3']));
log.clear();
});
testWidgets('Update inherited when removing node and child has global key with constant child', (WidgetTester tester) async {
final List<int> log = <int>[];
Key key = new GlobalKey();
Widget child = new Builder(
builder: (BuildContext context) {
ValueInherited v = context.inheritFromWidgetOfExactType(ValueInherited);
log.add(v.value);
return new Text('');
}
);
await tester.pumpWidget(
new Container(
child: new ValueInherited(
value: 1,
child: new Container(
child: new FlipWidget(
left: new Container(
child: new ValueInherited(
value: 2,
child: new Container(
child: new ValueInherited(
value: 3,
child: new Container(
key: key,
child: child
)
)
)
)
),
right: new Container(
child: new ValueInherited(
value: 2,
child: new Container(
child: new Container(
key: key,
child: child
)
)
)
)
)
)
)
)
);
expect(log, equals(<int>[3]));
log.clear();
await tester.pump();
expect(log, equals(<int>[]));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<int>[2]));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<int>[3]));
log.clear();
});
testWidgets('Update inherited when removing node and child has global key with constant child, minimised', (WidgetTester tester) async {
final List<int> log = <int>[];
Widget child = new Builder(
key: new GlobalKey(),
builder: (BuildContext context) {
ValueInherited v = context.inheritFromWidgetOfExactType(ValueInherited);
log.add(v.value);
return new Text('');
}
);
await tester.pumpWidget(
new ValueInherited(
value: 2,
child: new FlipWidget(
left: new ValueInherited(
value: 3,
child: child
),
right: child
)
)
);
expect(log, equals(<int>[3]));
log.clear();
await tester.pump();
expect(log, equals(<int>[]));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<int>[2]));
log.clear();
flipStatefulWidget(tester);
await tester.pump();
expect(log, equals(<int>[3]));
log.clear();
});
testWidgets('Inherited widget notifies descendants when descendant previously failed to find a match', (WidgetTester tester) async {
int inheritedValue = -1;
final Widget inner = new Container(
key: new GlobalKey(),
child: new Builder(
builder: (BuildContext context) {
ValueInherited widget = context.inheritFromWidgetOfExactType(ValueInherited);
inheritedValue = widget?.value;
return new Container();
}
)
);
await tester.pumpWidget(
inner
);
expect(inheritedValue, isNull);
inheritedValue = -2;
await tester.pumpWidget(
new ValueInherited(
value: 3,
child: inner
)
);
expect(inheritedValue, equals(3));
});
testWidgets('Inherited widget doesn\'t notify descendants when descendant did not previously fail to find a match and had no dependencies', (WidgetTester tester) async {
int buildCount = 0;
final Widget inner = new Container(
key: new GlobalKey(),
child: new Builder(
builder: (BuildContext context) {
buildCount += 1;
return new Container();
}
)
);
await tester.pumpWidget(
inner
);
expect(buildCount, equals(1));
await tester.pumpWidget(
new ValueInherited(
value: 3,
child: inner
)
);
expect(buildCount, equals(1));
});
testWidgets('Inherited widget does notify descendants when descendant did not previously fail to find a match but did have other dependencies', (WidgetTester tester) async {
int buildCount = 0;
final Widget inner = new Container(
key: new GlobalKey(),
child: new TestInherited(
shouldNotify: false,
child: new Builder(
builder: (BuildContext context) {
context.inheritFromWidgetOfExactType(TestInherited);
buildCount += 1;
return new Container();
}
)
)
);
await tester.pumpWidget(
inner
);
expect(buildCount, equals(1));
await tester.pumpWidget(
new ValueInherited(
value: 3,
child: inner
)
);
expect(buildCount, equals(2));
});
}