Skip to content

Commit 8c3d920

Browse files
Merge pull request #43 from NativeScript/vladimirov/forbid-xcode-8
feat: drop support for Xcode versions below 9
2 parents afefd4c + de244dd commit 8c3d920

File tree

5 files changed

+151
-5
lines changed

5 files changed

+151
-5
lines changed

lib/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export class Constants {
1414
public static NATIVESCRIPT_KEY = "nativescript";
1515
public static ANDROID_RUNTIME = "tns-android";
1616
public static VERSION_PROPERTY_NAME = "version";
17+
public static XCODE_MIN_REQUIRED_VERSION = 9;
1718
}

lib/doctor.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,18 @@ export class Doctor implements NativeScriptDoctor.IDoctor {
186186
platforms: [Constants.IOS_PLATFORM_NAME]
187187
})
188188
);
189+
190+
if (sysInfoData.xcodeVer) {
191+
result = result.concat(
192+
this.processSysInfoItem({
193+
item: await this.iOSLocalBuildRequirements.isXcodeVersionValid(),
194+
infoMessage: `Xcode version ${sysInfoData.xcodeVer} satisfies minimum required version ${Constants.XCODE_MIN_REQUIRED_VERSION}.`,
195+
warningMessage: `Xcode version ${sysInfoData.xcodeVer} is lower than minimum required version ${Constants.XCODE_MIN_REQUIRED_VERSION}.`,
196+
additionalInformation: "To build your application for iOS, update your Xcode.",
197+
platforms: [Constants.IOS_PLATFORM_NAME]
198+
})
199+
);
200+
}
189201
}
190202

191203
return result;
@@ -208,7 +220,7 @@ export class Doctor implements NativeScriptDoctor.IDoctor {
208220
};
209221
}
210222

