[flutter_tools] Ensure flutter daemon clients can detect preview device (#140112)
Part of https://github.com/flutter/flutter/issues/130277
This commit is contained in:
parent
90badf7050
commit
674fbd26bc
@ -62,14 +62,22 @@ The `shutdown()` command will terminate the flutter daemon. It is not necessary
|
|||||||
|
|
||||||
#### daemon.getSupportedPlatforms
|
#### daemon.getSupportedPlatforms
|
||||||
|
|
||||||
The `getSupportedPlatforms()` command will enumerate all platforms supported by the project located at the provided `projectRoot`. It returns a Map with the key 'platforms' containing a List of strings which describe the set of all possibly supported platforms. Possible values include:
|
The `getSupportedPlatforms()` command will enumerate all platforms supported
|
||||||
- android
|
by the project located at the provided `projectRoot`. It returns a Map with
|
||||||
- ios
|
the key 'platformTypes' containing a Map of platform types to a Map with the
|
||||||
- linux #experimental
|
following entries:
|
||||||
- macos #experimental
|
|
||||||
- windows #experimental
|
- isSupported (bool) - whether or not the platform type is supported
|
||||||
- fuchsia #experimental
|
- reasons (List<Map<String, Object>>, only included if isSupported == false) - a list of reasons why the platform is not supported
|
||||||
- web #experimental
|
|
||||||
|
The schema for each element in `reasons` is:
|
||||||
|
|
||||||
|
- reasonText (String) - a description of why the platform is not supported
|
||||||
|
- fixText (String) - human readable instructions of how to fix this reason
|
||||||
|
- fixCode (String) - stringified version of the `_ReasonCode` enum. To be used
|
||||||
|
by daemon clients who intend to auto-fix.
|
||||||
|
|
||||||
|
The possible platform types are the `PlatformType` enumeration in the lib/src/device.dart library.
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
|
@ -416,36 +416,167 @@ class DaemonDomain extends Domain {
|
|||||||
/// is correct.
|
/// is correct.
|
||||||
Future<Map<String, Object>> getSupportedPlatforms(Map<String, Object?> args) async {
|
Future<Map<String, Object>> getSupportedPlatforms(Map<String, Object?> args) async {
|
||||||
final String? projectRoot = _getStringArg(args, 'projectRoot', required: true);
|
final String? projectRoot = _getStringArg(args, 'projectRoot', required: true);
|
||||||
final List<String> result = <String>[];
|
final List<String> platformTypes = <String>[];
|
||||||
|
final Map<String, Object> platformTypesMap = <String, Object>{};
|
||||||
try {
|
try {
|
||||||
final FlutterProject flutterProject = FlutterProject.fromDirectory(globals.fs.directory(projectRoot));
|
final FlutterProject flutterProject = FlutterProject.fromDirectory(globals.fs.directory(projectRoot));
|
||||||
final Set<SupportedPlatform> supportedPlatforms = flutterProject.getSupportedPlatforms().toSet();
|
final Set<SupportedPlatform> supportedPlatforms = flutterProject.getSupportedPlatforms().toSet();
|
||||||
if (featureFlags.isLinuxEnabled && supportedPlatforms.contains(SupportedPlatform.linux)) {
|
|
||||||
result.add('linux');
|
void handlePlatformType(
|
||||||
|
PlatformType platform,
|
||||||
|
) {
|
||||||
|
final List<Map<String, Object>> reasons = <Map<String, Object>>[];
|
||||||
|
switch (platform) {
|
||||||
|
case PlatformType.linux:
|
||||||
|
if (!featureFlags.isLinuxEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Linux feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-linux-desktop"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.isMacOSEnabled && supportedPlatforms.contains(SupportedPlatform.macos)) {
|
if (!supportedPlatforms.contains(SupportedPlatform.linux)) {
|
||||||
result.add('macos');
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Linux platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=linux ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.isWindowsEnabled && supportedPlatforms.contains(SupportedPlatform.windows)) {
|
case PlatformType.macos:
|
||||||
result.add('windows');
|
if (!featureFlags.isMacOSEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the macOS feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-macos-desktop"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.isIOSEnabled && supportedPlatforms.contains(SupportedPlatform.ios)) {
|
if (!supportedPlatforms.contains(SupportedPlatform.macos)) {
|
||||||
result.add('ios');
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the macOS platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=macos ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.isAndroidEnabled && supportedPlatforms.contains(SupportedPlatform.android)) {
|
case PlatformType.windows:
|
||||||
result.add('android');
|
if (!featureFlags.isWindowsEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Windows feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-windows-desktop"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.isWebEnabled && supportedPlatforms.contains(SupportedPlatform.web)) {
|
if (!supportedPlatforms.contains(SupportedPlatform.windows)) {
|
||||||
result.add('web');
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Windows platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=windows ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.isFuchsiaEnabled && supportedPlatforms.contains(SupportedPlatform.fuchsia)) {
|
case PlatformType.ios:
|
||||||
result.add('fuchsia');
|
if (!featureFlags.isIOSEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the iOS feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-ios"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (featureFlags.areCustomDevicesEnabled) {
|
if (!supportedPlatforms.contains(SupportedPlatform.ios)) {
|
||||||
result.add('custom');
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the iOS platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=ios ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
case PlatformType.android:
|
||||||
|
if (!featureFlags.isAndroidEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Android feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-android"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!supportedPlatforms.contains(SupportedPlatform.android)) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Android platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=android ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case PlatformType.web:
|
||||||
|
if (!featureFlags.isWebEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Web feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-web"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!supportedPlatforms.contains(SupportedPlatform.web)) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Web platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=web ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case PlatformType.fuchsia:
|
||||||
|
if (!featureFlags.isFuchsiaEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Fuchsia feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-fuchsia"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!supportedPlatforms.contains(SupportedPlatform.fuchsia)) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Fuchsia platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=fuchsia ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case PlatformType.custom:
|
||||||
|
if (!featureFlags.areCustomDevicesEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the custom devices feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-custom-devices"',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case PlatformType.windowsPreview:
|
||||||
|
// TODO(fujino): detect if there any plugins with native code
|
||||||
|
if (!featureFlags.isPreviewDeviceEnabled) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Preview Device feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-flutter-preview',
|
||||||
|
'fixCode': _ReasonCode.config.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!supportedPlatforms.contains(SupportedPlatform.windows)) {
|
||||||
|
reasons.add(<String, Object>{
|
||||||
|
'reasonText': 'the Windows platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=windows ." in your application directory',
|
||||||
|
'fixCode': _ReasonCode.create.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reasons.isEmpty) {
|
||||||
|
platformTypes.add(platform.name);
|
||||||
|
platformTypesMap[platform.name] = const <String, Object>{
|
||||||
|
'isSupported': true,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
platformTypesMap[platform.name] = <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': reasons,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformType.values.forEach(handlePlatformType);
|
||||||
|
|
||||||
return <String, Object>{
|
return <String, Object>{
|
||||||
'platforms': result,
|
// TODO(fujino): delete this key https://github.com/flutter/flutter/issues/140473
|
||||||
|
'platforms': platformTypes,
|
||||||
|
'platformTypes': platformTypesMap,
|
||||||
};
|
};
|
||||||
} on Exception catch (err, stackTrace) {
|
} on Exception catch (err, stackTrace) {
|
||||||
sendEvent('log', <String, Object?>{
|
sendEvent('log', <String, Object?>{
|
||||||
@ -454,12 +585,16 @@ class DaemonDomain extends Domain {
|
|||||||
'error': true,
|
'error': true,
|
||||||
});
|
});
|
||||||
// On any sort of failure, fall back to Android and iOS for backwards
|
// On any sort of failure, fall back to Android and iOS for backwards
|
||||||
// comparability.
|
// compatibility.
|
||||||
return <String, Object>{
|
return const <String, Object>{
|
||||||
'platforms': <String>[
|
'platforms': <String>[
|
||||||
'android',
|
'android',
|
||||||
'ios',
|
'ios',
|
||||||
],
|
],
|
||||||
|
'platformTypes': <String, Object>{
|
||||||
|
'android': <String, Object>{'isSupported': true},
|
||||||
|
'ios': <String, Object>{'isSupported': true},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,6 +605,14 @@ class DaemonDomain extends Domain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The reason a [PlatformType] is not currently supported.
|
||||||
|
///
|
||||||
|
/// The [name] of this value will be sent as a response to daemon client.
|
||||||
|
enum _ReasonCode {
|
||||||
|
create,
|
||||||
|
config,
|
||||||
|
}
|
||||||
|
|
||||||
typedef RunOrAttach = Future<void> Function({
|
typedef RunOrAttach = Future<void> Function({
|
||||||
Completer<DebugConnectionInfo>? connectionInfoCompleter,
|
Completer<DebugConnectionInfo>? connectionInfoCompleter,
|
||||||
Completer<void>? appStartedCompleter,
|
Completer<void>? appStartedCompleter,
|
||||||
|
@ -45,34 +45,20 @@ enum Category {
|
|||||||
|
|
||||||
/// The platform sub-folder that a device type supports.
|
/// The platform sub-folder that a device type supports.
|
||||||
enum PlatformType {
|
enum PlatformType {
|
||||||
web._('web'),
|
web,
|
||||||
android._('android'),
|
android,
|
||||||
ios._('ios'),
|
ios,
|
||||||
linux._('linux'),
|
linux,
|
||||||
macos._('macos'),
|
macos,
|
||||||
windows._('windows'),
|
windows,
|
||||||
fuchsia._('fuchsia'),
|
fuchsia,
|
||||||
custom._('custom');
|
custom,
|
||||||
|
windowsPreview;
|
||||||
const PlatformType._(this.value);
|
|
||||||
|
|
||||||
final String value;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => value;
|
String toString() => name;
|
||||||
|
|
||||||
static PlatformType? fromString(String platformType) {
|
static PlatformType? fromString(String platformType) => values.asNameMap()[platformType];
|
||||||
return const <String, PlatformType>{
|
|
||||||
'web': web,
|
|
||||||
'android': android,
|
|
||||||
'ios': ios,
|
|
||||||
'linux': linux,
|
|
||||||
'macos': macos,
|
|
||||||
'windows': windows,
|
|
||||||
'fuchsia': fuchsia,
|
|
||||||
'custom': custom,
|
|
||||||
}[platformType];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A discovery mechanism for flutter-supported development devices.
|
/// A discovery mechanism for flutter-supported development devices.
|
||||||
|
@ -29,7 +29,7 @@ BundleBuilder _defaultBundleBuilder() {
|
|||||||
return BundleBuilder();
|
return BundleBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
class PreviewDeviceDiscovery extends DeviceDiscovery {
|
class PreviewDeviceDiscovery extends PollingDeviceDiscovery {
|
||||||
PreviewDeviceDiscovery({
|
PreviewDeviceDiscovery({
|
||||||
required Platform platform,
|
required Platform platform,
|
||||||
required Artifacts artifacts,
|
required Artifacts artifacts,
|
||||||
@ -42,7 +42,8 @@ class PreviewDeviceDiscovery extends DeviceDiscovery {
|
|||||||
_processManager = processManager,
|
_processManager = processManager,
|
||||||
_fileSystem = fileSystem,
|
_fileSystem = fileSystem,
|
||||||
_platform = platform,
|
_platform = platform,
|
||||||
_features = featureFlags;
|
_features = featureFlags,
|
||||||
|
super('Flutter preview device');
|
||||||
|
|
||||||
final Platform _platform;
|
final Platform _platform;
|
||||||
final Artifacts _artifacts;
|
final Artifacts _artifacts;
|
||||||
@ -61,9 +62,8 @@ class PreviewDeviceDiscovery extends DeviceDiscovery {
|
|||||||
List<String> get wellKnownIds => <String>['preview'];
|
List<String> get wellKnownIds => <String>['preview'];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<Device>> devices({
|
Future<List<Device>> pollingGetDevices({
|
||||||
Duration? timeout,
|
Duration? timeout,
|
||||||
DeviceDiscoveryFilter? filter,
|
|
||||||
}) async {
|
}) async {
|
||||||
final File previewBinary = _fileSystem.file(_artifacts.getArtifactPath(Artifact.flutterPreviewDevice));
|
final File previewBinary = _fileSystem.file(_artifacts.getArtifactPath(Artifact.flutterPreviewDevice));
|
||||||
if (!previewBinary.existsSync()) {
|
if (!previewBinary.existsSync()) {
|
||||||
@ -76,16 +76,8 @@ class PreviewDeviceDiscovery extends DeviceDiscovery {
|
|||||||
processManager: _processManager,
|
processManager: _processManager,
|
||||||
previewBinary: previewBinary,
|
previewBinary: previewBinary,
|
||||||
);
|
);
|
||||||
final bool matchesRequirements;
|
|
||||||
if (!_features.isPreviewDeviceEnabled) {
|
|
||||||
matchesRequirements = false;
|
|
||||||
} else if (filter == null) {
|
|
||||||
matchesRequirements = true;
|
|
||||||
} else {
|
|
||||||
matchesRequirements = await filter.matchesRequirements(device);
|
|
||||||
}
|
|
||||||
return <Device>[
|
return <Device>[
|
||||||
if (matchesRequirements)
|
if (_features.isPreviewDeviceEnabled)
|
||||||
device,
|
device,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -114,7 +106,7 @@ class PreviewDevice extends Device {
|
|||||||
_fileSystem = fileSystem,
|
_fileSystem = fileSystem,
|
||||||
_bundleBuilderFactory = builderFactory,
|
_bundleBuilderFactory = builderFactory,
|
||||||
_artifacts = artifacts,
|
_artifacts = artifacts,
|
||||||
super('preview', ephemeral: false, category: Category.desktop, platformType: PlatformType.custom);
|
super('preview', ephemeral: false, category: Category.desktop, platformType: PlatformType.windowsPreview);
|
||||||
|
|
||||||
final ProcessManager _processManager;
|
final ProcessManager _processManager;
|
||||||
final Logger _logger;
|
final Logger _logger;
|
||||||
@ -161,7 +153,7 @@ class PreviewDevice extends Device {
|
|||||||
bool isSupportedForProject(FlutterProject flutterProject) => true;
|
bool isSupportedForProject(FlutterProject flutterProject) => true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get name => 'preview';
|
String get name => 'Preview';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();
|
DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();
|
||||||
|
@ -7,10 +7,12 @@ import 'dart:io' as io;
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:fake_async/fake_async.dart';
|
import 'package:fake_async/fake_async.dart';
|
||||||
|
import 'package:file/memory.dart';
|
||||||
import 'package:file/src/interface/file.dart';
|
import 'package:file/src/interface/file.dart';
|
||||||
import 'package:flutter_tools/src/android/android_device.dart';
|
import 'package:flutter_tools/src/android/android_device.dart';
|
||||||
import 'package:flutter_tools/src/android/android_workflow.dart';
|
import 'package:flutter_tools/src/android/android_workflow.dart';
|
||||||
import 'package:flutter_tools/src/application_package.dart';
|
import 'package:flutter_tools/src/application_package.dart';
|
||||||
|
import 'package:flutter_tools/src/artifacts.dart';
|
||||||
import 'package:flutter_tools/src/base/dds.dart';
|
import 'package:flutter_tools/src/base/dds.dart';
|
||||||
import 'package:flutter_tools/src/base/logger.dart';
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/base/utils.dart';
|
import 'package:flutter_tools/src/base/utils.dart';
|
||||||
@ -22,8 +24,10 @@ import 'package:flutter_tools/src/features.dart';
|
|||||||
import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart';
|
import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||||
import 'package:flutter_tools/src/ios/ios_workflow.dart';
|
import 'package:flutter_tools/src/ios/ios_workflow.dart';
|
||||||
|
import 'package:flutter_tools/src/preview_device.dart';
|
||||||
import 'package:flutter_tools/src/resident_runner.dart';
|
import 'package:flutter_tools/src/resident_runner.dart';
|
||||||
import 'package:flutter_tools/src/vmservice.dart';
|
import 'package:flutter_tools/src/vmservice.dart';
|
||||||
|
import 'package:flutter_tools/src/windows/windows_workflow.dart';
|
||||||
import 'package:test/fake.dart';
|
import 'package:test/fake.dart';
|
||||||
|
|
||||||
import '../../src/common.dart';
|
import '../../src/common.dart';
|
||||||
@ -121,10 +125,91 @@ void main() {
|
|||||||
|
|
||||||
expect(response.data['id'], 0);
|
expect(response.data['id'], 0);
|
||||||
expect(response.data['result'], isNotEmpty);
|
expect(response.data['result'], isNotEmpty);
|
||||||
expect((response.data['result']! as Map<String, Object?>)['platforms'], <String>{'macos'});
|
expect(
|
||||||
|
response.data['result']! as Map<String, Object?>,
|
||||||
|
const <String, Object>{
|
||||||
|
'platforms': <String>['macos', 'windows', 'windowsPreview'],
|
||||||
|
'platformTypes': <String, Map<String, Object>>{
|
||||||
|
'web': <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': <Map<String, String>>[
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the Web feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-web"',
|
||||||
|
'fixCode': 'config',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'android': <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': <Map<String, String>>[
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the Android feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-android"',
|
||||||
|
'fixCode': 'config',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'ios': <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': <Map<String, String>>[
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the iOS feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-ios"',
|
||||||
|
'fixCode': 'config',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'linux': <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': <Map<String, String>>[
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the Linux feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-linux-desktop"',
|
||||||
|
'fixCode': 'config',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'macos': <String, bool>{'isSupported': true},
|
||||||
|
'windows': <String, bool>{'isSupported': true},
|
||||||
|
'fuchsia': <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': <Map<String, String>>[
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the Fuchsia feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-fuchsia"',
|
||||||
|
'fixCode': 'config',
|
||||||
|
},
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the Fuchsia platform is not enabled for this project',
|
||||||
|
'fixText': 'Run "flutter create --platforms=fuchsia ." in your application directory',
|
||||||
|
'fixCode': 'create',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'custom': <String, Object>{
|
||||||
|
'isSupported': false,
|
||||||
|
'reasons': <Map<String, String>>[
|
||||||
|
<String, String>{
|
||||||
|
'reasonText': 'the custom devices feature is not enabled',
|
||||||
|
'fixText': 'Run "flutter config --enable-custom-devices"',
|
||||||
|
'fixCode': 'config',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'windowsPreview': <String, bool>{'isSupported': true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
// Disable Android/iOS and enable macOS to make sure result is consistent and defaults are tested off.
|
// Disable Android/iOS and enable macOS to make sure result is consistent and defaults are tested off.
|
||||||
FeatureFlags: () => TestFeatureFlags(isAndroidEnabled: false, isIOSEnabled: false, isMacOSEnabled: true),
|
FeatureFlags: () => TestFeatureFlags(
|
||||||
|
isAndroidEnabled: false,
|
||||||
|
isIOSEnabled: false,
|
||||||
|
isMacOSEnabled: true,
|
||||||
|
isPreviewDeviceEnabled: true,
|
||||||
|
isWindowsEnabled: true,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('printError should send daemon.logMessage event', () async {
|
testUsingContext('printError should send daemon.logMessage event', () async {
|
||||||
@ -342,18 +427,75 @@ void main() {
|
|||||||
final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
|
final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
|
||||||
daemon.deviceDomain.addDeviceDiscoverer(discoverer);
|
daemon.deviceDomain.addDeviceDiscoverer(discoverer);
|
||||||
discoverer.addDevice(FakeAndroidDevice());
|
discoverer.addDevice(FakeAndroidDevice());
|
||||||
|
final MemoryFileSystem fs = MemoryFileSystem.test();
|
||||||
|
discoverer.addDevice(PreviewDevice(
|
||||||
|
processManager: FakeProcessManager.empty(),
|
||||||
|
logger: BufferLogger.test(),
|
||||||
|
fileSystem: fs,
|
||||||
|
previewBinary: fs.file(r'preview_device.exe'),
|
||||||
|
artifacts: Artifacts.test(fileSystem: fs),
|
||||||
|
builderFactory: () => throw UnimplementedError('TODO implement builder factory'),
|
||||||
|
));
|
||||||
|
|
||||||
return daemonStreams.outputs.stream.skipWhile(_isConnectedEvent).first.then<void>((DaemonMessage response) async {
|
final List<Map<String, Object?>> names = <Map<String, Object?>>[];
|
||||||
|
await daemonStreams.outputs.stream.skipWhile(_isConnectedEvent).take(2).forEach((DaemonMessage response) async {
|
||||||
expect(response.data['event'], 'device.added');
|
expect(response.data['event'], 'device.added');
|
||||||
expect(response.data['params'], isMap);
|
expect(response.data['params'], isMap);
|
||||||
|
|
||||||
final Map<String, Object?> params = castStringKeyedMap(response.data['params'])!;
|
final Map<String, Object?> params = castStringKeyedMap(response.data['params'])!;
|
||||||
expect(params['platform'], isNotEmpty); // the fake device has a platform of 'android-arm'
|
names.add(params);
|
||||||
});
|
});
|
||||||
|
await daemonStreams.outputs.close();
|
||||||
|
expect(
|
||||||
|
names,
|
||||||
|
containsAll(const <Map<String, Object?>>[
|
||||||
|
<String, Object?>{
|
||||||
|
'id': 'device',
|
||||||
|
'name': 'android device',
|
||||||
|
'platform': 'android-arm',
|
||||||
|
'emulator': false,
|
||||||
|
'category': 'mobile',
|
||||||
|
'platformType': 'android',
|
||||||
|
'ephemeral': false,
|
||||||
|
'emulatorId': 'device',
|
||||||
|
'sdk': 'Android 12',
|
||||||
|
'capabilities': <String, Object?>{
|
||||||
|
'hotReload': true,
|
||||||
|
'hotRestart': true,
|
||||||
|
'screenshot': true,
|
||||||
|
'fastStart': true,
|
||||||
|
'flutterExit': true,
|
||||||
|
'hardwareRendering': true,
|
||||||
|
'startPaused': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
<String, Object?>{
|
||||||
|
'id': 'preview',
|
||||||
|
'name': 'Preview',
|
||||||
|
'platform': 'windows-x64',
|
||||||
|
'emulator': false,
|
||||||
|
'category': 'desktop',
|
||||||
|
'platformType': 'windowsPreview',
|
||||||
|
'ephemeral': false,
|
||||||
|
'emulatorId': null,
|
||||||
|
'sdk': 'preview',
|
||||||
|
'capabilities': <String, Object?>{
|
||||||
|
'hotReload': true,
|
||||||
|
'hotRestart': true,
|
||||||
|
'screenshot': false,
|
||||||
|
'fastStart': false,
|
||||||
|
'flutterExit': true,
|
||||||
|
'hardwareRendering': true,
|
||||||
|
'startPaused': true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
AndroidWorkflow: () => FakeAndroidWorkflow(),
|
AndroidWorkflow: () => FakeAndroidWorkflow(),
|
||||||
IOSWorkflow: () => FakeIOSWorkflow(),
|
IOSWorkflow: () => FakeIOSWorkflow(),
|
||||||
FuchsiaWorkflow: () => FakeFuchsiaWorkflow(),
|
FuchsiaWorkflow: () => FakeFuchsiaWorkflow(),
|
||||||
|
WindowsWorkflow: () => FakeWindowsWorkflow(),
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('device.discoverDevices should respond with list', () async {
|
testUsingContext('device.discoverDevices should respond with list', () async {
|
||||||
@ -930,6 +1072,13 @@ bool _notEvent(DaemonMessage message) => message.data['event'] == null;
|
|||||||
|
|
||||||
bool _isConnectedEvent(DaemonMessage message) => message.data['event'] == 'daemon.connected';
|
bool _isConnectedEvent(DaemonMessage message) => message.data['event'] == 'daemon.connected';
|
||||||
|
|
||||||
|
class FakeWindowsWorkflow extends Fake implements WindowsWorkflow {
|
||||||
|
FakeWindowsWorkflow({ this.canListDevices = true });
|
||||||
|
|
||||||
|
@override
|
||||||
|
final bool canListDevices;
|
||||||
|
}
|
||||||
|
|
||||||
class FakeFuchsiaWorkflow extends Fake implements FuchsiaWorkflow {
|
class FakeFuchsiaWorkflow extends Fake implements FuchsiaWorkflow {
|
||||||
FakeFuchsiaWorkflow({ this.canListDevices = true });
|
FakeFuchsiaWorkflow({ this.canListDevices = true });
|
||||||
|
|
||||||
@ -956,7 +1105,7 @@ class FakeAndroidDevice extends Fake implements AndroidDevice {
|
|||||||
final String id = 'device';
|
final String id = 'device';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final String name = 'device';
|
final String name = 'android device';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> get emulatorId async => 'device';
|
Future<String> get emulatorId async => 'device';
|
||||||
|
@ -52,7 +52,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(await device.isLocalEmulator, false);
|
expect(await device.isLocalEmulator, false);
|
||||||
expect(device.name, 'preview');
|
expect(device.name, 'Preview');
|
||||||
expect(await device.sdkNameAndVersion, 'preview');
|
expect(await device.sdkNameAndVersion, 'preview');
|
||||||
expect(await device.targetPlatform, TargetPlatform.windows_x64);
|
expect(await device.targetPlatform, TargetPlatform.windows_x64);
|
||||||
expect(device.category, Category.desktop);
|
expect(device.category, Category.desktop);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user