blob: 6ee3c2448371580bb3195087c3d10f16fbab32e1 [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:async';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/cocoapods.dart';
import 'package:flutter_tools/src/ios/ios_workflow.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../src/context.dart';
void main() {
group('iOS Workflow validation', () {
MockIMobileDevice iMobileDevice;
MockXcode xcode;
MockProcessManager processManager;
MockCocoaPods cocoaPods;
FileSystem fs;
setUp(() {
iMobileDevice = new MockIMobileDevice();
xcode = new MockXcode();
processManager = new MockProcessManager();
cocoaPods = new MockCocoaPods();
fs = new MemoryFileSystem();
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck)
.thenAnswer((_) => new Future<bool>.value(true));
when(cocoaPods.isCocoaPodsInitialized)
.thenAnswer((_) => new Future<bool>.value(true));
});
testUsingContext('Emit missing status when nothing is installed', () async {
when(xcode.isInstalled).thenReturn(false);
when(xcode.xcodeSelectPath).thenReturn(null);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(
hasPythonSixModule: false,
hasHomebrew: false,
hasIosDeploy: false,
);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.missing);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode is not installed', () async {
when(xcode.isInstalled).thenReturn(false);
when(xcode.xcodeSelectPath).thenReturn(null);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode is partially installed', () async {
when(xcode.isInstalled).thenReturn(false);
when(xcode.xcodeSelectPath).thenReturn('/Library/Developer/CommandLineTools');
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode version too low', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 7.0.1\nBuild version 7C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(false);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when Xcode EULA not signed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(false);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when python six not installed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(hasPythonSixModule: false);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when homebrew not installed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(hasHomebrew: false);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when libimobiledevice is not installed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => new MockIMobileDevice(isInstalled: false, isWorking: false),
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when libimobiledevice is installed but not working', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => new MockIMobileDevice(isWorking: false),
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when ios-deploy is not installed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(hasIosDeploy: false);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when ios-deploy version is too low', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget(iosDeployVersionText: '1.8.0');
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when CocoaPods is not installed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck)
.thenAnswer((_) => new Future<bool>.value(false));
when(cocoaPods.hasCocoaPods).thenAnswer((_) => new Future<bool>.value(false));
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when CocoaPods version is too low', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck)
.thenAnswer((_) => new Future<bool>.value(false));
when(cocoaPods.hasCocoaPods).thenAnswer((_) => new Future<bool>.value(true));
when(cocoaPods.cocoaPodsVersionText)
.thenAnswer((_) => new Future<String>.value('0.39.0'));
when(xcode.isSimctlInstalled).thenReturn(true);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Emits partial status when CocoaPods is not initialized', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(cocoaPods.isCocoaPodsInstalledAndMeetsVersionCheck).thenAnswer((_) async => false);
when(cocoaPods.hasCocoaPods).thenAnswer((_) async => true);
when(cocoaPods.isCocoaPodsInitialized).thenAnswer((_) async => false);
when(xcode.isSimctlInstalled).thenReturn(true);
final ValidationResult result = await new IOSWorkflowTestTarget().validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
ProcessManager: () => processManager,
});
testUsingContext('Emits partial status when simctl is not installed', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(false);
final IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
});
testUsingContext('Succeeds when all checks pass', () async {
when(xcode.isInstalled).thenReturn(true);
when(xcode.versionText)
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
ensureDirectoryExists(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master', 'README.md'));
final ValidationResult result = await new IOSWorkflowTestTarget().validate();
expect(result.type, ValidationType.installed);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
IMobileDevice: () => iMobileDevice,
Xcode: () => xcode,
CocoaPods: () => cocoaPods,
ProcessManager: () => processManager,
});
});
}
final ProcessResult exitsHappy = new ProcessResult(
1, // pid
0, // exitCode
'', // stdout
'', // stderr
);
class MockIMobileDevice extends IMobileDevice {
MockIMobileDevice({
this.isInstalled: true,
bool isWorking: true,
}) : isWorking = new Future<bool>.value(isWorking);
@override
final bool isInstalled;
@override
final Future<bool> isWorking;
}
class MockXcode extends Mock implements Xcode {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockCocoaPods extends Mock implements CocoaPods {}
class IOSWorkflowTestTarget extends IOSWorkflow {
IOSWorkflowTestTarget({
this.hasPythonSixModule: true,
this.hasHomebrew: true,
bool hasIosDeploy: true,
String iosDeployVersionText: '1.9.2',
bool hasIDeviceInstaller: true,
}) : hasIosDeploy = new Future<bool>.value(hasIosDeploy),
iosDeployVersionText = new Future<String>.value(iosDeployVersionText),
hasIDeviceInstaller = new Future<bool>.value(hasIDeviceInstaller);
@override
final bool hasPythonSixModule;
@override
final bool hasHomebrew;
@override
final Future<bool> hasIosDeploy;
@override
final Future<String> iosDeployVersionText;
@override
final Future<bool> hasIDeviceInstaller;
}