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 {
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'));
// '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();
bool get supportsScreenshot => _xcodeVersionSupportsScreenshot;
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();
}
}
......
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: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() {
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,
}
);
});
}
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