mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Move simulator screenshot logic to use simctl (#8216)
* Move simulator screenshot logic to use simctl * Add simulator screenshot tests
This commit is contained in:
parent
1773e47b03
commit
3985ddbcd4
@ -76,6 +76,12 @@ class Xcode {
|
||||
String _xcodeVersionText;
|
||||
String get xcodeVersionText => _xcodeVersionText;
|
||||
|
||||
int _xcodeMajorVersion;
|
||||
int get xcodeMajorVersion => _xcodeMajorVersion;
|
||||
|
||||
int _xcodeMinorVersion;
|
||||
int get xcodeMinorVersion => _xcodeMinorVersion;
|
||||
|
||||
final RegExp xcodeVersionRegex = new RegExp(r'Xcode ([0-9.]+)');
|
||||
|
||||
bool get xcodeVersionSatisfactory {
|
||||
@ -85,10 +91,10 @@ class Xcode {
|
||||
String version = xcodeVersionRegex.firstMatch(xcodeVersionText).group(1);
|
||||
List<String> components = version.split('.');
|
||||
|
||||
int major = int.parse(components[0]);
|
||||
int minor = components.length == 1 ? 0 : int.parse(components[1]);
|
||||
_xcodeMajorVersion = int.parse(components[0]);
|
||||
_xcodeMinorVersion = components.length == 1 ? 0 : int.parse(components[1]);
|
||||
|
||||
return _xcodeVersionCheckValid(major, minor);
|
||||
return _xcodeVersionCheckValid(_xcodeMajorVersion, _xcodeMinorVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -249,6 +249,10 @@ class SimControl {
|
||||
args.addAll(launchArgs);
|
||||
runCheckedSync(args);
|
||||
}
|
||||
|
||||
void takeScreenshot(String outputPath) {
|
||||
runCheckedSync(<String>[_xcrunPath, 'simctl', 'io', 'booted', 'screenshot', outputPath]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerates all data sections of `xcrun simctl list --json` command.
|
||||
@ -582,44 +586,18 @@ class IOSSimulator extends Device {
|
||||
logFile.writeAsBytesSync(<int>[]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get supportsScreenshot => true;
|
||||
bool get _xcodeVersionSupportsScreenshot {
|
||||
return Xcode.instance.xcodeMajorVersion > 8 ||
|
||||
(Xcode.instance.xcodeMajorVersion == 8 && Xcode.instance.xcodeMinorVersion >= 2);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Null> takeScreenshot(File outputFile) async {
|
||||
Directory desktopDir = fs.directory(fs.path.join(homeDirPath, 'Desktop'));
|
||||
bool get supportsScreenshot => _xcodeVersionSupportsScreenshot;
|
||||
|
||||
// 'Simulator Screen Shot Mar 25, 2016, 2.59.43 PM.png'
|
||||
|
||||
Set<File> getScreenshots() {
|
||||
return new Set<File>.from(desktopDir.listSync().where((FileSystemEntity entity) {
|
||||
String name = fs.path.basename(entity.path);
|
||||
return entity is File && name.startsWith('Simulator') && name.endsWith('.png');
|
||||
}));
|
||||
}
|
||||
|
||||
Set<File> existingScreenshots = getScreenshots();
|
||||
|
||||
runSync(<String>[
|
||||
'osascript',
|
||||
'-e',
|
||||
'activate application "Simulator"\n'
|
||||
'tell application "System Events" to keystroke "s" using command down'
|
||||
]);
|
||||
|
||||
// There is some latency here from the applescript call.
|
||||
await new Future<Null>.delayed(new Duration(seconds: 1));
|
||||
|
||||
Set<File> shots = getScreenshots().difference(existingScreenshots);
|
||||
|
||||
if (shots.isEmpty) {
|
||||
printError('Unable to locate the screenshot file.');
|
||||
return false;
|
||||
}
|
||||
|
||||
File shot = shots.first;
|
||||
outputFile.writeAsBytesSync(shot.readAsBytesSync());
|
||||
shot.delete();
|
||||
@override
|
||||
Future<Null> takeScreenshot(File outputFile) {
|
||||
SimControl.instance.takeScreenshot(outputFile.path);
|
||||
return new Future<Null>.value();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
import 'dart:io' show ProcessResult;
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/ios/mac.dart';
|
||||
import 'package:flutter_tools/src/ios/simulators.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:flutter_tools/src/ios/simulators.dart';
|
||||
import '../context.dart';
|
||||
|
||||
class MockXcode extends Mock implements Xcode {}
|
||||
class MockFile extends Mock implements File {}
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
|
||||
void main() {
|
||||
group('compareIosVersions', () {
|
||||
@ -85,4 +96,63 @@ void main() {
|
||||
expect(new IOSSimulator('x', name: 'iPhone 7 Plus').isSupported(), true);
|
||||
});
|
||||
});
|
||||
|
||||
group('Simulator screenshot', () {
|
||||
MockXcode mockXcode;
|
||||
MockProcessManager mockProcessManager;
|
||||
IOSSimulator deviceUnderTest;
|
||||
|
||||
setUp(() {
|
||||
mockXcode = new MockXcode();
|
||||
mockProcessManager = new MockProcessManager();
|
||||
// Let everything else return exit code 0 so process.dart doesn't crash.
|
||||
when(
|
||||
mockProcessManager.runSync(any, environment: null, workingDirectory: null)
|
||||
).thenReturn(
|
||||
new ProcessResult(2, 0, '', null)
|
||||
);
|
||||
// Doesn't matter what the device is.
|
||||
deviceUnderTest = new IOSSimulator('x', name: 'iPhone SE');
|
||||
});
|
||||
|
||||
testUsingContext(
|
||||
'old Xcode doesn\'t support screenshot',
|
||||
() {
|
||||
when(mockXcode.xcodeMajorVersion).thenReturn(7);
|
||||
when(mockXcode.xcodeMinorVersion).thenReturn(1);
|
||||
expect(deviceUnderTest.supportsScreenshot, false);
|
||||
},
|
||||
overrides: <Type, Generator>{ Xcode: () => mockXcode }
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'Xcode 8.2+ supports screenshots',
|
||||
() {
|
||||
when(mockXcode.xcodeMajorVersion).thenReturn(8);
|
||||
when(mockXcode.xcodeMinorVersion).thenReturn(2);
|
||||
expect(deviceUnderTest.supportsScreenshot, true);
|
||||
MockFile mockFile = new MockFile();
|
||||
when(mockFile.path).thenReturn('/some/path/to/screenshot.png');
|
||||
deviceUnderTest.takeScreenshot(mockFile);
|
||||
verify(mockProcessManager.runSync(
|
||||
<String>[
|
||||
'/usr/bin/xcrun',
|
||||
'simctl',
|
||||
'io',
|
||||
'booted',
|
||||
'screenshot',
|
||||
'/some/path/to/screenshot.png'
|
||||
],
|
||||
environment: null,
|
||||
workingDirectory: null
|
||||
));
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
// Test a real one. Screenshot doesn't require instance states.
|
||||
SimControl: () => new SimControl(),
|
||||
Xcode: () => mockXcode,
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user