Commit d7b0f7db authored by xster's avatar xster Committed by GitHub

Support iOS screenshot 1/2 (#8210)

* Support iOS screenshot 1/3

* Use path.join

* use fs.path instead
parent 0736fac4
...@@ -44,6 +44,7 @@ class IOSDevice extends Device { ...@@ -44,6 +44,7 @@ class IOSDevice extends Device {
_iproxyPath = _checkForCommand('iproxy'); _iproxyPath = _checkForCommand('iproxy');
_debuggerPath = _checkForCommand('idevicedebug'); _debuggerPath = _checkForCommand('idevicedebug');
_loggerPath = _checkForCommand('idevicesyslog'); _loggerPath = _checkForCommand('idevicesyslog');
_screenshotPath = _checkForCommand('idevicescreenshot');
_pusherPath = _checkForCommand( _pusherPath = _checkForCommand(
'ios-deploy', 'ios-deploy',
'To copy files to iOS devices, please install ios-deploy. ' 'To copy files to iOS devices, please install ios-deploy. '
...@@ -70,6 +71,9 @@ class IOSDevice extends Device { ...@@ -70,6 +71,9 @@ class IOSDevice extends Device {
String _loggerPath; String _loggerPath;
String get loggerPath => _loggerPath; String get loggerPath => _loggerPath;
String _screenshotPath;
String get screenshotPath => _screenshotPath;
String _pusherPath; String _pusherPath;
String get pusherPath => _pusherPath; String get pusherPath => _pusherPath;
...@@ -118,12 +122,10 @@ class IOSDevice extends Device { ...@@ -118,12 +122,10 @@ class IOSDevice extends Device {
return runSync(<String>[informerPath, '-k', infoKey, '-u', deviceID]).trim(); return runSync(<String>[informerPath, '-k', infoKey, '-u', deviceID]).trim();
} }
static final Map<String, String> _commandMap = <String, String>{};
static String _checkForCommand( static String _checkForCommand(
String command, [ String command, [
String macInstructions = _ideviceinstallerInstructions String macInstructions = _ideviceinstallerInstructions
]) { ]) {
return _commandMap.putIfAbsent(command, () {
try { try {
command = runCheckedSync(<String>['which', command]).trim(); command = runCheckedSync(<String>['which', command]).trim();
} catch (e) { } catch (e) {
...@@ -132,9 +134,9 @@ class IOSDevice extends Device { ...@@ -132,9 +134,9 @@ class IOSDevice extends Device {
} else { } else {
printError('Cannot control iOS devices or simulators. $command is not available on your platform.'); printError('Cannot control iOS devices or simulators. $command is not available on your platform.');
} }
return null;
} }
return command; return command;
});
} }
@override @override
...@@ -364,14 +366,12 @@ class IOSDevice extends Device { ...@@ -364,14 +366,12 @@ class IOSDevice extends Device {
} }
@override @override
bool get supportsScreenshot => false; bool get supportsScreenshot => screenshotPath != null && screenshotPath.isNotEmpty;
@override @override
Future<Null> takeScreenshot(File outputFile) { Future<Null> takeScreenshot(File outputFile) {
// We could use idevicescreenshot here (installed along with the brew runCheckedSync(<String>[screenshotPath, outputFile.path]);
// ideviceinstaller tools). It however requires a developer disk image on return new Future<Null>.value();
// the device.
return new Future<Null>.error('Taking screenshots is not supported on iOS devices. Consider using a simulator instead.');
} }
} }
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show ProcessResult;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../context.dart';
class MockProcessManager extends Mock implements ProcessManager {}
class MockFile extends Mock implements File {}
void main() {
group('test screenshot', () {
MockProcessManager mockProcessManager;
MockFile mockOutputFile;
IOSDevice iosDeviceUnderTest;
setUp(() {
mockProcessManager = new MockProcessManager();
mockOutputFile = new MockFile();
});
testUsingContext(
'screenshot without ideviceinstaller error',
() async {
when(mockOutputFile.path).thenReturn(fs.path.join('some', 'test', 'path', 'image.png'));
// Let everything else return exit code 0 so process.dart doesn't crash.
// The matcher order is important.
when(
mockProcessManager.runSync(any, environment: null, workingDirectory: null)
).thenReturn(
new ProcessResult(2, 0, '', null)
);
// Let `which idevicescreenshot` fail with exit code 1.
when(
mockProcessManager.runSync(
<String>['which', 'idevicescreenshot'], environment: null, workingDirectory: null)
).thenReturn(
new ProcessResult(1, 1, '', null)
);
iosDeviceUnderTest = new IOSDevice('1234');
iosDeviceUnderTest.takeScreenshot(mockOutputFile);
verify(mockProcessManager.runSync(
<String>['which', 'idevicescreenshot'], environment: null, workingDirectory: null));
verifyNever(mockProcessManager.runSync(
<String>['idevicescreenshot', fs.path.join('some', 'test', 'path', 'image.png')],
environment: null,
workingDirectory: null
));
expect(testLogger.errorText, contains('brew install ideviceinstaller'));
},
overrides: <Type, Generator>{ProcessManager: () => mockProcessManager}
);
testUsingContext(
'screenshot with ideviceinstaller gets command',
() async {
when(mockOutputFile.path).thenReturn(fs.path.join('some', 'test', 'path', 'image.png'));
// Let everything else return exit code 0.
// The matcher order is important.
when(
mockProcessManager.runSync(any, environment: null, workingDirectory: null)
).thenReturn(
new ProcessResult(4, 0, '', null)
);
// Let there be idevicescreenshot in the PATH.
when(
mockProcessManager.runSync(
<String>['which', 'idevicescreenshot'], environment: null, workingDirectory: null)
).thenReturn(
new ProcessResult(3, 0, fs.path.join('some', 'path', 'to', 'iscreenshot'), null)
);
iosDeviceUnderTest = new IOSDevice('1234');
iosDeviceUnderTest.takeScreenshot(mockOutputFile);
verify(mockProcessManager.runSync(
<String>['which', 'idevicescreenshot'], environment: null, workingDirectory: null));
verify(mockProcessManager.runSync(
<String>[
fs.path.join('some', 'path', 'to', 'iscreenshot'),
fs.path.join('some', 'test', 'path', 'image.png')
],
environment: null,
workingDirectory: null
));
},
overrides: <Type, Generator>{ProcessManager: () => mockProcessManager}
);
});
}
import 'dart:io' show ProcessResult; import 'dart:io' show ProcessResult;
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/ios/mac.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:mockito/mockito.dart';
...@@ -122,7 +123,7 @@ void main() { ...@@ -122,7 +123,7 @@ void main() {
when(mockXcode.xcodeMinorVersion).thenReturn(1); when(mockXcode.xcodeMinorVersion).thenReturn(1);
expect(deviceUnderTest.supportsScreenshot, false); expect(deviceUnderTest.supportsScreenshot, false);
}, },
overrides: <Type, Generator>{ Xcode: () => mockXcode } overrides: <Type, Generator>{Xcode: () => mockXcode}
); );
testUsingContext( testUsingContext(
...@@ -132,7 +133,7 @@ void main() { ...@@ -132,7 +133,7 @@ void main() {
when(mockXcode.xcodeMinorVersion).thenReturn(2); when(mockXcode.xcodeMinorVersion).thenReturn(2);
expect(deviceUnderTest.supportsScreenshot, true); expect(deviceUnderTest.supportsScreenshot, true);
MockFile mockFile = new MockFile(); MockFile mockFile = new MockFile();
when(mockFile.path).thenReturn('/some/path/to/screenshot.png'); when(mockFile.path).thenReturn(fs.path.join('some', 'path', 'to', 'screenshot.png'));
deviceUnderTest.takeScreenshot(mockFile); deviceUnderTest.takeScreenshot(mockFile);
verify(mockProcessManager.runSync( verify(mockProcessManager.runSync(
<String>[ <String>[
...@@ -141,7 +142,7 @@ void main() { ...@@ -141,7 +142,7 @@ void main() {
'io', 'io',
'booted', 'booted',
'screenshot', 'screenshot',
'/some/path/to/screenshot.png' fs.path.join('some', 'path', 'to', 'screenshot.png'),
], ],
environment: null, environment: null,
workingDirectory: null workingDirectory: null
......
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