blob: 007c2e12188ca2f7ee9be3b8d8c7a9948a21a228 [file] [log] [blame]
// 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:convert';
import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:flutter_plugin_tools/src/xctest_command.dart';
import 'package:test/test.dart';
import 'package:flutter_plugin_tools/src/common.dart';
import 'mocks.dart';
import 'util.dart';
final _kDeviceListMap = {
"runtimes": [
{
"bundlePath":
"/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 13.0.simruntime",
"buildversion": "17A577",
"runtimeRoot":
"/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 13.0.simruntime/Contents/Resources/RuntimeRoot",
"identifier": "com.apple.CoreSimulator.SimRuntime.iOS-13-0",
"version": "13.0",
"isAvailable": true,
"name": "iOS 13.0"
},
{
"bundlePath":
"/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 13.4.simruntime",
"buildversion": "17L255",
"runtimeRoot":
"/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 13.4.simruntime/Contents/Resources/RuntimeRoot",
"identifier": "com.apple.CoreSimulator.SimRuntime.iOS-13-4",
"version": "13.4",
"isAvailable": true,
"name": "iOS 13.4"
},
{
"bundlePath":
"/Applications/Xcode_11_7.app/Contents/Developer/Platforms/WatchOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/watchOS.simruntime",
"buildversion": "17T531",
"runtimeRoot":
"/Applications/Xcode_11_7.app/Contents/Developer/Platforms/WatchOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/watchOS.simruntime/Contents/Resources/RuntimeRoot",
"identifier": "com.apple.CoreSimulator.SimRuntime.watchOS-6-2",
"version": "6.2.1",
"isAvailable": true,
"name": "watchOS 6.2"
}
],
"devices": {
"com.apple.CoreSimulator.SimRuntime.iOS-13-4": [
{
"dataPath":
"/Users/xxx/Library/Developer/CoreSimulator/Devices/2706BBEB-1E01-403E-A8E9-70E8E5A24774/data",
"logPath":
"/Users/xxx/Library/Logs/CoreSimulator/2706BBEB-1E01-403E-A8E9-70E8E5A24774",
"udid": "2706BBEB-1E01-403E-A8E9-70E8E5A24774",
"isAvailable": true,
"deviceTypeIdentifier":
"com.apple.CoreSimulator.SimDeviceType.iPhone-8",
"state": "Shutdown",
"name": "iPhone 8"
},
{
"dataPath":
"/Users/xxx/Library/Developer/CoreSimulator/Devices/1E76A0FD-38AC-4537-A989-EA639D7D012A/data",
"logPath":
"/Users/xxx/Library/Logs/CoreSimulator/1E76A0FD-38AC-4537-A989-EA639D7D012A",
"udid": "1E76A0FD-38AC-4537-A989-EA639D7D012A",
"isAvailable": true,
"deviceTypeIdentifier":
"com.apple.CoreSimulator.SimDeviceType.iPhone-8-Plus",
"state": "Shutdown",
"name": "iPhone 8 Plus"
}
]
}
};
void main() {
const String _kDestination = '--ios-destination';
const String _kTarget = '--target';
const String _kSkip = '--skip';
group('test xctest_command', () {
CommandRunner<Null> runner;
RecordingProcessRunner processRunner;
setUp(() {
initializeFakePackages();
processRunner = RecordingProcessRunner();
final XCTestCommand command = XCTestCommand(
mockPackagesDir, mockFileSystem,
processRunner: processRunner);
runner = CommandRunner<Null>('xctest_command', 'Test for xctest_command');
runner.addCommand(command);
cleanupPackages();
});
test('Not specifying --target throws', () async {
await expectLater(
() => runner.run(<String>['xctest', _kDestination, 'a_destination']),
throwsA(const TypeMatcher<ToolExit>()));
});
test('skip if ios is not supported', () async {
createFakePlugin('plugin',
withExtraFiles: <List<String>>[
<String>['example', 'test'],
],
isIosPlugin: false);
final Directory pluginExampleDirectory =
mockPackagesDir.childDirectory('plugin').childDirectory('example');
createFakePubspec(pluginExampleDirectory, isFlutter: true);
final MockProcess mockProcess = MockProcess();
mockProcess.exitCodeCompleter.complete(0);
processRunner.processToReturn = mockProcess;
final List<String> output = await runCapturingPrint(runner, <String>[
'xctest',
_kTarget,
'foo_scheme',
_kDestination,
'foo_destination'
]);
expect(output, contains('iOS is not supported by this plugin.'));
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
cleanupPackages();
});
test('running with correct scheme and destination, did not find scheme',
() async {
createFakePlugin('plugin',
withExtraFiles: <List<String>>[
<String>['example', 'test'],
],
isIosPlugin: true);
final Directory pluginExampleDirectory =
mockPackagesDir.childDirectory('plugin').childDirectory('example');
createFakePubspec(pluginExampleDirectory, isFlutter: true);
final MockProcess mockProcess = MockProcess();
mockProcess.exitCodeCompleter.complete(0);
processRunner.processToReturn = mockProcess;
processRunner.resultStdout = '{"project":{"targets":["bar_scheme"]}}';
await expectLater(() async {
final List<String> output = await runCapturingPrint(runner, <String>[
'xctest',
_kTarget,
'foo_scheme',
_kDestination,
'foo_destination'
]);
expect(output,
contains('foo_scheme not configured for plugin, test failed.'));
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('xcrun', <String>['simctl', 'list', '--json'], null),
ProcessCall(
'xcodebuild',
<String>[
'-project',
'ios/Runner.xcodeproj',
'-list',
'-json'
],
pluginExampleDirectory.path),
]));
}, throwsA(const TypeMatcher<ToolExit>()));
cleanupPackages();
});
test('running with correct scheme and destination, found scheme', () async {
createFakePlugin('plugin',
withExtraFiles: <List<String>>[
<String>['example', 'test'],
],
isIosPlugin: true);
final Directory pluginExampleDirectory =
mockPackagesDir.childDirectory('plugin').childDirectory('example');
createFakePubspec(pluginExampleDirectory, isFlutter: true);
final MockProcess mockProcess = MockProcess();
mockProcess.exitCodeCompleter.complete(0);
processRunner.processToReturn = mockProcess;
processRunner.resultStdout =
'{"project":{"targets":["bar_scheme", "foo_scheme"]}}';
List<String> output = await runCapturingPrint(runner, <String>[
'xctest',
_kTarget,
'foo_scheme',
_kDestination,
'foo_destination'
]);
expect(output, contains('Successfully ran xctest for plugin'));
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
'xcodebuild',
<String>['-project', 'ios/Runner.xcodeproj', '-list', '-json'],
pluginExampleDirectory.path),
ProcessCall(
'xcodebuild',
<String>[
'test',
'-workspace',
'ios/Runner.xcworkspace',
'-scheme',
'foo_scheme',
'-destination',
'foo_destination',
'CODE_SIGN_IDENTITY=""',
'CODE_SIGNING_REQUIRED=NO'
],
pluginExampleDirectory.path),
]));
cleanupPackages();
});
test('running with correct scheme and destination, skip 1 plugin',
() async {
createFakePlugin('plugin1',
withExtraFiles: <List<String>>[
<String>['example', 'test'],
],
isIosPlugin: true);
createFakePlugin('plugin2',
withExtraFiles: <List<String>>[
<String>['example', 'test'],
],
isIosPlugin: true);
final Directory pluginExampleDirectory1 =
mockPackagesDir.childDirectory('plugin1').childDirectory('example');
createFakePubspec(pluginExampleDirectory1, isFlutter: true);
final Directory pluginExampleDirectory2 =
mockPackagesDir.childDirectory('plugin2').childDirectory('example');
createFakePubspec(pluginExampleDirectory2, isFlutter: true);
final MockProcess mockProcess = MockProcess();
mockProcess.exitCodeCompleter.complete(0);
processRunner.processToReturn = mockProcess;
processRunner.resultStdout =
'{"project":{"targets":["bar_scheme", "foo_scheme"]}}';
List<String> output = await runCapturingPrint(runner, <String>[
'xctest',
_kTarget,
'foo_scheme',
_kDestination,
'foo_destination',
_kSkip,
'plugin1'
]);
expect(output, contains('plugin1 was skipped with the --skip flag.'));
expect(output, contains('Successfully ran xctest for plugin2'));
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
'xcodebuild',
<String>['-project', 'ios/Runner.xcodeproj', '-list', '-json'],
pluginExampleDirectory2.path),
ProcessCall(
'xcodebuild',
<String>[
'test',
'-workspace',
'ios/Runner.xcworkspace',
'-scheme',
'foo_scheme',
'-destination',
'foo_destination',
'CODE_SIGN_IDENTITY=""',
'CODE_SIGNING_REQUIRED=NO'
],
pluginExampleDirectory2.path),
]));
cleanupPackages();
});
test('Not specifying --ios-destination assigns an available simulator',
() async {
createFakePlugin('plugin',
withExtraFiles: <List<String>>[
<String>['example', 'test'],
],
isIosPlugin: true);
final Directory pluginExampleDirectory =
mockPackagesDir.childDirectory('plugin').childDirectory('example');
createFakePubspec(pluginExampleDirectory, isFlutter: true);
final MockProcess mockProcess = MockProcess();
mockProcess.exitCodeCompleter.complete(0);
processRunner.processToReturn = mockProcess;
final Map<String, dynamic> schemeCommandResult = {
"project": {
"targets": ["bar_scheme", "foo_scheme"]
}
};
// For simplicity of the test, we combine all the mock results into a single mock result, each internal command
// will get this result and they should still be able to parse them correctly.
processRunner.resultStdout =
jsonEncode(schemeCommandResult..addAll(_kDeviceListMap));
await runner.run(<String>[
'xctest',
_kTarget,
'foo_scheme',
]);
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall('xcrun', <String>['simctl', 'list', '--json'], null),
ProcessCall(
'xcodebuild',
<String>['-project', 'ios/Runner.xcodeproj', '-list', '-json'],
pluginExampleDirectory.path),
ProcessCall(
'xcodebuild',
<String>[
'test',
'-workspace',
'ios/Runner.xcworkspace',
'-scheme',
'foo_scheme',
'-destination',
'id=1E76A0FD-38AC-4537-A989-EA639D7D012A',
'CODE_SIGN_IDENTITY=""',
'CODE_SIGNING_REQUIRED=NO'
],
pluginExampleDirectory.path),
]));
cleanupPackages();
});
});
}