Commit 3985ddbc authored by xster's avatar xster Committed by GitHub

Move simulator screenshot logic to use simctl (#8216)

* Move simulator screenshot logic to use simctl

* Add simulator screenshot tests
parent 1773e47b
...@@ -76,6 +76,12 @@ class Xcode { ...@@ -76,6 +76,12 @@ class Xcode {
String _xcodeVersionText; String _xcodeVersionText;
String get xcodeVersionText => _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.]+)'); final RegExp xcodeVersionRegex = new RegExp(r'Xcode ([0-9.]+)');
bool get xcodeVersionSatisfactory { bool get xcodeVersionSatisfactory {
...@@ -85,10 +91,10 @@ class Xcode { ...@@ -85,10 +91,10 @@ class Xcode {
String version = xcodeVersionRegex.firstMatch(xcodeVersionText).group(1); String version = xcodeVersionRegex.firstMatch(xcodeVersionText).group(1);
List<String> components = version.split('.'); List<String> components = version.split('.');
int major = int.parse(components[0]); _xcodeMajorVersion = int.parse(components[0]);
int minor = components.length == 1 ? 0 : int.parse(components[1]); _xcodeMinorVersion = components.length == 1 ? 0 : int.parse(components[1]);
return _xcodeVersionCheckValid(major, minor); return _xcodeVersionCheckValid(_xcodeMajorVersion, _xcodeMinorVersion);
} }
} }
......
...@@ -249,6 +249,10 @@ class SimControl { ...@@ -249,6 +249,10 @@ class SimControl {
args.addAll(launchArgs); args.addAll(launchArgs);
runCheckedSync(args); runCheckedSync(args);
} }
void takeScreenshot(String outputPath) {
runCheckedSync(<String>[_xcrunPath, 'simctl', 'io', 'booted', 'screenshot', outputPath]);
}
} }
/// Enumerates all data sections of `xcrun simctl list --json` command. /// Enumerates all data sections of `xcrun simctl list --json` command.
...@@ -582,44 +586,18 @@ class IOSSimulator extends Device { ...@@ -582,44 +586,18 @@ class IOSSimulator extends Device {
logFile.writeAsBytesSync(<int>[]); logFile.writeAsBytesSync(<int>[]);
} }
@override bool get _xcodeVersionSupportsScreenshot {
bool get supportsScreenshot => true; return Xcode.instance.xcodeMajorVersion > 8 ||
(Xcode.instance.xcodeMajorVersion == 8 && Xcode.instance.xcodeMinorVersion >= 2);
}
@override @override
Future<Null> takeScreenshot(File outputFile) async { bool get supportsScreenshot => _xcodeVersionSupportsScreenshot;
Directory desktopDir = fs.directory(fs.path.join(homeDirPath, 'Desktop'));
// '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>[ @override
'osascript', Future<Null> takeScreenshot(File outputFile) {
'-e', SimControl.instance.takeScreenshot(outputFile.path);
'activate application "Simulator"\n' return new Future<Null>.value();
'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();
} }
} }
......
import 'package:test/test.dart'; 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:flutter_tools/src/ios/simulators.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../context.dart';
class MockXcode extends Mock implements Xcode {}
class MockFile extends Mock implements File {}
class MockProcessManager extends Mock implements ProcessManager {}
void main() { void main() {
group('compareIosVersions', () { group('compareIosVersions', () {
...@@ -85,4 +96,63 @@ void main() { ...@@ -85,4 +96,63 @@ void main() {
expect(new IOSSimulator('x', name: 'iPhone 7 Plus').isSupported(), true); 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,
}
);
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment