Test service extensions (#7849)
...and fix bugs that the tests uncovered. WRITE TEST FIND BUG
This commit is contained in:
parent
cce70d7069
commit
be7be2b8b6
@ -2,9 +2,16 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
class TestTestBinding extends AutomatedTestWidgetsFlutterBinding {
|
||||
@override
|
||||
DebugPrintCallback get debugPrintOverride => testPrint;
|
||||
static void testPrint(String message, { int wrapWidth }) { print(message); }
|
||||
}
|
||||
|
||||
Future<Null> guardedHelper(WidgetTester tester) {
|
||||
return TestAsyncUtils.guard(() async {
|
||||
await tester.pumpWidget(new Text('Hello'));
|
||||
@ -12,8 +19,8 @@ Future<Null> guardedHelper(WidgetTester tester) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
new TestTestBinding();
|
||||
testWidgets('TestAsyncUtils - custom guarded sections', (WidgetTester tester) async {
|
||||
debugPrint = (String message, { int wrapWidth }) { print(message); };
|
||||
await tester.pumpWidget(new Container());
|
||||
expect(find.byElementType(Container), isNotNull);
|
||||
guardedHelper(tester);
|
||||
|
@ -2,16 +2,22 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
class TestTestBinding extends AutomatedTestWidgetsFlutterBinding {
|
||||
@override
|
||||
DebugPrintCallback get debugPrintOverride => testPrint;
|
||||
static void testPrint(String message, { int wrapWidth }) { print(message); }
|
||||
}
|
||||
|
||||
Future<Null> helperFunction(WidgetTester tester) async {
|
||||
await tester.pump();
|
||||
}
|
||||
|
||||
void main() {
|
||||
new TestTestBinding();
|
||||
testWidgets('TestAsyncUtils - handling unguarded async helper functions', (WidgetTester tester) async {
|
||||
debugPrint = (String message, { int wrapWidth }) { print(message); };
|
||||
helperFunction(tester);
|
||||
helperFunction(tester);
|
||||
// this should fail
|
||||
|
@ -46,7 +46,7 @@ class TestAssetBundle extends AssetBundle {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> loadStructuredData<T>(String key, Future<T> parser(String value)) async {
|
||||
Future<T> loadStructuredData<T>(String key, Future<T> parser(String value)) async {
|
||||
return parser(await loadString(key));
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ export 'src/foundation/assertions.dart';
|
||||
export 'src/foundation/basic_types.dart';
|
||||
export 'src/foundation/binding.dart';
|
||||
export 'src/foundation/change_notifier.dart';
|
||||
export 'src/foundation/debug.dart';
|
||||
export 'src/foundation/licenses.dart';
|
||||
export 'src/foundation/observer_list.dart';
|
||||
export 'src/foundation/platform.dart';
|
||||
|
@ -19,7 +19,7 @@ import 'basic_types.dart';
|
||||
/// "type" key will be set to the string `_extensionType` to indicate
|
||||
/// that this is a return value from a service extension, and the
|
||||
/// "method" key will be set to the full name of the method.
|
||||
typedef Future<Map<String, dynamic>> ServiceExtensionCallback(Map<String, String> parameters);
|
||||
typedef Future<Map<String, String>> ServiceExtensionCallback(Map<String, String> parameters);
|
||||
|
||||
/// Base class for mixins that provide singleton services (also known as
|
||||
/// "bindings").
|
||||
@ -56,7 +56,7 @@ abstract class BindingBase {
|
||||
initServiceExtensions();
|
||||
assert(_debugServiceExtensionsRegistered);
|
||||
|
||||
developer.postEvent('Flutter.FrameworkInitialization', <String, dynamic>{});
|
||||
developer.postEvent('Flutter.FrameworkInitialization', <String, String>{});
|
||||
|
||||
developer.Timeline.finishSync();
|
||||
}
|
||||
@ -150,7 +150,7 @@ abstract class BindingBase {
|
||||
name: name,
|
||||
callback: (Map<String, String> parameters) async {
|
||||
await callback();
|
||||
return <String, dynamic>{};
|
||||
return <String, String>{};
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -181,7 +181,7 @@ abstract class BindingBase {
|
||||
callback: (Map<String, String> parameters) async {
|
||||
if (parameters.containsKey('enabled'))
|
||||
await setter(parameters['enabled'] == 'true');
|
||||
return <String, dynamic>{ 'enabled': await getter() };
|
||||
return <String, String>{ 'enabled': await getter() ? 'true' : 'false' };
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -211,7 +211,7 @@ abstract class BindingBase {
|
||||
callback: (Map<String, String> parameters) async {
|
||||
if (parameters.containsKey(name))
|
||||
await setter(double.parse(parameters[name]));
|
||||
return <String, dynamic>{ name: await getter() };
|
||||
return <String, String>{ name: (await getter()).toString() };
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -240,7 +240,7 @@ abstract class BindingBase {
|
||||
callback: (Map<String, String> parameters) async {
|
||||
if (parameters.containsKey('value'))
|
||||
await setter(parameters['value']);
|
||||
return <String, dynamic>{ 'value': await getter() };
|
||||
return <String, String>{ 'value': await getter() };
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -267,7 +267,7 @@ abstract class BindingBase {
|
||||
assert(method == methodName);
|
||||
dynamic caughtException;
|
||||
StackTrace caughtStack;
|
||||
Map<String, dynamic> result;
|
||||
Map<String, String> result;
|
||||
try {
|
||||
result = await callback(parameters);
|
||||
} catch (exception, stack) {
|
||||
@ -286,10 +286,10 @@ abstract class BindingBase {
|
||||
));
|
||||
return new developer.ServiceExtensionResponse.error(
|
||||
developer.ServiceExtensionResponse.extensionError,
|
||||
JSON.encode(<String, dynamic>{
|
||||
JSON.encode(<String, String>{
|
||||
'exception': caughtException.toString(),
|
||||
'stack': caughtStack.toString(),
|
||||
'method': method
|
||||
'method': method,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
28
packages/flutter/lib/src/foundation/debug.dart
Normal file
28
packages/flutter/lib/src/foundation/debug.dart
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2017 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 'assertions.dart';
|
||||
import 'print.dart';
|
||||
|
||||
/// Returns true if none of the foundation library debug variables have been
|
||||
/// changed.
|
||||
///
|
||||
/// This function is used by the test framework to ensure that debug variables
|
||||
/// haven't been inadvertently changed.
|
||||
///
|
||||
/// The `debugPrintOverride` argument can be specified to indicate the expected
|
||||
/// value of the [debugPrint] variable. This is useful for test frameworks that
|
||||
/// override [debugPrint] themselves and want to check that their own custom
|
||||
/// value wasn't overridden by a test.
|
||||
///
|
||||
/// See [https://docs.flutter.io/flutter/foundation/foundation-library.html] for
|
||||
/// a complete list.
|
||||
bool debugAssertAllFoundationVarsUnset(String reason, { DebugPrintCallback debugPrintOverride: debugPrintThrottled }) {
|
||||
assert(() {
|
||||
if (debugPrint != debugPrintOverride)
|
||||
throw new FlutterError(reason);
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
}
|
@ -57,8 +57,7 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding,
|
||||
if (debugPaintSizeEnabled == value)
|
||||
return new Future<Null>.value();
|
||||
debugPaintSizeEnabled = value;
|
||||
_forceRepaint();
|
||||
return endOfFrame;
|
||||
return _forceRepaint();
|
||||
}
|
||||
);
|
||||
return true;
|
||||
@ -78,8 +77,8 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding,
|
||||
bool repaint = debugRepaintRainbowEnabled && !value;
|
||||
debugRepaintRainbowEnabled = value;
|
||||
if (repaint)
|
||||
_forceRepaint();
|
||||
return endOfFrame;
|
||||
return _forceRepaint();
|
||||
return new Future<Null>.value();
|
||||
}
|
||||
);
|
||||
return true;
|
||||
@ -249,13 +248,14 @@ abstract class RendererBinding extends BindingBase implements SchedulerBinding,
|
||||
super.hitTest(result, position); // ignore: abstract_super_member_reference
|
||||
}
|
||||
|
||||
void _forceRepaint() {
|
||||
Future<Null> _forceRepaint() {
|
||||
RenderObjectVisitor visitor;
|
||||
visitor = (RenderObject child) {
|
||||
child.markNeedsPaint();
|
||||
child.visitChildren(visitor);
|
||||
};
|
||||
instance?.renderView?.visitChildren(visitor);
|
||||
return endOfFrame;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ abstract class AssetBundle {
|
||||
///
|
||||
/// Implementations may cache the result, so a particular key should only be
|
||||
/// used with one parser for the lifetime of the asset bundle.
|
||||
Future<dynamic> loadStructuredData<T>(String key, Future<T> parser(String value));
|
||||
Future<T> loadStructuredData<T>(String key, Future<T> parser(String value));
|
||||
|
||||
/// If this is a caching asset bundle, and the given key describes a cached
|
||||
/// asset, then evict the asset from the cache so that the next time it is
|
||||
@ -110,7 +110,7 @@ class NetworkAssetBundle extends AssetBundle {
|
||||
/// The result is not cached. The parser is run each time the resource is
|
||||
/// fetched.
|
||||
@override
|
||||
Future<dynamic> loadStructuredData<T>(String key, Future<T> parser(String value)) async {
|
||||
Future<T> loadStructuredData<T>(String key, Future<T> parser(String value)) async {
|
||||
assert(key != null);
|
||||
assert(parser != null);
|
||||
return parser(await loadString(key));
|
||||
@ -159,7 +159,7 @@ abstract class CachingAssetBundle extends AssetBundle {
|
||||
/// subsequent calls will be a [SynchronousFuture], which resolves its
|
||||
/// callback synchronously.
|
||||
@override
|
||||
Future<dynamic> loadStructuredData<T>(String key, Future<T> parser(String value)) {
|
||||
Future<T> loadStructuredData<T>(String key, Future<T> parser(String value)) {
|
||||
assert(key != null);
|
||||
assert(parser != null);
|
||||
if (_structuredDataCache.containsKey(key))
|
||||
|
@ -86,8 +86,7 @@ abstract class WidgetsBinding extends BindingBase implements GestureBinding, Ren
|
||||
if (WidgetsApp.showPerformanceOverlayOverride == value)
|
||||
return new Future<Null>.value();
|
||||
WidgetsApp.showPerformanceOverlayOverride = value;
|
||||
buildOwner.reassemble(renderViewElement);
|
||||
return endOfFrame;
|
||||
return _forceRebuild();
|
||||
}
|
||||
);
|
||||
|
||||
@ -98,12 +97,19 @@ abstract class WidgetsBinding extends BindingBase implements GestureBinding, Ren
|
||||
if (WidgetsApp.debugAllowBannerOverride == value)
|
||||
return new Future<Null>.value();
|
||||
WidgetsApp.debugAllowBannerOverride = value;
|
||||
buildOwner.reassemble(renderViewElement);
|
||||
return endOfFrame;
|
||||
return _forceRebuild();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Future<Null> _forceRebuild() {
|
||||
if (renderViewElement != null) {
|
||||
buildOwner.reassemble(renderViewElement);
|
||||
return endOfFrame;
|
||||
}
|
||||
return new Future<Null>.value();
|
||||
}
|
||||
|
||||
/// The [BuildOwner] in charge of executing the build pipeline for the
|
||||
/// widget tree rooted at this binding.
|
||||
BuildOwner get buildOwner => _buildOwner;
|
||||
|
336
packages/flutter/test/foundation/service_extensions_test.dart
Normal file
336
packages/flutter/test/foundation/service_extensions_test.dart
Normal file
@ -0,0 +1,336 @@
|
||||
// Copyright 2017 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 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class TestServiceExtensionsBinding extends BindingBase
|
||||
with SchedulerBinding,
|
||||
ServicesBinding,
|
||||
GestureBinding,
|
||||
RendererBinding,
|
||||
WidgetsBinding {
|
||||
|
||||
final Map<String, ServiceExtensionCallback> extensions = <String, ServiceExtensionCallback>{};
|
||||
|
||||
@override
|
||||
void registerServiceExtension({
|
||||
@required String name,
|
||||
@required ServiceExtensionCallback callback
|
||||
}) {
|
||||
expect(extensions.containsKey(name), isFalse);
|
||||
extensions[name] = callback;
|
||||
}
|
||||
|
||||
Future<Map<String, String>> testExtension(String name, Map<String, String> arguments) {
|
||||
expect(extensions.containsKey(name), isTrue);
|
||||
return extensions[name](arguments);
|
||||
}
|
||||
|
||||
int reassembled = 0;
|
||||
@override
|
||||
Future<Null> reassembleApplication() {
|
||||
reassembled += 1;
|
||||
return super.reassembleApplication();
|
||||
}
|
||||
|
||||
bool frameScheduled = false;
|
||||
@override
|
||||
void scheduleFrame() {
|
||||
frameScheduled = true;
|
||||
}
|
||||
void doFrame() {
|
||||
frameScheduled = false;
|
||||
if (ui.window.onBeginFrame != null)
|
||||
ui.window.onBeginFrame(const Duration());
|
||||
}
|
||||
|
||||
Future<Null> flushMicrotasks() {
|
||||
Completer<Null> completer = new Completer<Null>();
|
||||
new Timer(const Duration(), () {
|
||||
completer.complete();
|
||||
});
|
||||
return completer.future;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestServiceExtensionsBinding binding;
|
||||
List<String> console = <String>[];
|
||||
|
||||
test('Service extensions - pretest', () async {
|
||||
binding = new TestServiceExtensionsBinding();
|
||||
expect(binding.frameScheduled, isTrue);
|
||||
binding.doFrame(); // initial frame scheduled by creating the binding
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
|
||||
expect(debugPrint, equals(debugPrintThrottled));
|
||||
debugPrint = (String message, { int wrapWidth }) {
|
||||
console.add(message);
|
||||
};
|
||||
});
|
||||
|
||||
// The following list is alphabetical, one test per extension.
|
||||
//
|
||||
// The order doesn't really matter except that the pretest and posttest tests
|
||||
// must be first and last respectively.
|
||||
|
||||
test('Service extensions - debugAllowBanner', () async {
|
||||
Map<String, String> result;
|
||||
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
expect(WidgetsApp.debugAllowBannerOverride, true);
|
||||
result = await binding.testExtension('debugAllowBanner', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.debugAllowBannerOverride, true);
|
||||
result = await binding.testExtension('debugAllowBanner', <String, String>{ 'enabled': 'false' });
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.debugAllowBannerOverride, false);
|
||||
result = await binding.testExtension('debugAllowBanner', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.debugAllowBannerOverride, false);
|
||||
result = await binding.testExtension('debugAllowBanner', <String, String>{ 'enabled': 'true' });
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.debugAllowBannerOverride, true);
|
||||
result = await binding.testExtension('debugAllowBanner', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.debugAllowBannerOverride, true);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - debugDumpApp', () async {
|
||||
Map<String, String> result;
|
||||
|
||||
result = await binding.testExtension('debugDumpApp', <String, String>{});
|
||||
expect(result, <String, String>{});
|
||||
expect(console, <String>['TestServiceExtensionsBinding - CHECKED MODE', '<no tree currently mounted>']);
|
||||
console.clear();
|
||||
});
|
||||
|
||||
test('Service extensions - debugDumpRenderTree', () async {
|
||||
Map<String, String> result;
|
||||
|
||||
result = await binding.testExtension('debugDumpRenderTree', <String, String>{});
|
||||
expect(result, <String, String>{});
|
||||
expect(console, <String>[
|
||||
'RenderView\n'
|
||||
' debug mode enabled - linux\n'
|
||||
' window size: Size(800.0, 600.0) (in physical pixels)\n'
|
||||
' device pixel ratio: 1.0 (physical pixels per logical pixel)\n'
|
||||
' configuration: Size(800.0, 600.0) at 1.0x (in logical pixels)\n'
|
||||
'\n'
|
||||
]);
|
||||
console.clear();
|
||||
});
|
||||
|
||||
test('Service extensions - debugPaint', () async {
|
||||
Map<String, String> result;
|
||||
Future<Map<String, String>> pendingResult;
|
||||
bool completed;
|
||||
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
expect(debugPaintSizeEnabled, false);
|
||||
result = await binding.testExtension('debugPaint', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(debugPaintSizeEnabled, false);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
pendingResult = binding.testExtension('debugPaint', <String, String>{ 'enabled': 'true' });
|
||||
completed = false;
|
||||
pendingResult.whenComplete(() { completed = true; });
|
||||
await binding.flushMicrotasks();
|
||||
expect(binding.frameScheduled, isTrue);
|
||||
expect(completed, isFalse);
|
||||
binding.doFrame();
|
||||
await binding.flushMicrotasks();
|
||||
expect(completed, isTrue);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
result = await pendingResult;
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(debugPaintSizeEnabled, true);
|
||||
result = await binding.testExtension('debugPaint', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(debugPaintSizeEnabled, true);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
pendingResult = binding.testExtension('debugPaint', <String, String>{ 'enabled': 'false' });
|
||||
await binding.flushMicrotasks();
|
||||
expect(binding.frameScheduled, isTrue);
|
||||
binding.doFrame();
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
result = await pendingResult;
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(debugPaintSizeEnabled, false);
|
||||
result = await binding.testExtension('debugPaint', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(debugPaintSizeEnabled, false);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - evict', () async {
|
||||
Map<String, String> result;
|
||||
bool completed;
|
||||
|
||||
completed = false;
|
||||
PlatformMessages.setMockBinaryMessageHandler('flutter/assets', (ByteData message) async {
|
||||
expect(UTF8.decode(message.buffer.asUint8List()), 'test');
|
||||
completed = true;
|
||||
return new ByteData(5); // 0x0000000000
|
||||
});
|
||||
bool data;
|
||||
data = await rootBundle.loadStructuredData<bool>('test', (String value) async { expect(value, '\x00\x00\x00\x00\x00'); return true; });
|
||||
expect(data, isTrue);
|
||||
expect(completed, isTrue);
|
||||
completed = false;
|
||||
data = await rootBundle.loadStructuredData('test', (String value) async { expect(true, isFalse); return null; });
|
||||
expect(data, isTrue);
|
||||
expect(completed, isFalse);
|
||||
result = await binding.testExtension('evict', <String, String>{ 'value': 'test' });
|
||||
expect(result, <String, String>{ 'value': '' });
|
||||
expect(completed, isFalse);
|
||||
data = await rootBundle.loadStructuredData<bool>('test', (String value) async { expect(value, '\x00\x00\x00\x00\x00'); return false; });
|
||||
expect(data, isFalse);
|
||||
expect(completed, isTrue);
|
||||
PlatformMessages.setMockBinaryMessageHandler('flutter/assets', null);
|
||||
});
|
||||
|
||||
test('Service extensions - exit', () async {
|
||||
// no test for _calling_ 'exit', because that should terminate the process!
|
||||
expect(binding.extensions.containsKey('exit'), isTrue);
|
||||
});
|
||||
|
||||
test('Service extensions - frameworkPresent', () async {
|
||||
Map<String, String> result;
|
||||
|
||||
result = await binding.testExtension('frameworkPresent', <String, String>{});
|
||||
expect(result, <String, String>{});
|
||||
});
|
||||
|
||||
test('Service extensions - repaintRainbow', () async {
|
||||
Map<String, String> result;
|
||||
Future<Map<String, String>> pendingResult;
|
||||
bool completed;
|
||||
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
expect(debugRepaintRainbowEnabled, false);
|
||||
result = await binding.testExtension('repaintRainbow', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(debugRepaintRainbowEnabled, false);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
pendingResult = binding.testExtension('repaintRainbow', <String, String>{ 'enabled': 'true' });
|
||||
completed = false;
|
||||
pendingResult.whenComplete(() { completed = true; });
|
||||
await binding.flushMicrotasks();
|
||||
expect(completed, true);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
result = await pendingResult;
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(debugRepaintRainbowEnabled, true);
|
||||
result = await binding.testExtension('repaintRainbow', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(debugRepaintRainbowEnabled, true);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
pendingResult = binding.testExtension('repaintRainbow', <String, String>{ 'enabled': 'false' });
|
||||
completed = false;
|
||||
pendingResult.whenComplete(() { completed = true; });
|
||||
await binding.flushMicrotasks();
|
||||
expect(completed, false);
|
||||
expect(binding.frameScheduled, isTrue);
|
||||
binding.doFrame();
|
||||
await binding.flushMicrotasks();
|
||||
expect(completed, true);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
result = await pendingResult;
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(debugRepaintRainbowEnabled, false);
|
||||
result = await binding.testExtension('repaintRainbow', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(debugRepaintRainbowEnabled, false);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - reassemble', () async {
|
||||
Map<String, String> result;
|
||||
Future<Map<String, String>> pendingResult;
|
||||
bool completed;
|
||||
|
||||
completed = false;
|
||||
expect(binding.reassembled, 0);
|
||||
pendingResult = binding.testExtension('reassemble', <String, String>{});
|
||||
pendingResult.whenComplete(() { completed = true; });
|
||||
await binding.flushMicrotasks();
|
||||
expect(binding.frameScheduled, isTrue);
|
||||
expect(completed, false);
|
||||
binding.doFrame();
|
||||
await binding.flushMicrotasks();
|
||||
expect(completed, true);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
result = await pendingResult;
|
||||
expect(result, <String, String>{});
|
||||
expect(binding.reassembled, 1);
|
||||
});
|
||||
|
||||
test('Service extensions - showPerformanceOverlay', () async {
|
||||
Map<String, String> result;
|
||||
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
expect(WidgetsApp.showPerformanceOverlayOverride, false);
|
||||
result = await binding.testExtension('showPerformanceOverlay', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.showPerformanceOverlayOverride, false);
|
||||
result = await binding.testExtension('showPerformanceOverlay', <String, String>{ 'enabled': 'true' });
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.showPerformanceOverlayOverride, true);
|
||||
result = await binding.testExtension('showPerformanceOverlay', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'true' });
|
||||
expect(WidgetsApp.showPerformanceOverlayOverride, true);
|
||||
result = await binding.testExtension('showPerformanceOverlay', <String, String>{ 'enabled': 'false' });
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.showPerformanceOverlayOverride, false);
|
||||
result = await binding.testExtension('showPerformanceOverlay', <String, String>{});
|
||||
expect(result, <String, String>{ 'enabled': 'false' });
|
||||
expect(WidgetsApp.showPerformanceOverlayOverride, false);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - timeDilation', () async {
|
||||
Map<String, String> result;
|
||||
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
expect(timeDilation, 1.0);
|
||||
result = await binding.testExtension('timeDilation', <String, String>{});
|
||||
expect(result, <String, String>{ 'timeDilation': '1.0' });
|
||||
expect(timeDilation, 1.0);
|
||||
result = await binding.testExtension('timeDilation', <String, String>{ 'timeDilation': '100.0' });
|
||||
expect(result, <String, String>{ 'timeDilation': '100.0' });
|
||||
expect(timeDilation, 100.0);
|
||||
result = await binding.testExtension('timeDilation', <String, String>{});
|
||||
expect(result, <String, String>{ 'timeDilation': '100.0' });
|
||||
expect(timeDilation, 100.0);
|
||||
result = await binding.testExtension('timeDilation', <String, String>{ 'timeDilation': '1.0' });
|
||||
expect(result, <String, String>{ 'timeDilation': '1.0' });
|
||||
expect(timeDilation, 1.0);
|
||||
result = await binding.testExtension('timeDilation', <String, String>{});
|
||||
expect(result, <String, String>{ 'timeDilation': '1.0' });
|
||||
expect(timeDilation, 1.0);
|
||||
expect(binding.frameScheduled, isFalse);
|
||||
});
|
||||
|
||||
test('Service extensions - posttest', () async {
|
||||
// If you add a service extension... TEST IT! :-)
|
||||
// ...then increment this number.
|
||||
expect(binding.extensions.length, 11);
|
||||
|
||||
expect(console, isEmpty);
|
||||
debugPrint = debugPrintThrottled;
|
||||
});
|
||||
}
|
@ -86,6 +86,14 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
||||
RendererBinding,
|
||||
// Services binding omitted to avoid dragging in the licenses code.
|
||||
WidgetsBinding {
|
||||
|
||||
TestWidgetsFlutterBinding() {
|
||||
debugPrint = debugPrintOverride;
|
||||
}
|
||||
|
||||
@protected
|
||||
DebugPrintCallback get debugPrintOverride => debugPrint;
|
||||
|
||||
/// Creates and initializes the binding. This function is
|
||||
/// idempotent; calling it a second time will just return the
|
||||
/// previously-created instance.
|
||||
@ -399,6 +407,10 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
||||
assert(debugAssertNoTransientCallbacks(
|
||||
'An animation is still running even after the widget tree was disposed.'
|
||||
));
|
||||
assert(debugAssertAllFoundationVarsUnset(
|
||||
'The value of a foundation debug variable was changed by the test.',
|
||||
debugPrintOverride: debugPrintOverride,
|
||||
));
|
||||
assert(debugAssertAllRenderVarsUnset(
|
||||
'The value of a rendering debug variable was changed by the test.'
|
||||
));
|
||||
@ -431,7 +443,6 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
|
||||
class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
|
||||
@override
|
||||
void initInstances() {
|
||||
debugPrint = debugPrintSynchronously;
|
||||
super.initInstances();
|
||||
ui.window.onBeginFrame = null;
|
||||
}
|
||||
@ -439,6 +450,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
|
||||
FakeAsync _fakeAsync;
|
||||
Clock _clock;
|
||||
|
||||
@override
|
||||
DebugPrintCallback get debugPrintOverride => debugPrintSynchronously;
|
||||
|
||||
@override
|
||||
test_package.Timeout get defaultTestTimeout => const test_package.Timeout(const Duration(seconds: 5));
|
||||
|
||||
|
@ -82,7 +82,7 @@ Future<Null> _testFile(String testName, int wantedExitCode, String workingDirect
|
||||
expect(haveSeenStdErrMarker, isFalse);
|
||||
haveSeenStdErrMarker = true;
|
||||
}
|
||||
expect(outputLine, matches(expectationLine));
|
||||
expect(outputLine, matches(expectationLine), verbose: true, reason: 'Full output:\n- - - -----8<----- - - -\n${output.join("\n")}\n- - - -----8<----- - - -');
|
||||
expectationLineNumber += 1;
|
||||
outputLineNumber += 1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user