Print DevTools inspector links in RenderFlex Overflow errors (#74251)
This commit is contained in:
parent
eeb7c261f2
commit
b45088c0cf
@ -245,6 +245,15 @@ abstract class BindingBase {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
registerStringServiceExtension(
|
||||||
|
name: 'activeDevToolsServerAddress',
|
||||||
|
getter: () async => activeDevToolsServerAddress ?? '',
|
||||||
|
setter: (String serverAddress) async {
|
||||||
|
activeDevToolsServerAddress = serverAddress;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
assert(() {
|
assert(() {
|
||||||
|
@ -109,3 +109,7 @@ String debugFormatDouble(double? value) {
|
|||||||
/// * [WidgetsApp], which uses the [debugBrightnessOverride] setting in debug mode
|
/// * [WidgetsApp], which uses the [debugBrightnessOverride] setting in debug mode
|
||||||
/// to construct a [MediaQueryData].
|
/// to construct a [MediaQueryData].
|
||||||
ui.Brightness? debugBrightnessOverride;
|
ui.Brightness? debugBrightnessOverride;
|
||||||
|
|
||||||
|
/// The address for the active DevTools server used for debugging this
|
||||||
|
/// application.
|
||||||
|
String? activeDevToolsServerAddress;
|
||||||
|
@ -713,6 +713,12 @@ mixin WidgetInspectorService {
|
|||||||
_instance = instance;
|
_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about the VM service protocol for the running application.
|
||||||
|
///
|
||||||
|
/// This information is necessary to provide Flutter DevTools deep links in
|
||||||
|
/// error messages.
|
||||||
|
developer.ServiceProtocolInfo? _serviceInfo;
|
||||||
|
|
||||||
static bool _debugServiceExtensionsRegistered = false;
|
static bool _debugServiceExtensionsRegistered = false;
|
||||||
|
|
||||||
/// Ground truth tracking what object(s) are currently selected used by both
|
/// Ground truth tracking what object(s) are currently selected used by both
|
||||||
@ -976,6 +982,12 @@ mixin WidgetInspectorService {
|
|||||||
/// * [BindingBase.initServiceExtensions], which explains when service
|
/// * [BindingBase.initServiceExtensions], which explains when service
|
||||||
/// extensions can be used.
|
/// extensions can be used.
|
||||||
void initServiceExtensions(_RegisterServiceExtensionCallback registerServiceExtensionCallback) {
|
void initServiceExtensions(_RegisterServiceExtensionCallback registerServiceExtensionCallback) {
|
||||||
|
if (!kIsWeb) {
|
||||||
|
developer.Service.getInfo().then((developer.ServiceProtocolInfo info) {
|
||||||
|
_serviceInfo = info;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_structuredExceptionHandler = _reportError;
|
_structuredExceptionHandler = _reportError;
|
||||||
if (isStructuredErrorsEnabled()) {
|
if (isStructuredErrorsEnabled()) {
|
||||||
FlutterError.onError = _structuredExceptionHandler;
|
FlutterError.onError = _structuredExceptionHandler;
|
||||||
@ -1385,6 +1397,46 @@ mixin WidgetInspectorService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a DevTools uri linking to a specific element on the inspector page.
|
||||||
|
String? _devToolsInspectorUriForElement(Object? object) {
|
||||||
|
if (activeDevToolsServerAddress != null && _serviceInfo != null) {
|
||||||
|
final Uri? vmServiceUri = _serviceInfo!.serverUri;
|
||||||
|
if (vmServiceUri != null) {
|
||||||
|
final String? inspectorRef = toId(object, _consoleObjectGroup);
|
||||||
|
if (inspectorRef != null) {
|
||||||
|
return devToolsInspectorUri(vmServiceUri, inspectorRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the DevTools inspector uri for the given vm service connection and
|
||||||
|
/// inspector reference.
|
||||||
|
@visibleForTesting
|
||||||
|
String devToolsInspectorUri(Uri vmServiceUri, String inspectorRef) {
|
||||||
|
final Uri uri = Uri.parse(activeDevToolsServerAddress!).replace(
|
||||||
|
queryParameters: <String, dynamic>{
|
||||||
|
'uri': '$vmServiceUri',
|
||||||
|
'inspectorRef': inspectorRef,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// We cannot add the '/#/inspector' path by means of
|
||||||
|
// [Uri.replace(path: '/#/inspector')] because the '#' character will be
|
||||||
|
// encoded when we try to print the url as a string. DevTools will not
|
||||||
|
// load properly if this character is encoded in the url.
|
||||||
|
// Related: https://github.com/flutter/devtools/issues/2475.
|
||||||
|
final String devToolsInspectorUri = uri.toString();
|
||||||
|
final int startQueryParamIndex = devToolsInspectorUri.indexOf('?');
|
||||||
|
// The query parameter character '?' should be present because we manually
|
||||||
|
// added query parameters above.
|
||||||
|
assert(startQueryParamIndex != -1);
|
||||||
|
return '${devToolsInspectorUri.substring(0, startQueryParamIndex)}'
|
||||||
|
'/#/inspector'
|
||||||
|
'${devToolsInspectorUri.substring(startQueryParamIndex)}';
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns JSON representing the chain of [DiagnosticsNode] instances from
|
/// Returns JSON representing the chain of [DiagnosticsNode] instances from
|
||||||
/// root of thee tree to the [Element] or [RenderObject] matching `id`.
|
/// root of thee tree to the [Element] or [RenderObject] matching `id`.
|
||||||
///
|
///
|
||||||
@ -2877,15 +2929,26 @@ Iterable<DiagnosticsNode> _describeRelevantUserCode(Element element) {
|
|||||||
// TODO(chunhtai): should print out all the widgets that are about to cross
|
// TODO(chunhtai): should print out all the widgets that are about to cross
|
||||||
// package boundaries.
|
// package boundaries.
|
||||||
if (debugIsLocalCreationLocation(target)) {
|
if (debugIsLocalCreationLocation(target)) {
|
||||||
nodes.add(
|
|
||||||
|
DiagnosticsNode? devToolsDiagnostic;
|
||||||
|
final String? devToolsInspectorUri =
|
||||||
|
WidgetInspectorService.instance._devToolsInspectorUriForElement(target);
|
||||||
|
if (devToolsInspectorUri != null) {
|
||||||
|
devToolsDiagnostic = DiagnosticsNode.message(
|
||||||
|
'To inspect this widget in Flutter DevTools, visit: $devToolsInspectorUri',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.addAll(<DiagnosticsNode>[
|
||||||
DiagnosticsBlock(
|
DiagnosticsBlock(
|
||||||
name: 'The relevant error-causing widget was',
|
name: 'The relevant error-causing widget was',
|
||||||
children: <DiagnosticsNode>[
|
children: <DiagnosticsNode>[
|
||||||
ErrorDescription('${target.widget.toStringShort()} ${_describeCreationLocation(target)}'),
|
ErrorDescription('${target.widget.toStringShort()} ${_describeCreationLocation(target)}'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
ErrorSpacer(),
|
||||||
nodes.add(ErrorSpacer());
|
if (devToolsDiagnostic != null) ...<DiagnosticsNode>[devToolsDiagnostic, ErrorSpacer()],
|
||||||
|
]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -167,7 +167,7 @@ void main() {
|
|||||||
const int disabledExtensions = kIsWeb ? 2 : 0;
|
const int disabledExtensions = kIsWeb ? 2 : 0;
|
||||||
// If you add a service extension... TEST IT! :-)
|
// If you add a service extension... TEST IT! :-)
|
||||||
// ...then increment this number.
|
// ...then increment this number.
|
||||||
expect(binding.extensions.length, 29 + widgetInspectorExtensionCount - disabledExtensions);
|
expect(binding.extensions.length, 30 + widgetInspectorExtensionCount - disabledExtensions);
|
||||||
|
|
||||||
expect(console, isEmpty);
|
expect(console, isEmpty);
|
||||||
debugPrint = debugPrintThrottled;
|
debugPrint = debugPrintThrottled;
|
||||||
@ -758,4 +758,17 @@ void main() {
|
|||||||
|
|
||||||
expect(brightnessValue, 'Brightness.light');
|
expect(brightnessValue, 'Brightness.light');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Service extensions - activeDevToolsServerAddress', () async {
|
||||||
|
Map<String, dynamic> result;
|
||||||
|
result = await binding.testExtension('activeDevToolsServerAddress', <String, String>{});
|
||||||
|
String serverAddress = result['value'] as String;
|
||||||
|
expect(serverAddress, '');
|
||||||
|
result = await binding.testExtension('activeDevToolsServerAddress', <String, String>{'value': 'http://127.0.0.1:9101'});
|
||||||
|
serverAddress = result['value'] as String;
|
||||||
|
expect(serverAddress, 'http://127.0.0.1:9101');
|
||||||
|
result = await binding.testExtension('activeDevToolsServerAddress', <String, String>{'value': 'http://127.0.0.1:9102'});
|
||||||
|
serverAddress = result['value'] as String;
|
||||||
|
expect(serverAddress, 'http://127.0.0.1:9102');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -2825,6 +2825,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
|
|||||||
expect(debugIsLocalCreationLocation(paddingElement.widget), isFalse);
|
expect(debugIsLocalCreationLocation(paddingElement.widget), isFalse);
|
||||||
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // Test requires --track-widget-creation flag.
|
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // Test requires --track-widget-creation flag.
|
||||||
|
|
||||||
|
test('devToolsInspectorUri test', () {
|
||||||
|
activeDevToolsServerAddress = 'http://127.0.0.1:9100';
|
||||||
|
expect(
|
||||||
|
WidgetInspectorService.instance.devToolsInspectorUri(
|
||||||
|
Uri.parse('http://127.0.0.1:55269/798ay5al_FM=/'),
|
||||||
|
'inspector-0',
|
||||||
|
),
|
||||||
|
equals('http://127.0.0.1:9100/#/inspector?uri=http%3A%2F%2F127.0.0.1%3A55269%2F798ay5al_FM%3D%2F&inspectorRef=inspector-0'),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,6 +1284,27 @@ abstract class ResidentRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> maybeCallDevToolsUriServiceExtension() async {
|
||||||
|
_devToolsLauncher ??= DevtoolsLauncher.instance;
|
||||||
|
if (_devToolsLauncher.activeDevToolsServer != null) {
|
||||||
|
|
||||||
|
await Future.wait(<Future<vm_service.Isolate>>[
|
||||||
|
for (final FlutterDevice device in flutterDevices)
|
||||||
|
waitForExtension(device.vmService, 'ext.flutter.activeDevToolsServerAddress'),
|
||||||
|
]);
|
||||||
|
try {
|
||||||
|
unawaited(invokeFlutterExtensionRpcRawOnFirstIsolate(
|
||||||
|
'ext.flutter.activeDevToolsServerAddress',
|
||||||
|
params: <String, dynamic>{
|
||||||
|
'value': _devToolsLauncher.activeDevToolsServer.uri.toString(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
} on Exception catch (e) {
|
||||||
|
globals.printError(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> shutdownDevTools() async {
|
Future<void> shutdownDevTools() async {
|
||||||
await _devToolsLauncher?.close();
|
await _devToolsLauncher?.close();
|
||||||
_devToolsLauncher = null;
|
_devToolsLauncher = null;
|
||||||
@ -1391,6 +1412,28 @@ abstract class ResidentRunner {
|
|||||||
|
|
||||||
// Clears the screen.
|
// Clears the screen.
|
||||||
void clearScreen() => globals.logger.clear();
|
void clearScreen() => globals.logger.clear();
|
||||||
|
|
||||||
|
Future<vm_service.Isolate> waitForExtension(vm_service.VmService vmService, String extension) async {
|
||||||
|
final Completer<void> completer = Completer<void>();
|
||||||
|
try {
|
||||||
|
await vmService.streamListen(vm_service.EventStreams.kExtension);
|
||||||
|
} on Exception {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
vmService.onExtensionEvent.listen((vm_service.Event event) {
|
||||||
|
if (event.json['extensionKind'] == 'Flutter.FrameworkInitialization') {
|
||||||
|
completer.complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
final vm_service.IsolateRef isolateRef = (await vmService.getVM()).isolates.first;
|
||||||
|
final vm_service.Isolate isolate = await vmService.getIsolate(isolateRef.id);
|
||||||
|
if (isolate.extensionRPCs.contains(extension)) {
|
||||||
|
return isolate;
|
||||||
|
}
|
||||||
|
await completer.future;
|
||||||
|
return isolate;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OperationResult {
|
class OperationResult {
|
||||||
|
@ -6,6 +6,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import 'base/common.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'build_info.dart';
|
import 'build_info.dart';
|
||||||
import 'device.dart';
|
import 'device.dart';
|
||||||
@ -120,6 +121,10 @@ class ColdRunner extends ResidentRunner {
|
|||||||
appFinished();
|
appFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debuggingEnabled) {
|
||||||
|
unawaited(maybeCallDevToolsUriServiceExtension());
|
||||||
|
}
|
||||||
|
|
||||||
appStartedCompleter?.complete();
|
appStartedCompleter?.complete();
|
||||||
|
|
||||||
writeVmServiceFile();
|
writeVmServiceFile();
|
||||||
@ -161,6 +166,9 @@ class ColdRunner extends ResidentRunner {
|
|||||||
globals.printTrace('Connected to $view.');
|
globals.printTrace('Connected to $view.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unawaited(maybeCallDevToolsUriServiceExtension());
|
||||||
|
|
||||||
appStartedCompleter?.complete();
|
appStartedCompleter?.complete();
|
||||||
if (stayResident) {
|
if (stayResident) {
|
||||||
return waitForAppToFinish();
|
return waitForAppToFinish();
|
||||||
|
@ -8,6 +8,7 @@ import 'package:vm_service/vm_service.dart' as vm_service;
|
|||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:pool/pool.dart';
|
import 'package:pool/pool.dart';
|
||||||
|
|
||||||
|
import 'base/common.dart';
|
||||||
import 'base/context.dart';
|
import 'base/context.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'base/logger.dart';
|
import 'base/logger.dart';
|
||||||
@ -214,6 +215,9 @@ class HotRunner extends ResidentRunner {
|
|||||||
globals.printError('Error initializing DevFS: $error');
|
globals.printError('Error initializing DevFS: $error');
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unawaited(maybeCallDevToolsUriServiceExtension());
|
||||||
|
|
||||||
final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start();
|
final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start();
|
||||||
final UpdateFSReport devfsResult = await _updateDevFS(fullRestart: true);
|
final UpdateFSReport devfsResult = await _updateDevFS(fullRestart: true);
|
||||||
_addBenchmarkData(
|
_addBenchmarkData(
|
||||||
|
@ -72,4 +72,30 @@ void main() {
|
|||||||
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
await _flutterAttach.attach(_flutterRun.vmServicePort);
|
||||||
await _flutterAttach.hotReload();
|
await _flutterAttach.hotReload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('sets activeDevToolsServerAddress extension', () async {
|
||||||
|
await _flutterRun.run(
|
||||||
|
startPaused: true,
|
||||||
|
withDebugger: true,
|
||||||
|
);
|
||||||
|
await _flutterRun.resume();
|
||||||
|
await pollForServiceExtensionValue(
|
||||||
|
testDriver: _flutterRun,
|
||||||
|
extension: 'ext.flutter.activeDevToolsServerAddress',
|
||||||
|
continuePollingValue: '',
|
||||||
|
expectedValue: 'http://127.0.0.1:9100',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Attach with a different DevTools server address.
|
||||||
|
await _flutterAttach.attach(
|
||||||
|
_flutterRun.vmServicePort,
|
||||||
|
additionalCommandArgs: <String>['--devtools-server-address', 'http://127.0.0.1:9110'],
|
||||||
|
);
|
||||||
|
await pollForServiceExtensionValue(
|
||||||
|
testDriver: _flutterAttach,
|
||||||
|
extension: 'ext.flutter.activeDevToolsServerAddress',
|
||||||
|
continuePollingValue: '',
|
||||||
|
expectedValue: 'http://127.0.0.1:9110',
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -53,4 +53,19 @@ void main() {
|
|||||||
await _flutter.run(pidFile: pidFile);
|
await _flutter.run(pidFile: pidFile);
|
||||||
expect(pidFile.existsSync(), isTrue);
|
expect(pidFile.existsSync(), isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('sets activeDevToolsServerAddress extension', () async {
|
||||||
|
await _flutter.run(
|
||||||
|
startPaused: true,
|
||||||
|
withDebugger: true,
|
||||||
|
additionalCommandArgs: <String>['--devtools-server-address', 'http://127.0.0.1:9110'],
|
||||||
|
);
|
||||||
|
await _flutter.resume();
|
||||||
|
await pollForServiceExtensionValue(
|
||||||
|
testDriver: _flutter,
|
||||||
|
extension: 'ext.flutter.activeDevToolsServerAddress',
|
||||||
|
continuePollingValue: '',
|
||||||
|
expectedValue: 'http://127.0.0.1:9110',
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,19 @@ abstract class FlutterTestDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Response> callServiceExtension(
|
||||||
|
String extension, {
|
||||||
|
Map<String, dynamic> args = const <String, dynamic>{},
|
||||||
|
}) async {
|
||||||
|
final VmService vmService = await vmServiceConnectUri('ws://localhost:$vmServicePort/ws');
|
||||||
|
final Isolate isolate = await waitForExtension(vmService, 'ext.flutter.activeDevToolsServerAddress');
|
||||||
|
return await vmService.callServiceExtension(
|
||||||
|
extension,
|
||||||
|
isolateId: isolate.id,
|
||||||
|
args: args,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<int> quit() => _killGracefully();
|
Future<int> quit() => _killGracefully();
|
||||||
|
|
||||||
Future<int> _killGracefully() async {
|
Future<int> _killGracefully() async {
|
||||||
@ -493,6 +506,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
|
|||||||
bool pauseOnExceptions = false,
|
bool pauseOnExceptions = false,
|
||||||
File pidFile,
|
File pidFile,
|
||||||
bool singleWidgetReloads = false,
|
bool singleWidgetReloads = false,
|
||||||
|
List<String> additionalCommandArgs,
|
||||||
}) async {
|
}) async {
|
||||||
await _setupProcess(
|
await _setupProcess(
|
||||||
<String>[
|
<String>[
|
||||||
@ -505,6 +519,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
|
|||||||
'flutter-tester',
|
'flutter-tester',
|
||||||
'--debug-port',
|
'--debug-port',
|
||||||
'$port',
|
'$port',
|
||||||
|
...?additionalCommandArgs,
|
||||||
],
|
],
|
||||||
withDebugger: withDebugger,
|
withDebugger: withDebugger,
|
||||||
startPaused: startPaused,
|
startPaused: startPaused,
|
||||||
@ -825,7 +840,7 @@ class SourcePosition {
|
|||||||
final int column;
|
final int column;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Isolate> waitForExtension(VmService vmService) async {
|
Future<Isolate> waitForExtension(VmService vmService, String extension) async {
|
||||||
final Completer<void> completer = Completer<void>();
|
final Completer<void> completer = Completer<void>();
|
||||||
await vmService.streamListen(EventStreams.kExtension);
|
await vmService.streamListen(EventStreams.kExtension);
|
||||||
vmService.onExtensionEvent.listen((Event event) {
|
vmService.onExtensionEvent.listen((Event event) {
|
||||||
@ -835,7 +850,7 @@ Future<Isolate> waitForExtension(VmService vmService) async {
|
|||||||
});
|
});
|
||||||
final IsolateRef isolateRef = (await vmService.getVM()).isolates.first;
|
final IsolateRef isolateRef = (await vmService.getVM()).isolates.first;
|
||||||
final Isolate isolate = await vmService.getIsolate(isolateRef.id);
|
final Isolate isolate = await vmService.getIsolate(isolateRef.id);
|
||||||
if (isolate.extensionRPCs.contains('ext.flutter.brightnessOverride')) {
|
if (isolate.extensionRPCs.contains(extension)) {
|
||||||
return isolate;
|
return isolate;
|
||||||
}
|
}
|
||||||
await completer.future;
|
await completer.future;
|
||||||
|
@ -6,9 +6,12 @@ import 'package:file/file.dart';
|
|||||||
import 'package:file/local.dart';
|
import 'package:file/local.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart';
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/base/platform.dart';
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
|
import 'package:vm_service/vm_service.dart';
|
||||||
|
|
||||||
import '../src/common.dart';
|
import '../src/common.dart';
|
||||||
|
import 'test_driver.dart';
|
||||||
|
|
||||||
/// The [FileSystem] for the integration test environment.
|
/// The [FileSystem] for the integration test environment.
|
||||||
const FileSystem fileSystem = LocalFileSystem();
|
const FileSystem fileSystem = LocalFileSystem();
|
||||||
@ -73,3 +76,21 @@ List<String> getLocalEngineArguments() {
|
|||||||
'--local-engine-src-path=${platform.environment[kLocalEngineLocation]}',
|
'--local-engine-src-path=${platform.environment[kLocalEngineLocation]}',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> pollForServiceExtensionValue<T>({
|
||||||
|
@required FlutterTestDriver testDriver,
|
||||||
|
@required String extension,
|
||||||
|
@required T continuePollingValue,
|
||||||
|
@required T expectedValue,
|
||||||
|
String valueKey = 'value',
|
||||||
|
}) async {
|
||||||
|
for (int i = 10; i < 10; i++) {
|
||||||
|
final Response response = await testDriver.callServiceExtension(extension);
|
||||||
|
if (response.json[valueKey] == continuePollingValue) {
|
||||||
|
await Future<void>.delayed(const Duration(seconds: 1));
|
||||||
|
} else {
|
||||||
|
expect(response.json[valueKey], equals(expectedValue));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -96,7 +96,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('ext.flutter.brightnessOverride can toggle window brightness', () async {
|
testWithoutContext('ext.flutter.brightnessOverride can toggle window brightness', () async {
|
||||||
final Isolate isolate = await waitForExtension(vmService);
|
final Isolate isolate = await waitForExtension(vmService, 'ext.flutter.brightnessOverride');
|
||||||
final Response response = await vmService.callServiceExtension(
|
final Response response = await vmService.callServiceExtension(
|
||||||
'ext.flutter.brightnessOverride',
|
'ext.flutter.brightnessOverride',
|
||||||
isolateId: isolate.id,
|
isolateId: isolate.id,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user