211-
private processValidationErrors(data: { warnings: NativeScriptDoctor.IWarning[], infoMessage: string, platforms: string[]}): NativeScriptDoctor.IInfo[] {
223+
private processValidationErrors(data: { warnings: NativeScriptDoctor.IWarning[], infoMessage: string, platforms: string[] }): NativeScriptDoctor.IInfo[] {
212224
if (data.warnings.length > 0) {
213225
return data.warnings.map(warning => this.convertWarningToInfo(warning));
214226
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import { HostInfo } from "../host-info";
2+
import * as semver from "semver";
3+
import { Constants } from "../constants";
24

35
export class IosLocalBuildRequirements {
46
constructor(private sysInfo: NativeScriptDoctor.ISysInfo,
57
private hostInfo: HostInfo) { }
68

79
public async checkRequirements(): Promise<boolean> {
810
if (!this.hostInfo.isDarwin ||
9-
!await this.sysInfo.getXcodeVersion() ||
11+
!await this.isXcodeVersionValid() ||
1012
!await this.sysInfo.getXcodeprojLocation()) {
1113
return false;
1214
}
1315

1416
return true;
1517
}
18+
19+
public async isXcodeVersionValid(): Promise<boolean> {
20+
const xcodeVersion = await this.sysInfo.getXcodeVersion();
21+
22+
return !!xcodeVersion && (semver.major(semver.coerce(xcodeVersion)) >= Constants.XCODE_MIN_REQUIRED_VERSION);
23+
}
1624
}

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nativescript-doctor",
3-
"version": "1.4.0",
3+
"version": "1.5.0",
44
"description": "Library that helps identifying if the environment can be used for development of {N} apps.",
55
"main": "lib/index.js",
66
"types": "./typings/nativescript-doctor.d.ts",
@@ -25,7 +25,7 @@
2525
"devDependencies": {
2626
"@types/chai": "4.1.0",
2727
"@types/mocha": "2.2.32",
28-
"@types/semver": "5.3.30",
28+
"@types/semver": "5.5.0",
2929
"@types/temp": "0.8.29",
3030
"@types/winreg": "1.2.30",
3131
"chai": "4.1.2",
@@ -43,7 +43,7 @@
4343
},
4444
"dependencies": {
4545
"osenv": "0.1.3",
46-
"semver": "5.3.0",
46+
"semver": "5.5.1",
4747
"temp": "0.8.3",
4848
"unzip": "0.1.11",
4949
"winreg": "1.2.2"

test/ios-local-build-requirements.ts

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { IosLocalBuildRequirements } from "../lib/local-build-requirements/ios-local-build-requirements";
2+
import { assert } from "chai";
3+
import { HostInfo } from "../lib/host-info";
4+
import { Constants } from "../lib/constants";
5+
6+
interface ITestCaseData {
7+
testName: string;
8+
expectedResult: boolean;
9+
getXcodeVersion?: string;
10+
minRequiredXcodeVersion?: number;
11+
getXcodeprojLocation?: string;
12+
isDarwin?: boolean;
13+
}
14+
15+
describe("iOSLocalBuildRequirements", () => {
16+
const setupTestCase = (results: ITestCaseData): IosLocalBuildRequirements => {
17+
const sysInfo: NativeScriptDoctor.ISysInfo = <any>{
18+
getXcodeVersion: async (): Promise<string> => results.hasOwnProperty("getXcodeVersion") ? results.getXcodeVersion : "10.0",
19+
getXcodeprojLocation: async (): Promise<string> => results.hasOwnProperty("getXcodeprojLocation") ? results.getXcodeprojLocation : "path to xcodeproj",
20+
};
21+
22+
const hostInfo: HostInfo = <any>{
23+
isDarwin: results.hasOwnProperty("isDarwin") ? results.isDarwin : true
24+
};
25+
26+
const iOSLocalBuildRequirements = new IosLocalBuildRequirements(sysInfo, hostInfo);
27+
return iOSLocalBuildRequirements;
28+
};
29+
30+
describe("isXcodeVersionValid", () => {
31+
const testCases: ITestCaseData[] = [
32+
{
33+
testName: "returns false when Xcode is not installed",
34+
getXcodeVersion: null,
35+
expectedResult: false
36+
},
37+
{
38+
testName: "returns false when Xcode's major version is below min required version",
39+
getXcodeVersion: "10.0",
40+
minRequiredXcodeVersion: 11,
41+
expectedResult: false
42+
},
43+
{
44+
testName: "returns true when Xcode's major version equals min required version",
45+
getXcodeVersion: "10.0",
46+
minRequiredXcodeVersion: 10,
47+
expectedResult: true
48+
},
49+
{
50+
testName: "returns true when Xcode's major version equals min required version",
51+
getXcodeVersion: "12.0",
52+
minRequiredXcodeVersion: 10,
53+
expectedResult: true
54+
}
55+
];
56+
57+
testCases.forEach(testCase => {
58+
it(testCase.testName, async () => {
59+
const iOSLocalBuildRequirements = setupTestCase(testCase);
60+
let originalXcodeVersion = Constants.XCODE_MIN_REQUIRED_VERSION;
61+
Constants.XCODE_MIN_REQUIRED_VERSION = testCase.minRequiredXcodeVersion || Constants.XCODE_MIN_REQUIRED_VERSION;
62+
63+
const isXcodeVersionValid = await iOSLocalBuildRequirements.isXcodeVersionValid();
64+
65+
// Get back the XCODE_MIN_REQUIRED_VERSION value.
66+
Constants.XCODE_MIN_REQUIRED_VERSION = originalXcodeVersion;
67+
68+
assert.equal(isXcodeVersionValid, testCase.expectedResult);
69+
});
70+
});
71+
});
72+
73+
describe("checkRequirements", () => {
74+
const testCases: ITestCaseData[] = [
75+
{
76+
testName: "returns false when OS is not macOS",
77+
isDarwin: false,
78+
expectedResult: false
79+
},
80+
{
81+
testName: "returns false when Xcode is not installed",
82+
getXcodeVersion: null,
83+
expectedResult: false
84+
},
85+
{
86+
testName: "returns false when Xcode's major version is below min required version",
87+
getXcodeVersion: "10.0",
88+
minRequiredXcodeVersion: 11,
89+
expectedResult: false
90+
},
91+
{
92+
testName: "returns false when xcodeproj is not installed",
93+
getXcodeprojLocation: null,
94+
expectedResult: false
95+
},
96+
{
97+
testName: "returns true when Xcode's major version equals min required version",
98+
getXcodeVersion: "10.0",
99+
minRequiredXcodeVersion: 10,
100+
expectedResult: true
101+
},
102+
{
103+
testName: "returns true when Xcode's major version equals min required version",
104+
getXcodeVersion: "12.0",
105+
minRequiredXcodeVersion: 10,
106+
expectedResult: true
107+
}
108+
];
109+
110+
testCases.forEach(testCase => {
111+
it(testCase.testName, async () => {
112+
const iOSLocalBuildRequirements = setupTestCase(testCase);
113+
let originalXcodeVersion = Constants.XCODE_MIN_REQUIRED_VERSION;
114+
Constants.XCODE_MIN_REQUIRED_VERSION = testCase.minRequiredXcodeVersion || Constants.XCODE_MIN_REQUIRED_VERSION;
115+
116+
const isXcodeVersionValid = await iOSLocalBuildRequirements.checkRequirements();
117+
118+
// Get back the XCODE_MIN_REQUIRED_VERSION value.
119+
Constants.XCODE_MIN_REQUIRED_VERSION = originalXcodeVersion;
120+
121+
assert.equal(isXcodeVersionValid, testCase.expectedResult);
122+
});
123+
});
124+
});
125+
});

0 commit comments

Comments
 (0)