mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Show unsupported devices when no supported devices are connected (#56531)
This commit is contained in:
parent
91e7678f79
commit
6c8d7b00ff
@ -237,6 +237,9 @@ class UserMessages {
|
|||||||
"matching '$deviceId'";
|
"matching '$deviceId'";
|
||||||
String get flutterNoDevicesFound => 'No devices found';
|
String get flutterNoDevicesFound => 'No devices found';
|
||||||
String get flutterNoSupportedDevices => 'No supported devices connected.';
|
String get flutterNoSupportedDevices => 'No supported devices connected.';
|
||||||
|
String flutterMissPlatformProjects(List<String> unsupportedDevicesType) =>
|
||||||
|
'If you would like your app to run on ${unsupportedDevicesType.join(' or ')}, consider running `flutter create .` to generate projects for these platforms.';
|
||||||
|
String get flutterFoundButUnsupportedDevices => 'The following devices were found, but are not supported by this project:';
|
||||||
String flutterFoundSpecifiedDevices(int count, String deviceId) =>
|
String flutterFoundSpecifiedDevices(int count, String deviceId) =>
|
||||||
'Found $count devices with name or id matching $deviceId:';
|
'Found $count devices with name or id matching $deviceId:';
|
||||||
String get flutterSpecifyDeviceWithAllOption =>
|
String get flutterSpecifyDeviceWithAllOption =>
|
||||||
|
@ -557,6 +557,13 @@ abstract class Device {
|
|||||||
await descriptions(devices).forEach(globals.printStatus);
|
await descriptions(devices).forEach(globals.printStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<String> devicesPlatformTypes(List<Device> devices) {
|
||||||
|
return devices
|
||||||
|
.map(
|
||||||
|
(Device d) => d.platformType.toString(),
|
||||||
|
).toSet().toList()..sort();
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert the Device object to a JSON representation suitable for serialization.
|
/// Convert the Device object to a JSON representation suitable for serialization.
|
||||||
Future<Map<String, Object>> toJson() async {
|
Future<Map<String, Object>> toJson() async {
|
||||||
final bool isLocalEmu = await isLocalEmulator;
|
final bool isLocalEmu = await isLocalEmulator;
|
||||||
|
@ -823,11 +823,28 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
|
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
|
||||||
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId));
|
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId));
|
||||||
return null;
|
return null;
|
||||||
} else if (devices.isEmpty && deviceManager.hasSpecifiedAllDevices) {
|
|
||||||
globals.printStatus(userMessages.flutterNoDevicesFound);
|
|
||||||
return null;
|
|
||||||
} else if (devices.isEmpty) {
|
} else if (devices.isEmpty) {
|
||||||
globals.printStatus(userMessages.flutterNoSupportedDevices);
|
if (deviceManager.hasSpecifiedAllDevices) {
|
||||||
|
globals.printStatus(userMessages.flutterNoDevicesFound);
|
||||||
|
} else {
|
||||||
|
globals.printStatus(userMessages.flutterNoSupportedDevices);
|
||||||
|
}
|
||||||
|
final List<Device> unsupportedDevices = await deviceManager.getDevices();
|
||||||
|
if (unsupportedDevices.isNotEmpty) {
|
||||||
|
final StringBuffer result = StringBuffer();
|
||||||
|
result.writeln(userMessages.flutterFoundButUnsupportedDevices);
|
||||||
|
result.writeAll(
|
||||||
|
await Device.descriptions(unsupportedDevices)
|
||||||
|
.map((String desc) => desc)
|
||||||
|
.toList(),
|
||||||
|
'\n',
|
||||||
|
);
|
||||||
|
result.writeln('');
|
||||||
|
result.writeln(userMessages.flutterMissPlatformProjects(
|
||||||
|
Device.devicesPlatformTypes(unsupportedDevices),
|
||||||
|
));
|
||||||
|
globals.printStatus(result.toString());
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
} else if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices) {
|
} else if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices) {
|
||||||
if (deviceManager.hasSpecifiedDeviceId) {
|
if (deviceManager.hasSpecifiedDeviceId) {
|
||||||
|
@ -38,6 +38,16 @@ void main() {
|
|||||||
ProcessManager: () => MockProcessManager(),
|
ProcessManager: () => MockProcessManager(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testUsingContext('get devices\' platform types', () async {
|
||||||
|
final List<String> platformTypes = Device.devicesPlatformTypes(
|
||||||
|
await deviceManager.getAllConnectedDevices(),
|
||||||
|
);
|
||||||
|
expect(platformTypes, <String>['android', 'web']);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
DeviceManager: () => _FakeDeviceManager(),
|
||||||
|
ProcessManager: () => MockProcessManager(),
|
||||||
|
});
|
||||||
|
|
||||||
testUsingContext('Outputs parsable JSON with --machine flag', () async {
|
testUsingContext('Outputs parsable JSON with --machine flag', () async {
|
||||||
final DevicesCommand command = DevicesCommand();
|
final DevicesCommand command = DevicesCommand();
|
||||||
await createTestCommandRunner(command).run(<String>['devices', '--machine']);
|
await createTestCommandRunner(command).run(<String>['devices', '--machine']);
|
||||||
|
@ -241,6 +241,62 @@ void main() {
|
|||||||
ProcessManager: () => mockProcessManager,
|
ProcessManager: () => mockProcessManager,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testUsingContext('shows unsupported devices when no supported devices are found', () async {
|
||||||
|
final RunCommand command = RunCommand();
|
||||||
|
applyMocksToCommand(command);
|
||||||
|
|
||||||
|
final MockDevice mockDevice = MockDevice(TargetPlatform.android_arm);
|
||||||
|
when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) => Future<bool>.value(true));
|
||||||
|
when(mockDevice.isSupported()).thenAnswer((Invocation invocation) => true);
|
||||||
|
when(mockDevice.supportsFastStart).thenReturn(true);
|
||||||
|
when(mockDevice.id).thenReturn('mock-id');
|
||||||
|
when(mockDevice.name).thenReturn('mock-name');
|
||||||
|
when(mockDevice.platformType).thenReturn(PlatformType.android);
|
||||||
|
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) => Future<String>.value('api-14'));
|
||||||
|
|
||||||
|
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
|
||||||
|
return Future<List<Device>>.value(<Device>[
|
||||||
|
mockDevice,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
|
||||||
|
(Invocation invocation) => Future<List<Device>>.value(<Device>[]),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await createTestCommandRunner(command).run(<String>[
|
||||||
|
'run',
|
||||||
|
'--no-pub',
|
||||||
|
'--no-hot',
|
||||||
|
]);
|
||||||
|
fail('Expect exception');
|
||||||
|
} on ToolExit catch (e) {
|
||||||
|
expect(e.message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(
|
||||||
|
testLogger.statusText,
|
||||||
|
containsIgnoringWhitespace(userMessages.flutterNoSupportedDevices),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
testLogger.statusText,
|
||||||
|
containsIgnoringWhitespace(userMessages.flutterFoundButUnsupportedDevices),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
testLogger.statusText,
|
||||||
|
containsIgnoringWhitespace(
|
||||||
|
userMessages.flutterMissPlatformProjects(
|
||||||
|
Device.devicesPlatformTypes(<Device>[mockDevice]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
DeviceManager: () => mockDeviceManager,
|
||||||
|
FileSystem: () => fs,
|
||||||
|
ProcessManager: () => mockProcessManager,
|
||||||
|
});
|
||||||
|
|
||||||
testUsingContext('updates cache before checking for devices', () async {
|
testUsingContext('updates cache before checking for devices', () async {
|
||||||
final RunCommand command = RunCommand();
|
final RunCommand command = RunCommand();
|
||||||
applyMocksToCommand(command);
|
applyMocksToCommand(command);
|
||||||
|
@ -11,7 +11,7 @@ import 'package:flutter_tools/src/project.dart';
|
|||||||
/// (`Device.toJson()` and `--machine` flag for `devices` command)
|
/// (`Device.toJson()` and `--machine` flag for `devices` command)
|
||||||
List<FakeDeviceJsonData> fakeDevices = <FakeDeviceJsonData>[
|
List<FakeDeviceJsonData> fakeDevices = <FakeDeviceJsonData>[
|
||||||
FakeDeviceJsonData(
|
FakeDeviceJsonData(
|
||||||
FakeDevice('ephemeral', 'ephemeral', true),
|
FakeDevice('ephemeral', 'ephemeral', true, true, PlatformType.android),
|
||||||
<String, Object>{
|
<String, Object>{
|
||||||
'name': 'ephemeral',
|
'name': 'ephemeral',
|
||||||
'id': 'ephemeral',
|
'id': 'ephemeral',
|
||||||
@ -56,9 +56,9 @@ List<FakeDeviceJsonData> fakeDevices = <FakeDeviceJsonData>[
|
|||||||
|
|
||||||
/// Fake device to test `devices` command
|
/// Fake device to test `devices` command
|
||||||
class FakeDevice extends Device {
|
class FakeDevice extends Device {
|
||||||
FakeDevice(this.name, String id, [bool ephemeral = true, this._isSupported = true]) : super(
|
FakeDevice(this.name, String id, [bool ephemeral = true, this._isSupported = true, PlatformType type = PlatformType.web]) : super(
|
||||||
id,
|
id,
|
||||||
platformType: PlatformType.web,
|
platformType: type,
|
||||||
category: Category.mobile,
|
category: Category.mobile,
|
||||||
ephemeral: ephemeral,
|
ephemeral: ephemeral,
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user